Exemple #1
0
        public async Task <UserViewModel> Handle(CreateUserCommand request, CancellationToken cancellationToken)
        {
            // Validate the username is not in use
            var existingUserByUserName = await _userManager.FindByNameAsync(request.User.Username);

            if (existingUserByUserName != null)
            {
                throw new ConduitApiException($"Username {request.User.Username} is already in use", HttpStatusCode.BadRequest);
            }

            // Validate the email is not in use
            var existingUserByEmail = await _userManager.FindByEmailAsync(request.User.Email);

            if (existingUserByEmail != null)
            {
                throw new ConduitApiException($"Email {request.User.Email} is already in use", HttpStatusCode.BadRequest);
            }

            // Instantiate and attempt to create the user
            var newUser = new ConduitUser
            {
                UserName = request.User.Username,
                Email    = request.User.Email,
            };
            var createUserResult = await _userManager.CreateAsync(newUser, request.User.Password);

            // Instantiate the creation exception and errors, if necessary
            if (!createUserResult.Succeeded)
            {
                var exception = new ConduitApiException($"Could not create user with [{request.User.Username}]", HttpStatusCode.BadRequest);

                foreach (var error in createUserResult.Errors)
                {
                    var conduitError = new ConduitApiError(error.Code, error.Description);
                    exception.ApiErrors.Add(conduitError);
                }

                throw exception;
            }

            // Generate the token and map the user
            var token         = _tokenService.CreateToken(newUser);
            var userViewModel = new UserViewModel
            {
                User = _mapper.Map <UserDto>(newUser)
            };

            userViewModel.User.Token = token;

            await _context.AddActivityAndSaveChangesAsync(ActivityType.UserCreated, TransactionType.ConduitUser, newUser.Id, cancellationToken);

            _logger.LogInformation($"{request.User.Username}] created successfully");
            return(userViewModel);
        }
        /// <inheritdoc />
        /// <summary>
        /// Overrides the default model state validation from ASP.NET Core, passing any validation failures on request
        /// to API exceptions thrown here so they may be handled manually during the request pipeline.
        /// </summary>
        /// <param name="context">HTTP context passed from the web layer</param>
        /// <exception cref="T:Conduit.Core.Exceptions">API exception handled by the pipeline</exception>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var modelState = context.ModelState;

            if (!modelState.IsValid)
            {
                // Retrieve all model state errors
                var modelErrors = modelState.Keys.SelectMany(key => modelState[key].Errors);

                // Build a list of ConduitApiErrors to return to the request pipeline
                var conduitApiErrors = modelErrors.Select(modelError => new ConduitApiError(modelError.ErrorMessage)).ToList();

                // Instantiate the exception
                var conduitApiException = new ConduitApiException(
                    $"Invalid model state during request to [{context.Controller.GetType().Name}]. Trace ID: [{context.HttpContext.TraceIdentifier}]",
                    HttpStatusCode.UnsupportedMediaType,
                    conduitApiErrors);

                // Throw the API exception to be caught during the pipeline
                throw conduitApiException;
            }

            base.OnActionExecuting(context);
        }