ASP.NET Core Identity userManager.AddToRoleAsync() - add by id
Asked Answered
A

1

5

I have a custom user role class with CompanyId as a foreign key. So I could create user roles relative to the company. That means Administrator role or any other role per se, can be in multiple companies. I cannot go for a many-to-many relationship with Company and Role because claims of Administrator for one company may vary for another. So I have added the company Id in user role entity.

My problem is, user manager takes role name as a parameter in AddToRoleAsync(), I cannot use this since the role name could be redundant. If I'm able to add user role by Id, that would be great. Is there a workaround to achieve this?

My current workaround is to add the company name as a prefix to role name. Like: ABC - Administrator; XYZ - Administrator. I don't like this very much, so won't the users.

If I could create a an overload method for both AddToRoleAsync() and IsInRoleAync() to look for role by it's ID and not by name, It would be great.

Amadaamadas answered 5/6, 2021 at 5:36 Comment(1)
How about naming the role based on the company? var roleName = $"Administrator_{companyId}";Uranalysis
G
9

You can extend the UserManager class and add another method to assign a role to a user by 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;
    }
}

Then register you own UserManager:

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

And finally:

await _userManager.AddToRoleByRoleIdAsync(user, role.Id);
Gonnella answered 6/6, 2021 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.