16 get_user_sessions, rproperty) |
16 get_user_sessions, rproperty) |
17 from cubicweb.server.repository import FTIndexEntityOp |
17 from cubicweb.server.repository import FTIndexEntityOp |
18 |
18 |
19 def relation_deleted(session, eidfrom, rtype, eidto): |
19 def relation_deleted(session, eidfrom, rtype, eidto): |
20 session.add_query_data('pendingrelations', (eidfrom, rtype, eidto)) |
20 session.add_query_data('pendingrelations', (eidfrom, rtype, eidto)) |
21 |
21 |
22 |
22 |
23 # base meta-data handling ##################################################### |
23 # base meta-data handling ##################################################### |
24 |
24 |
25 def setctime_before_add_entity(session, entity): |
25 def setctime_before_add_entity(session, entity): |
26 """before create a new entity -> set creation and modification date |
26 """before create a new entity -> set creation and modification date |
27 |
27 |
28 this is a conveniency hook, you shouldn't have to disable it |
28 this is a conveniency hook, you shouldn't have to disable it |
29 """ |
29 """ |
30 if not 'creation_date' in entity: |
30 if not 'creation_date' in entity: |
31 entity['creation_date'] = datetime.now() |
31 entity['creation_date'] = datetime.now() |
32 if not 'modification_date' in entity: |
32 if not 'modification_date' in entity: |
34 |
34 |
35 def setmtime_before_update_entity(session, entity): |
35 def setmtime_before_update_entity(session, entity): |
36 """update an entity -> set modification date""" |
36 """update an entity -> set modification date""" |
37 if not 'modification_date' in entity: |
37 if not 'modification_date' in entity: |
38 entity['modification_date'] = datetime.now() |
38 entity['modification_date'] = datetime.now() |
39 |
39 |
40 class SetCreatorOp(PreCommitOperation): |
40 class SetCreatorOp(PreCommitOperation): |
41 |
41 |
42 def precommit_event(self): |
42 def precommit_event(self): |
43 if self.eid in self.session.query_data('pendingeids', ()): |
43 if self.eid in self.session.query_data('pendingeids', ()): |
44 # entity have been created and deleted in the same transaction |
44 # entity have been created and deleted in the same transaction |
45 return |
45 return |
46 ueid = self.session.user.eid |
46 ueid = self.session.user.eid |
47 execute = self.session.unsafe_execute |
47 execute = self.session.unsafe_execute |
48 if not execute('Any X WHERE X created_by U, X eid %(x)s', |
48 if not execute('Any X WHERE X created_by U, X eid %(x)s', |
49 {'x': self.eid}, 'x'): |
49 {'x': self.eid}, 'x'): |
50 execute('SET X created_by U WHERE X eid %(x)s, U eid %(u)s', |
50 execute('SET X created_by U WHERE X eid %(x)s, U eid %(u)s', |
51 {'x': self.eid, 'u': ueid}, 'x') |
51 {'x': self.eid, 'u': ueid}, 'x') |
52 |
52 |
53 def setowner_after_add_entity(session, entity): |
53 def setowner_after_add_entity(session, entity): |
54 """create a new entity -> set owner and creator metadata""" |
54 """create a new entity -> set owner and creator metadata""" |
91 entities is necessary. |
91 entities is necessary. |
92 """ |
92 """ |
93 if session.repo.schema.rschema(rtype).fulltext_container: |
93 if session.repo.schema.rschema(rtype).fulltext_container: |
94 FTIndexEntityOp(session, entity=session.entity(eidto)) |
94 FTIndexEntityOp(session, entity=session.entity(eidto)) |
95 FTIndexEntityOp(session, entity=session.entity(eidfrom)) |
95 FTIndexEntityOp(session, entity=session.entity(eidfrom)) |
96 |
96 |
97 class SyncOwnersOp(PreCommitOperation): |
97 class SyncOwnersOp(PreCommitOperation): |
98 |
98 |
99 def precommit_event(self): |
99 def precommit_event(self): |
100 self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,' |
100 self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,' |
101 'NOT EXISTS(X owned_by U, X eid %(x)s)', |
101 'NOT EXISTS(X owned_by U, X eid %(x)s)', |
102 {'c': self.compositeeid, 'x': self.composedeid}, |
102 {'c': self.compositeeid, 'x': self.composedeid}, |
103 ('c', 'x')) |
103 ('c', 'x')) |
104 |
104 |
105 def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto): |
105 def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto): |
106 """when adding composite relation, the composed should have the same owners |
106 """when adding composite relation, the composed should have the same owners |
107 has the composite |
107 has the composite |
108 """ |
108 """ |
109 if rtype == 'wf_info_for': |
109 if rtype == 'wf_info_for': |
112 composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
112 composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
113 if composite == 'subject': |
113 if composite == 'subject': |
114 SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto) |
114 SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto) |
115 elif composite == 'object': |
115 elif composite == 'object': |
116 SyncOwnersOp(session, compositeeid=eidto, composedeid=eidfrom) |
116 SyncOwnersOp(session, compositeeid=eidto, composedeid=eidfrom) |
117 |
117 |
118 def _register_metadata_hooks(hm): |
118 def _register_metadata_hooks(hm): |
119 """register meta-data related hooks on the hooks manager""" |
119 """register meta-data related hooks on the hooks manager""" |
120 hm.register_hook(setctime_before_add_entity, 'before_add_entity', '') |
120 hm.register_hook(setctime_before_add_entity, 'before_add_entity', '') |
121 hm.register_hook(setmtime_before_update_entity, 'before_update_entity', '') |
121 hm.register_hook(setmtime_before_update_entity, 'before_update_entity', '') |
122 hm.register_hook(setowner_after_add_entity, 'after_add_entity', '') |
122 hm.register_hook(setowner_after_add_entity, 'after_add_entity', '') |
125 hm.register_hook(fti_update_after_delete_relation, 'after_delete_relation', '') |
125 hm.register_hook(fti_update_after_delete_relation, 'after_delete_relation', '') |
126 if 'is' in hm.schema: |
126 if 'is' in hm.schema: |
127 hm.register_hook(setis_after_add_entity, 'after_add_entity', '') |
127 hm.register_hook(setis_after_add_entity, 'after_add_entity', '') |
128 if 'CWUser' in hm.schema: |
128 if 'CWUser' in hm.schema: |
129 hm.register_hook(setowner_after_add_user, 'after_add_entity', 'CWUser') |
129 hm.register_hook(setowner_after_add_user, 'after_add_entity', 'CWUser') |
130 |
130 |
131 # core hooks ################################################################## |
131 # core hooks ################################################################## |
132 |
132 |
133 class DelayedDeleteOp(PreCommitOperation): |
133 class DelayedDeleteOp(PreCommitOperation): |
134 """delete the object of composite relation except if the relation |
134 """delete the object of composite relation except if the relation |
135 has actually been redirected to another composite |
135 has actually been redirected to another composite |
136 """ |
136 """ |
137 |
137 |
138 def precommit_event(self): |
138 def precommit_event(self): |
139 session = self.session |
139 session = self.session |
140 if not self.eid in session.query_data('pendingeids', ()): |
140 if not self.eid in session.query_data('pendingeids', ()): |
141 etype = session.describe(self.eid)[0] |
141 etype = session.describe(self.eid)[0] |
142 session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s' |
142 session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s' |
143 % (etype, self.relation), |
143 % (etype, self.relation), |
144 {'x': self.eid}, 'x') |
144 {'x': self.eid}, 'x') |
145 |
145 |
146 def handle_composite_before_del_relation(session, eidfrom, rtype, eidto): |
146 def handle_composite_before_del_relation(session, eidfrom, rtype, eidto): |
147 """delete the object of composite relation""" |
147 """delete the object of composite relation""" |
148 composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
148 composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
149 if composite == 'subject': |
149 if composite == 'subject': |
150 DelayedDeleteOp(session, eid=eidto, relation='Y %s X' % rtype) |
150 DelayedDeleteOp(session, eid=eidto, relation='Y %s X' % rtype) |
155 """check that we don't remove the owners group""" |
155 """check that we don't remove the owners group""" |
156 check_internal_entity(session, eid, ('owners',)) |
156 check_internal_entity(session, eid, ('owners',)) |
157 |
157 |
158 |
158 |
159 # schema validation hooks ##################################################### |
159 # schema validation hooks ##################################################### |
160 |
160 |
161 class CheckConstraintsOperation(LateOperation): |
161 class CheckConstraintsOperation(LateOperation): |
162 """check a new relation satisfy its constraints |
162 """check a new relation satisfy its constraints |
163 """ |
163 """ |
164 def precommit_event(self): |
164 def precommit_event(self): |
165 eidfrom, rtype, eidto = self.rdef |
165 eidfrom, rtype, eidto = self.rdef |
174 try: |
174 try: |
175 constraint.repo_check(self.session, eidfrom, rtype, eidto) |
175 constraint.repo_check(self.session, eidfrom, rtype, eidto) |
176 except NotImplementedError: |
176 except NotImplementedError: |
177 self.critical('can\'t check constraint %s, not supported', |
177 self.critical('can\'t check constraint %s, not supported', |
178 constraint) |
178 constraint) |
179 |
179 |
180 def commit_event(self): |
180 def commit_event(self): |
181 pass |
181 pass |
182 |
182 |
183 def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto): |
183 def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto): |
184 """check the relation satisfy its constraints |
184 """check the relation satisfy its constraints |
185 |
185 |
186 this is delayed to a precommit time operation since other relation which |
186 this is delayed to a precommit time operation since other relation which |
187 will make constraint satisfied may be added later. |
187 will make constraint satisfied may be added later. |
211 class CheckRequiredRelationOperation(LateOperation): |
211 class CheckRequiredRelationOperation(LateOperation): |
212 """checking relation cardinality has to be done after commit in |
212 """checking relation cardinality has to be done after commit in |
213 case the relation is being replaced |
213 case the relation is being replaced |
214 """ |
214 """ |
215 eid, rtype = None, None |
215 eid, rtype = None, None |
216 |
216 |
217 def precommit_event(self): |
217 def precommit_event(self): |
218 # recheck pending eids |
218 # recheck pending eids |
219 if self.eid in self.session.query_data('pendingeids', ()): |
219 if self.eid in self.session.query_data('pendingeids', ()): |
220 return |
220 return |
221 if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
221 if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
222 etype = self.session.describe(self.eid)[0] |
222 etype = self.session.describe(self.eid)[0] |
223 msg = self.session._('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
223 msg = self.session._('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
224 raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype, |
224 raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype, |
225 'etype': etype, |
225 'etype': etype, |
226 'eid': self.eid}}) |
226 'eid': self.eid}}) |
227 |
227 |
228 def commit_event(self): |
228 def commit_event(self): |
229 pass |
229 pass |
230 |
230 |
231 def _rql(self): |
231 def _rql(self): |
232 raise NotImplementedError() |
232 raise NotImplementedError() |
233 |
233 |
234 class CheckSRelationOp(CheckRequiredRelationOperation): |
234 class CheckSRelationOp(CheckRequiredRelationOperation): |
235 """check required subject relation""" |
235 """check required subject relation""" |
236 def _rql(self): |
236 def _rql(self): |
237 return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
237 return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
238 |
238 |
239 class CheckORelationOp(CheckRequiredRelationOperation): |
239 class CheckORelationOp(CheckRequiredRelationOperation): |
240 """check required object relation""" |
240 """check required object relation""" |
241 def _rql(self): |
241 def _rql(self): |
242 return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
242 return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
243 |
243 |
246 for op in session.pending_operations: |
246 for op in session.pending_operations: |
247 if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
247 if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
248 break |
248 break |
249 else: |
249 else: |
250 opcls(session, rtype=rtype, eid=eid) |
250 opcls(session, rtype=rtype, eid=eid) |
251 |
251 |
252 def cardinalitycheck_after_add_entity(session, entity): |
252 def cardinalitycheck_after_add_entity(session, entity): |
253 """check cardinalities are satisfied""" |
253 """check cardinalities are satisfied""" |
254 eid = entity.eid |
254 eid = entity.eid |
255 for rschema, targetschemas, x in entity.e_schema.relation_definitions(): |
255 for rschema, targetschemas, x in entity.e_schema.relation_definitions(): |
256 # skip automatically handled relations |
256 # skip automatically handled relations |
281 |
281 |
282 |
282 |
283 def _register_core_hooks(hm): |
283 def _register_core_hooks(hm): |
284 hm.register_hook(handle_composite_before_del_relation, 'before_delete_relation', '') |
284 hm.register_hook(handle_composite_before_del_relation, 'before_delete_relation', '') |
285 hm.register_hook(before_del_group, 'before_delete_entity', 'CWGroup') |
285 hm.register_hook(before_del_group, 'before_delete_entity', 'CWGroup') |
286 |
286 |
287 #hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '') |
287 #hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '') |
288 hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '') |
288 hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '') |
289 hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '') |
289 hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '') |
290 hm.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '') |
290 hm.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '') |
291 hm.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '') |
291 hm.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '') |
292 hm.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '') |
292 hm.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '') |
293 |
293 |
294 |
294 |
295 # user/groups synchronisation ################################################# |
295 # user/groups synchronisation ################################################# |
296 |
296 |
297 class GroupOperation(Operation): |
297 class GroupOperation(Operation): |
298 """base class for group operation""" |
298 """base class for group operation""" |
299 geid = None |
299 geid = None |
300 def __init__(self, session, *args, **kwargs): |
300 def __init__(self, session, *args, **kwargs): |
301 """override to get the group name before actual groups manipulation: |
301 """override to get the group name before actual groups manipulation: |
302 |
302 |
303 we may temporarily loose right access during a commit event, so |
303 we may temporarily loose right access during a commit event, so |
304 no query should be emitted while comitting |
304 no query should be emitted while comitting |
305 """ |
305 """ |
306 rql = 'Any N WHERE G eid %(x)s, G name N' |
306 rql = 'Any N WHERE G eid %(x)s, G name N' |
307 result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False) |
307 result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False) |
316 try: |
316 try: |
317 groups.remove(self.group) |
317 groups.remove(self.group) |
318 except KeyError: |
318 except KeyError: |
319 self.error('user %s not in group %s', self.cnxuser, self.group) |
319 self.error('user %s not in group %s', self.cnxuser, self.group) |
320 return |
320 return |
321 |
321 |
322 def after_del_in_group(session, fromeid, rtype, toeid): |
322 def after_del_in_group(session, fromeid, rtype, toeid): |
323 """modify user permission, need to update users""" |
323 """modify user permission, need to update users""" |
324 for session_ in get_user_sessions(session.repo, fromeid): |
324 for session_ in get_user_sessions(session.repo, fromeid): |
325 DeleteGroupOp(session, cnxuser=session_.user, geid=toeid) |
325 DeleteGroupOp(session, cnxuser=session_.user, geid=toeid) |
326 |
326 |
327 |
327 |
328 class AddGroupOp(GroupOperation): |
328 class AddGroupOp(GroupOperation): |
329 """synchronize user when a in_group relation has been added""" |
329 """synchronize user when a in_group relation has been added""" |
330 def commit_event(self): |
330 def commit_event(self): |
331 """the observed connections pool has been commited""" |
331 """the observed connections pool has been commited""" |
332 groups = self.cnxuser.groups |
332 groups = self.cnxuser.groups |
345 class DelUserOp(Operation): |
345 class DelUserOp(Operation): |
346 """synchronize user when a in_group relation has been added""" |
346 """synchronize user when a in_group relation has been added""" |
347 def __init__(self, session, cnxid): |
347 def __init__(self, session, cnxid): |
348 self.cnxid = cnxid |
348 self.cnxid = cnxid |
349 Operation.__init__(self, session) |
349 Operation.__init__(self, session) |
350 |
350 |
351 def commit_event(self): |
351 def commit_event(self): |
352 """the observed connections pool has been commited""" |
352 """the observed connections pool has been commited""" |
353 try: |
353 try: |
354 self.repo.close(self.cnxid) |
354 self.repo.close(self.cnxid) |
355 except BadConnectionId: |
355 except BadConnectionId: |
357 |
357 |
358 def after_del_user(session, eid): |
358 def after_del_user(session, eid): |
359 """modify user permission, need to update users""" |
359 """modify user permission, need to update users""" |
360 for session_ in get_user_sessions(session.repo, eid): |
360 for session_ in get_user_sessions(session.repo, eid): |
361 DelUserOp(session, session_.id) |
361 DelUserOp(session, session_.id) |
362 |
362 |
363 def _register_usergroup_hooks(hm): |
363 def _register_usergroup_hooks(hm): |
364 """register user/group related hooks on the hooks manager""" |
364 """register user/group related hooks on the hooks manager""" |
365 hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser') |
365 hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser') |
366 hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group') |
366 hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group') |
367 hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group') |
367 hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group') |
428 {'x' : entity.eid, 's' : rset[0][0]}, 'x') |
428 {'x' : entity.eid, 's' : rset[0][0]}, 'x') |
429 |
429 |
430 |
430 |
431 def set_initial_state_after_add(session, entity): |
431 def set_initial_state_after_add(session, entity): |
432 SetInitialStateOp(session, entity=entity) |
432 SetInitialStateOp(session, entity=entity) |
433 |
433 |
434 def _register_wf_hooks(hm): |
434 def _register_wf_hooks(hm): |
435 """register workflow related hooks on the hooks manager""" |
435 """register workflow related hooks on the hooks manager""" |
436 if 'in_state' in hm.schema: |
436 if 'in_state' in hm.schema: |
437 hm.register_hook(before_add_in_state, 'before_add_relation', 'in_state') |
437 hm.register_hook(before_add_in_state, 'before_add_relation', 'in_state') |
438 hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state') |
438 hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state') |
445 # CWProperty hooks ############################################################# |
445 # CWProperty hooks ############################################################# |
446 |
446 |
447 |
447 |
448 class DelCWPropertyOp(Operation): |
448 class DelCWPropertyOp(Operation): |
449 """a user's custom properties has been deleted""" |
449 """a user's custom properties has been deleted""" |
450 |
450 |
451 def commit_event(self): |
451 def commit_event(self): |
452 """the observed connections pool has been commited""" |
452 """the observed connections pool has been commited""" |
453 try: |
453 try: |
454 del self.epropdict[self.key] |
454 del self.epropdict[self.key] |
455 except KeyError: |
455 except KeyError: |
456 self.error('%s has no associated value', self.key) |
456 self.error('%s has no associated value', self.key) |
457 |
457 |
458 class ChangeCWPropertyOp(Operation): |
458 class ChangeCWPropertyOp(Operation): |
459 """a user's custom properties has been added/changed""" |
459 """a user's custom properties has been added/changed""" |
460 |
460 |
461 def commit_event(self): |
461 def commit_event(self): |
462 """the observed connections pool has been commited""" |
462 """the observed connections pool has been commited""" |
463 self.epropdict[self.key] = self.value |
463 self.epropdict[self.key] = self.value |
464 |
464 |
465 class AddCWPropertyOp(Operation): |
465 class AddCWPropertyOp(Operation): |
466 """a user's custom properties has been added/changed""" |
466 """a user's custom properties has been added/changed""" |
467 |
467 |
468 def commit_event(self): |
468 def commit_event(self): |
469 """the observed connections pool has been commited""" |
469 """the observed connections pool has been commited""" |
470 eprop = self.eprop |
470 eprop = self.eprop |
471 if not eprop.for_user: |
471 if not eprop.for_user: |
472 self.repo.vreg.eprop_values[eprop.pkey] = eprop.value |
472 self.repo.vreg.eprop_values[eprop.pkey] = eprop.value |
483 if not session.user.matching_groups('managers'): |
483 if not session.user.matching_groups('managers'): |
484 session.unsafe_execute('SET P for_user U WHERE P eid %(x)s,U eid %(u)s', |
484 session.unsafe_execute('SET P for_user U WHERE P eid %(x)s,U eid %(u)s', |
485 {'x': entity.eid, 'u': session.user.eid}, 'x') |
485 {'x': entity.eid, 'u': session.user.eid}, 'x') |
486 else: |
486 else: |
487 AddCWPropertyOp(session, eprop=entity) |
487 AddCWPropertyOp(session, eprop=entity) |
488 |
488 |
489 def after_update_eproperty(session, entity): |
489 def after_update_eproperty(session, entity): |
490 key, value = entity.pkey, entity.value |
490 key, value = entity.pkey, entity.value |
491 try: |
491 try: |
492 value = session.vreg.typed_value(key, value) |
492 value = session.vreg.typed_value(key, value) |
493 except UnknownProperty: |
493 except UnknownProperty: |
500 key=key, value=value) |
500 key=key, value=value) |
501 else: |
501 else: |
502 # site wide properties |
502 # site wide properties |
503 ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values, |
503 ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values, |
504 key=key, value=value) |
504 key=key, value=value) |
505 |
505 |
506 def before_del_eproperty(session, eid): |
506 def before_del_eproperty(session, eid): |
507 for eidfrom, rtype, eidto in session.query_data('pendingrelations', ()): |
507 for eidfrom, rtype, eidto in session.query_data('pendingrelations', ()): |
508 if rtype == 'for_user' and eidfrom == eid: |
508 if rtype == 'for_user' and eidfrom == eid: |
509 # if for_user was set, delete has already been handled |
509 # if for_user was set, delete has already been handled |
510 break |
510 break |
522 raise ValidationError(fromeid, |
522 raise ValidationError(fromeid, |
523 {'for_user': session._("site-wide property can't be set for user")}) |
523 {'for_user': session._("site-wide property can't be set for user")}) |
524 for session_ in get_user_sessions(session.repo, toeid): |
524 for session_ in get_user_sessions(session.repo, toeid): |
525 ChangeCWPropertyOp(session, epropdict=session_.user.properties, |
525 ChangeCWPropertyOp(session, epropdict=session_.user.properties, |
526 key=key, value=value) |
526 key=key, value=value) |
527 |
527 |
528 def before_del_for_user(session, fromeid, rtype, toeid): |
528 def before_del_for_user(session, fromeid, rtype, toeid): |
529 key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |
529 key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |
530 {'x': fromeid}, 'x')[0][0] |
530 {'x': fromeid}, 'x')[0][0] |
531 relation_deleted(session, fromeid, rtype, toeid) |
531 relation_deleted(session, fromeid, rtype, toeid) |
532 for session_ in get_user_sessions(session.repo, toeid): |
532 for session_ in get_user_sessions(session.repo, toeid): |