OrchardCMS / Orchard

Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
https://orchardproject.net
BSD 3-Clause "New" or "Revised" License
2.37k stars 1.12k forks source link

Users, Roles and Permissions for a Group of Users #7397

Open HermesSbicego-Laser opened 7 years ago

HermesSbicego-Laser commented 7 years ago

HI all, I cannot figure me out how should I approach this particular scenario:

  1. We have a ContentType named "Event"
  2. Each User (with the particular Role of "Event Contributor") can manage all his own Events and also Events owned by Users of the same "team", but cannot manage "Event" if the owner of the content belongs to a different "team" Now I cannot achieve this behaviour because the only permissions I have are "Edit" and "Edit for others".

Example

User Group Role Permission
A1 A Event Contrbutor Edit Event for own Group (it means A)
A2 A Event Contrbutor Edit Event for own Group (it means A)
A3 A Event Contrbutor Edit Event for own Group (it means A)
B1 B Event Contrbutor Edit Event for own Group (it means B)
C1 C Event Contrbutor Edit Event for own Group (it means C)

AuthenticatedUser is A1

Content Owned By Edit
Event 1 A1 Y
Event 2 A2 Y
Event 3 A3 Y
Event 4 B1 N
Event 5 B2 N
Event 6 C1 N

AuthenticatedUser is B1

Content Owned By Edit
Event 1 A1 N
Event 2 A2 N
Event 3 A3 N
Event 4 B1 Y
Event 5 B2 Y
Event 6 C1 N

What probably I need here is a permission for "Edit for his group".

Could be an Idea to have such a functionality in orchard OOB or should I implement my own module?

ActivePHOENiX commented 7 years ago

I think you can use content permissions for Edit for all and edit for own content permissions and restrictions, have a look at Content Permission module, you may need to tweak the module or clone and change some code for your detailed preference and granularity of security intended.

HermesSbicego-Laser commented 7 years ago

Thank you @ActivePHOENiX , you're right. Going deeper in the code it can be done like a separate feature too. Question for the community: Could this feature be interesting in order to increase core modules or should I implement it in a gallery module?

ifle commented 7 years ago

Yes, this is feature is very interesting and hope will be available.

ViRuSTriNiTy commented 7 years ago

I think you can solve this by implementing IAuthorizationServiceEventHandler and creating additional roles for each group. Then assign these group roles to each user individually.

Now, since a content item has an owner, you should be able to determine the roles of the owner and compare these to the roles of the current user.

If both users are in role Group A then current user can edit Event 1, Event 2 and Event 3 (as stated in your table above).

HermesSbicego-Laser commented 7 years ago

What I had in my mind was something a little bit diffrerent working in sync with other permissions on each ContentType. What we could do is a separate feature which can work like this:

  1. It makes a Setting in order to define User Groups, site scope.
  2. It defines a "GroupPart", attached to User (ContentType) which can store informations about the membership of a user to one or more groups
  3. It implements new permissions per ContentType like in the table below where the Edit/Delete/Publish permission is implied by the corresponding Group permission and Group permission is implied by the corresponding "for tohers" permission

Page

Permission Allow Effective
Delete Page for others _ _
Delete Page for own groups x x
Delete Page _ x
Edit Page for others _ _
Edit Page for own groups x x
Edit Page _ x
Publish or unpublish Page for others _ _
Publish or unpublish Page for own groups x x
Publish or unpublish Page _ x
View Page by others _ x
View own Page _ x

What do you think about this approach?

ViRuSTriNiTy commented 7 years ago

Reasonable approach but what excactly do you gain by adding "groups" and additional settings and parts? Imho Orchard already provides everything necessary:

User Group Settings = User Role Management GroupPart = User Roles Part New Permissions = needs just renaming, e.g. for own groups -> for same role(s)

You would basically reinvent the wheel. Just my 2 cents.

HermesSbicego-Laser commented 7 years ago

Yes, I understand your position but your solution cannot be applied in my scenario, because it's too difficult to manage it with large volumes of groups. I have more or less 500 users organized in 200 different team/groups. All users can Edit "Pages" of their, and only their, team/group. With your approach I would have to create 200 different Roles and define for each role permissions, (that means 200 times). Furthermore, imagine if I need to add or change a permission later (e.g. adding Edit permission to other Content Types) for these roles, it means x200 again.

I know I can manage it in a separate custom module and if this feature is not reasonable for the community i will proceed in that way. Mine was a suggestion in order to know if it could be useful also for others.

Best, Hermes

ActivePHOENiX commented 7 years ago

At some point in the past I needed to have the exact functionality you are discussing, at the time I came to conclusion that I did not need all the permissions complexity that are available and all the security setup needed to get done in code, you can imagine the scenario like this, there were groups of sales managers and some sales reps below them, and there were some business units that some sales managers along their sales reps would belong to those units , the granularity of permissions would jump to 2 to the power of 3 if I needed to set permission for each step going down or up the hierarchy. for some users the permission was as simple as the content should be visible for others or it would be a private content.

by orchard default setup, sales managers would create a user, then they had to create a role for user and then set the permissions for that role, because a user may or may not be part of a group and a team may or may not be part of several business units, so at first I thought I needed to create roles per user as well as roles per groups and units, by doing so I reached to the point that I needed to change my thinking and needed another way to get the task done because of limitations or different concept of security that was ingrained in orchard. at that time, it worked and I think it was a hack than a good and viable solution.

Maybe you can come up with a better and valid idea , It would be useful for others mainly those who are seeking to extend orchard to use it in enterprise level applications and do not look at orchard as a weblog app or cms alone. in my mind orchard is a very flexible engine that is able to generate what ever output you needed provided that you are able to add necessary tools and be able to change or adapt your ultimate product design for this engine to get consumed.

ifle commented 7 years ago

It would be useful for others mainly those who are seeking to extend orchard to use it in enterprise level applications

Strongly agree

ViRuSTriNiTy commented 7 years ago

@HermesSbicego-Laser

With your approach I would have to create 200 different Roles and define for each role permissions, (that means 200 times). Furthermore, imagine if I need to add or change a permission later (e.g. adding Edit permission to other Content Types) for these roles, it means x200 again.

Ok, that's a lot. We use Orchard in my company as base system for enterprise stuff which often involve complex permission relationships, we have 77 roles already and i can say that these tasks can be done in migrations or simply put some code in an MVC action and execute it.

I'm still not convinced why the GroupPart approach should be easier. You have to do exactly the same steps here. Define 200 groups, assign these groups, assign permissions.

The only thing i'm concerned now is the bloating of the role part UI (e.g. when you create (edit a user). But creating a nicer UI should be possible.

HermesSbicego-Laser commented 7 years ago

@ViRuSTriNiTy Let me try to explain me better: What I would love to achieve is not a functionality dedicated to programmers or IT people, but a functionality for a CMS administrator. Migration: it would not work in a multitenancy environment MVC: can be applied only for programmers

Scenario I want some users be able to Editing Page for his own groups I want some other users be able to Publish Page for his own groups I want some other users be able to Delete Page for his own groups I have 10 groups/teams of users

My way (13 items to edit)

Groups Roles
10 3

Your way (30 items to edit)

Groups Roles
0 30

Scenario evolves I want some other users be able to Editing AnotherPage (Custom Content Type) for his own groups I want some other users be able to Publish AnotherPage (Custom Content Type) for his own groups I want some other users be able to Delete AnotherPage (Custom Content Type) for his own groups

My way imply the definition of 3 new Roles (3 more items to edit)

Groups Roles
10 6

Your way imply the definition of 30 new Roles (30 more items to edit)

Groups Roles
0 60

@ActivePHOENiX using hierarchical teams and manage permissions consequently could be a solution in your case?

ViRuSTriNiTy commented 7 years ago

I'm a bit puzzled about the 60 Roles thing. I don't understand where this number comes from. But anyway, my suggestion does not fit anymore as you have mentioned "hierarchical teams" now.

:Edit

I've read your initial post again and i think you don't understand my suggestion. Based on your initial post here is an example:

If i don't have a fallacy here, the role count is exactly the same as the team count regardless of the number of content items.

ActivePHOENiX commented 7 years ago

@HermesSbicego-Laser with regard to Hierarchical ability to define and assign roles/permissions would be a nice task to achieve as it seems to be the standard designed in most enterprise level open source software we could see. but I think it makes the design more complex, I tried to do it and have failed unfortunately.

Xceno commented 7 years ago

Hey guys, sorry if I hijack your discussion but there is a thing that really bothers me. I understand the different needs for groups/Team roles etc. some of you have mentioned here and the way to build team-roles like @ViRuSTriNiTy describes it is a totaly valid approach. However, having a lot of team-roles (we also have a legacy orchard with ~250 roles) becomes quite cumbersome to manage; but I think that is another discussion for UX/UI design.

What I wanted to throw in here is this: We have a project where we needed to make very fine grained permissions on a per-user basis. Now, in theory one can do this by creating a new role and utilizing the ContentPermissionPart. But this becomes a UI nightmare pretty fast if the user base grows.

So I came up with a part called AccessControlPart which looks like this: cac

It allows you to add a user by it's email address. As you can see you can also notify the user and you can configure it, so that users who don't exist in your db yet get an invitation mail which triggers a double-opt-in registration workflow.

It also has 3 AccessLevels, Read, Edit and FullAccess which should be self explanatory. The rules defined via this part are cascading; meaning, that if you define FullAccess for a user on a ContentItem with a ContainerPart the user has also FullAccess to all its children, etc.

Right now this part is tightly coupled to one of our modules but I planned to make it generic anyway (and I could pretty sure use some help with that ;) ).

Maybe this could also solve some of the issues mentioned here if it would be enhanced properly, by adding support for grouping users or something like that.

Well, just my 2 cents here... what do you think?

ViRuSTriNiTy commented 7 years ago

@Xceno Awesome. Sooner or later i will start something similar as the ContentPermissionPart is just not suitable for my needs. I would like to be able to select specific users or roles instead of typing in an email address. Maybe you should put it on GitHub to allow participation in the development of this part.

sebastienros commented 7 years ago

I want to understand how you can get to 250 roles ;)

ViRuSTriNiTy commented 7 years ago

@sebastienros Simple, many modules whereas each module requires its set of roles.

sebastienros commented 7 years ago

@ViRuSTriNiTy still don't understand. Modules can have permissions, how do you have a module require a role? Example?

ViRuSTriNiTy commented 7 years ago

@sebastienros A simple example is a document management module we developed in our company. This module provides fine grained control over document / folder permissions by using the Orchard user / role system.

Lets say there is a folder A. Folder A should be administered by User 1, so a role "Folder A Administrator" is needed to a) assign this role to User 1 in Orchard Admin and b) to grant edit / delete / whatever permission to the forementioned role.

But there should also be users with read only permissions for example. Therefore a role "Folder A User" is needed to a) assign this role to these users and b) grant view permissions.

In this simple example we already have 2 roles for 1 simple folder. As the module grows the role count is going up rapidly.

Now imagine other modules with similar requirements and the role count is going up even more rapidly.

Hope this makes sense.

sebastienros commented 7 years ago

This is the usual theory vs. practice issue with permissions/roles. In theory, you can access Folder1 not because you are you, but because you have a specific trait, and you should find these traits (service, division, building, cost center,company, type of job, ...), there can't be that many. In practice people are too lazy or it's too much work to organize permissions this way, so we say, let's be able to add permissions to users ;) then it's a mess, all permissions are scattered around your folders, and security issues happen.

sebastienros commented 7 years ago

Something that could help and would still be logical would be Roles inheritance (same thing as sub roles).

Xceno commented 7 years ago

@sebastienros I get your point; but here is the example of our legacy system (1.6).

It is a system that provides access to certain business data. We have a ContentType SQLQuery this is administered by a single super user. Now we have a bunch of people all around the world from different companies who can run these queries.

Now in theory we could of course build our own cross table where we store all the relationships between User and SQLQuery and be done with it. But since we wanted to use the built in auth system, we now have a lot of roles assigned to only one or two users, with a read permission for the SQLQuery.

Now to spin that thing around: We could have also built a single role called SQLQuery User and assign it to all those people. But since we need to have fine grained "per-user" access rules this just wasn't sufficient.


(Since the scenario described here is obviously a real mess I came up with that AccessPart described above in the first place. And also because of the permission cascading built into it.)

Well I don't know if there is an elephant in the room here, if so please enlighten us :)

I understand your security and management concerns with access rules scattered across different ContentItems. But I still think there should be a way to build a per-user permission system that isn't a total mess.

Also, I think role inheritance would solve a bunch of problems (including hierarchical teams mentioned by @HermesSbicego-Laser), but I don't see how it would solve the scenarios described by @ViRuSTriNiTy and me.

ViRuSTriNiTy commented 7 years ago

Can someone enlighten me what "roles inheritance" based on an example means?

ActivePHOENiX commented 7 years ago

Any news on this issue/feature? any progress or new decision for abandoning the idea? road blocks? I would appreciate your update.

ActivePHOENiX commented 7 years ago

Hi everybody, I would appreciate any update or information on the progress of this issue, is it abandoned or is on progress? thanks.

HermesSbicego-Laser commented 7 years ago

@ActivePHOENiX, @ViRuSTriNiTy, @Xceno, @sebastienros We, Laser, are not working on it, cause there are many different ideas on requirements and what to do, as you can see. Our position is that Orchard should extend the ability to give permissions over contents (only own/for others is not enough for us). That said, we have a basic module already implemented, doing stuff around group, but is really basic, it requires some "suppress dependency" (I dislike that approach, but in our case was the only possible way) and it covers very few cases (at least in our scenarios). So what now? We are planning something a little bit different, more ambitious, that is to introduce a module to support "claims permissions" in Orchard, which should covers all above requirements. @MatteoPiovanelli-Laser, @GiuseppeMusso-Laser, @LorenzoFrediani-Laser and I, we did a bit of analysis, we investigate on how this could be implemented, and we did some initial work already. If anyone wants more details, or wants to participate, feels free to ping me, we can code something together...

Xceno commented 7 years ago

Hey folks! After re-reading everything here, I think claim based authorization would indeed be a nice thing to have, but a whole lot of work to do. With that said, @HermesSbicego-Laser I'm far from an expert on this topic but I'd love to see what you already have! I also agree with @sebastienros now, scattering permissions all over the place is probably a bad idea and will open the gates to security issues and maintenance hell.

Besides that, we're still using the AccessControlPart mentioned above (8. Dezember 2016) and it works really well. So If anyone's interested I can shed some more light on this too.

ActivePHOENiX commented 7 years ago

@Xceno I appreciate any further clarification on the solution you are currently satisfied with, Thanks in advance.