Example #1
0
        public async Task <IServiceResult <UserType> > CreateUserAsync(UserType userEntity, string password, string[]?roles = null)
        {
            Validator.ValidateObject(userEntity, new ComponentDataValidationContext(userEntity), true);
            using var transactionScope = await dbContext.Database.BeginTransactionAsync();

            var      userName     = userEntity.UserName;
            UserType existingUser = await userManager.FindByNameAsync(userName);

            if (!ReferenceEquals(existingUser, null))
            {
                return($"The user '{userName}' has been already created."
                       .ToJsonError(AccountManagerErrorCodes.UserAlreadyCreated.GetStringValue())
                       .ToServiceResult <UserType>()
                       .WithHttpStatusCode(HttpStatusCode.BadRequest));
            }
            // User does not exist, we continue user creation.
            else
            {
                var insensitiveErrorMessage = $"The user '{userName}' could not be created.";

                try {
                    var userResult = await userManager.CreateAsync(userEntity, password);

                    if (!userResult.Succeeded)
                    {
                        var resultJsonErrors = userResult.ToJsonErrors();
                        resultJsonErrors.Insert(0, insensitiveErrorMessage.ToJsonError());

                        return(resultJsonErrors
                               .ToServiceResult <UserType>()
                               .WithHttpStatusCode(HttpStatusCode.BadRequest));
                    }
                } catch (Exception error) {
                    return(errorDetailsProvider.LogCriticalThenBuildAppropiateError <UserType>(error, insensitiveErrorMessage)
                           .WithHttpStatusCode(HttpStatusCode.InternalServerError));
                }
            }

            var loadUserResult = await loadUserByNameAsync(userName);

            if (!loadUserResult.Succeeded)
            {
                return(loadUserResult);
            }

            var loadedUser = loadUserResult.Content !;
            //dbContext.Entrie(loadedUser).State = EntityState.Detached;
            IServiceResult <UserType>?userRoleAssignmentResult = null;

            if (roles != null)
            {
                foreach (var roleName in roles)
                {
                    var roleAssignmentErrorMessage = $"The user '{userName}' could not be assigned to role '{roleName}'. The user creation has been aborted.";

                    try {
                        if (string.IsNullOrWhiteSpace(roleName))
                        {
                            var errorMessage = $"The role '{userName}' is null or empty.";

                            userRoleAssignmentResult = errorMessage
                                                       .ToJsonError()
                                                       .ToServiceResult <UserType>()
                                                       .WithHttpStatusCode(HttpStatusCode.InternalServerError);

                            break;
                        }

                        if (!await userManager.IsInRoleAsync(loadedUser, roleName))
                        {
                            var result = await userManager.AddToRoleAsync(loadedUser, roleName);

                            if (!result.Succeeded)
                            {
                                var resultJsonErrors = result.ToJsonErrors();
                                resultJsonErrors.Insert(0, roleAssignmentErrorMessage);

                                userRoleAssignmentResult = resultJsonErrors
                                                           .ToServiceResult <UserType>()
                                                           .WithHttpStatusCode(HttpStatusCode.BadRequest);

                                break;
                            }
                        }
                    } catch (Exception error) {
                        userRoleAssignmentResult = errorDetailsProvider.LogCriticalThenBuildAppropiateError <UserType>(error, roleAssignmentErrorMessage)
                                                   .WithHttpStatusCode(HttpStatusCode.InternalServerError);
                    }
                }
            }

            var shouldAbortUserCreation = !(userRoleAssignmentResult?.Success() ?? true);

            if (shouldAbortUserCreation)
            {
                try {
                    // TODO: Check if it works.
                    await transactionScope.RollbackAsync();
                } catch (Exception error) {
                    var errorMessage = $"The abortion of the user creation failed. The user '{userName}' could not be deleted from the database.";
                    logger?.LogCritical(error, errorMessage);
                }

                return(userRoleAssignmentResult !);
            }
            else
            {
                await transactionScope.CommitAsync();

                return(ServiceResult <UserType>
                       .Success(loadedUser)
                       .WithHttpStatusCode(HttpStatusCode.OK));
            }
        }
 public static bool Success(this IServiceResult serviceResult, params string[] excludeErrorCodes) =>
 serviceResult.Success((IEnumerable <string>)excludeErrorCodes);