[Zope-dev] ZCatalog - hiding query results

abel deuring a.deuring@satzbau-gmbh.de
Sat, 10 Nov 2001 22:33:09 +0100


Igor Stroh wrote:
> 
> Hi all,
> 
> I don't know if it's the right list to post to, but I have the following
> problem:
> I have several objects (documents, folders etc) that are accessible only
> by a certain user role, this objects are cataloged. Now if I query the
> catalog the brains of these objects are returned correctly, but to _all_
> users that issue a query. That means, users that don't have the permission
> to "View" or "Access Content Information" can see the brains as well...
> I tried to filter the result set by converting the brains into real
> objects (brain.getObject) in an external method (I thought, this way I
> should be able to exclude unauthorized users by adding the
> "skip_unauthorized" to the dtml-in), but that doesn't work
> since there are "brains" that are actually NoBrainer instances...
> 
> Does anyone have an idea of how I could solve this problem?
> Actually I thought this kind of "information hiding" is supported by basic
> ZCatalog machinery, but now it looks like I'll have to hack a
> workaround...
> 
> Any help greatly appreciated.

Igor,

I had exactly the same problem and solved it this way:

1. define a method 'catalog_permission' in the classes of the objects
that will be indexed:

from AccessControl.PermissionRole import rolesForPermissionOn

class someClass(Folder):
    def catalog_permission(self):
        """ return: Liste der roles, die die permissions 'View',
            'Access Content Information" sowie "view archivDoc" haben
        """
        l1 = rolesForPermissionOn('View', self)
        if type(l1) == type(''):
            l1 = [l1, ]
 
        l2 = rolesForPermissionOn('Access contents information', self)
        if type(l2) == type(''):
            l2 = [l2, ]
 
        res = []
        for x in l1:
            if x in l2:
                res.append(x)
        return res

2. define a new Catalog class, with a newly defined method
searchResults:

from Products.ZCatalog.ZCatalog import ZCatalog
from AccessControl import getSecurityManager

class ACatalog(ZCatalog):
    def searchResults(self, REQUEST=None, used=None, **kw):
        """  """
        roles = getSecurityManager().getUser().getRoles()
        if REQUEST is not None:
            REQUEST['catalog_permission'] = roles
        elif kw != {}:
            kw['catalog_permission'] = roles
        else:
            self.REQUEST['catalog_permission'] = roles
        return ZCatalog.searchResults(self, REQUEST, used, **kw)

3. Add a keyword index 'catalog_permission' to the ACatalog instance.
(Ok, that could be done automatically in ACatalog.__init__ , but I was
too lazy to write that...)

A more reliable implemetation should make sure that only those objects
are indexed, which define a method catalog_permission. Or
Catalog.catalogObject could be overloaded to automatically build the
information to be thrown into the catalog_permission index.

Abel