public async void CanThrottle() { Assert.True(LimitRequestZone.TryParse("zone=mylimit rate=10r/s burst=20", out var limitRequestZone)); var delay = new MockDelay(); var service = new RateLimitService(delay); await Assert.ThrowsAsync <KeyNotFoundException>(async() => await service.Throttle("mylimit")); Assert.Equal(0, service.BucketsCount); service.SetZone(limitRequestZone); var throttling = service.Throttle("mylimit"); // Will execute immediately, slot reserved until +100 Assert.True(throttling.Wait(10)); Assert.Equal(1, service.BucketsCount); var throttling2 = service.Throttle("mylimit"); // Will execute at +100, slot reserved until +200 Assert.False(throttling2.Wait(10)); Assert.Equal(1, service.BucketsCount); delay.AdvanceMilliseconds(100); Assert.True(throttling2.Wait(10)); Assert.True(throttling2.IsCompletedSuccessfully); Assert.Equal(1, service.BucketsCount); // Still bucket 1, because the slot used by throttling2 is still here delay.AdvanceMilliseconds(100); // The bucket should be empty, though but wait one more period before deleting the bucket Thread.Sleep(10); Assert.Equal(1, service.BucketsCount); delay.AdvanceMilliseconds(100); Thread.Sleep(100); Assert.Equal(0, service.BucketsCount); }
internal async Task Handle(HttpContext ctx) { if (ctx.Request.Path.Value == "") { if (!(await TryExtractArguments(ctx.Request, ctx.RequestAborted) is string[] args)) { ctx.Response.StatusCode = 400; return; } var response = await Transport.SendCommandAsync(args, ctx.RequestAborted); ctx.Response.StatusCode = 200; ctx.Response.Headers["Content-Type"] = "text/plain"; await ctx.Response.WriteAsync(response, ctx.RequestAborted); return; } else if (ctx.Request.Path.StartsWithSegments("/request-permission")) { if (!ctx.Request.Headers.TryGetValue("Origin", out var origin)) { ctx.Response.StatusCode = 400; return; } if (!await _rateLimitService.Throttle(RateLimitZones.Prompt, ThrottleSingletonObject, ctx.RequestAborted)) { ctx.Response.StatusCode = 429; return; } if (await _permissionsService.IsGranted(origin)) { ctx.Response.StatusCode = 200; return; } if (!await _permissionPrompt.AskPermission(origin, ctx.RequestAborted)) { _logger.LogInformation($"Permission to {origin} got denied"); ctx.Response.StatusCode = 401; return; } _logger.LogInformation($"Permission to {origin} got granted"); ctx.Response.StatusCode = 200; return; } }
public async Task <IActionResult> CreateUser(CreateApplicationUserRequest request, CancellationToken cancellationToken = default) { if (request.Email is null) { ModelState.AddModelError(nameof(request.Email), "Email is missing"); } if (!string.IsNullOrEmpty(request.Email) && !Validation.EmailValidator.IsEmail(request.Email)) { ModelState.AddModelError(nameof(request.Email), "Invalid email"); } if (request.Password is null) { ModelState.AddModelError(nameof(request.Password), "Password is missing"); } if (!ModelState.IsValid) { return(this.CreateValidationError(ModelState)); } if (User.Identity is null) { throw new JsonHttpException(this.StatusCode(401)); } var anyAdmin = (await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin)).Any(); var policies = await _settingsRepository.GetSettingAsync <PoliciesSettings>() ?? new PoliciesSettings(); var isAuth = User.Identity.AuthenticationType == GreenfieldConstants.AuthenticationType; // If registration are locked and that an admin exists, don't accept unauthenticated connection if (anyAdmin && policies.LockSubscription && !isAuth) { return(this.CreateAPIError(401, "unauthenticated", "New user creation isn't authorized to users who are not admin")); } // Even if subscription are unlocked, it is forbidden to create admin unauthenticated if (anyAdmin && request.IsAdministrator is true && !isAuth) { return(this.CreateAPIError(401, "unauthenticated", "New admin creation isn't authorized to users who are not admin")); } // You are de-facto admin if there is no other admin, else you need to be auth and pass policy requirements bool isAdmin = anyAdmin ? (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded && (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.Unrestricted))).Succeeded && isAuth : true; // You need to be admin to create an admin if (request.IsAdministrator is true && !isAdmin) { return(this.CreateAPIPermissionError(Policies.Unrestricted, $"Insufficient API Permissions. Please use an API key with permission: {Policies.Unrestricted} and be an admin.")); } if (!isAdmin && (policies.LockSubscription || (await _settingsRepository.GetPolicies()).DisableNonAdminCreateUserApi)) { // If we are not admin and subscriptions are locked, we need to check the Policies.CanCreateUser.Key permission var canCreateUser = (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanCreateUser))).Succeeded; if (!isAuth || !canCreateUser) { return(this.CreateAPIPermissionError(Policies.CanCreateUser)); } } var user = new ApplicationUser { UserName = request.Email, Email = request.Email, RequiresEmailConfirmation = policies.RequiresConfirmedEmail, Created = DateTimeOffset.UtcNow, }; var passwordValidation = await this._passwordValidator.ValidateAsync(_userManager, user, request.Password); if (!passwordValidation.Succeeded) { foreach (var error in passwordValidation.Errors) { ModelState.AddModelError(nameof(request.Password), error.Description); } return(this.CreateValidationError(ModelState)); } if (!isAdmin) { if (!await _throttleService.Throttle(ZoneLimits.Register, this.HttpContext.Connection.RemoteIpAddress, cancellationToken)) { return(new TooManyRequestsResult(ZoneLimits.Register)); } } var identityResult = await _userManager.CreateAsync(user, request.Password); if (!identityResult.Succeeded) { foreach (var error in identityResult.Errors) { if (error.Code == "DuplicateUserName") { ModelState.AddModelError(nameof(request.Email), error.Description); } else { ModelState.AddModelError(string.Empty, error.Description); } } return(this.CreateValidationError(ModelState)); } if (request.IsAdministrator is true) { if (!anyAdmin) { await _roleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin)); } await _userManager.AddToRoleAsync(user, Roles.ServerAdmin); if (!anyAdmin) { var settings = await _settingsRepository.GetSettingAsync <ThemeSettings>(); if (settings != null) { settings.FirstRun = false; await _settingsRepository.UpdateSetting(settings); } await _settingsRepository.FirstAdminRegistered(policies, _options.UpdateUrl != null, _options.DisableRegistration, Logs); } } _eventAggregator.Publish(new UserRegisteredEvent() { RequestUri = Request.GetAbsoluteRootUri(), User = user, Admin = request.IsAdministrator is true });
public async Task <ActionResult <ApplicationUserData> > CreateUser(CreateApplicationUserRequest request, CancellationToken cancellationToken = default) { if (request?.Email is null) { return(BadRequest(CreateValidationProblem(nameof(request.Email), "Email is missing"))); } if (!Validation.EmailValidator.IsEmail(request.Email)) { return(BadRequest(CreateValidationProblem(nameof(request.Email), "Invalid email"))); } if (request?.Password is null) { return(BadRequest(CreateValidationProblem(nameof(request.Password), "Password is missing"))); } var anyAdmin = (await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin)).Any(); var policies = await _settingsRepository.GetSettingAsync <PoliciesSettings>() ?? new PoliciesSettings(); var isAuth = User.Identity.AuthenticationType == APIKeyConstants.AuthenticationType; // If registration are locked and that an admin exists, don't accept unauthenticated connection if (anyAdmin && policies.LockSubscription && !isAuth) { return(Unauthorized()); } // Even if subscription are unlocked, it is forbidden to create admin unauthenticated if (anyAdmin && request.IsAdministrator is true && !isAuth) { return(Forbid(AuthenticationSchemes.ApiKey)); } // You are de-facto admin if there is no other admin, else you need to be auth and pass policy requirements bool isAdmin = anyAdmin ? (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanModifyServerSettings))).Succeeded && (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.Unrestricted))).Succeeded && isAuth : true; // You need to be admin to create an admin if (request.IsAdministrator is true && !isAdmin) { return(Forbid(AuthenticationSchemes.ApiKey)); } if (!isAdmin && policies.LockSubscription) { // If we are not admin and subscriptions are locked, we need to check the Policies.CanCreateUser.Key permission var canCreateUser = (await _authorizationService.AuthorizeAsync(User, null, new PolicyRequirement(Policies.CanCreateUser))).Succeeded; if (!isAuth || !canCreateUser) { return(Forbid(AuthenticationSchemes.ApiKey)); } } var user = new ApplicationUser { UserName = request.Email, Email = request.Email, RequiresEmailConfirmation = policies.RequiresConfirmedEmail }; var passwordValidation = await this._passwordValidator.ValidateAsync(_userManager, user, request.Password); if (!passwordValidation.Succeeded) { foreach (var error in passwordValidation.Errors) { ModelState.AddModelError(nameof(request.Password), error.Description); } return(BadRequest(new ValidationProblemDetails(ModelState))); } if (!isAdmin) { if (!await _throttleService.Throttle(ZoneLimits.Register, this.HttpContext.Connection.RemoteIpAddress, cancellationToken)) { return(new TooManyRequestsResult(ZoneLimits.Register)); } } var identityResult = await _userManager.CreateAsync(user, request.Password); if (!identityResult.Succeeded) { foreach (var error in identityResult.Errors) { ModelState.AddModelError(string.Empty, error.Description); } return(BadRequest(new ValidationProblemDetails(ModelState))); } if (request.IsAdministrator is true) { if (!anyAdmin) { await _roleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin)); } await _userManager.AddToRoleAsync(user, Roles.ServerAdmin); if (!anyAdmin) { if (_options.DisableRegistration) { // automatically lock subscriptions now that we have our first admin Logs.PayServer.LogInformation("First admin created, disabling subscription (disable-registration is set to true)"); policies.LockSubscription = true; await _settingsRepository.UpdateSetting(policies); } } } _eventAggregator.Publish(new UserRegisteredEvent() { Request = Request, User = user, Admin = request.IsAdministrator is true });