Removing user from role and checking - asp.net-mvc

I have two roles (freeUser , subscribedUser) and when i try to remove a user from role (subscribed user) using
await UserManager.RemoveFromRoleAsync(subscription.UserId, RoleName.SubscribedUser);
it succesfully delete him from AspNetUserRoles table but when i check again to see if the user is subscribed using
var roles = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
var enumerable = roles as IList<string> ?? roles.ToList();
or using User.IsInRole(RoleName.SubscribedUser)
it's return ture ! and the user is still in role subscribedUser even that i checked the AspNetUserRoles table and he is delete

Delete your cookies history, check in different browser or re-start the application. Sometimes, session will validate the user even nolonger exists in database.

Related

ASP MVC Identity 2 get user in "User" role

I add user and assign role as below code, I user ASP MVC 5 identity and EF code first.
//some Code
var result = manager.Create(insert, applicationUser.PasswordHash);
IdentityResult result2 =null;
if (result.Succeeded)
{
result2 = manager.AddToRole(insert.Id, "User");
}
//Some Code
So i need to show list of user with custom role in view like "User" role. i wrote this code :
ApplicationDbContext myDbContext = new ApplicationDbContext();
var getRoleId = myDbContext.Roles.Where(r => r.Name == "User").Select(m => m.Id).SingleOrDefault();
var fetch = myDbContext.Users.Where(u => u.Roles.Any(r => r.RoleId.ToString() == getRoleId)).ToList();
return View(fetch);
getRoleId value is "4", it is right , but fetch always count equal 0.I try more than 3 4 hours but i can not get result.Where is my wrong ? and what is the solution ?
Thank you.
UPDATE :
I found my problem in add role but i do not know how can fix that !
When adding the users to roles using the above, the users id is added to the UserId column of the UserRoles table, but there was a third column called IdentityUser_Id which was always null.
Out of curiosity I added my user id to that column as well and now the everything works. the application picked up my user role.
My follow up question to this is can I set the IdentityUser_Id automatically? using something similar to the UserManager.AddToRole() which adds the userId to both columns?
Why are you getting getRowId and not pull Users by Role Name? Try Below:
var fetch = myDbContext.Users.Where(u => u.Roles.Any(r => r.Name ==
"User")).ToList();

Find users based on a specific role

I am trying to find all users based on a specific role in my application. I currently have two roles Admin and User. When I try to return a list of users that have a role of "User" with the following linq query:
var users = context.Users
.Where(u => u.Roles.Select(r => r.RoleId).Contains("User")).ToList();
it returns 0 users. I have looked at similar questions here but many of them are now outdated. I know that RoleID for example is a hashed key and what I am searching for is plain text "User".
RoleId is not the same as the actual role name string, so that's why you're not getting any matches. The way you need to do this is:
var roleId = context.Roles.Where(m => m.Name == "User").Select(m => m.Id).SingleOrDefault();
Then:
var users = context.Users
.Where(u => u.Roles.Any(r => r.RoleId == roleId)).ToList();

How to stop user from changing ID in url to access other records?

using asp mvc 4.
When the user goes to a student record, the URL says:
http://studentTracker.org/Record/Student?studentId=380
Currently a user can change the studentId right there in the url and get that students record, unless it doesn't exist. How can I either hide the query string part of the url, or detect/validate at the controller if the user has changed the url?
First, you cannot stop a user from doing anything, really, especially something like changing an id in a URL. What you can do is ensure that if they do so, they get something like a 404 or 403, instead of the actual content.
The way to do that is to do object-level permissioning, which basically just means tying the object to the user(s) allowed to view/edit it in some way. Usually, this will done via foreign key to something like your "user" entity or something broader like a group or role.
For example, if the "Student 380" record is owned by jdoe, then you can prevent access to it by anyone but jdoe by first adding a foreign key to your "user" entity on your "student" entity. (Assuming Identity, since unspecified):
public class Student
{
...
[ForeignKey("Owner")]
public string OwnerId { get; set; }
public virtual ApplicationUser Owner { get; set; }
}
Then, in your action, instead of querying by just the id, you query by both the id in the URL and the id of the authenticated user:
var userId = User.Identity.GetUserId();
var student = db.Students.SingleOrDefault(m => m.Id == studentId && m.OwnerId == userId);
if (student == null)
{
return new HttpNotFoundResult();
}
Now, if the user changes studentId but is not set as the "owner" of the student that matches, they'll get a 404.

ASP.Net identity, Users in role are always empty

I have implemented ASP.Net identity with some custom properties following this article -
http://typecastexception.com/post/2014/06/22/ASPNET-Identity-20-Customizing-Users-and-Roles.aspx
Everything works well, except. I want to get users under specific role (e.g. Get me all the users under Admin role).
I tried following ways to retrieve the users -
var userRole = _roleManager.Roles.SingleOrDefault(m => m.Name == role.Name);
var usersInRole = _userManager.Users.Where(m => m.Roles.Any(r => r.RoleId == userRole.Id));
var usersInRole2 = _userService.GetUsers().Where(u => u.Roles.Any(r => r.RoleId == userRole.Id));
Where _roleManager is of type ApplicationRoleManager : RoleManager<ApplicationRole>. _userManageris of type ApplicationUserManager : UserManager<ApplicationUser, string>.
I am unable to get Roles under user in _userManager and _userService
PS : _userService is service that extends IRepository which queries DbSet<ApplicationUser>.
I can see Roles being properly mapped in table ApplicationUserRoles and I get expected result when I do _userManager.IsInRole(user.Id, "Admin");.
What could've gone wrong with this?
Rahul.
If you are using Entity Framework, it sounds like you are being caught out by lazy loading (since the roles are being added to the database but not when requested from a queryable).
Try something like the following:
_userManager.Users.Include(x => x.Roles).Where(m => m.Roles.Any(r => r.RoleId == userRole.Id));
I figured out where the issue was -
Initially the table ApplicationUserRoles had only primary key definitions, not the foreign key mapping (many to many mapping)..
I added this in OnModelCreating
modelBuilder.Entity<ApplicationUserRole>().HasKey((ApplicationUserRole r) => new { UserId = r.UserId, RoleId = r.RoleId });
//added these definitions
modelBuilder.Entity<ApplicationUser>().HasMany(p => p.Roles).WithRequired().HasForeignKey(p => p.UserId);
modelBuilder.Entity<ApplicationRole>().HasMany(p => p.Users).WithRequired().HasForeignKey(p => p.RoleId);
This completed the relationship and now I can see the Users under Roles and vice versa.
This resulted issue while updating the database, however I just had to do some changes in migration -
The object 'PK_Dbo.ApplicationUserRole' is dependent on column
'UserId'. ALTER TABLE DROP COLUMN UserId failed because one or more
objects access this column.
All I did is, I went to the migration file and moved these lines above DropColumn
DropIndex("dbo.ApplicationUserRole", new[] { "ApplicationUser_Id" });
DropIndex("dbo.ApplicationUserRole", new[] { "ApplicationRole_Id" });
DropPrimaryKey("dbo.ApplicationUserRole");
This solved the update-database exceptions as well.
Rahul

Return unique results when using findAllBy

I have the following method in a service, please note the .user on the def usersByRole line:
def getUsersByRole(String desiredRole1, String desiredRole2, String desiredRole3) {
Role role1 = Role.findByAuthority(desiredRole1)
Role role2 = Role.findByAuthority(desiredRole2)
Role role3 = Role.findByAuthority(desiredRole3)
def usersByRole = UserRole.findAllByRoleInList([role1, role2, role3]).user
return usersByRole
}
It works good, but when a user has multiple roles (i.e. ROLE_ADMIN, and ROLE_OWNER) then that user exists twice in the collection if both of the previously mentioned roles are given as parameters. Is there any clean way I can make the collection contain only unique results?
A similar question as yours can be found here: GORM createCriteria and list do not return the same results : what can I do?
Method 1
If you want to return unique list of users directly from DB query then you can use listDistinct on User (supposing that user has a roles OneToMany association with UserRoles)
User.createCriteria().listDistinct {
roles {
in 'role', [role1, role2, role3]
}
}
Method 2
You can also try to query UserRole directly and group by User using the groupProperty (see http://www.grails.org/doc/latest/ref/Domain%20Classes/createCriteria.html)
Method 3
Remove duplicated users from the returned list:
UserRole.findAllByRoleInList([role1, role2, role3])*.user.unique()
The finder will return a List, and calling .user also returns a List, but you can cheat and cast it to a Set and it will remove duplicates. Since there's no order needed (you're returning def so it doesn't appear that you care about the collection type) you don't need to convert it back:
def getUsersByRole(String desiredRole1, String desiredRole2, String desiredRole3) {
Role role1 = Role.findByAuthority(desiredRole1)
Role role2 = Role.findByAuthority(desiredRole2)
Role role3 = Role.findByAuthority(desiredRole3)
return UserRole.findAllByRoleInList([role1, role2, role3]).user as Set
}
This presumes that you have a well-defined equals and hashCode in your User class so the uniqueness check makes sense.

Resources