271 |
271 |
272 # base classes for relation propagation ######################################## |
272 # base classes for relation propagation ######################################## |
273 |
273 |
274 from cubicweb.server.pool import PreCommitOperation |
274 from cubicweb.server.pool import PreCommitOperation |
275 |
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 |
276 |
283 class PropagateSubjectRelationHook(Hook): |
277 class PropagateSubjectRelationHook(Hook): |
284 """propagate permissions and nosy list when new entity are added""" |
278 """propagate permissions and nosy list when new entity are added""" |
285 events = ('after_add_relation',) |
279 events = ('after_add_relation',) |
286 # to set in concrete class |
280 # to set in concrete class |
297 if rtype in self.subject_relations: |
291 if rtype in self.subject_relations: |
298 meid, seid = fromeid, toeid |
292 meid, seid = fromeid, toeid |
299 else: |
293 else: |
300 assert rtype in self.object_relations |
294 assert rtype in self.object_relations |
301 meid, seid = toeid, fromeid |
295 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'\ |
296 session.unsafe_execute( |
303 % (self.rtype, self.rtype, self.rtype) |
297 'SET E %s P WHERE X %s P, X eid %%(x)s, E eid %%(e)s, NOT E %s P'\ |
304 rqls = [(rql, {'x': meid, 'e': seid}, ('x', 'e'))] |
298 % (self.rtype, self.rtype, self.rtype), |
305 RQLPrecommitOperation(session, rqls=rqls) |
299 {'x': meid, 'e': seid}, ('x', 'e')) |
306 |
300 |
307 |
301 |
308 class PropagateSubjectRelationAddHook(Hook): |
302 class PropagateSubjectRelationAddHook(Hook): |
309 """propagate on existing entities when a permission or nosy list is added""" |
303 """propagate on existing entities when a permission or nosy list is added""" |
310 events = ('after_add_relation',) |
304 events = ('after_add_relation',) |
314 object_relations = None |
308 object_relations = None |
315 accepts = None # (self.rtype,) |
309 accepts = None # (self.rtype,) |
316 |
310 |
317 def call(self, session, fromeid, rtype, toeid): |
311 def call(self, session, fromeid, rtype, toeid): |
318 eschema = self.schema.eschema(session.describe(fromeid)[0]) |
312 eschema = self.schema.eschema(session.describe(fromeid)[0]) |
319 rqls = [] |
313 execute = session.unsafe_execute |
320 for rel in self.subject_relations: |
314 for rel in self.subject_relations: |
321 if eschema.has_subject_relation(rel): |
315 if eschema.has_subject_relation(rel): |
322 rqls.append(('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
316 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
323 'X %s R, NOT R %s P' % (rtype, rel, rtype), |
317 'X %s R, NOT R %s P' % (rtype, rel, rtype), |
324 {'x': fromeid, 'p': toeid}, 'x')) |
318 {'x': fromeid, 'p': toeid}, 'x') |
325 for rel in self.object_relations: |
319 for rel in self.object_relations: |
326 if eschema.has_object_relation(rel): |
320 if eschema.has_object_relation(rel): |
327 rqls.append(('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
321 execute('SET R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
328 'R %s X, NOT R %s P' % (rtype, rel, rtype), |
322 'R %s X, NOT R %s P' % (rtype, rel, rtype), |
329 {'x': fromeid, 'p': toeid}, 'x')) |
323 {'x': fromeid, 'p': toeid}, 'x') |
330 if rqls: |
|
331 RQLPrecommitOperation(session, rqls=rqls) |
|
332 |
324 |
333 |
325 |
334 class PropagateSubjectRelationDelHook(Hook): |
326 class PropagateSubjectRelationDelHook(Hook): |
335 """propagate on existing entities when a permission is deleted""" |
327 """propagate on existing entities when a permission is deleted""" |
336 events = ('after_delete_relation',) |
328 events = ('after_delete_relation',) |
340 object_relations = None |
332 object_relations = None |
341 accepts = None # (self.rtype,) |
333 accepts = None # (self.rtype,) |
342 |
334 |
343 def call(self, session, fromeid, rtype, toeid): |
335 def call(self, session, fromeid, rtype, toeid): |
344 eschema = self.schema.eschema(session.describe(fromeid)[0]) |
336 eschema = self.schema.eschema(session.describe(fromeid)[0]) |
345 rqls = [] |
337 execute = session.unsafe_execute |
346 for rel in self.subject_relations: |
338 for rel in self.subject_relations: |
347 if eschema.has_subject_relation(rel): |
339 if eschema.has_subject_relation(rel): |
348 rqls.append(('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
340 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
349 'X %s R' % (rtype, rel), |
341 'X %s R' % (rtype, rel), |
350 {'x': fromeid, 'p': toeid}, 'x')) |
342 {'x': fromeid, 'p': toeid}, 'x') |
351 for rel in self.object_relations: |
343 for rel in self.object_relations: |
352 if eschema.has_object_relation(rel): |
344 if eschema.has_object_relation(rel): |
353 rqls.append(('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
345 execute('DELETE R %s P WHERE X eid %%(x)s, P eid %%(p)s, ' |
354 'R %s X' % (rtype, rel), |
346 'R %s X' % (rtype, rel), |
355 {'x': fromeid, 'p': toeid}, 'x')) |
347 {'x': fromeid, 'p': toeid}, 'x') |
356 if rqls: |
|
357 RQLPrecommitOperation(session, rqls=rqls) |
|