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