def getDefaultViewFor(self, ob, view='view'): """Return the object that renders the default view for the given object """ ec = createExpressionContext(ob) other_action = None for action in self.getActionList(): if action['id'] == view or (action['category'] is not None and action['category'].endswith('_' + view)): if action.test(ec): break elif other_action is None: # In case that "view" (or "list") action is not present or not allowed, # find something that's allowed (of the same category, if possible). if action.test(ec): other_action = action else: action = other_action if action is None: raise AccessControl_Unauthorized( 'No accessible views available for %r' % ob.getPath()) target = action.cook(ec)['url'].strip().split( ec.vars['object_url'])[-1] if target.startswith('/'): target = target[1:] __traceback_info__ = self.getId(), target return ob.restrictedTraverse(target)
def getActionInfo(self, action_chain, object=None, check_visibility=0, check_condition=0): """ Get an ActionInfo object specified by a chain of actions. """ action_infos = self.listActionInfos(action_chain, object, check_visibility=check_visibility, check_permissions=False, check_condition=check_condition) if not action_infos: if object is None: provider = self else: provider = object msg = 'Action "%s" not available for %s' % (action_chain, '/'.join( provider.getPhysicalPath())) raise ValueError(msg) for ai in action_infos: if ai['allowed']: return ai raise AccessControl_Unauthorized('You are not allowed to access any ' 'of the specified Actions.')
def setPassword(self, value) : """ Set the password, only if the password is not empty. """ if value is not None: if not _checkPermission(Permissions.SetOwnPassword, self): raise AccessControl_Unauthorized('setPassword') self._setPassword(value) self.reindexObject()
def constructInstance(self, container, id, *args, **kw): """Build an instance of the type. Builds the instance in 'container', using 'id' as its id. Returns the object. """ if not self.isConstructionAllowed(container): raise AccessControl_Unauthorized('Cannot create %s' % self.getId()) return self._constructInstance(container, id, *args, **kw)
def _getFactoryMethod(self, container, check_security=1): if not self.product or not self.factory: raise ValueError, ('Product factory for %s was undefined' % self.getId()) p = container.manage_addProduct[self.product] m = getattr(p, self.factory, None) if m is None: raise ValueError, ('Product factory for %s was invalid' % self.getId()) if not check_security: return m if getSecurityManager().validate(p, p, self.factory, m): return m raise AccessControl_Unauthorized('Cannot create %s' % self.getId())
def _limitGrantedRoles(roles, context, special_roles=()): # Only allow a user to grant roles already possessed by that user, # with the exception that all special_roles can also be granted. user = _getAuthenticatedUser(context) if user is None: user_roles = () else: user_roles = user.getRolesInContext(context) if 'Manager' in user_roles: # Assume all other roles are allowed. return for role in roles: if role not in special_roles and role not in user_roles: raise AccessControl_Unauthorized('Too many roles specified.')
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): 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 _setUserId(self, value): """ Set the user id. This method is defined explicitly, because: - we want to apply a different permission - we want to prevent duplicated user ids, but only when PAS _AND_ ERP5LoginUserManager are used """ existing_user_id = self.getUserId() if value != existing_user_id: if value: self.__checkUserIdAvailability( pas_plugin_class=ERP5LoginUserManager, user_id=value, ) if existing_user_id and not _checkPermission(Permissions.ManageUsers, self): raise AccessControl_Unauthorized('setUserId') self._baseSetUserId(value)
def index_html(self, REQUEST, RESPONSE=None, template_relative_url=None, format=None, batch_mode=False): """Render and view a printout document. format: conversion format requested by User. take precedence of format in REQUEST batch_mode: if True then avoid overriding response headers. """ obj = getattr(self, 'aq_parent', None) if obj is not None: container = obj.aq_inner.aq_parent if not _checkPermission(Permissions.View, obj): raise AccessControl_Unauthorized('This document is not authorized for view.') else: container = None form = getattr(obj, self.form_name) if template_relative_url: printout_template = obj.getPortalObject().\ restrictedTraverse(template_relative_url) elif self.template: printout_template = getattr(obj, self.template) else: raise ValueError('Can not create a ODF Document without a printout template') report_method = None if hasattr(form, 'report_method'): report_method = getattr(obj, form.report_method) extra_context = dict(container=container, printout_template=printout_template, report_method=report_method, form=form, here=obj) # Never set value when rendering! If you do, then every time # writing occur and it creates conflict error which kill ERP5 # scalability! To get acquisition, you just have to call __of__. # Also frequent writing make data.fs very huge so quickly. content_type = printout_template.content_type strategy = self._createStrategy(content_type).__of__(self) printout = strategy.render(extra_context=extra_context) return self._oooConvertByFormat(printout, content_type, extra_context, REQUEST, format, batch_mode)
def __call__(self, *args, **kwargs): # Security # # The minimal action consists in checking that # we have View permission on the current object # before rendering a form. Otherwise, object with # AccessContentInformation can be viewed by invoking # a form directly. # # What would be better is to prevent calling certain # forms to render objects. This can not be done # through actions since we are using sometimes forms # to render the results of a report dialog form. # An a appropriate solutions could consist in adding # a permission field to the form. Another solutions # is the use of REFERER in the rendering process. # # Both solutions are not perfect if the goal is, for # example, to prevent displaying private information of # staff. The only real solution is to use a special # permission (ex. AccessPrivateInformation) for those # properties which are sensitive. kwargs.setdefault('args', args) key_prefix = kwargs.pop('key_prefix', None) obj = getattr(self, 'aq_parent', None) if obj is not None: container = obj.aq_inner.aq_parent if not _checkPermission(Permissions.View, obj): raise AccessControl_Unauthorized('This document is not authorized for view.') else: container = None pt = getattr(self,self.pt) extra_context = dict( container=container, template=self, form=self, key_prefix=key_prefix, options=kwargs, here=obj, context=obj, ) return pt.pt_render(extra_context=extra_context)
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. mt = getattr(object, '__factory_meta_type__', None) meta_types = getattr(self, 'all_meta_types', None) if mt is not None and meta_types is not None: method_name = None mt_permission = None if callable(meta_types): meta_types = meta_types() for d in meta_types: if d['name'] == mt: method_name = d['action'] mt_permission = d.get('permission') break if mt_permission is not None: sm = getSecurityManager() if sm.checkPermission(mt_permission, self): if validate_src: # Ensure the user is allowed to access the object on # the clipboard. parent = aq_parent(aq_inner(object)) if not sm.validate(None, parent, None, object): raise AccessControl_Unauthorized(object.getId()) if validate_src == 2: # moving if not sm.checkPermission(DeleteObjects, parent): raise AccessControl_Unauthorized('Delete not ' 'allowed.') else: raise AccessControl_Unauthorized('You do not possess the ' '%r permission in the context of the container ' 'into which you are pasting, thus you are not ' 'able to perform this operation.' % mt_permission) else: raise AccessControl_Unauthorized('The object %r does not ' 'support this operation.' % object.getId()) else: # Call OFS' _verifyObjectPaste if necessary PortalFolderBase.inheritedAttribute( '_verifyObjectPaste')(self, object, validate_src) # Finally, check allowed content types if hasattr(aq_base(object), 'getPortalTypeName'): type_name = object.getPortalTypeName() if type_name is not None: pt = getToolByName(self, 'portal_types') myType = pt.getTypeInfo(self) if myType is not None and not myType.allowType(type_name): raise ValueError('Disallowed subobject type: %s' % type_name)
def constructInstance(self, container, id, created_by_builder=0, temp_object=0, compute_local_role=None, notify_workflow=True, is_indexable=None, activate_kw=None, reindex_kw=None, **kw): """ Build a "bare" instance of the appropriate type in 'container', using 'id' as its id. Call the init_script for the portal_type. Returns the object. """ if compute_local_role is None: # If temp object, set to False compute_local_role = not temp_object if not temp_object and not self.isConstructionAllowed(container): raise AccessControl_Unauthorized('Cannot create %s' % self.getId()) portal = container.getPortalObject() klass = portal.portal_types.getPortalTypeClass(self.getId(), temp=temp_object) base_ob = klass(id) ob = base_ob.__of__(container) if temp_object: # Setup only Owner local role on Document like # container._setObject(set_owner=True) does. user = getSecurityManager().getUser() if user is not None: user_id = user.getId() else: user_id = 'Anonymous Owner' ob.manage_setLocalRoles(user_id, ['Owner']) else: if activate_kw is not None: ob.setDefaultActivateParameterDict(activate_kw) if reindex_kw is not None: ob.setDefaultReindexParameterDict(reindex_kw) if is_indexable is not None: base_ob.isIndexable = is_indexable container._setObject(id, base_ob) # if no activity tool, the object has already an uid if getattr(base_ob, 'uid', None) is None: ob.uid = portal.portal_catalog.newUid() # Portal type has to be set before setting other attributes # in order to initialize aq_dynamic ob.portal_type = self.getId() if compute_local_role: # Do not reindex object because it's already done by manage_afterAdd self.updateLocalRolesOnDocument(ob, reindex=False) if notify_workflow: # notify workflow after generating local roles, in order to prevent # Unauthorized error on transition's condition workflow_tool = getToolByName(portal, 'portal_workflow', None) if workflow_tool is not None: for workflow in workflow_tool.getWorkflowsFor(ob): workflow.notifyCreated(ob) if not temp_object: init_script = self.getTypeInitScriptId() if init_script: # Acquire the init script in the context of this object getattr(ob, init_script)(created_by_builder=created_by_builder, edit_kw=kw) if kw: ob._edit(force_update=1, **kw) return ob
def constructInstance(self, container, id, created_by_builder=0, temp_object=0, compute_local_role=None, notify_workflow=True, is_indexable=None, activate_kw=None, reindex_kw=None, immediate_reindex=False, **kw): """ Build a "bare" instance of the appropriate type in 'container', using 'id' as its id. Call the init_script for the portal_type. immediate_reindex (bool, ImmediateReindexContextManager) Immediately (=during current transaction) reindex created document, so it is possible to find it in catalog before transaction ends. If a ImmediateReindexContextManager instance is given, a context (in python sense) must have been entered with it, and indexation will occur when that context is exited, allowing further changes before first indexation (ex: workflow state change, property change). Returns the object. """ if compute_local_role is None: # If temp object, set to False compute_local_role = not temp_object if not temp_object and not self.isConstructionAllowed(container): raise AccessControl_Unauthorized('Cannot create %s' % self.getId()) portal = container.getPortalObject() klass = portal.portal_types.getPortalTypeClass( self.getId(), temp=temp_object) base_ob = klass(id) ob = base_ob.__of__(container) if temp_object: # Setup only Owner local role on Document like # container._setObject(set_owner=True) does. user = getSecurityManager().getUser() if user is not None: user_id = user.getId() else: user_id = 'Anonymous Owner' ob.manage_setLocalRoles(user_id, ['Owner']) else: if activate_kw is not None: ob.setDefaultActivateParameterDict(activate_kw) if reindex_kw is not None: ob.setDefaultReindexParameterDict(reindex_kw) if is_indexable is not None: base_ob.isIndexable = is_indexable container._setObject(id, base_ob) # if no activity tool, the object has already an uid if getattr(base_ob, 'uid', None) is None: ob.uid = portal.portal_catalog.newUid() # Portal type has to be set before setting other attributes # in order to initialize aq_dynamic ob.portal_type = self.getId() if compute_local_role: # Do not reindex object because it's already done by manage_afterAdd self.updateLocalRolesOnDocument(ob, reindex=False) if notify_workflow: # notify workflow after generating local roles, in order to prevent # Unauthorized error on transition's condition workflow_tool = portal.portal_workflow if workflow_tool is not None: for workflow in workflow_tool.getWorkflowValueListFor(ob): workflow.notifyCreated(ob) if not temp_object: init_script = self.getTypeInitScriptId() if init_script: # Acquire the init script in the context of this object getattr(ob, init_script)(created_by_builder=created_by_builder, edit_kw=kw) if kw: ob._edit(force_update=1, **kw) if not temp_object and immediate_reindex is not None: # As we just created ob, we assume the whole subtree is of a # reasonable size and hence can be walked in current transaction. # Subtree may come from: # - acquired setter (ex: address on a Person which actually exists on # a subdocument), which should be in very limited quantity # - type-based init script, which will have to delegate any # large-document creation needs to later transactions # (activities). Or just not request immediate indexation. # - if ImmediateReindexContextManager is used, anything until # context manager exits. method = ob._reindexOnCreation if activate_kw is not None: if reindex_kw is None: reindex_kw = {} reindex_kw.setdefault('activate_kw', {}).update(activate_kw) if reindex_kw is not None: method = partial(method, **reindex_kw) if isinstance(immediate_reindex, ImmediateReindexContextManager): immediate_reindex.append(method) elif immediate_reindex: # Immediately reindexing document that we just created is safe, as no # other transaction can by definition see it, so there cannot be a race # condition leading to stale catalog content. method() return ob
def checkUserCanChangePassword(self): if not _checkPermission(Permissions.SetOwnPassword, self): raise AccessControl_Unauthorized('setPassword')