hooks/security.py
branchstable
changeset 5670 80dc2135bf5f
parent 5449 a7e1b316af03
child 5679 0f2ded880d01
child 5813 0b250d72fcfa
equal deleted inserted replaced
5669:1340f14c38c9 5670:80dc2135bf5f
    24 from cubicweb import Unauthorized
    24 from cubicweb import Unauthorized
    25 from cubicweb.selectors import objectify_selector, lltrace
    25 from cubicweb.selectors import objectify_selector, lltrace
    26 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook
    26 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook
    27 
    27 
    28 
    28 
    29 def check_entity_attributes(session, entity, editedattrs=None):
    29 def check_entity_attributes(session, entity, editedattrs=None, creation=False):
    30     eid = entity.eid
    30     eid = entity.eid
    31     eschema = entity.e_schema
    31     eschema = entity.e_schema
    32     # .skip_security_attributes is there to bypass security for attributes
    32     # .skip_security_attributes is there to bypass security for attributes
    33     # set by hooks by modifying the entity's dictionnary
    33     # set by hooks by modifying the entity's dictionnary
    34     dontcheck = entity.skip_security_attributes
    34     dontcheck = entity.skip_security_attributes
    41         if attr in dontcheck:
    41         if attr in dontcheck:
    42             continue
    42             continue
    43         rdef = eschema.rdef(attr)
    43         rdef = eschema.rdef(attr)
    44         if rdef.final: # non final relation are checked by other hooks
    44         if rdef.final: # non final relation are checked by other hooks
    45             # add/delete should be equivalent (XXX: unify them into 'update' ?)
    45             # add/delete should be equivalent (XXX: unify them into 'update' ?)
       
    46             if creation and not rdef.permissions.get('update'):
       
    47                 continue
    46             rdef.check_perm(session, 'update', eid=eid)
    48             rdef.check_perm(session, 'update', eid=eid)
    47     # don't update dontcheck until everything went fine: see usage in
    49     # don't update dontcheck until everything went fine: see usage in
    48     # after_update_entity, where if we got an Unauthorized at hook time, we will
    50     # after_update_entity, where if we got an Unauthorized at hook time, we will
    49     # retry and commit time
    51     # retry and commit time
    50     dontcheck |= frozenset(editedattrs)
    52     dontcheck |= frozenset(editedattrs)
    56         session = self.session
    58         session = self.session
    57         for values in session.transaction_data.pop('check_entity_perm_op'):
    59         for values in session.transaction_data.pop('check_entity_perm_op'):
    58             entity = session.entity_from_eid(values[0])
    60             entity = session.entity_from_eid(values[0])
    59             action = values[1]
    61             action = values[1]
    60             entity.check_perm(action)
    62             entity.check_perm(action)
    61             check_entity_attributes(session, entity, values[2:])
    63             check_entity_attributes(session, entity, values[2:],
       
    64                                     creation=self.creation)
    62 
    65 
    63     def commit_event(self):
    66     def commit_event(self):
    64         pass
    67         pass
    65 
    68 
    66 
    69 
    93     events = ('after_add_entity',)
    96     events = ('after_add_entity',)
    94 
    97 
    95     def __call__(self):
    98     def __call__(self):
    96         hook.set_operation(self._cw, 'check_entity_perm_op',
    99         hook.set_operation(self._cw, 'check_entity_perm_op',
    97                            (self.entity.eid, 'add') + tuple(self.entity.edited_attributes),
   100                            (self.entity.eid, 'add') + tuple(self.entity.edited_attributes),
    98                            _CheckEntityPermissionOp)
   101                            _CheckEntityPermissionOp, creation=True)
    99 
   102 
   100 
   103 
   101 class AfterUpdateEntitySecurityHook(SecurityHook):
   104 class AfterUpdateEntitySecurityHook(SecurityHook):
   102     __regid__ = 'securityafterupdateentity'
   105     __regid__ = 'securityafterupdateentity'
   103     events = ('after_update_entity',)
   106     events = ('after_update_entity',)
   112             # save back editedattrs in case the entity is reedited later in the
   115             # save back editedattrs in case the entity is reedited later in the
   113             # same transaction, which will lead to edited_attributes being
   116             # same transaction, which will lead to edited_attributes being
   114             # overwritten
   117             # overwritten
   115             hook.set_operation(self._cw, 'check_entity_perm_op',
   118             hook.set_operation(self._cw, 'check_entity_perm_op',
   116                                (self.entity.eid, 'update') + tuple(self.entity.edited_attributes),
   119                                (self.entity.eid, 'update') + tuple(self.entity.edited_attributes),
   117                                _CheckEntityPermissionOp)
   120                                _CheckEntityPermissionOp, creation=False)
   118 
   121 
   119 
   122 
   120 class BeforeDelEntitySecurityHook(SecurityHook):
   123 class BeforeDelEntitySecurityHook(SecurityHook):
   121     __regid__ = 'securitybeforedelentity'
   124     __regid__ = 'securitybeforedelentity'
   122     events = ('before_delete_entity',)
   125     events = ('before_delete_entity',)