We have in one of our customisations implemented permission checks with dynamic authorities in Alfresco. When migrating to solr the search results for those nodes affected by our dynamic permissions became faulty. The reason seems to be that permission checks are done at query time, however our dynamic permissions are not taken into account :(
Here is a short explanations of how our dynamic authorities work:
Check if a node has an association to an authority, if the current user belongs to that authority (group) -> approve access. The node has a lot of different associations and everyone is checked and given READ or WRITE access depending on to which association it belongs.
Is there anyway to tell the Search service to do permission checking on the returned nodes instead (like lucene does)? One workaround I thought of would be to run the query as administrator, then iterate over the result and manually do the permission checks?
Could that be a way to solve it? Any other ideas you could share with me?
Alfresco will perform after-query permission checks on SOLR results when the security.anyDenyDenies property is set to true. This check will involve any dynamic authorities, i.e. it will be a standard check.
The main problem then would be to get the full results from SOLR without pre-filtering there. Other than setting the runAs user to System in a custom sub-class of org.alfresco.repo.search.impl.solr.SolrQueryLanguage (within / around super.executeQuery method call - bean(s) search.lucene.alfresco, search.solr.alfresco, search.fts.alfresco.index and search.solr.cmis in solr-search-context.xml), I see no simpler way to achieve this.
Note: This applies to Alfresco 4.2d and later - I don't know when after-query permissions for SOLR have actually been introduced, but they weren't present when 4.0 came out AFAIK.
Related
...without actually saving data to that node?
For example, I have a chat app. I'd like to check whether a user has write access to a node before showing the "Send message" button.
Define another node with the exact same set of security rules, that exists for no reason other than to perform these checks, and attempt a write there first to see if it finishes without error.
The most common approach is to replicate a similar, simplified version of the rules in your application code. You'd typically only replicate the benign checks, and leave extra validations against malicious users solely on the server.
Although I must admit Doug's version also sounds interesting. :-)
I have a CMS system where admin can create user groups and can grant permissions to groups to do certain things. The permissions (CRUD) are granted on the objects (i.e: can add post, can edit own post, can delete someone else's post, ...)
It's easy to come to the conclusion that we should use something like the provided ACL and store permissions on object or class. However, the question is where should we put these security checking code?
One thing came to my mind was to put that in the controller, but now it means I have to edit every controller I have, or even if I don't I need to somehow identify the object/class that the specific controller action is trying to modify. Sometimes, the controller action will involve several objects/models at once and that makes things even more complicated.
I could also put that in the manager, so that whenever I invoke the save() method I can check for permission. For some reason, that approach seems wrong in term of performance and complexity.
I have read many posts explaining voters, acl and such for Symfony and I understand all that but I'm having trouble putting all that into a solution that would avoid dirty hacks such as editing every single controller.
I find the Symfony2 toolbar very useful, especially the DB queries counter all the way to the right.
The program I'm writing needs to access this value before returning a response, in my case, redirecting to another url.
Is it possible?
Check how you can access it in functional tests.
http://symfony.com/doc/current/cookbook/testing/profiling.html
To enable custom user preferences during publishing we would like to find out in the resolve step (inside a custom resolver) what the publishing user is (so not the user account configured for the Publisher service but the user that initiated the publish operation).
To find the original publishing user we would need to have access to the PublishTransaction object (specifically the Creator property); we cannot use the User property from the Session inside the custom resolver as this Session is created by the Publisher service (and would give us the service account).
To find the current PublishTransaction Mihai has provided us with an excellent hack.
In essence; if we can get our hands on an Engine object we can determine the context publish transaction.
In our custom resolver the Resolve method is called with four parameters:
public void Resolve(
IdentifiableObject item,
ResolveInstruction instruction,
PublishContext context,
ISet<ResolvedItem> resolvedItems
) { }
The item can be used to provide us with a Session object but neither an IdentifiableObject nor a Session hold a reference to the Engine.
The resolve instruction is just a set of data properties for the resolve.
The publish context (unfortunately not a PublishingContext) holds the publication and publication target only.
A ResolvedItem can give us access to the Session again but not the Engine.
My question (finally) would be two-fold:
1. have I missed any potential points where the context user account can be determined from (other than the PublishTransaction)?
2. have I missed any potential points where the Engine can be determined from the parameters the IResolver.Resolve() method is being called with?
Edit: I realize I left out the broader picture on why we want to customize the publish activity with extra metadata (from user preferences) because it is a bit of a long story;
What I ultimately need is to activate for a specific version of a component in the component template (by walking up the version list and finding a version that is linked to a dedicated marker component) but in order to do that I need to know what the marker component is. For this reason we publish the marker component (which will resolve all linked components and ultimately pages) and the custom resolver allowed us to push the TCMURI of the marker component into the session cache (making it accessible in the CT).
Now we want to set a "preference" for a specific marker component at a user level to allow smaller batches of assets to be published within this marker context (as opposed to publishing everything linked to the marker at once).
Because the TBBs running inside the CT actually DO have an Engine object available, we can use Mihai's method and determine the publishing user (as opposed to pushing the marker context from the resolver what we initially did) and in this way bypass the issue completely.
I was wondering why there is such a difference in information availability between a resolve and a render operation; both are afterall part of the same publishing context. I cannot help but feel I'm overlooking something very basic but maybe I'm not and accessing a publishing context or engine from the resolver is simply impossible.
Edit: as presumed by Dominic and confirmed by Nuno there is no "Engine" at the time of resolving; as such this half of my question has been answered.
That leaves
have I missed any potential points where the context user account can be determined from (other than the PublishTransaction)?
I went down this road before in a project (trying to get the user in a Resolver extension) and it was a world of pain.
I moved from a Resolver extension to a Render Extension, and even considered a Transport extension, just to go back to the simplest approach possible: a TBB.
Granted, my use case was different than yours, as it looks like you may want to change the resolving behavior based on the user (some users don't like link propagation, right? - if they're afraid of changing content, then they shouldn't change it ;-) ) but I ended up not implementing it that way.
I think there was an Enhancement Request to include more info about the user triggering publishing actions, but if that is implemented in the product it will be for Tridion 2013, not sure you can wait that long.
I'd guess that you can't get your hands on an engine at this point. After all, you're resolving, not rendering. You mention that you want to "enable user preferences", but you don't tell us much more about your actual problem, rather than the line of investigation you are currently following (which may or may not be a dead end).
What kind of user preferences are relevant to publishing, and why do you need to have them in the resolver?
Where I work we are designing a webapp in which users may belong to multiple groups and each group has access on a set of resources not known in advanced. Plus, users can enter or leave groups and groups can acquire or lose access to resources, so the whole permission granting system needs to be dynamic.
We are using Symfony2 and the FOSUserBundle.
We like how the ACL system works, but we could not find a way to apply it to the Group object.
Has anyone done something like that with Symfony? Or do you have any suggestion on how to implement it in other ways?
According to the cookbook, you can use the RoleSecurityIdentity instead of just the UserSecurityIdentity. So from my understanding of it your Role is your Group. Im working on a similar issue now. When have have done a little more with it Ill try and update this with some code snippets.
But for now have a look at: http://symfony.com/doc/current/cookbook/security/acl_advanced.html
EDIT:
We have gone in another direction and are instead going more with a permission per controller action system. So every controller action is assigned a permission name using annotations.
#SomeDomain/SomeBundle/Controller/SomeController.php
/**
* #Permissions(perm="some.name.for.the.node")
*/
public function indexAction(){ ... }
Then we have a permission bundle with a service that checks the permissions when a controller function is called. Our admins are given a GUI that will allow them to manage the permissions that groups will have and individual users.
Check out this gist that inspired what we are doing: https://gist.github.com/1391850
Im aware this isnt the acl system you were looking for but just thought i would update with what we are doing.