I have successfully created custom users and roles within the Asp.Net Identity framework, however one section which is lacking is support for the 'Roles' collection within a User. I added a logical 'Deleted' flag within a UserRole and I want this to be included when EF retrieves the info from the database, however all it does is retrieve everything (which isn't what I want). Senario:
User A has a Role of 'admin' (non-deleted)
I then add a Role of 'super-admin' and then delete 'admin'
If I then access my version of IdentityUser (which has the 'Roles' ICollection - custom type) I still see the 2 roles (1 deleted, 1 not)
What I want to happen is on login (using mostly default functions with various sections overridden), when EF retrieves the data it should know to exclude any row which is flagged as deleted, however I have been unable to find any method of doing this. Because all the boilerplate code is locked, I cannot easily see what is happening or find any logical place to override this functionality.
Can anyone help with this?
You could just scan the roles after login and remove them with code similar to this:
var roles = UserManager.GetRoles(userId);
foreach (var roleName in roles)
{
var role = RoleManager.FindByName(roleName);
if (role.IsDeleted) UserManager.RemoveFromRole(userId, roleName);
}
Related
I am following this really good tutorial to setup a BaseEntity class that will contain 5 fields:
Active, DateCreated, UserCreated, DateModified, UserModified.
All of my entities that need these tracking fields will inherit from this class.
In the small tutorial below he shows me how to override the SaveChanges() method in my dbContext so that these fields will be set properly based on Creation/Updating.
I am trying to figure out how I would store the current logged in user's ID rather than the Name to the UserCreated and UserModified fields
Please let me know if the UserID shouldn't be what I am storing. This is always what I used to do in some of the webforms apps I created back in the day.
Also, what would be the best way to setup Active to always be true when adding new records. Should this be done in the db context also or within my BaseEntity class. I'm thinking I would create a function in the BaseEntity class called Disable() that will change Active=False.
Please view the small tutorial that I am using
You could create a custom implementation of IIdentity/IPrincipal which contains the UserID. Then you can retrieve this value from the Context or Thread and cast it to the correct type.
Set HttpContext.Current.User from Thread.CurrentPrincipal
Suppose a web application which has three part or so-called three access level:
One for every visitor (just for seeing the content and no need for authentication)
One for Users (Authorized for users)
One for the Administrator (authorized for admin)
now, administrator has access for every content and every operation in the system and Users could do some operations. I don't wanna to create separate areas for Users and Administrator because I don't want to repeat the same code in every area. for example both admin and user can create product, see the list of products, create catalog and... and also every visitor can also sees the list of product, blog posts, ...
So it's not a good idea to separate and make the code duplicated just for separating the tasks. I haven't created any area and I want to control the authentication and authorization by defining the user role when he/she is in the system(ideas!?) but the main issue comes when I want to have separate user interface (views) for users and admin. as I want to use just one Controller for products, Catalog, ... and set authentication and authorization for them, how can I render different view for every request by admin and user? I also don't want to make my code dirty by putting bunch of if/else to define which view to render (I'd rather to duplicate the code in areas!), any solution?
Probably the easiest solution is to write your own RazorViewEngine(Assuming you are using razor).
Then when you want to retrieve a view for a user, you can check the user role and assign the view you want. This is a basic and crude example:
public override ViewEngineResult FindPartialView(
ControllerContext controllerContext,
string partialViewName,
bool useCache)
{
if (controllerContext.User.IsInRole("Admin"))
{
var adminViewLocations = new string[] {"~/AdminViews/" }
return new ViewEngineResult(adminViewLocations);
}
return base.FindPartialView(controllerContext, partialViewName, useCache);
}
Doing this means that all users use the same controllers and authentication, but the views change based on roles (or whatever you want).
You can read more about A Custom View Engine with Dynamic View Location.
What would be the easiest way to get AD user object properties via a webform based on user input?
To elaborate a bit more this is what I would need:
User enters input to an input field (Employee number - we store it as an extension attribute in AD)
On button click the form returns additional user object properties of the account (such as sAMAccountname, Manager) and displays it on the page (preferably)
I also need to have these properties converted to variables the form can use to pass on to another page sending an e-mail with the retrieved information.
We're using asp for our webforms. So far we only needed to pass user input directly to the mail sender, but this one seems more tricky.
Appreciate any help, thanks!
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// display the various properties of the "user" object in your web page
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Generally when implementing some sort of role based access control, we have the following well-known concepts:
Role
User
Permission
And users would be assigned to roles each of which have a set of permissions (to perform an operation / access a resource etc).
So users gain permissions to perform operations by being assigned to one or more roles (which have been assigned a set of permissions).
In any given application, permissions are defined at compile time since the code actually enforces the permissions at various places where access to resources .
My thinking is that if the set of possible permissions/operations changes – it requires changes to the code and recompilation any way, so having a lookup/reference table in the database won’t really provide any value beyond the fact that a db admin could do a quick sql query to list all permissions used by an app.
Yet most applications I’ve seen create a lookup table for the permissions and -also- map it to a enum in the code.
Given this, is there any reason to actually have a database table representing the list of possible permissions (other than the fact that it is probably easier for some to look in the db as opposed to digging into the code to find the list/enum of permissions)?
Checklist:
1) Do you need to make changes while the website is online, without downtime?
2) Will you be using built-in role/membership provider?
3) You want to use attributes (like mvc [Authorize]) etc?
4) You want to allow users to programatically change permissions/roles?
Any of the above means you have to store the info on DB.
For smaller scale apps I prefer to just create some static methods that also use some kind of inheritance, ie:
isadmin()
{
if (usernameArray.Contains[currentname])
return true;
[...]
}
ispublisher()
{
if (isadmin()) return true;
[...]
}
And a table with permissions for each user pseudo-class.
Update: DB schema for specific access: (* is key, & is foreign key)
Users:
Username *
[...]
UserClasses (EG: admin...)
ID *
description
AccessTypes (EG: can delete)
ID *
description
UserClassesAssign
classid *&
username *&
AccessPerClass
accessid *&
classid *&
So anytime you want to see if 'username' is able to 'CanDelete' you have to check if the User 'username' is linked to any classes that are linked to the access 'CanDelete', and these links can of course change during runtime
My vision includes having globally defined roles which are pushed from AD but also I'd like to be able to add to Context.User.IsInRole("ATransientRoleForThisDocumentOnly") and have that work...
I thought about pushing roles into the Thread.CurrentPrincipal and passing in Context.User.Identity and an array of roles but I was concerned about getting all the ADRoles that you get out of the box, I really just want to add some AdHoc roles that will live for the lifetime of the request.
Does that seem possible? All Role manager methods are static so even if I did custom role manager how would that manager know that for document-id #1 that you're reader... while on document #2 you're read/write?
Inherit from a Security class that allows you to override CreatePermission, for instance CodeAccessSecurityAttribute and return this :
public override IPermission CreatePermission()
{
return new PrincipalPermission(string.Empty, "MyCustomRole");
}