Granting a Drupal role to all users that have a certain role - drupal

I need to automatically apply a role, Role X, to all Drupal users that have been granted a separate role, Role Y. In other words, I wish for Role X to be a subset of Role Y. How can I do this?

You could implement hook_user() in a custom module. On the 'insert' and/or 'update' action, you'd check for role Y in the $account->roles array. If present, add role X if not already there. This would ensure that your rule gets applied every time a user account gets created and/or changed.
For a bootstrapping/one time operation, take a look at user_multiple_role_edit(). It lets you add or remove roles for an array of user ids. Alternatively, you could do it directly in the database:
INSERT INTO users_roles (uid, rid)
SELECT uid, [roleX_ID] AS rid FROM users_roles
WHERE uid IN
(SELECT uid FROM users_roles WHERE rid = [roleY_ID])
AND uid NOT IN
(SELECT uid FROM users_roles WHERE rid = [roleX_ID])
;

I agree with Henrik Opel on using hook_user in a custom module would be a good solution to maintain the users and make sure they are up to date all the time.
Normally I wouldn't mind writing SQL or something alike, but in this case, since it's on a production site, I would prefer a different route, since if something can easily go wrong when writing raw SQL, a little typo can cause big troubles. Another good point is that you can run into problems as drupal wont be aware of what raw SQL you run on your database and might get out of sync with some processes, hooks and other processes that's normally run when you do things through the Drupal API.
Instead you can use the drupal user admin interface. I actually think that in this case, it is the easiest way to do what you want. Simply filter all users that are students. Click all the users and give them the member role. This is done with a few clicks in no time, and is very secure since Drupal will handle all the SQL for you.
Updated
With that many users, I'm surprised that you don't have a custom user and content managing page setup using views_bulk_operations. Using a few minutes, you can setup a admin page which you can use to preform bulk operations like changing user status, roles, or perform similar tasks for nodes. You can create your own filters using exposed views filters. So with a few clicks you can select all the users with role of student and that isn't member, select them all and add the member roll to them. The advantage doing this is not only that it's quick and safe, but you can create some nice managing pages for your site administrators, content creators etc. You should consider looking into this module.

The LDAP module allows you to dynamically assign roles based on DN. I actually had to write my own module that is tailored specifically to our system, otherwise I would be more than happy to share it.
link text

Related

Migrate Plone users and groups to relational data

I have a Plone 4 site which contains a lot of users and groups which are stored in the ZODB. Over time, we added some functionality which uses relational data (in a PostgreSQL database); some tables have fields which contain user or group ids.
However, currently the users and groups are defined in ZODB rather than the RDB, so we don't have proper foreign keys here. Thus, the obvious idea is to migrate the user and groups data to the RDB - those who/which are used by the Plone site, at least; I assume emergency users need to be an exception to this (but those are no members of any groups anyway).
Would this be a good thing to do?
Are there reasons to do it only partly, or should I transfer everything including group memberships? (Since memberships are stored as lists of users (and/or groups) with the containing group, I could imagine a reverse table which holds all groups a user is member of, and which is maintained by a trigger function.)
Are there any special tools to use?
Thank you!
imho it's based on what you want to achieve. In Plone you have PAS, so technically it doesn't really matter, where you put users, groups and user group relationships.
You can store users/groups in:
Plone (by default)
SQL - pas.plugins.sqlalchemy
LDAP/AD - Products.PloneLDAP
There are also many other plugins for AUTH, like RPX, Goolge+, etc.
You can enable, disable and modify the behabvior of every plugin thru PAS.
Does it make sense, to NOT use Plone users?
Of course, if you want to share user credentials (Example LDAP), or if you need the user informations in other Apps, etc.
Migration
Should be very simple if the PAS plugins you are using supports "Properties" and "User enumeration".
Get the data from one plugin and put the data into another one with a simple python script. Both supports the same API.
the tool you're looking for is https://pypi.python.org/pypi/pas.plugins.sqlalchemy/0.3
I've used this in a webportal where users are "shared" with a newsletter system.
I've 200 users and any problem.
I think the only "good reason" to store users in an external DB rather in zodb/plone is in a use-case like mine.
Have you ever think about "extend" plone users (ex. https://plone.org/products/collective.examples.userdata)? With plone.api you can easly manipulate users' properties in your code.

Proper place to store CustomerID per user account in Meteor

I'm using the accounts-ui package which works great. I need to store additional information for each user account. Things like their CustomerID so I can have multiple users associated with the same Customer. Or maybe isAdmin to flag whether they are an admin user for that Customer or just a normal user.
If there is a simple way to facilitate having multiple user accounts with a Customer and I just haven't seen it, please let me know.
From the docs under Accounts, Meteor.users, the most applicable field would be profile but it also says the following:
profile: an Object which (by default) the user can create and update
with any data.
While this is a great place to store things like their first and last name, I would obviously not want the user to be able to modify/update the CustomerID or isAdmin so I'm not sure if this is the best place to store this type of data. Or maybe it is and I should just use a Deny rule so inappropriate users cannot modify this data.
Should I store the CustomerID here or in a separate Customer collection. Or if I'm going about this entirely wrong, I'd appreciate being pointed in the right direction. I noticed the Roles package but that seems to be mostly extending the accounts package and also not storing accounts and roles on a per Customer basis. Also thought about building my own authentication system instead of using accounts-ui which is certainly an option.
Well it's clear you've done your homework. Here are a few suggestions:
If you only have one role type, then the roles package may be overkill.
It is safe to use the profile to store role data only if you add a deny rule for updates (see below) As the docs point out, user profiles are currently editable by default even when then insecure package has been removed. I have been lobbying the core devs to change this - so far to no avail.
I don't know enough about your data to suggest how to model your customer relationships. You could put an id in the profile, as you suggested, or you could have an array of user ids on the customer objects (you could do something similar with the notion of admins for the customer). It mostly depends on how these documents will be updated/queried/published/etc. Generally I prefer to store only user-specific data in the profile (name, preferences, etc.) and keep the relationships in other collections.
In general, I recommend writing your own login UI. It really isn't that hard and in many cases, it's probably a good investment in flexibility for the future.
Meteor.users.deny({
update: function() {
return true;
}
});

Use of session in role based access control (RBAC)

I am trying to understand access control based on RBAC model. I referred to the following link.
NIST RBAC Data Model
I haven't understood this part clearly as mentioned in the excerpt -
*"Each session is a mapping of one user to possibly many roles, i.e., a user establishes a session during which the user activates some subset of roles that he or she is assigned. Each session is associated with a single user and each user is associated with one or more sessions. The function session_roles gives us the roles activated by the session and the function user_sessions gives us the set of sessions that are associated with a user. The permissions available to the user are the permissions assigned to the roles that are activated across all the user.s sessions."*
Question - How can session be used to activate roles ? The relationship between the user / group and roles are inserted as admin data. So, how does session activate subset of roles for a user ?
P.S -> I asked this question earlier here but without an answer. May be this question is too basic to ask but I am keen to understand it. Any use case or a link will definitely be helpful.
Thanks for your time.
In RBAC, administrators give permissions by assigning them to roles, and in addition by assigning roles to users. As you know, for a user to be able to use a particular permission, he will have to have been assigned at least one role that provides said solution.
So each user has a set of roles assigned to him. During a session, he can choose to activate (or deactivate) any of these roles, but no other. The activated roles determine which permissions are available to the user at a given time during the session. This is useful, for example, for dynamic separation of duty constraints, where two roles A and B can be assigned to the same user U, but can't be used together. Therefore, if U wants to use A, he will have to deactivate B before activating A.
From my experience in implementing RBAC, I pretty much avoided using dynamic management of multi-sessions.
At first it sounded like a pretty neat and flexible idea, but as you questioned on who activates/deactivates roles (and when), I realized the complexity and security risks wasn't worth the effort (my personal opinion).
The important thing to understand here and for which #Imontriux (above) mentioned:
"This is useful, for example, for dynamic separation of duty
constraints, where two roles A and B can be assigned to the same user
U, but can't be used together. Therefore, if U wants to use A, he will
have to deactivate B before activating A."
Most of the time, there are separation of duty constraints that must apply and in order to honour this, I simply chose to only have/manage one valid session per user at a time. If a user wants to authenticate under different set of roles, he/she is responsible in logging out and logging back in.
It pretty much simplified a lot of my code. It was a compromise I chose and could easily live with.

Best Practices in User Privileges/Session Variables in MVC3

Hi Stack Community Members,
I am developing an application under MVC3 where users have department-specific CRUD privileges. In other words, all users can view data for all departments, but only certain users can make changes to the data for any one given department. User-department privilege data is held in a join table in a database.
What I typically do in this kind of situation (in PHP) is to create a Session variable (an array) on login which is populated with the id's of the departments which the user is allowed to edit. When a user then goes to access the editing feature a drop-down list is populated with only these specific departments. I also populate a few other session variables which are used frequently like the user's name and the id of the current time period (business quarter).
Is this type of approach a good way to go in MVC3, or is some alternative approach better? While I figure that I'm going to use Forms Authentication and some specific roles (employee, admin, etc.) these types of roles are just too broad to be able to target department-by-department access, and I'm not sure that MVC3 has an out-of-the-box method which is better than what I'm planning to do.
Your guidance is appreciated!
I'm using Forms Authentication, add specific roles, and combine them if needed. I don't mind being specific for the roles, as they can be combined anyway I want. I can still have broad roles for more general actions.
I store similar data (UserId, DepartmentId, etc) in session since it does not change for the user and it is a small amount of data. It is my opinion that session state would be a good approach for you also.

Best way to ensure page-level security

I wish to ensure a user has access to an aspx page by 'Zone'. For example, "Financials" is a Security Zone which some users should not have access to.
The result should not involve patterns such as MVP, MVC, MVVM, etc. I'm looking for something that's light and quick to do.
To make things easier I have a base class which each aspx page derives from. What is the easiest/best way to have each page to be checked versus a security zone given the userID?
Thanks.
I've used this, whether it's the best way is seriously questionable. I have a class I derive from Page, called SecurePage. In that I usually have a cross table in a database that lists objects, such as the page, and groups/users that have access to that page. Running a stored procedure using the UserID and the Object name (Page name in this case, but can be a field, or whatever) it returns whether that user or a group that the user belongs in has access. You can check this during the page init, and if it doesn't match up, then response.redirect them or whatever you want to do.
You basically need to create a little ACL implementation. (Access Control List).
Create a acl_roles table, with all your roles (Admin, Accountant, whatever, guest) and stuff. Then link the id of it with your user table, so each user has a role_id.
Then define a acl_resources table, where you add the "zones" in your app and the minimum role they have to be to access it.
Then at the start of each script simply do check if the current user has enough privileges to be in that zone.
There are more details into this, but that is the basic idea.
Yeah, use forms or Windows authentication. You can easily lock down different parts of your site based on the authenticated user's role. Look into using locations.
Why not just use the security features such as forms authentication built into .NET? It's very easy.

Resources