server/securityhooks.py
changeset 0 b97547f5f1fa
child 475 b32a5772ff06
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 """Security hooks: check permissions to add/delete/update entities according to
       
     2 the user connected to a session
       
     3 
       
     4 :organization: Logilab
       
     5 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     7 """
       
     8 __docformat__ = "restructuredtext en"
       
     9 
       
    10 from cubicweb import Unauthorized
       
    11 from cubicweb.server.pool import LateOperation
       
    12 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS
       
    13 
       
    14 def check_entity_attributes(session, entity):
       
    15     eid = entity.eid
       
    16     eschema = entity.e_schema
       
    17     # ._default_set is only there on entity creation to indicate unspecified
       
    18     # attributes which has been set to a default value defined in the schema
       
    19     defaults = getattr(entity, '_default_set', ())
       
    20     for attr in entity.keys():
       
    21         if attr in defaults:
       
    22             continue
       
    23         rschema = eschema.subject_relation(attr)
       
    24         if rschema.is_final(): # non final relation are checked by other hooks
       
    25             # add/delete should be equivalent (XXX: unify them into 'update' ?)
       
    26             rschema.check_perm(session, 'add', eid)
       
    27             
       
    28     
       
    29 class CheckEntityPermissionOp(LateOperation):
       
    30     def precommit_event(self):
       
    31         #print 'CheckEntityPermissionOp', self.session.user, self.entity, self.action
       
    32         self.entity.check_perm(self.action)
       
    33         check_entity_attributes(self.session, self.entity)
       
    34         
       
    35     def commit_event(self):
       
    36         pass
       
    37             
       
    38     
       
    39 class CheckRelationPermissionOp(LateOperation):
       
    40     def precommit_event(self):
       
    41         self.rschema.check_perm(self.session, self.action, self.fromeid, self.toeid)
       
    42         
       
    43     def commit_event(self):
       
    44         pass
       
    45     
       
    46 def after_add_entity(session, entity):
       
    47     if not session.is_super_session:
       
    48         CheckEntityPermissionOp(session, entity=entity, action='add')
       
    49 
       
    50 def after_update_entity(session, entity):
       
    51     if not session.is_super_session:
       
    52         try:
       
    53             # check user has permission right now, if not retry at commit time
       
    54             entity.check_perm('update')
       
    55             check_entity_attributes(session, entity)
       
    56         except Unauthorized:
       
    57             CheckEntityPermissionOp(session, entity=entity, action='update')
       
    58         
       
    59 def before_del_entity(session, eid):
       
    60     if not session.is_super_session:
       
    61         eschema = session.repo.schema[session.describe(eid)[0]]
       
    62         eschema.check_perm(session, 'delete', eid)
       
    63 
       
    64 
       
    65 def before_add_relation(session, fromeid, rtype, toeid):
       
    66     if rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
       
    67         rschema = session.repo.schema[rtype]
       
    68         rschema.check_perm(session, 'add', fromeid, toeid)
       
    69         
       
    70 def after_add_relation(session, fromeid, rtype, toeid):
       
    71     if not rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
       
    72         rschema = session.repo.schema[rtype]
       
    73         if rtype in ON_COMMIT_ADD_RELATIONS:
       
    74             CheckRelationPermissionOp(session, action='add', rschema=rschema,
       
    75                                       fromeid=fromeid, toeid=toeid)
       
    76         else:
       
    77             rschema.check_perm(session, 'add', fromeid, toeid)
       
    78 
       
    79 def before_del_relation(session, fromeid, rtype, toeid):
       
    80     if not session.is_super_session:
       
    81         session.repo.schema[rtype].check_perm(session, 'delete', fromeid, toeid)
       
    82 
       
    83 def register_security_hooks(hm):
       
    84     """register meta-data related hooks on the hooks manager"""
       
    85     hm.register_hook(after_add_entity, 'after_add_entity', '')
       
    86     hm.register_hook(after_update_entity, 'after_update_entity', '')
       
    87     hm.register_hook(before_del_entity, 'before_delete_entity', '')
       
    88     hm.register_hook(before_add_relation, 'before_add_relation', '')
       
    89     hm.register_hook(after_add_relation, 'after_add_relation', '')
       
    90     hm.register_hook(before_del_relation, 'before_delete_relation', '')
       
    91