Use ACL isGranted inside a voter isGranted - security

Edit: See my answer below.
For my needs, I decided to use both ACL and voters for my app (maybe it is not the best way, please, tell me if I'm wrong with this).
My entities represent a factory where there are :
Lines owning Workshops owning Equipments owning Spare Parts.
I want to give either a manager or a viewer access to a line level. For this purpose, I use an ACL on the line.
Because there are more than 5000 spare parts per line, I don't want to write 5000 ace to tell symfony that this user, which is allowed to manage this line, can manage the spare parts of the line.
To solve this problem, I decided to add a voter before the acl check.
I do a isGranted('edit',$sparepart) which is handled by a voter, and inside my own voter, I want to perform a isGranted('OPERATOR',$line).
Actually, I have many more things to check (is the user plant manager ? for example) and I like to combine the voter and the ACL.
Unfortunately, I'm a bit lost and I don't manage to call the right "isGranted" from my voter, I get an infinite loop error.
Voter isGranted
$authChecker = $this->get('security.authorization_checker');
$authChecker->isGranted('', $post);
ACL isGranted
$securityContext = $this->get('security.context');
$securityContext->isGranted('EDIT', $comment);
I understand this might be a bit confusing, and maybe I'm not doing it the right way :s
Thanks for your help !
So I finally did this in another way.
I use one voter and I created new entities to manage my access.
I have a LineAccess entity with:
ManyToOne: Line
ManyToOne: User
Sp_access: smallint
Cart_access: smallint
Line_access: smallint
So I check everything by myself and I also manage the links with my LineAccess entity and CustomerAccess entity.
Finally, it is the best way I think. Good luck
Here is the full problem for the curious :
For each user, I want to be able to select his permissions with this table.
If, for example, I check Boeing (the customer) manage. I will create an ACL/ACE with OPERATOR for this $customer.
That's it. Later, I want to check if this user is able to manage a line by first looking at a 'OPERATOR' on $line but if it doesn't exist, I will check 'OPERATOR' on $plant, and then 'OPERATOR' on $customer.
If I select Manage Dreamliner plant, I get this :
You can see that I'm still able to chose the kind of access to spare parts and cart. I can set this user, which is a plant manager, another permission : Spare parts manage. For that kind of permission, I can use the mask builder feature which allows me to store with a single integer "SP_MANAGER, CART_VALIDATE, LINE MANAGE', for example.
You can see that it gets a little complex here and this is why I think that ACL are my best friends, but I wanted to add a level of control in which I can manually select which isGranted() method, and on which entity.
I tried to be precise but it is not that easy :s
Thanks a lot for your help !

Voters and ACL are both standalone architecture approach to authorization. I'd recommend using Voters only, since they're easier to understand, use and extend.
For more details on this comparison, check these explanatory slides.
Where exactly you can't use Voters instead of ACL?
Also, why you need to nest Voters/ACL?

Thanks for your quick answer !
Actually, I thought I needed ACL because I have to put in the database my permissions. And here is the kind of permissions I want :
User A:
Manage line 1 (include workshops, equipments, sp) and can create shopping carts in this line.
View line 2 (can't manage the line but can see it's content) and can only validate the shopping carts.
So I thought it was good to use ACL because that way I can write in the database the permissions for each objects.
I also like the fact that I can use masks.
(There is the same logic on the Plant level)

Related

How can i provide role based security to notes in MS CRM 2011

I am working on Notes in MS CRM 2011.
I have many roles over many entities.
I want role based security to notes for any entity records.
let me explain what i want:
Suppose i have an entity namely E1.
Role R1 and R2 has read and write access to E1.
But i want that user having role R2 can only upload and view notes for any record of entity E1.
Hope now my requirement is clear to all of you.
Please suggest me how can i achieve it using MS CRM 2011.
I can think of two ways to do this.
You can create a plugin on create/update of the annotation(note) and check if the note is related to entity E1 and check the roles of the user making the change and see if they only have the R2 role. If that is the case you can throw an InvalidPluginExecutionException with a message like 'You do not have permissions to edit/create these records'.
You can try using role based forms or JS to hide the notes area for R1 users.
You probably want to use a combination of #1 & #2. The users can still access the notes via advanced find and thus will be able to edit those notes. The plugin will prevent that fringe case as well.
*Edit
There are a couple more things that you might be able to deal with the advanced find records. You can remove the annotation entity from advanced find via the unsupported method described here.
Otherwise there is one more thing you can do if you want to prevent those results showing up at all, and you want to stay supported. You can write a plugin on Post-RetrieveMultiple of the annotation entity to strip out the results directly from the return result. There are a couple downsides to this though.
You are executing your plug-in every time the retrieve multiple is called on the entity. So this code will need to be as efficient as possible since that delay will be noticeable by the end user whenever they retrieve these records.
Things like advanced find will display odd results. For example if your paging is set to 50 records and you strip out 10, they will only see 40 records on their page and the total record count will include the records you are stripping out.
Through roles i don't know a way to do that, because you configure the access to notes generic, so applies to all entities. You have to access with Javascript navigating in DOM. Check a example:
document.getElementById("notescontrol").contentWindow.document.getElementById("NotesTable")
You can check this with the help of a develeper tool in your browser.

Orchard CMS - Grouping fields

Is there a possibility to have fields that are added to a contentpart to be grouped. I don't know upfront what fields the customer will add. And if he adds a lot of fields to the contentpart, it would be nice if there was some kind of identifier to group them.
Should I take over the Orchard.Fields module and modify it or is there an easier way?
There is no easy way to do that today, but this is such a common request that I think it should be submitted as a work item (or even better, a patch) on CodePlex. We should add a group attribute to fields and maybe even parts.
UPDATE: I created it for you: http://orchard.codeplex.com/workitem/18920 Feel free to vote for it.

Determine all groups for a defined user

I am currently creating a java method(part of and XPages managed bean) to retrieve a list groups a user(not necessarly current user) is a member of.
Is there any easy method to retieve this information or am i going to have to loop through all the groups to check for the user and also check if those groups are sub groups of other groups?
Answered this in a blog post here: http://ntf.gbs.com/nathan/escape.nsf/d6plinks/NTFN-8TMHRP
Simple version is that what you're looking for is...
lotus.notes.addins.DominoServer server = new lotus.notes.addins.DominoServer("YourCanonicalServerName");
Collection nameList = server.getNamesList("TheUserNameYou'reLookingFor");
That should be all you need.
use this snippets:
XSPContext context = XSPContext.getXSPContext(FacesContext.getCurrentInstance());
DirectoryUser currentUser = context.getUser();
Vector<String> groups = new Vector(currentUser.getGroups());
You can retrieve this information from ($ServerAccess) view in names.nsf, which is categorized by user name.
session.evaluate( "#UserNamesList" );
Rather than looping through all the groups in all the directories on the server you might prefer to create a special view in each director organized by group members. That makes the finding of matches quite a lot faster.
The GroupManager tools mentioned by Jasper are also a good example of LotusScript code which accomplishes most of what you want. The objects in Java are the same, the syntax is just a lot more pesky.
/Newbs
Not sure if you can (re)use the LotusScript here, but this article (IBM DeveloperWorks, look at the 4th paragraph) is a great start. It mentions the NotesGroupManager and NotesGroup classes. These classes could be used as a basis for rewriting the code for XPages. There seems to be no other "easy" way to find all the groups a user belongs to. The straight answer to the question seems to be NO.

How to Enabled a single field for update for a particular role in CRM 2011

What I need
I have a custom Entity with that with multiple fields. Admin Role has "god" access. All other roles except for one have read only. The one non admin role with update access, should only be able to update a single field.
What I believe to be true
I believe I have three main options to implement this requirement:
Enable Update Access to the role for that entity then write Javascript to disable all fields on the form for that role, except for the one that I want that role to be able to edit
Enable Update Access to the role for that entity then create a new form that disables all fields on the form for that role, except for the one that I want that role to be able to edit.
Enable Update Access to the role for that entity then turn on field security for each field, disabling access using the field security, for each field except for the one I want them to edit.
What's the Best Practice?
What options should I choose?
If I go with options 1 or 2, will the user be able to edit the field on the bulk edit form?
From a user perspective, I think it's confusing when a form opens up with things enabled, then they get locked down. Plus someone could possibly get data in there before the fields get locked. I'd say you'd have to combine this with a plugin to prevent changing fields you don't want changed.
I like this option better, although again, the field can be unlocked if someone knows what they're doing, so a plugin to double check would be nice.
This would avoid having to double check in a plugin, but you also have to rely on the admin correctly setting up security for new fields going forward. If that's not a concern, this might be best.
Bulk edit is a global privilege, so they'd have bulk edit for all entities. Also, the bulk edit form does not load scripts, so that knocks out option 1. I'd say if it's just this one field, I might leave the privilege locked down and provide my own Bulk edit button on the grid that would show a custom page that just has that one field on it, then handle the updates though script.
2 is most likely best, or as an alternative put the fields in the header or footer rather than as read-only fields on the form.
This also means the fields won't be available to bulk edit, but other methods such as data import or workflows would let users get round this if they know how and have rights to do such things.
3 Field Security is the most robust and works for all scenarios
Possible option 4: create another entity to contain those fields and apply different security to that entity. If created as a child, show the record in a grid on the form with the values included in the view. If it is a parent then you could use methods such as showing the values via an HTML webresource page included on the form.

Best way to implement RBAC with Access

I'm programming a new application with many users, a few roles and specific permissions for those roles. For that I want to create the following tables:
Users (ID,Login, password,..)
Roles(ID,Rolename)
User_Roles(User_ID, Role_ID)
Permissions(ID,PermissionName)
Permission_Roles(Permission_ID, Role_ID)
My idea was to build a function, which allows to check if a user has a specific permission to access a form. I would do that by creating Permissions/Rules like 'canReadFormX', 'canEditFormX' which would allow me to use one main function to check and perfom those specific rules and a function per form to call it.
Is that a way to go (or rather did I understand everything correctly regarding RBAC) or is that just far to complicated? Any advise is very appreciated!
It seems fair to me, and similar to what we have already set, for the first 3 tables.
You then have to solve the 'action' problem, ie to distribute permissions to use your appl's actions. I am not sure that your 'Permissions' proposal will cover all the situations, as you have to deal with 2 major categories of actions:
The 'Open form' actions, that you already have identified: you effectively have to define 2 levels of authorisation for each form: the 'view' right, and the 'update' right.
All other actions, such as form specific buttons or menus, that will allow you to run a specific action other than just opening a form (execute a report, make a specific calculation, automatically import or update data, etc).
One solution/My advice is to maintain 2 tables for this:
A 'Forms' table
An 'Actions' table
And the corresponding link tables:
A 'Form_Role' table
An 'Action_Role' table
With such a configuration, you are fully covered. You can even decide which role has the right to see a specific report on a specific form, as long as the corresponding action is accessed through a specific control or menu on the form.
Both Forms and Actions tables are very interesting as they both participate in your application metamodel...
EDIT: By the way, if you are on a domain, you can use user's domain credentials to control his\her access rights to your system. In this case you do not need to store a password in your RBAC system.

Resources