New at ASP.NET MVC. I am looking for some UI design ideas not entirely specific to MVC. There is probably not an exact answer but here is what I have started.
There would need to be a page with 3 tabs on it.
Permissions | Groups | Users
1) Permissions View would allow you to do CRUD operations on Permissions in a Grid
Delete on a specific permission is only allowed when the permission is not being used in any Group.
2) On Groups View, CRUD operations on Groups are allowed in grid.
Also, a Permissions link is provided that will allow to do mapping (Add/Remove) Permissions for a Group
Again, a DELETE operation on a Group is only allowed when the Group is not being used by any User.
3) On Users View, all the existing Users in the system will be presented. The grid show allow for searching a user by username, first name or last name.
Groups link should be provided for each user that when clicked allows to do mapping (Add/Remove) Groups for a User.
Below this mapping in the same view, a separate section of Permission Overrides should be provided so that a specific permission can be added with IsGranted (true/false).
Description of the database design:
1) Groups will be assigned Permissions. Based on the group that the user belongs to, User will get the Permissions.
2) UserPermissionOverrides will handle the scenario where
- a User needs to be granted certain permissions (regardless of the role they are in) or
- if certain permissions need to be revoked from a user, even if they belong to a certain group.
This will allow us good flexibility to handle the special scenarios of adding or removing specific permissions.
So, when the user logs in - 1) above will be used to retrieve the group permissions for a user and then 2) will be executed to retrieve the overrides (granted/revoked). Combining 1) and 2) will give us the final permissions for the user which will then get stored in the forms authentication cookie to prevent further database hits
Your model and functionality all make sense to me. However, I think you need to revisit the UX principles you are employing for the interface.
Write a few user stories i.e. what a user of the security system intends to do and what goal they need to fulfill for that visit.
You need not always tightly couple your UI to your model i.e. just because you have structured your model in a certain way, those entities needn't be presented as principle objects for CRUD operations to a user. It's probably very unlikely that a user of the system will come in, add a permission and leave.
Pertaining to the above, personally I would approach your user permission UI as a wizard rather than a set of tabs:
Step 1: Pick a user or add a user.
Step 2: Which roles do they need (offer the opportunity to add a role).
Step 3: In which groups do they belong (offer them to add groups here if necessary).
... or similar.
Basically, your aim should be to get your user in and out of the system as quickly as possible. I think the act of creating user stories and wizards you glean from them would be the method I would employ in the UX design of your system.
Good luck!
Related
What is the best way of dynamic authorizing users with their roles. Indeed I have some roles that changes overtimes and currently I have this code for some of my actions or contorllers:
[Authorize(Roles = "Admin,MainFedration,FederationUser")]
public string ConfirmAccident(int? id)
{ .... }
Then if a role add or change it's permission i should search and change most of actions and roles to config new permission.
What is the best way to remove this redundant work?
The only other way would be to configure the permissions each role has in a database and then subclass AuthorizeAttribute and overload the logic for how it determines which roles are allowed by utilizing the database-stored permissions.
However, it should be noted, that this is a problem mostly because you're using roles improperly. I see this all over, even in official Microsoft documentation, which is part of the problem. Something like "Admin" is a group; roles are different and should be things like "CanEdit". A group or a user can be assigned roles, so any user in the "Admin" group, would have the role "CanEdit". Then, you don't have to change the roles config on the action because the ability to edit is the ability to edit, no matter which users or groups have it.
Maybe you should take a look at how Access Control is organized: https://nsecurity.codeplex.com/. Here's a simple solution which outlines the principles of Access Control Entries, Access Control Lists, and how access to items, subject to security restrictions is set up. This way of (dis-)allowing users' access to certain items is much like the way it is organized in, say, Windows file system.
The idea is really simple: instead of giving user permissions (not) to do this or that, the items are guarded and access is granted/denied once a simple condition is satisfied. In other words, security is not geared towards users, but towards "securables". Or, keys are used to lock/unlock doors, but not to prevent users from moving around.
I'm working on migrating from SOAP to valence API. I'm having some problems with a few calls like getting users (All users, based on role, by userID, etc) and grades (All variations).
I see an empty list returned with no items. There's no error of any kind. When I try to get the data using SOAP, I get the desired data.
I've checked the permissions for "Search for Students", so technically, I should be getting something when I try to get all users or by role id of students. What else am I missing here...
The D2LWS service's authentication mechanism puts the API caller in the position of being a privileged caller. The Valence Learning Framework APIs use a different auth model: the user ID/Key tokens that identify a user get employed by the back-end to restrict the functionality of calls. That is: the authenticated user should have access to the same functionality and data as the user would get through the web UI, and no more.
In this particular case, the calls succeed: they send back all the elements in the result set that your calling user has privileges to see -- none of them.
This is almost certainly an issue with the role privileges afforded to your calling user, and debugging the permissions around calls can be challenging. The Valence project's documentation provides a walkthrough topic on investigating role permissions that might shed let on a possible approach here, especially with respect to the calls to gain access to user records (or properties that appear in user records).
As the walkthrough discusses, there are various aspects to making the general call to /d2l/api/lp/{version}/users/ that bring permissions into play:
If you're trying to filter with a query parameter, does the calling user context have permissions to use the data on which you want to filter
Does the calling user context have permission to see properties affected by User Information Privacy settings
Does the calling user have permission to search for all the user roles they need to, in order find users in the result set
The users call operates on the root organization unit, so the permissions the calling user requires must be set on the organization org unit type.
By contrast, the Grades-related API calls operate not on the root organization unit, but typically on course offerings, sections, or groups. The permissions surrounding the calls there will get checked in the associated org unit types, so the calling user will need the right permissions against those types. Additionally, many of the calls related to course offerings (also sections and groups) require that the calling user be enrolled in the org unit in question (and in some cases, explicitly enrolled, not merely enrolled by cascading enrollment).
If you're sure that your calling user context does give you access to these things (and allows you access to this data through the web UI), and you still see a mismatch like this when you're calling through the API, then you may have uncovered a defect of some kind and you should please ask your organization's support contact, or your account manager, to open a support ticket to report that through Desire2Learn's support desk.
Is there some way that I can retrieve the roleId of the current user context regardless of that user's role permissions within the LMS?
For example, I would like to programatically determine if a user is a 'student', 'teacher', etc. I know this can be done if the authenticated user has access to user roles but obviously a 'student' role would not possess such credentials.
Any insight into this matter would be greatly appreciated!
With many organizations the assigned role of a user's enrolment is considered sensitive information by the organization (for example, imagine the case where the organization wants to set up multiple roles for particular pay grades of instructors), and does not want the roles to be visible outside a small group of administrative users. Accordingly, there may not be a reliable way for a users to determine their own roleIds assigned to them within an organization unit (course, department, faculty, and so forth), let alone the roles assigned to other users.
Our typical recommendation is that client applications focus first on attempting actions that a user should be able to accomplish based on their access in the webUI: in some cases, this could involve a user characterizing their own general role in a context ("Are you a student in this course? An instructor? A Teaching Assistant?") or it could involve simply attempting actions and gracefully taking action based on results ("I'm sorry, you don't have permission to do/see that").
The various API calls that return an Enrollment.OrgUnitUser structure will contain role information for enrollments; notably the MyEnrollments API call does not return such a structure (it's intention was to be a "safe" call that any user could make to fetch back the list of their own enrollments with potentially privileged information redacted).
I am creating a Grails website where users will have access to the resources they create. Till here everything is clear to me. I define ROLE_USER and lock down my controllers and actions using the Config.groovy file.
The issue I am facing is that I have requirement to support group of users such that some resources created by a user can be edited/updated/deleted by other users of the same group. How do I associate a user with a "group" in spring security, what is the design/library I should use here?
What you will need to do is to have your users' roles (the authorizations) come from the database. Once that is the case, you can then easily adjust the roles a user (or set of users) has and create/remove them on the fly. The docs have some pretty good info on how to get the roles to come from the database, so I won't go any more into that here.
Once the dynamic roles are in place, however, you still need to be able to connect roles to the objects that are created. There are essentially two ways you can go about doing this:
Access Control Lists
Custom logic
Depending on the granularity you need and the flexibility you want, one option may be more appealing than another.
Access Control Lists essentially allow you to have a permission mapping between each user and each entity instance. As you can imagine, it's a fair bit of overhead and can perform poorly if you have a large number of entities and users.
Putting together your own logic, on the other hand, is much more flexible because you can set up your own scheme to connect entity instances or entity classes to users and their roles.
I dont think that spring-security provides such functionality out of the box so you will have to do that manually.
For each domain class that you this kind of functionality, store the user name of current logged in user
def authenticateService
def user = authenticateService.principal()
entity.setUser(user?.getUsername())
Then in the update/delete method of the contoller you should check if the role of the current logged in user matches
the role of the user that created the entity. If you have a match you should proceed with the update/delete otherwise throw an exception
/redirect the user to an error page
As role you can use the spring security roles or you can create a property on the user object you have created
Please consider the following setup:
Multi-tenant webapp.
Tenants create company accounts and company accounts have user accounts under them.
Users have roles, there's a special role "Owner" (the user who created the company account).
I'd like to have users to edit other user accounts (some admin tasks), but two conditions must be met:
Noone may edit owner's data (except for owner, when he's editing his own profile, and own profile editing is the same user editing).
Users may access user data and edit users only within their company account.
The app uses MVC architecture. Currently I check for those two conditions in the web layer and it works for me, but I have some concerns. If I go with some sort of API or some other type of data consumer, I may "forget" to re-inforce these conditions. Also, there will be other objects in the app with similar functionality requirements and which will have similar restrictions on them, so it's better for me to come up with some sort of pattern which will enforce my restrictions on data access level.
Could anyone recommend some approach worth looking into?
Thanks!
I beleive aspects or interceptors should be able to help you. If you work with objects you should be able to intercept requests containing your business data and check wether your user is allowed to work on it. The interceptor could then stop or proceed the execution.