diff -r 000000000000 -r b97547f5f1fa server/securityhooks.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/securityhooks.py Wed Nov 05 15:52:50 2008 +0100 @@ -0,0 +1,91 @@ +"""Security hooks: check permissions to add/delete/update entities according to +the user connected to a session + +:organization: Logilab +:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr +""" +__docformat__ = "restructuredtext en" + +from cubicweb import Unauthorized +from cubicweb.server.pool import LateOperation +from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS + +def check_entity_attributes(session, entity): + eid = entity.eid + eschema = entity.e_schema + # ._default_set is only there on entity creation to indicate unspecified + # attributes which has been set to a default value defined in the schema + defaults = getattr(entity, '_default_set', ()) + for attr in entity.keys(): + if attr in defaults: + continue + rschema = eschema.subject_relation(attr) + if rschema.is_final(): # non final relation are checked by other hooks + # add/delete should be equivalent (XXX: unify them into 'update' ?) + rschema.check_perm(session, 'add', eid) + + +class CheckEntityPermissionOp(LateOperation): + def precommit_event(self): + #print 'CheckEntityPermissionOp', self.session.user, self.entity, self.action + self.entity.check_perm(self.action) + check_entity_attributes(self.session, self.entity) + + def commit_event(self): + pass + + +class CheckRelationPermissionOp(LateOperation): + def precommit_event(self): + self.rschema.check_perm(self.session, self.action, self.fromeid, self.toeid) + + def commit_event(self): + pass + +def after_add_entity(session, entity): + if not session.is_super_session: + CheckEntityPermissionOp(session, entity=entity, action='add') + +def after_update_entity(session, entity): + if not session.is_super_session: + try: + # check user has permission right now, if not retry at commit time + entity.check_perm('update') + check_entity_attributes(session, entity) + except Unauthorized: + CheckEntityPermissionOp(session, entity=entity, action='update') + +def before_del_entity(session, eid): + if not session.is_super_session: + eschema = session.repo.schema[session.describe(eid)[0]] + eschema.check_perm(session, 'delete', eid) + + +def before_add_relation(session, fromeid, rtype, toeid): + if rtype in BEFORE_ADD_RELATIONS and not session.is_super_session: + rschema = session.repo.schema[rtype] + rschema.check_perm(session, 'add', fromeid, toeid) + +def after_add_relation(session, fromeid, rtype, toeid): + if not rtype in BEFORE_ADD_RELATIONS and not session.is_super_session: + rschema = session.repo.schema[rtype] + if rtype in ON_COMMIT_ADD_RELATIONS: + CheckRelationPermissionOp(session, action='add', rschema=rschema, + fromeid=fromeid, toeid=toeid) + else: + rschema.check_perm(session, 'add', fromeid, toeid) + +def before_del_relation(session, fromeid, rtype, toeid): + if not session.is_super_session: + session.repo.schema[rtype].check_perm(session, 'delete', fromeid, toeid) + +def register_security_hooks(hm): + """register meta-data related hooks on the hooks manager""" + hm.register_hook(after_add_entity, 'after_add_entity', '') + hm.register_hook(after_update_entity, 'after_update_entity', '') + hm.register_hook(before_del_entity, 'before_delete_entity', '') + hm.register_hook(before_add_relation, 'before_add_relation', '') + hm.register_hook(after_add_relation, 'after_add_relation', '') + hm.register_hook(before_del_relation, 'before_delete_relation', '') +