server/hooksmanager.py
branch3.5
changeset 2918 452b4c9ee61d
parent 2579 e69b2342bd8b
child 2968 0e3460341023
child 3088 854a30d8c092
equal deleted inserted replaced
2917:9a243ba71260 2918:452b4c9ee61d
   266 
   266 
   267 from logging import getLogger
   267 from logging import getLogger
   268 from cubicweb import set_log_methods
   268 from cubicweb import set_log_methods
   269 set_log_methods(HooksManager, getLogger('cubicweb.hooksmanager'))
   269 set_log_methods(HooksManager, getLogger('cubicweb.hooksmanager'))
   270 set_log_methods(Hook, getLogger('cubicweb.hooks'))
   270 set_log_methods(Hook, getLogger('cubicweb.hooks'))
       
   271 
       
   272 # base classes for relation propagation ########################################
       
   273 
       
   274 from cubicweb.server.pool import PreCommitOperation
       
   275 
       
   276 class RQLPrecommitOperation(PreCommitOperation):
       
   277     def precommit_event(self):
       
   278         execute = self.session.unsafe_execute
       
   279         for rql in self.rqls:
       
   280             execute(*rql)
       
   281 
       
   282 
       
   283 class PropagateSubjectRelationHook(Hook):
       
   284     """propagate permissions and nosy list when new entity are added"""
       
   285     events = ('after_add_relation',)
       
   286     # to set in concrete class
       
   287     rtype = None
       
   288     subject_relations = None
       
   289     object_relations = None
       
   290     accepts = None # subject_relations + object_relations
       
   291 
       
   292     def call(self, session, fromeid, rtype, toeid):
       
   293         for eid in (fromeid, toeid):
       
   294             etype = session.describe(eid)[0]
       
   295             if not self.schema.eschema(etype).has_subject_relation(self.rtype):
       
   296                 return
       
   297         if rtype in self.subject_relations:
       
   298             meid, seid = fromeid, toeid
       
   299         else:
       
   300             assert rtype in self.object_relations
       
   301             meid, seid = toeid, fromeid
       
   302         rql = 'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P'\
       
   303               % (self.rtype, self.rtype, self.rtype)
       
   304         rqls = [(rql, {'x': meid, 'e': seid}, ('x', 'e'))]
       
   305         RQLPrecommitOperation(session, rqls=rqls)
       
   306 
       
   307 
       
   308 class PropagateSubjectRelationAddHook(Hook):
       
   309     """propagate on existing entities when a permission or nosy list is added"""
       
   310     events = ('after_add_relation',)
       
   311     # to set in concrete class
       
   312     rtype = None
       
   313     subject_relations = None
       
   314     object_relations = None
       
   315     accepts = None # (self.rtype,)
       
   316 
       
   317     def call(self, session, fromeid, rtype, toeid):
       
   318         eschema = self.schema.eschema(session.describe(fromeid)[0])
       
   319         rqls = []
       
   320         for rel in self.subject_relations:
       
   321             if eschema.has_subject_relation(rel):
       
   322                 rqls.append(('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
       
   323                              'X %s R, NOT R %s P' % (rtype, rel, rtype),
       
   324                              {'x': fromeid, 'p': toeid}, 'x'))
       
   325         for rel in self.object_relations:
       
   326             if eschema.has_object_relation(rel):
       
   327                 rqls.append(('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
       
   328                              'R %s X, NOT R %s P' % (rtype, rel, rtype),
       
   329                              {'x': fromeid, 'p': toeid}, 'x'))
       
   330         if rqls:
       
   331             RQLPrecommitOperation(session, rqls=rqls)
       
   332 
       
   333 
       
   334 class PropagateSubjectRelationDelHook(Hook):
       
   335     """propagate on existing entities when a permission is deleted"""
       
   336     events = ('after_delete_relation',)
       
   337     # to set in concrete class
       
   338     rtype = None
       
   339     subject_relations = None
       
   340     object_relations = None
       
   341     accepts = None # (self.rtype,)
       
   342 
       
   343     def call(self, session, fromeid, rtype, toeid):
       
   344         eschema = self.schema.eschema(session.describe(fromeid)[0])
       
   345         rqls = []
       
   346         for rel in self.subject_relations:
       
   347             if eschema.has_subject_relation(rel):
       
   348                 rqls.append(('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
       
   349                              'X %s R' % (rtype, rel),
       
   350                              {'x': fromeid, 'p': toeid}, 'x'))
       
   351         for rel in self.object_relations:
       
   352             if eschema.has_object_relation(rel):
       
   353                 rqls.append(('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, '
       
   354                              'R %s X' % (rtype, rel),
       
   355                              {'x': fromeid, 'p': toeid}, 'x'))
       
   356         if rqls:
       
   357             RQLPrecommitOperation(session, rqls=rqls)