mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Properly validate create user input
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -24,16 +25,19 @@ namespace BTCPayServer.Controllers.RestApi.Users
|
||||
private readonly RoleManager<IdentityRole> _roleManager;
|
||||
private readonly SettingsRepository _settingsRepository;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly IPasswordValidator<ApplicationUser> _passwordValidator;
|
||||
|
||||
public UsersController(UserManager<ApplicationUser> userManager, BTCPayServerOptions btcPayServerOptions,
|
||||
RoleManager<IdentityRole> roleManager, SettingsRepository settingsRepository,
|
||||
EventAggregator eventAggregator)
|
||||
EventAggregator eventAggregator,
|
||||
IPasswordValidator<ApplicationUser> passwordValidator)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_btcPayServerOptions = btcPayServerOptions;
|
||||
_roleManager = roleManager;
|
||||
_settingsRepository = settingsRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_passwordValidator = passwordValidator;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyProfile.Key, AuthenticationSchemes = AuthenticationSchemes.ApiKey)]
|
||||
@@ -48,6 +52,14 @@ namespace BTCPayServer.Controllers.RestApi.Users
|
||||
[HttpPost("~/api/v1/users")]
|
||||
public async Task<ActionResult<ApplicationUserData>> CreateUser(CreateApplicationUserRequest request)
|
||||
{
|
||||
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 policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>() ?? new PoliciesSettings();
|
||||
var anyAdmin = (await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin)).Any();
|
||||
var admin = request.IsAdministrator.GetValueOrDefault(!anyAdmin);
|
||||
@@ -58,10 +70,22 @@ namespace BTCPayServer.Controllers.RestApi.Users
|
||||
RequiresEmailConfirmation = policies.RequiresConfirmedEmail,
|
||||
EmailConfirmed = request.EmailConfirmed.GetValueOrDefault(false)
|
||||
};
|
||||
var identityResult = await _userManager.CreateAsync(user);
|
||||
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));
|
||||
}
|
||||
var identityResult = await _userManager.CreateAsync(user, request.Password);
|
||||
if (!identityResult.Succeeded)
|
||||
{
|
||||
AddErrors(identityResult);
|
||||
foreach (var error in identityResult.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
return BadRequest(new ValidationProblemDetails(ModelState));
|
||||
}
|
||||
else if (admin)
|
||||
@@ -69,12 +93,17 @@ namespace BTCPayServer.Controllers.RestApi.Users
|
||||
await _roleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin));
|
||||
await _userManager.AddToRoleAsync(user, Roles.ServerAdmin);
|
||||
}
|
||||
|
||||
_eventAggregator.Publish(new UserRegisteredEvent() {Request = Request, User = user, Admin = admin});
|
||||
|
||||
return CreatedAtAction("", user);
|
||||
}
|
||||
|
||||
private ValidationProblemDetails CreateValidationProblem(string propertyName, string errorMessage)
|
||||
{
|
||||
var modelState = new ModelStateDictionary();
|
||||
modelState.AddModelError(propertyName, errorMessage);
|
||||
return new ValidationProblemDetails(modelState);
|
||||
}
|
||||
|
||||
private static ApplicationUserData FromModel(ApplicationUser data)
|
||||
{
|
||||
return new ApplicationUserData()
|
||||
@@ -85,33 +114,5 @@ namespace BTCPayServer.Controllers.RestApi.Users
|
||||
RequiresEmailConfirmation = data.RequiresEmailConfirmation
|
||||
};
|
||||
}
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ModelMetadataType(typeof(CreateApplicationUserRequestMetadata))]
|
||||
public class CreateApplicationUserRequest : BTCPayServer.Client.Models.CreateApplicationUserRequest
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class CreateApplicationUserRequestMetadata
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Password")]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user