hooks/security.py
branchstable
changeset 9129 6c4ae3a06619
parent 8239 c6cdd060212e
child 9254 e1369f2dba79
child 9521 9eb810333b0f
equal deleted inserted replaced
9128:d988eec2d5d3 9129:6c4ae3a06619
    21 
    21 
    22 __docformat__ = "restructuredtext en"
    22 __docformat__ = "restructuredtext en"
    23 
    23 
    24 from logilab.common.registry import objectify_predicate
    24 from logilab.common.registry import objectify_predicate
    25 
    25 
       
    26 from yams import buildobjs
       
    27 
    26 from cubicweb import Unauthorized
    28 from cubicweb import Unauthorized
    27 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook
    29 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook
    28 
    30 
    29 
    31 
       
    32 _DEFAULT_UPDATE_ATTRPERM = buildobjs.DEFAULT_ATTRPERMS['update']
    30 def check_entity_attributes(session, entity, editedattrs=None, creation=False):
    33 def check_entity_attributes(session, entity, editedattrs=None, creation=False):
    31     eid = entity.eid
    34     eid = entity.eid
    32     eschema = entity.e_schema
    35     eschema = entity.e_schema
    33     # ._cw_skip_security_attributes is there to bypass security for attributes
    36     # ._cw_skip_security_attributes is there to bypass security for attributes
    34     # set by hooks by modifying the entity's dictionary
    37     # set by hooks by modifying the entity's dictionary
    37     dontcheck = editedattrs.skip_security
    40     dontcheck = editedattrs.skip_security
    38     for attr in editedattrs:
    41     for attr in editedattrs:
    39         if attr in dontcheck:
    42         if attr in dontcheck:
    40             continue
    43             continue
    41         rdef = eschema.rdef(attr)
    44         rdef = eschema.rdef(attr)
    42         if rdef.final: # non final relation are checked by other hooks
    45         if rdef.final: # non final relation are checked by standard hooks
    43             # add/delete should be equivalent (XXX: unify them into 'update' ?)
    46             # attributes only have a specific 'update' permission
    44             if creation and not rdef.permissions.get('update'):
    47             updateperm = rdef.permissions.get('update')
       
    48             # comparison below works because the default update perm is:
       
    49             #
       
    50             #  ('managers', ERQLExpression(Any X WHERE U has_update_permission X, X eid %(x)s, U eid %(u)s))
       
    51             #
       
    52             # is deserialized in this order (groups first), and ERQLExpression
       
    53             # implements comparison by expression.
       
    54             if updateperm == _DEFAULT_UPDATE_ATTRPERM:
       
    55                 # The default update permission is to delegate to the entity
       
    56                 # update permission. This is an historical artefact but it is
       
    57                 # costly (in general). Hence we take this permission object as a
       
    58                 # marker saying "no specific" update permissions for this
       
    59                 # attribute. Thus we just do nothing.
       
    60                 continue
       
    61             if creation and updateperm == ():
       
    62                 # That actually means an immutable attribute.  We make an
       
    63                 # _exception_ to the `check attr update perms at entity create &
       
    64                 # update time` rule for this case.
    45                 continue
    65                 continue
    46             rdef.check_perm(session, 'update', eid=eid)
    66             rdef.check_perm(session, 'update', eid=eid)
    47 
    67 
    48 
    68 
    49 class CheckEntityPermissionOp(hook.DataOperationMixIn, hook.LateOperation):
    69 class CheckEntityPermissionOp(hook.DataOperationMixIn, hook.LateOperation):