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);