unrestrictedSearchResults vs allowedRolesAndUsers
Sometimes you need to get all items in a result set without having the rights to actually view them.
Doing a default catalog query as a logged in Plone user will limit the results based on your roles and view permission. This is great catalog behavior when we search for items or show folder listings.
But in my case we want to show a memberlist, using only the title of the object. The title can be accessed when we've got 'Access Contents Information' permission.
The workflow:
<state state_id="published" title="Published">
<permission-map name="Access contents information" acquired="False">
<permission-role>Member</permission-role>
<permission-role>Manager</permission-role>
</permission-map>
<permission-map name="View" acquired="False">
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
</permission-map>
</state>
The code in the browserview:
def getMember(self, sort_on="sortable_title", sort_order=""):
"""get members within a memberfolder"""
query = {
'portal_type': 'member',
'sort_on': sort_on,
'path': '/'.join(project.getPhysicalPath()),
}
catalog = getToolByName(self.context, 'portal_catalog')
values = [x._unrestrictedGetObject() for x in \
catalog.unrestrictedSearchResults(query)]
results = []
for obj in values:
if not checkPermission('zope2.AccessContentsInformation', obj):
continue
results.append(obj)
return results
We use 'unrestrictedSearchResults' to get all objects from the catalog and ignore the allowedRolesAndUsers list. As we're getting a set of brains which we are unable to access using getObject, we need to get all objects unrestrictedly as well, using '_unrestrictedGetObject'.
At the end we check if we've got zope2.AccessContentsInformation permissions and if not, we drop the items from the list.
The tal code:
<div metal:fill-slot="main"
tal:define="vrijwilligers view/getVrijwilligers;
batch vrijwilligers">
<div id="template-vrijwilligerfolder_view"
tal:define="mtool context/portal_membership;">
<table id="vrijwilligerslisting" condition="vrijwilligers">
<tr tal:repeat="item batch">
<tal:block tal:define="item_url item/getURL|item/absolute_url;
modify python:mtool.checkPermission('Modify portal content', item);
may_view python:mtool.checkPermission('View', item)">
<td><a tal:attributes="href item_url"
tal:omit-tag="python:not modify or not may_view"
tal:content="string: ${item/getFirstname}">Jos</a></td>
</tr>
</table>
</div>
</div>
Note the tal:omit-tag, this is used to show a link to the object when we've got the right to really access (view) the object. In this case Manager and Owner will be able to access the member objects. Members will only get a list of users.
Please note, use this wisely, as unrestrictedSearchResults will return all objects in the catalog that satisfy your query, and ignores your rights. When having many objects, checking their permissions one by one is getting really stressful for your application.