ASP.NET Менеджер пользователей основной идентификации.AddToRoleAsync() — добавить по идентификатору

#c# #asp.net-core #asp.net-identity #usermanager #role-manager

Вопрос:

У меня есть пользовательский класс ролей пользователя с CompanyId внешним ключом. Таким образом, я мог бы создавать роли пользователей относительно компании. Это означает, что роль администратора или любая другая роль как таковая может быть в нескольких компаниях. Я не могу пойти на отношения «многие ко многим» с компанией и Ролью, потому что требования администратора для одной компании могут отличаться для другой. Поэтому я добавил идентификатор компании в сущность роли пользователя.

Моя проблема в том, что менеджер пользователей принимает имя роли в качестве параметра AddToRoleAsync() , я не могу использовать это, так как имя роли может быть избыточным. Если бы я мог добавить роль пользователя по идентификатору, это было бы здорово. Есть ли обходной путь для достижения этой цели?

Мой текущий обходной путь-добавить название компании в качестве префикса к имени роли. Например: ABC — Администратор; XYZ — Администратор. Мне это не очень нравится, так же как и пользователям.

Если бы я мог создать метод перегрузки для обоих AddToRoleAsync() и IsInRoleAync() искать роль по ее идентификатору, а не по имени, это было бы здорово.

Комментарии:

1. Как насчет того, чтобы назвать роль в зависимости от компании? var roleName = $"Administrator_{companyId}";

Ответ №1:

Вы можете расширить UserManager класс и добавить другой метод для добавления роли с помощью RoleId

 public class ApplicationUserManager : UserManager<IdentityUser>
{
    private readonly UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
        IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>> _store;

    public ApplicationUserManager(
        IUserStore<IdentityUser> store,
        IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<IdentityUser> passwordHasher,
        IEnumerable<IUserValidator<IdentityUser>> userValidators,
        IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators,
        ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors,
        IServiceProvider services,
        ILogger<UserManager<IdentityUser>> logger)
        : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
    {
        _store = (UserStore<IdentityUser, IdentityRole, ApplicationDbContext, string, IdentityUserClaim<string>,
            IdentityUserRole<string>, IdentityUserLogin<string>, IdentityUserToken<string>, IdentityRoleClaim<string>>)store;
    }

    public virtual async Task<IdentityResult> AddToRoleByRoleIdAsync(IdentityUser user, string roleId)
    {
        ThrowIfDisposed();

        if (user == null)
            throw new ArgumentNullException(nameof(user));

        if (string.IsNullOrWhiteSpace(roleId))
            throw new ArgumentNullException(nameof(roleId));

        if (await IsInRoleByRoleIdAsync(user, roleId, CancellationToken))
            return IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(roleId));

        _store.Context.Set<IdentityUserRole<string>>().Add(new IdentityUserRole<string> { RoleId = roleId, UserId = user.Id });

        return await UpdateUserAsync(user);
    }

    public async Task<bool> IsInRoleByRoleIdAsync(IdentityUser user, string roleId, CancellationToken cancellationToken = default(CancellationToken))
    {
        cancellationToken.ThrowIfCancellationRequested();
        ThrowIfDisposed();

        if (user == null)
            throw new ArgumentNullException(nameof(user));

        if (string.IsNullOrWhiteSpace(roleId))
            throw new ArgumentNullException(nameof(roleId));

        var role = await _store.Context.Set<IdentityRole>().FindAsync(roleId);
        if (role == null)
            return false;

        var userRole = await _store.Context.Set<IdentityUserRole<string>>().FindAsync(new object[] { user.Id, roleId }, cancellationToken);
        return userRole != null;
    }
}
 

Затем зарегистрируйте свой собственный UserManager :

 services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddUserManager<ApplicationUserManager>() // Add ApplicationUserManager
    .AddDefaultTokenProviders()
    .AddDefaultUI();
 

И, наконец,:

 await _userManager.AddToRoleByRoleIdAsync(user, role.Id);