Support forum for ASP.NET Zero (https://aspnetzero.com/).
User avatar
By sbenfares
#31976 Hello,

I’m trying to add 2 areas to my project, i would like to properly redirect users on login.
Each user have a specific role, depending on his role he will be redirected to the good area.

What is your advice to handle this properly ?

I’m modifying AccountController and HomeController with a GetAppHomeUrl method which use a User.IsInRole verification.

My problem is with the NormalizeReturnUrl function and the UserManager.UserIsInRole verification which is not working.
The IsInRole always return false for my users, but return true for the default admin user.

My users are created in the SeedHelper and roles are set with the context :
_context.UserRoles.Add(new UserRole(_tenantId, user.Id, role.Id));


When i create the users in SeedHelper, should i use UserManager.AddToRoleAsync to make IsInRoleAsync work ?
If yes, should i inject UserManager in the SeedHelper ?

Thanks

PS : Multytenancy disabled.
User avatar
By sbenfares
#31988 OK so there was 2 problems here :

1 - The _userManager.IsInRole was not working when i created a user in SeedHelper.
To correct this i injected UserManager in SeedHelper and pass it to TenantRoleAndUserBuilder.

Code: Select allpublic static class SeedHelper
    {
       private static UserManager UserManager { get; set; }

        public static void SeedHostDb(IIocResolver iocResolver)
        {
            UserManager = iocResolver.Resolve<UserManager>();
            WithDbContext<PlatformDbContext>(iocResolver, SeedHostDb);
        }

        public static void SeedHostDb(PlatformDbContext context)
        {
            context.SuppressAutoSetTenantId = true;

            //Host seed
            new InitialHostDbBuilder(context).Create();

            //Default tenant seed (in host database).
            new DefaultTenantBuilder(context).Create();
            new TenantRoleAndUserBuilder(context, 1, UserManager).Create();
       }

....

}


Then in TenantRoleAndUserBuilder i've added a UserManager readonly field and get it from the constructor.
Then in the CreateUser method, i replaced :

Code: Select all//Assign Admin role to admin user
                _context.UserRoles.Add(new UserRole(_tenantId, adminUser.Id, adminRole.Id));
                _context.SaveChanges();


by

Code: Select all 
//Assign role to user
            _userManager.AddToRoleAsync(user, role.Name).Wait();


Then the _userManager.IsInRole is working now in the AccountController for my users created in SeedHelper.


2 - The second problem was to handle properly the url changes depending on the roles of users.

In the home controller in the Index method i've done this :

Code: Select allvar homeUrl = HomeUrlForUser();

            return AbpSession.UserId.HasValue ?
                RedirectToAction("Index", "Home", new { area = homeUrl }) :
                RedirectToAction("Login", "Account");



Then i created a HomeUrlForUser method :

Code: Select allprivate string HomeUrlForUser()
        {
            if (User.IsInRole(StaticRoleNames.Tenants.Candidat)) return "Candidat";
            return User.IsInRole(StaticRoleNames.Tenants.Employeur) ? "Employeur" : "Admin";
        }


In the account controller i've created a method :

Code: Select all
private string CheckReturnUrlForRole(string returnUrl, string userNameOrEmailAddress)
        {
            var user = _userManager.FindByNameOrEmailAsync(userNameOrEmailAddress).Result;
            var isEmployeur = _userManager.IsInRoleAsync(user, StaticRoleNames.Tenants.Employeur).Result;
            var isCandidat = _userManager.IsInRoleAsync(user, StaticRoleNames.Tenants.Candidat).Result;

            if (isEmployeur) return returnUrl.Replace("Admin", "Employeur");
            return isCandidat ? returnUrl.Replace("Admin", "Candidat") : returnUrl;
        }


And then in the login method add a call to this CheckReturnUrlForRole function just after GetLoginResultAsync call :

Code: Select all var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, GetTenancyNameOrNull());
returnUrl = CheckReturnUrlForRole(returnUrl, loginModel.UsernameOrEmailAddress);


Don't know if this is optimal but it works, and i hope it will help someone having same needs.
By ryancyq
#31991 UserManager should not be required to add role to users during seeding.

Do the user roles get created correctly in the database if you have the following instead of using UserManager?
Code: Select all//Assign Admin role to admin user
_context.UserRoles.Add(new UserRole(_tenantId, adminUser.Id, adminRole.Id));
 _context.SaveChanges();

Remember to check the Tenant Id set in the user roles table.

Also, noticed that you were using userManager.Find...Async().Result which is not recommended.

You should write similar like this instead
Code: Select allpublic async Task MyMethod(){
    await userManager.Find...Async();
}
User avatar
By sbenfares
#31993 You are right it's working without UserManager, it was a missing tenantId that caused my problem.

:D Thanks !

PS : And yes i learned why we should replace XXXX.Result by await thanks to (https://stackoverflow.com/questions/24623120/await-on-a-completed-task-same-as-task-result) :ugeek: