IUserValidator для IdentityUser - PullRequest
2 голосов
/ 09 мая 2019

У меня есть пользовательский валидатор электронной почты для менеджера пользователей Identity.

Он был создан для проверки электронной почты пользователя на основе дополнительного свойства IsDeleted (новые пользователи могут быть добавлены с помощью электронной почты удаленного пользователя).

Вот так это выглядит.

public class UserEmailValidator<TUser> : IUserValidator<TUser>
    where TUser : UserAuth
{
    private readonly IUnitOfWork _unitOfWork;

    public UserEmailValidator(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user)
    {
        var errors = new List<IdentityError>();

        var existingAccount = await _unitOfWork.AuthUsers.Get()
            .FirstOrDefaultAsync(u => u.NormalizedEmail == user.Email.ToUpper() && !u.IsDeleted);
        if (existingAccount != null)
            errors.Add(new IdentityError() { Code = GlobalData.Translations.IdentityKeys.DuplicateEmail });

        return errors.Any()
            ? IdentityResult.Failed(errors.ToArray())
            : IdentityResult.Success;
    }
}

Когда я использую метод var res1 = await userManager.CreateAsync(newUser), он работает как положено. Значение res1 - Успешно.

Но на самом деле метод ValidateAsycn также вызывается, когда пользователь назначает роль

var res2 = await userManager.AddToRoleAsync(newUser, "admin") 

и результат res2 - Failed из-за дублирования электронной почты. Есть ли способ уточнить, какое действие будет проверяться (создание пользователя, добавление в роль или любой другой тип действия), чтобы обеспечить правильную проверку для всех случаев?

Вот настройка из Startup.cs

var userBuilder = services.AddIdentity<UserAuth, Role>(options =>
{
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
    options.Lockout.MaxFailedAccessAttempts = 10;
    options.Lockout.AllowedForNewUsers = true;

    options.ClaimsIdentity.UserIdClaimType = GlobalData.CustomClaimNames.UserId;
}).AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserValidator<UserEmailValidator<UserAuth>>()
.AddDefaultTokenProviders()
.AddEmailAndPasswordConfimationTotpTokenProvider();

UPD:

await _userManager.UpdateAsync(user);
await _userManager.RemovePasswordAsync(user);

также вызовите тот же метод ValidateAsync

1 Ответ

1 голос
/ 10 мая 2019

Есть ли способ уточнить, какое действие будет проверяться ...?

Нет контекста для вызова на ValidateUser, кроме Userсамо по себе, что означает, что нет реального способа точно узнать , почему он вызывается.

UserManager содержит метод protected (ValidateAsync), которыйвызывается внутри системы всякий раз, когда вызывается UserManager.CreateAsync или UserManager.UpdateUserAsync.Вызов AddToRoleAsync приводит к вызову UpdateUserAsync, который заканчивается ValidateAsync выполнением реализаций IUserValidator<TUser> для выполнения проверки.

Реализация встроенного UserValidator<TUser>, который вы заменили, обрабатывает вашу проблему с помощью следующей проверки ( source ):

var owner = await manager.FindByEmailAsync(email);
if (owner != null && 
    !string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)))
{
    errors.Add(Describer.DuplicateEmail(email));
}

Сначала он проверяет, существует ли существующая учетная запись сэтот адрес электронной почты, а затем проверяет, совпадает ли эта учетная запись с проверяемой.Если это то же самое, это не дубликат.

Все это означает, что вы должны иметь возможность расширить проверку для выполнения аналогичной логики.Например:

var existingAccount = await _unitOfWork.AuthUsers.Get().FirstOrDefaultAsync(u =>
    u.NormalizedEmail == user.Email.ToUpper() &&
    !u.IsDeleted &&
    u.Id != user.Id);

Здесь я добавил u.Id != user.Id, что намного меньше, чем встроенная реализация, так как ваш код знает, что он работает с UserAuth и может напрямую использовать его свойства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...