# HG changeset patch # User Aurelien Campeas # Date 1372853781 -7200 # Node ID 6c4ae3a0661985d75e24ee3e54835e342bc30158 # Parent d988eec2d5d359c4788128ce8b765deea3e456f6 [hooks/security] Streamline attributes default permission check. The current default permission on attributes delegates the check to the entity permission update policy. Since this is already checked it can be skipped. The equality comparison will work, even with a deserialized schema, because the default update perm is:: ('managers', ERQLExpression(Any X WHERE U has_update_permission X, X eid %(x)s, U eid %(u)s)) which will always be deserialized in this order (groups first). However this is a slight semantic change: entity type level 'update' permissions can now be effectively used to encode update-time rules if the default attribute permissions are used (before this change, the 'update' rules at entity type level were fired at creation time). Closes #2930861. diff -r d988eec2d5d3 -r 6c4ae3a06619 hooks/security.py --- a/hooks/security.py Wed Jun 26 14:22:22 2013 +0200 +++ b/hooks/security.py Wed Jul 03 14:16:21 2013 +0200 @@ -23,10 +23,13 @@ from logilab.common.registry import objectify_predicate +from yams import buildobjs + from cubicweb import Unauthorized from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook +_DEFAULT_UPDATE_ATTRPERM = buildobjs.DEFAULT_ATTRPERMS['update'] def check_entity_attributes(session, entity, editedattrs=None, creation=False): eid = entity.eid eschema = entity.e_schema @@ -39,9 +42,26 @@ if attr in dontcheck: continue rdef = eschema.rdef(attr) - if rdef.final: # non final relation are checked by other hooks - # add/delete should be equivalent (XXX: unify them into 'update' ?) - if creation and not rdef.permissions.get('update'): + if rdef.final: # non final relation are checked by standard hooks + # attributes only have a specific 'update' permission + updateperm = rdef.permissions.get('update') + # comparison below works because the default update perm is: + # + # ('managers', ERQLExpression(Any X WHERE U has_update_permission X, X eid %(x)s, U eid %(u)s)) + # + # is deserialized in this order (groups first), and ERQLExpression + # implements comparison by expression. + if updateperm == _DEFAULT_UPDATE_ATTRPERM: + # The default update permission is to delegate to the entity + # update permission. This is an historical artefact but it is + # costly (in general). Hence we take this permission object as a + # marker saying "no specific" update permissions for this + # attribute. Thus we just do nothing. + continue + if creation and updateperm == (): + # That actually means an immutable attribute. We make an + # _exception_ to the `check attr update perms at entity create & + # update time` rule for this case. continue rdef.check_perm(session, 'update', eid=eid)