def doActionFor(self, ob, action, comment=''): ''' Allows the user to request a workflow action. This method must perform its own security checks. ''' allow_review = _checkPermission('Review portal content', ob) allow_request = _checkPermission('Request review', ob) review_state = self.getReviewStateOf(ob) tool = aq_parent(aq_inner(self)) if action == 'submit': if not allow_request or review_state != 'private': raise 'Unauthorized' self.setReviewStateOf(ob, 'pending', action, comment) elif action == 'retract': if not allow_request or review_state == 'private': raise 'Unauthorized' content_creator = ob.Creator() pm = getToolByName(self, 'portal_membership') current_user = pm.getAuthenticatedMember().getUserName() if content_creator != current_user: raise 'Unauthorized' self.setReviewStateOf(ob, 'private', action, comment) elif action == 'publish': if not allow_review: raise 'Unauthorized' self.setReviewStateOf(ob, 'published', action, comment) elif action == 'reject': if not allow_review: raise 'Unauthorized' self.setReviewStateOf(ob, 'private', action, comment)
def listGlobalActions(self, info): ''' Allows this workflow to include actions to be displayed in the actions box. Called on every request. Returns the actions to be displayed to the user. ''' if (info.isAnonymous or not _checkPermission( 'Review portal content', info.portal)): return None actions = [] catalog = getToolByName(self, 'portal_catalog', None) if catalog is not None: pending = len(catalog.searchResults( review_state='pending')) if pending > 0: actions.append( {'name': 'Pending review (%d)' % pending, 'url': info.portal_url + '/search?review_state=pending', 'permissions': (), 'category': 'global'} ) return actions
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = queryUtility(ISiteRoot) if site is None: # fallback portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission(ManagePortal, portal): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter( lambda record, user_id=user_id: record['user_name'].split()[-1] == user_id, transactions ) return transactions
def listDAVObjects(self): # List sub-objects for PROPFIND requests. # (method is without docstring to disable publishing) # if _checkPermission(ManagePortal, self): return self.objectValues() else: return self.listFolderContents()
def checkPermission(self, permissionName, object, subobjectName=None): ''' Checks whether the current user has the given permission on the given object or subobject. ''' if subobjectName is not None: object = getattr(object, subobjectName) return _checkPermission(permissionName, object)
def _verifyActionPermissions(self, action): pp = action.get('permissions', ()) if not pp: return 1 for p in pp: if _checkPermission(p, self): return 1 return 0
def _verifyObjectPaste(self, object, validate_src=1): # This assists the version in OFS.CopySupport. # It enables the clipboard to function correctly # with objects created by a multi-factory. if (hasattr(object, '__factory_meta_type__') and hasattr(self, 'all_meta_types')): mt = object.__factory_meta_type__ method_name=None permission_name = None meta_types = self.all_meta_types if callable(meta_types): meta_types = meta_types() for d in meta_types: if d['name']==mt: method_name=d['action'] permission_name = d.get('permission', None) break if permission_name is not None: if _checkPermission(permission_name,self): if not validate_src: # We don't want to check the object on the clipboard return try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): # validation succeeded return raise 'Unauthorized', object.getId() else: raise 'Unauthorized', permission_name # # Old validation for objects that may not have registered # themselves in the proper fashion. # elif method_name is not None: meth=self.unrestrictedTraverse(method_name) if hasattr(meth, 'im_self'): parent = meth.im_self else: try: parent = aq_parent(aq_inner(meth)) except: parent = None if getSecurityManager().validate(None, parent, None, meth): # Ensure the user is allowed to access the object on the # clipboard. if not validate_src: return try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): return id = object.getId() raise 'Unauthorized', id else: raise 'Unauthorized', method_name PortalFolder.inheritedAttribute( '_verifyObjectPaste')(self, object, validate_src)
def isConstructionAllowed( self, container ): """ Does the current user have the permission required in order to construct an instance? """ permission = self.permission if permission and not _checkPermission( permission, container ): return 0 return 1
def getInfoFor(self, ob, name, default): ''' Allows the user to request information provided by the workflow. This method must perform its own security checks. ''' allow_review = _checkPermission('Review portal content', ob) allow_request = _checkPermission('Request review', ob) if not allow_review and not allow_request: return default if name == 'review_state': return self.getReviewStateOf(ob) elif name == 'review_history': tool = aq_parent(aq_inner(self)) history = tool.getHistoryOf(self.id, ob) # Make copies for security. return tuple(map(lambda dict: dict.copy(), history))
def _verifyActionPermissions(self, action): pp = action.get('permissions', ()) if not pp: return 1 sm = getSecurityManager() for p in pp: if _checkPermission(p, self): return 1 return 0
def isConstructionAllowed(self, container): """ Does the current user have the permission required in order to construct an instance? """ permission = self.permission if permission and not _checkPermission(permission, container): return 0 return 1
def searchResults(self, REQUEST=None, **kw): """ Calls ZCatalog.searchResults with extra arguments that limit the results to what the user is allowed to see. """ user = _getAuthenticatedUser(self) kw[ 'allowedRolesAndUsers' ] = self._listAllowedRolesAndUsers( user ) if not _checkPermission( AccessInactivePortalContent, self ): base = aq_base( self ) now = DateTime() self._convertQuery(kw) # Intersect query restrictions with those implicit to the tool for k in 'effective', 'expires': if kw.has_key(k): range = kw[k]['range'] or '' query = kw[k]['query'] if (not isinstance(query, TupleType) and not isinstance(query, ListType)): query = (query,) else: range = '' query = None if range.find('min') > -1: lo = min(query) else: lo = None if range.find('max') > -1: hi = max(query) else: hi = None if k == 'effective': if hi is None or hi > now: hi = now if lo is not None and hi < lo: return () else: # 'expires': if lo is None or lo < now: lo = now if hi is not None and hi < lo: return () # Rebuild a query if lo is None: query = hi range = 'max' elif hi is None: query = lo range = 'min' else: query = (lo, hi) range = 'min:max' kw[k] = {'query': query, 'range': range} return ZCatalog.searchResults(self, REQUEST, **kw)
def searchResults(self, REQUEST=None, **kw): """ Calls ZCatalog.searchResults with extra arguments that limit the results to what the user is allowed to see. """ user = _getAuthenticatedUser(self) kw['allowedRolesAndUsers'] = self._listAllowedRolesAndUsers(user) if not _checkPermission(AccessInactivePortalContent, self): base = aq_base(self) now = DateTime() self._convertQuery(kw) # Intersect query restrictions with those implicit to the tool for k in 'effective', 'expires': if kw.has_key(k): range = kw[k]['range'] or '' query = kw[k]['query'] if (not isinstance(query, TupleType) and not isinstance(query, ListType)): query = (query, ) else: range = '' query = None if range.find('min') > -1: lo = min(query) else: lo = None if range.find('max') > -1: hi = max(query) else: hi = None if k == 'effective': if hi is None or hi > now: hi = now if lo is not None and hi < lo: return () else: # 'expires': if lo is None or lo < now: lo = now if hi is not None and hi < lo: return () # Rebuild a query if lo is None: query = hi range = 'max' elif hi is None: query = lo range = 'min' else: query = (lo, hi) range = 'min:max' kw[k] = {'query': query, 'range': range} return ZCatalog.searchResults(self, REQUEST, **kw)
def getInfoFor(self, ob, name, default): ''' Allows the user to request information provided by the workflow. This method must perform its own security checks. ''' # Treat this as public. if name == 'review_state': return self.getReviewStateOf(ob) allow_review = _checkPermission('Review portal content', ob) allow_request = _checkPermission('Request review', ob) if not allow_review and not allow_request: return default elif name == 'review_history': tool = aq_parent(aq_inner(self)) history = tool.getHistoryOf(self.id, ob) # Make copies for security. return tuple(map(lambda dict: dict.copy(), history))
def getCandidateLocalRoles(self, obj): """ What local roles can I assign? """ member = self.getAuthenticatedMember() member_roles = member.getRolesInContext(obj) if _checkPermission(ManageUsers, obj): local_roles = self.getPortalRoles() if "Manager" not in member_roles: local_roles.remove("Manager") else: local_roles = [role for role in member_roles if role not in ("Member", "Authenticated")] local_roles.sort() return tuple(local_roles)
def getCandidateLocalRoles(self, obj): """ What local roles can I assign? """ member = self.getAuthenticatedMember() member_roles = member.getRolesInContext(obj) if _checkPermission(ManageUsers, obj): local_roles = self.getPortalRoles() if 'Manager' not in member_roles: local_roles.remove('Manager') else: local_roles = [ role for role in member_roles if role not in ('Member', 'Authenticated') ] local_roles.sort() return tuple(local_roles)
def searchResults(self, REQUEST=None, **kw): """ Calls ZCatalog.searchResults with extra arguments that limit the results to what the user is allowed to see. """ user = _getAuthenticatedUser(self) kw[ 'allowedRolesAndUsers' ] = self._listAllowedRolesAndUsers( user ) if not _checkPermission( AccessInactivePortalContent, self ): now = DateTime() kw['effective'] = {'query': now, 'range': 'max'} kw['expires'] = {'query': now, 'range': 'min'} return ZCatalog.searchResults(self, REQUEST, **kw)
def listActionInfos(self, action_chain=None, object=None, check_visibility=1, check_permissions=1, check_condition=1, max=-1): # List Action info mappings. # (method is without docstring to disable publishing) # ec = getExprContext(self, object) actions = self.listActions(object=object) if action_chain: filtered_actions = [] if isinstance(action_chain, StringType): action_chain = (action_chain,) for action_ident in action_chain: sep = action_ident.rfind('/') category, id = action_ident[:sep], action_ident[sep+1:] for ai in actions: if id == ai.getId() and category == ai.getCategory(): filtered_actions.append(ai) actions = filtered_actions action_infos = [] for ai in actions: if check_visibility and not ai.getVisibility(): continue if check_permissions: permissions = ai.getPermissions() if permissions: category = ai.getCategory() if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (ec.contexts['folder'] is not None and category.startswith('folder')): context = ec.contexts['folder'] else: context = ec.contexts['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue if check_condition and not ai.testCondition(ec): continue action_infos.append( ai.getAction(ec) ) if max + 1 and len(action_infos) >= max: break return action_infos
def searchResults(self, REQUEST=None, **kw): """ Calls ZCatalog.searchResults with extra arguments that limit the results to what the user is allowed to see. """ user = _getAuthenticatedUser(self) kw['allowedRolesAndUsers'] = self._listAllowedRolesAndUsers(user) if not _checkPermission(AccessInactivePortalContent, self): now = DateTime() kw['effective'] = {'query': now, 'range': 'max'} kw['expires'] = {'query': now, 'range': 'min'} return ZCatalog.searchResults(self, REQUEST, **kw)
def deleteMembers(self, member_ids, delete_memberareas=1, delete_localroles=1, REQUEST=None): """ Delete members specified by member_ids. """ # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool # Delete members in acl_users. acl_users = self.acl_users if _checkPermission(ManageUsers, acl_users): if isinstance(member_ids, basestring): member_ids = (member_ids, ) member_ids = list(member_ids) for member_id in member_ids[:]: if not acl_users.getUserById(member_id, None): member_ids.remove(member_id) try: acl_users.userFolderDelUsers(member_ids) except (AttributeError, NotImplementedError, 'NotImplemented'): raise NotImplementedError('The underlying User Folder ' 'doesn\'t support deleting members.') else: raise AccessControl_Unauthorized( 'You need the \'Manage users\' ' 'permission for the underlying User Folder.') # Delete member data in portal_memberdata. mdtool = getToolByName(self, 'portal_memberdata', None) if mdtool is not None: for member_id in member_ids: mdtool.deleteMemberData(member_id) # Delete members' home folders including all content items. if delete_memberareas: for member_id in member_ids: self.deleteMemberArea(member_id) # Delete members' local roles. if delete_localroles: self.deleteLocalRoles(getUtility(ISiteRoot), member_ids, reindex=1, recursive=1) return tuple(member_ids)
def _checkId(self, id, allow_dup=0): PortalFolder.inheritedAttribute('_checkId')(self, id, allow_dup) # This method prevents people other than the portal manager # from overriding skinned names. if not allow_dup: if not _checkPermission('Manage portal', self): ob = self while ob is not None and not getattr(ob, '_isPortalRoot', 0): ob = aq_parent(aq_inner(ob)) if ob is not None: # If the portal root has an object by this name, # don't allow an override. # FIXME: needed to allow index_html for join code if hasattr(ob, id) and id != 'index_html': raise 'Bad Request', ('The id "%s" is reserved.' % id)
def _checkId(self, id, allow_dup=0): PortalFolder.inheritedAttribute('_checkId')(self, id, allow_dup) # This method prevents people other than the portal manager # from overriding skinned names. if not allow_dup: if not _checkPermission(ManagePortal, self): ob = self while ob is not None and not getattr(ob, '_isPortalRoot', 0): ob = aq_parent(aq_inner(ob)) if ob is not None: # If the portal root has an object by this name, # don't allow an override. # FIXME: needed to allow index_html for join code if hasattr(ob, id) and id != 'index_html': raise BadRequest('The id "%s" is reserved.' % id)
def setLocalRoles(self, obj, member_ids, member_role, reindex=1, REQUEST=None): """ Add local roles on an item. """ if _checkPermission(ChangeLocalRoles, obj) and member_role in self.getCandidateLocalRoles(obj): for member_id in member_ids: roles = list(obj.get_local_roles_for_userid(userid=member_id)) if member_role not in roles: roles.append(member_role) obj.manage_setLocalRoles(member_id, roles) if reindex: # It is assumed that all objects have the method # reindexObjectSecurity, which is in CMFCatalogAware and # thus PortalContent and PortalFolder. obj.reindexObjectSecurity()
def deleteLocalRoles(self, obj, member_ids, reindex=1, recursive=0): """ Delete local roles of specified members. """ if _checkPermission(ChangeLocalRoles, obj): for member_id in member_ids: if obj.get_local_roles_for_userid(userid=member_id): obj.manage_delLocalRoles(userids=member_ids) break if recursive and hasattr(aq_base(obj), 'contentValues'): for subobj in obj.contentValues(): self.deleteLocalRoles(subobj, member_ids, 0, 1) if reindex: # reindexObjectSecurity is always recursive obj.reindexObjectSecurity()
def deleteLocalRoles(self, obj, member_ids, reindex=1, recursive=0): """ Delete local roles of specified members. """ if _checkPermission(ChangeLocalRoles, obj): for member_id in member_ids: if obj.get_local_roles_for_userid(userid=member_id): obj.manage_delLocalRoles(userids=member_ids) break if recursive and hasattr( aq_base(obj), 'contentValues' ): for subobj in obj.contentValues(): self.deleteLocalRoles(subobj, member_ids, 0, 1) if reindex: # reindexObjectSecurity is always recursive obj.reindexObjectSecurity()
def deleteMembers(self, member_ids, delete_memberareas=1, delete_localroles=1): """ Delete members specified by member_ids. """ # Delete members in acl_users. acl_users = self.acl_users if _checkPermission(ManageUsers, acl_users): if type(member_ids) is StringType: member_ids = (member_ids, ) member_ids = list(member_ids) for member_id in member_ids[:]: if not acl_users.getUserById(member_id, None): member_ids.remove(member_id) try: acl_users.userFolderDelUsers(member_ids) except (NotImplementedError, 'NotImplemented'): raise CMFNotImplementedError( 'The underlying User Folder ' 'doesn\'t support deleting members.') else: raise CMFUnauthorizedError( 'You need the \'Manage users\' ' 'permission for the underlying User Folder.') # Delete member data in portal_memberdata. mdtool = getToolByName(self, 'portal_memberdata', None) if mdtool: for member_id in member_ids: mdtool.deleteMemberData(member_id) # Delete members' home folders including all content items. if delete_memberareas: for member_id in member_ids: self.deleteMemberArea(member_id) # Delete members' local roles. if delete_localroles: utool = getToolByName(self, 'portal_url', None) self.deleteLocalRoles(utool.getPortalObject(), member_ids, reindex=1, recursive=1) return tuple(member_ids)
def setLocalRoles(self, obj, member_ids, member_role, reindex=1): """ Add local roles on an item. """ if (_checkPermission(ChangeLocalRoles, obj) and member_role in self.getCandidateLocalRoles(obj)): for member_id in member_ids: roles = list(obj.get_local_roles_for_userid(userid=member_id)) if member_role not in roles: roles.append(member_role) obj.manage_setLocalRoles(member_id, roles) if reindex: # It is assumed that all objects have the method # reindexObjectSecurity, which is in CMFCatalogAware and # thus PortalContent and PortalFolder. obj.reindexObjectSecurity()
def _checkPermissions(self): """ Check permissions in the current context. """ category = self['category'] object = self._ec.contexts['object'] if object is not None and ( category.startswith('object') or category.startswith('workflow') ): context = object else: folder = self._ec.contexts['folder'] if folder is not None and category.startswith('folder'): context = folder else: context = self._ec.contexts['portal'] for permission in self['permissions']: if _checkPermission(permission, context): return True return False
def createMemberArea(self, member_id=''): """ Create a member area for 'member_id' or authenticated user. """ if not self.getMemberareaCreationFlag(): return None members = self.getMembersFolder() if not members: return None if self.isAnonymousUser(): return None # Note: We can't use getAuthenticatedMember() and getMemberById() # because they might be wrapped by MemberDataTool. user = _getAuthenticatedUser(self) user_id = user.getId() if member_id in ('', user_id): member = user member_id = user_id else: if _checkPermission(ManageUsers, self): member = self.acl_users.getUserById(member_id, None) if member: member = member.__of__(self.acl_users) else: raise ValueError('Member %s does not exist' % member_id) else: return None if hasattr( aq_base(members), member_id ): return None else: f_title = "%s's Home" % member_id members.manage_addPortalFolder( id=member_id, title=f_title ) f=getattr(members, member_id) f.manage_permission(View, ['Owner','Manager','Reviewer'], 0) f.manage_permission(AccessContentsInformation, ['Owner','Manager','Reviewer'], 0) # Grant Ownership and Owner role to Member f.changeOwnership(member) f.__ac_local_roles__ = None f.manage_setLocalRoles(member_id, ['Owner']) return f
def deleteMembers(self, member_ids, delete_memberareas=1, delete_localroles=1, REQUEST=None): """ Delete members specified by member_ids. """ # XXX: this method violates the rules for tools/utilities: # it depends on a non-utility tool # Delete members in acl_users. acl_users = self.acl_users if _checkPermission(ManageUsers, acl_users): if isinstance(member_ids, basestring): member_ids = (member_ids,) member_ids = list(member_ids) for member_id in member_ids[:]: if not acl_users.getUserById(member_id, None): member_ids.remove(member_id) try: acl_users.userFolderDelUsers(member_ids) except (AttributeError, NotImplementedError, 'NotImplemented'): raise NotImplementedError('The underlying User Folder ' 'doesn\'t support deleting members.') else: raise AccessControl_Unauthorized('You need the \'Manage users\' ' 'permission for the underlying User Folder.') # Delete member data in portal_memberdata. mdtool = getToolByName(self, 'portal_memberdata', None) if mdtool is not None: for member_id in member_ids: mdtool.deleteMemberData(member_id) # Delete members' home folders including all content items. if delete_memberareas: for member_id in member_ids: self.deleteMemberArea(member_id) # Delete members' local roles. if delete_localroles: self.deleteLocalRoles( getUtility(ISiteRoot), member_ids, reindex=1, recursive=1 ) return tuple(member_ids)
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) if not _checkPermission('Manage portal', portal): # Filter out transactions done by other members of the portal. user_name = _getAuthenticatedUser(self).getUserName() transactions = filter(lambda record, user_name=user_name: split( record['user_name'])[-1] == user_name, transactions) return transactions
def _checkPermissions(self, ec): """ Check permissions in the current context. """ category = self["category"] object = ec.contexts["object"] if object is not None and ( category.startswith("object") or category.startswith("workflow") or category.startswith("document") ): context = object else: folder = ec.contexts["folder"] if folder is not None and category.startswith("folder"): context = folder else: context = ec.contexts["portal"] for permission in self._permissions: if _checkPermission(permission, context): return True return False
def searchResults(self, REQUEST=None, **kw): """ Calls ZCatalog.searchResults with extra arguments that limit the results to what the user is allowed to see. """ user = _getAuthenticatedUser(self) kw[ 'allowedRolesAndUsers' ] = self._listAllowedRolesAndUsers( user ) if not _checkPermission( AccessInactivePortalContent, self ): base = aq_base( self ) now = DateTime() if hasattr( base, 'addIndex' ): # Zope 2.4 and above kw[ 'effective' ] = { 'query' : now, 'range' : 'max' } kw[ 'expires' ] = { 'query' : now, 'range' : 'min' } else: # Zope 2.3 kw[ 'effective' ] = kw[ 'expires' ] = now kw[ 'effective_usage'] = 'range:max' kw[ 'expires_usage' ] = 'range:min' return apply(ZCatalog.searchResults, (self, REQUEST), kw)
def deleteMembers(self, member_ids, delete_memberareas=1, delete_localroles=1): """ Delete members specified by member_ids. """ # Delete members in acl_users. acl_users = self.acl_users if _checkPermission(ManageUsers, acl_users): if isinstance(member_ids, basestring): member_ids = (member_ids,) member_ids = list(member_ids) for member_id in member_ids[:]: if not acl_users.getUserById(member_id, None): member_ids.remove(member_id) try: acl_users.userFolderDelUsers(member_ids) except (NotImplementedError, 'NotImplemented'): raise NotImplementedError('The underlying User Folder ' 'doesn\'t support deleting members.') else: raise AccessControl_Unauthorized('You need the \'Manage users\' ' 'permission for the underlying User Folder.') # Delete member data in portal_memberdata. mdtool = queryUtility(IMemberDataTool) if mdtool is not None: for member_id in member_ids: mdtool.deleteMemberData(member_id) # Delete members' home folders including all content items. if delete_memberareas: for member_id in member_ids: self.deleteMemberArea(member_id) # Delete members' local roles. if delete_localroles: utool = getUtility(IURLTool) self.deleteLocalRoles( utool.getPortalObject(), member_ids, reindex=1, recursive=1 ) return tuple(member_ids)
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) if not _checkPermission('Manage portal', portal): # Filter out transactions done by other members of the portal. user_name = _getAuthenticatedUser(self).getUserName() transactions = filter( lambda record, user_name=user_name: split(record['user_name'])[-1] == user_name, transactions ) return transactions
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): """ List all transaction IDs the user is allowed to undo on 'object'. """ transactions = object.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission(ManagePortal, object): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter(lambda record, user_id=user_id: record[ 'user_name'].split()[-1] == user_id, transactions) return transactions
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): """ List all transaction IDs the user is allowed to undo on 'object'. """ transactions = object.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission(ManagePortal, object): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter( lambda record, user_id=user_id: record['user_name'].split()[-1] == user_id, transactions ) return transactions
def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission('Manage portal', portal): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter(lambda record, user_id=user_id: record[ 'user_name'].split()[-1] == user_id, transactions) return transactions
def searchResults(self, REQUEST=None, **kw): '''Calls SiteIndex.searchResults() with extra arguments that limit the results to what the user is allowed to see. ''' if REQUEST is None: REQUEST = self.REQUEST user = _getAuthenticatedUser(self) kw['allowedRolesAndUsers'] = list(user.getRoles()) + \ ['Anonymous', 'user:'******'Date') and None: if kw.has_key('Date_usage'): kw['Date'] = min(kw['Date']) kw['Date'] = [kw['Date'], DateTime()] kw['Date_usage'] = 'range:min:max' else: kw['effective'] = kw['expires'] = DateTime() kw['effective_usage'] = 'range:max' kw['expires_usage'] = 'range:min' return apply(ZCatalog.searchResults, (self, REQUEST), kw)
def searchResults(self, REQUEST=None, **kw): '''Calls SiteIndex.searchResults() with extra arguments that limit the results to what the user is allowed to see. ''' if REQUEST is None: REQUEST = self.REQUEST user = _getAuthenticatedUser(self) kw['allowedRolesAndUsers'] = list(user.getRoles()) + \ ['Anonymous', 'user:'******'Date') and None: if kw.has_key('Date_usage'): kw['Date'] = min(kw['Date']) kw['Date'] = [kw['Date'], DateTime()] kw['Date_usage'] = 'range:min:max' else: kw[ 'effective' ] = kw[ 'expires' ] = DateTime() kw['effective_usage'] = 'range:max' kw['expires_usage'] = 'range:min' return apply(ZCatalog.searchResults, (self, REQUEST), kw)
def listGlobalActions(self, info): ''' Allows this workflow to include actions to be displayed in the actions box. Called on every request. Returns the actions to be displayed to the user. ''' if (info.isAnonymous or not _checkPermission('Review portal content', info.portal)): return None actions = [] catalog = getToolByName(self, 'portal_catalog', None) if catalog is not None: pending = len(catalog.searchResults(review_state='pending')) if pending > 0: actions.append({ 'name': 'Pending review (%d)' % pending, 'url': info.portal_url + '/search?review_state=pending', 'permissions': (), 'category': 'global' }) return actions
def listObjectActions(self, info): ''' Allows this workflow to include actions to be displayed in the actions box. Called only when this workflow is applicable to info.content. Returns the actions to be displayed to the user. ''' if info.isAnonymous: return None # The following operation is quite expensive. # We don't need to perform it if the user # doesn't have the required permission. content = info.content content_url = info.content_url content_creator = content.Creator() pm = getToolByName(self, 'portal_membership') current_user = pm.getAuthenticatedMember().getUserName() review_state = self.getReviewStateOf(content) actions = [] allow_review = _checkPermission('Review portal content', content) allow_request = _checkPermission('Request review', content) append_action = (lambda name, p, url=content_url, a=actions.append: a( { 'name': name, 'url': url + '/' + p, 'permissions': (), 'category': 'workflow' })) show_reject = 0 show_retract = 0 if review_state == 'private': if allow_request: append_action('Submit', 'content_submit_form') elif review_state == 'pending': if content_creator == current_user and allow_request: show_retract = 1 if allow_review: append_action('Publish', 'content_publish_form') show_reject = 1 elif review_state == 'published': if content_creator == current_user and allow_request: show_retract = 1 if allow_review: show_reject = 1 if show_retract: append_action('Retract', 'content_retract_form') if show_reject: append_action('Reject', 'content_reject_form') if allow_review or allow_request: append_action('Status history', 'content_status_history') return actions
def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) info = ActionInformation(self, folder, object) actions = [] # Include actions from specific tools. for provider_name in self.action_providers: provider = getattr(self, provider_name) a = provider.listActions(info) if a: actions.extend(list(a)) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName(self, 'portal_types') ti = types_tool.getTypeInfo(object) if ti is not None: defs = ti.getActions() if defs: c_url = info.content_url for d in defs: a = d['action'] if a: url = c_url + '/' + a else: url = c_url actions.append({ 'id': d.get('id', None), 'name': d['name'], 'url': url, 'permissions': d['permissions'], 'category': d.get('category', 'object'), 'visible': d.get('visible', 1), }) if hasattr(base, 'listActions'): a = object.listActions(info) if a: actions.extend(list(a)) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if category in ('object', 'workflow') and object is not None: context = object elif category == 'folder' and folder is not None: context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # If a bug occurs where actions appear more than once, # a little code right here can fix it. catlist.append(action) return filtered_actions
def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) ec = createExprContext(folder, portal, object) actions = [] append = actions.append info = oai(self, folder, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) self._listActions(append, provider, info, ec) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName(self, 'portal_types') # we might get None back from getTypeInfo. We construct # a dummy TypeInformation object here in that case (the 'or' # case). This prevents us from needing to check the condition. ti = types_tool.getTypeInfo(object) or TypeInformation('Dummy') defs = ti.getActions() url = object_url = object.absolute_url() for d in defs: # we can't modify or expose the original actionsd... this # stems from the fact that getActions returns a ref to the # actual dictionary used to store actions instead of a # copy. We copy it here to prevent it from being modified. d = d.copy() d['id'] = d.get('id', None) if d['action']: url = '%s/%s' % (object_url, d['action']) d['url'] = url d['category'] = d.get('category', 'object') d['visible'] = d.get('visible', 1) actions.append(d) if hasattr(base, 'listActions'): self._listActions(append, object, info, ec) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (folder is not None and category.startswith('folder')): context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # Filter out duplicate actions by identity... if not action in catlist: catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the two lines above) #if not [a for a in catlist if a==action]: # catlist.append(action) return filtered_actions
def listDAVObjects(self): if _checkPermission(ManagePortal, self): return self.objectValues() else: return self.listFolderContents()
def _listActionInfos(self, provider, object): """ for Action Providers written for CMF versions before 1.5 """ warn('ActionProvider interface not up to date. In CMF 2.0 ' 'portal_actions will ignore listActions() of \'%s\'.' % provider.getId(), DeprecationWarning) info = self._getOAI(object) actions = provider.listActions(info) action_infos = [] if actions and not isinstance(actions[0], dict): ec = self._getExprContext(object) for ai in actions: if not ai.getVisibility(): continue permissions = ai.getPermissions() if permissions: category = ai.getCategory() if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue if not ai.testCondition(ec): continue action_infos.append( ai.getAction(ec) ) else: for i in actions: if not i.get('visible', 1): continue permissions = i.get('permissions', None) if permissions: category = i['category'] if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue action_infos.append(i) return action_infos
def isRegistrationAllowed(self, REQUEST): '''Returns a boolean value indicating whether the user is allowed to add a member to the portal. ''' return _checkPermission(AddPortalMember, self.aq_inner.aq_parent)
def _verifyObjectPaste(self, object, validate_src=1): # This assists the version in OFS.CopySupport. # It enables the clipboard to function correctly # with objects created by a multi-factory. securityChecksDone = 0 if (hasattr(object, '__factory_meta_type__') and hasattr(self, 'all_meta_types')): mt = object.__factory_meta_type__ method_name = None permission_name = None meta_types = self.all_meta_types if callable(meta_types): meta_types = meta_types() for d in meta_types: if d['name'] == mt: method_name = d['action'] permission_name = d.get('permission', None) break if permission_name is not None: if _checkPermission(permission_name, self): if not validate_src: # We don't want to check the object on the clipboard securityChecksDone = 1 else: try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate( None, parent, None, object): # validation succeeded securityChecksDone = 1 else: raise 'Unauthorized', object.getId() else: raise 'Unauthorized', permission_name # # Old validation for objects that may not have registered # themselves in the proper fashion. # elif method_name is not None: meth = self.unrestrictedTraverse(method_name) if hasattr(meth, 'im_self'): parent = meth.im_self else: try: parent = aq_parent(aq_inner(meth)) except: parent = None if getSecurityManager().validate(None, parent, None, meth): # Ensure the user is allowed to access the object on the # clipboard. if not validate_src: securityChecksDone = 1 else: try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate( None, parent, None, object): securityChecksDone = 1 else: raise 'Unauthorized', object.getId() else: raise 'Unauthorized', method_name # Call OFS' _verifyObjectPaste if necessary if not securityChecksDone: PortalFolder.inheritedAttribute('_verifyObjectPaste')(self, object, validate_src) # Finally, check allowed content types if hasattr(aq_base(object), '_getPortalTypeName'): contentType = object._getPortalTypeName() if contentType is not None: pt = getToolByName(self, 'portal_types') myType = pt.getTypeInfo(self) if myType is not None and not myType.allowType(contentType): raise ValueError, \ "Disallowed to paste subobject type '%s'." % contentType
def _verifyObjectPaste(self, object, validate_src=1): # This assists the version in OFS.CopySupport. # It enables the clipboard to function correctly # with objects created by a multi-factory. if (hasattr(object, '__factory_meta_type__') and hasattr(self, 'all_meta_types')): mt = object.__factory_meta_type__ method_name = None permission_name = None meta_types = self.all_meta_types if callable(meta_types): meta_types = meta_types() for d in meta_types: if d['name'] == mt: method_name = d['action'] permission_name = d.get('permission', None) break if permission_name is not None: if _checkPermission(permission_name, self): if not validate_src: # We don't want to check the object on the clipboard return try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): # validation succeeded return raise 'Unauthorized', object.getId() else: raise 'Unauthorized', permission_name # # Old validation for objects that may not have registered # themselves in the proper fashion. # elif method_name is not None: meth = self.unrestrictedTraverse(method_name) if hasattr(meth, 'im_self'): parent = meth.im_self else: try: parent = aq_parent(aq_inner(meth)) except: parent = None if getSecurityManager().validate(None, parent, None, meth): # Ensure the user is allowed to access the object on the # clipboard. if not validate_src: return try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): return id = object.getId() raise 'Unauthorized', id else: raise 'Unauthorized', method_name PortalFolder.inheritedAttribute('_verifyObjectPaste')(self, object, validate_src)
def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) info = ActionInformation(self, folder, object) actions = [] # Include actions from specific tools. for provider_name in self.action_providers: provider = getattr(self, provider_name) a = provider.listActions(info) if a: actions.extend(list(a)) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName( self, 'portal_types' ) ti = types_tool.getTypeInfo( object ) if ti is not None: defs = ti.getActions() if defs: c_url = info.content_url for d in defs: a = d['action'] if a: url = c_url + '/' + a else: url = c_url actions.append({ 'id': d.get('id', None), 'name': d['name'], 'url': url, 'permissions': d['permissions'], 'category': d.get('category', 'object'), 'visible': d.get('visible', 1), }) if hasattr(base, 'listActions'): a = object.listActions(info) if a: actions.extend(list(a)) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if category in ('object', 'workflow') and object is not None: context = object elif category == 'folder' and folder is not None: context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # If a bug occurs where actions appear more than once, # a little code right here can fix it. catlist.append(action) return filtered_actions
def _verifyObjectPaste(self, object, validate_src=1): # This assists the version in OFS.CopySupport. # It enables the clipboard to function correctly # with objects created by a multi-factory. securityChecksDone = 0 if (hasattr(object, '__factory_meta_type__') and hasattr(self, 'all_meta_types')): mt = object.__factory_meta_type__ method_name=None permission_name = None meta_types = self.all_meta_types if callable(meta_types): meta_types = meta_types() for d in meta_types: if d['name']==mt: method_name=d['action'] permission_name = d.get('permission', None) break if permission_name is not None: if _checkPermission(permission_name,self): if not validate_src: # We don't want to check the object on the clipboard securityChecksDone = 1 else: try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): # validation succeeded securityChecksDone = 1 else: raise 'Unauthorized', object.getId() else: raise 'Unauthorized', permission_name # # Old validation for objects that may not have registered # themselves in the proper fashion. # elif method_name is not None: meth=self.unrestrictedTraverse(method_name) if hasattr(meth, 'im_self'): parent = meth.im_self else: try: parent = aq_parent(aq_inner(meth)) except: parent = None if getSecurityManager().validate(None, parent, None, meth): # Ensure the user is allowed to access the object on the # clipboard. if not validate_src: securityChecksDone = 1 else: try: parent = aq_parent(aq_inner(object)) except: parent = None if getSecurityManager().validate(None, parent, None, object): securityChecksDone = 1 else: raise 'Unauthorized', object.getId() else: raise 'Unauthorized', method_name # Call OFS' _verifyObjectPaste if necessary if not securityChecksDone: PortalFolder.inheritedAttribute( '_verifyObjectPaste')(self, object, validate_src) # Finally, check allowed content types if hasattr(aq_base(object), '_getPortalTypeName'): contentType = object._getPortalTypeName() if contentType is not None: pt = getToolByName(self, 'portal_types') myType = pt.getTypeInfo(self) if myType is not None and not myType.allowType(contentType): raise ValueError, \ "Disallowed to paste subobject type '%s'." % contentType
def _listActionInfos(self, provider, object): """ for Action Providers written for CMF versions before 1.5 """ warn('ActionProvider interface not up to date. In CMF 1.6 ' 'portal_actions will ignore listActions() of \'%s\'.' % provider.getId(), DeprecationWarning) info = getOAI(self, object) actions = provider.listActions(info) action_infos = [] if actions and type(actions[0]) is not DictionaryType: ec = getExprContext(self, object) for ai in actions: if not ai.getVisibility(): continue permissions = ai.getPermissions() if permissions: category = ai.getCategory() if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue if not ai.testCondition(ec): continue action_infos.append( ai.getAction(ec) ) else: for i in actions: if not i.get('visible', 1): continue permissions = i.get('permissions', None) if permissions: category = i['category'] if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue action_infos.append(i) return action_infos
def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) ec = createExprContext(folder, portal, object) actions = [] append = actions.append info = oai(self, folder, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) self._listActions(append,provider,info,ec) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName( self, 'portal_types' ) ti = types_tool.getTypeInfo( object ) if ti is not None: defs = ti.getActions() if defs: c_url = object.absolute_url() for d in defs: a = d['action'] if a: url = c_url + '/' + a else: url = c_url actions.append({ 'id': d.get('id', None), 'name': d['name'], 'action': d['action'], 'url': url, 'permissions': d['permissions'], 'category': d.get('category', 'object'), 'visible': d.get('visible', 1), }) if hasattr(base, 'listActions'): self._listActions(append,object,info,ec) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if category in ('object', 'workflow') and object is not None: context = object elif category == 'folder' and folder is not None: context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # Filter out duplicate actions by identity... if not action in catlist: catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the two lines above) #if not [a for a in catlist if a==action]: # catlist.append(action) return filtered_actions
def listFilteredActionsFor(self, object=None): """ Return a mapping containing of all actions available to the user against object, bucketing into categories. """ portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) ec = createExprContext(folder, portal, object) actions = [] append = actions.append info = oai(self, folder, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) self._listActions(append,provider,info,ec) # Include actions from object. if object is not None: base = aq_base(object) if hasattr(base, 'listActions'): self._listActions(append,object,info,ec) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: # startswith() is used so that we can have several # different categories that are checked in the object or # folder context. if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (folder is not None and category.startswith('folder')): context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # Filter out duplicate actions by identity... if not action in catlist: catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the two lines above) #if not [a for a in catlist if a==action]: # catlist.append(action) return filtered_actions