--- a/server/hooksmanager.py Thu Sep 17 19:38:04 2009 +0200
+++ b/server/hooksmanager.py Fri Sep 18 11:24:37 2009 +0200
@@ -268,3 +268,80 @@
from cubicweb import set_log_methods
set_log_methods(HooksManager, getLogger('cubicweb.hooksmanager'))
set_log_methods(Hook, getLogger('cubicweb.hooks'))
+
+# base classes for relation propagation ########################################
+
+from cubicweb.server.pool import PreCommitOperation
+
+
+class PropagateSubjectRelationHook(Hook):
+ """propagate permissions and nosy list when new entity are added"""
+ events = ('after_add_relation',)
+ # to set in concrete class
+ rtype = None
+ subject_relations = None
+ object_relations = None
+ accepts = None # subject_relations + object_relations
+
+ def call(self, session, fromeid, rtype, toeid):
+ for eid in (fromeid, toeid):
+ etype = session.describe(eid)[0]
+ if not self.schema.eschema(etype).has_subject_relation(self.rtype):
+ return
+ if rtype in self.subject_relations:
+ meid, seid = fromeid, toeid
+ else:
+ assert rtype in self.object_relations
+ meid, seid = toeid, fromeid
+ session.unsafe_execute(
+ 'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P'\
+ % (self.rtype, self.rtype, self.rtype),
+ {'x': meid, 'e': seid}, ('x', 'e'))
+
+
+class PropagateSubjectRelationAddHook(Hook):
+ """propagate on existing entities when a permission or nosy list is added"""
+ events = ('after_add_relation',)
+ # to set in concrete class
+ rtype = None
+ subject_relations = None
+ object_relations = None
+ accepts = None # (self.rtype,)
+
+ def call(self, session, fromeid, rtype, toeid):
+ eschema = self.schema.eschema(session.describe(fromeid)[0])
+ execute = session.unsafe_execute
+ for rel in self.subject_relations:
+ if eschema.has_subject_relation(rel):
+ execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
+ 'X %s R, NOT R %s P' % (rtype, rel, rtype),
+ {'x': fromeid, 'p': toeid}, 'x')
+ for rel in self.object_relations:
+ if eschema.has_object_relation(rel):
+ execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
+ 'R %s X, NOT R %s P' % (rtype, rel, rtype),
+ {'x': fromeid, 'p': toeid}, 'x')
+
+
+class PropagateSubjectRelationDelHook(Hook):
+ """propagate on existing entities when a permission is deleted"""
+ events = ('after_delete_relation',)
+ # to set in concrete class
+ rtype = None
+ subject_relations = None
+ object_relations = None
+ accepts = None # (self.rtype,)
+
+ def call(self, session, fromeid, rtype, toeid):
+ eschema = self.schema.eschema(session.describe(fromeid)[0])
+ execute = session.unsafe_execute
+ for rel in self.subject_relations:
+ if eschema.has_subject_relation(rel):
+ execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
+ 'X %s R' % (rtype, rel),
+ {'x': fromeid, 'p': toeid}, 'x')
+ for rel in self.object_relations:
+ if eschema.has_object_relation(rel):
+ execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
+ 'R %s X' % (rtype, rel),
+ {'x': fromeid, 'p': toeid}, 'x')