1 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
1 # copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # |
3 # |
4 # This file is part of CubicWeb. |
4 # This file is part of CubicWeb. |
5 # |
5 # |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
6 # CubicWeb is free software: you can redistribute it and/or modify it under the |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """Core hooks: synchronize living session on persistent data changes""" |
18 """Core hooks: synchronize living session on persistent data changes""" |
19 |
19 |
20 __docformat__ = "restructuredtext en" |
20 __docformat__ = "restructuredtext en" |
|
21 |
21 from cubicweb import _ |
22 from cubicweb import _ |
22 |
|
23 from cubicweb import UnknownProperty, BadConnectionId, validation_error |
23 from cubicweb import UnknownProperty, BadConnectionId, validation_error |
24 from cubicweb.predicates import is_instance |
24 from cubicweb.predicates import is_instance |
25 from cubicweb.server import hook |
25 from cubicweb.server import hook |
26 |
26 |
27 |
27 |
53 hook.Operation.__init__(self, cnx, *args, **kwargs) |
53 hook.Operation.__init__(self, cnx, *args, **kwargs) |
54 self.group = result[0][0] |
54 self.group = result[0][0] |
55 |
55 |
56 |
56 |
57 class _DeleteGroupOp(_GroupOperation): |
57 class _DeleteGroupOp(_GroupOperation): |
58 """synchronize user when a in_group relation has been deleted""" |
58 """Synchronize user when a in_group relation has been deleted""" |
59 |
59 |
60 def postcommit_event(self): |
60 def postcommit_event(self): |
61 """the observed connections set has been commited""" |
61 """the observed connections set has been commited""" |
62 groups = self.cnxuser.groups |
62 groups = self.cnxuser.groups |
63 try: |
63 try: |
65 except KeyError: |
65 except KeyError: |
66 self.error('user %s not in group %s', self.cnxuser, self.group) |
66 self.error('user %s not in group %s', self.cnxuser, self.group) |
67 |
67 |
68 |
68 |
69 class _AddGroupOp(_GroupOperation): |
69 class _AddGroupOp(_GroupOperation): |
70 """synchronize user when a in_group relation has been added""" |
70 """Synchronize user when a in_group relation has been added""" |
|
71 |
71 def postcommit_event(self): |
72 def postcommit_event(self): |
72 """the observed connections set has been commited""" |
73 """the observed connections set has been commited""" |
73 groups = self.cnxuser.groups |
74 groups = self.cnxuser.groups |
74 if self.group in groups: |
75 if self.group in groups: |
75 self.warning('user %s already in group %s', self.cnxuser, |
76 self.warning('user %s already in group %s', self.cnxuser, |
77 else: |
78 else: |
78 groups.add(self.group) |
79 groups.add(self.group) |
79 |
80 |
80 |
81 |
81 class SyncInGroupHook(SyncSessionHook): |
82 class SyncInGroupHook(SyncSessionHook): |
|
83 """Watch addition/removal of in_group relation to synchronize living sessions accordingly""" |
82 __regid__ = 'syncingroup' |
84 __regid__ = 'syncingroup' |
83 __select__ = SyncSessionHook.__select__ & hook.match_rtype('in_group') |
85 __select__ = SyncSessionHook.__select__ & hook.match_rtype('in_group') |
84 events = ('after_delete_relation', 'after_add_relation') |
86 events = ('after_delete_relation', 'after_add_relation') |
85 |
87 |
86 def __call__(self): |
88 def __call__(self): |
97 def __init__(self, cnx, sessionid): |
99 def __init__(self, cnx, sessionid): |
98 self.sessionid = sessionid |
100 self.sessionid = sessionid |
99 hook.Operation.__init__(self, cnx) |
101 hook.Operation.__init__(self, cnx) |
100 |
102 |
101 def postcommit_event(self): |
103 def postcommit_event(self): |
102 """the observed connections set has been commited""" |
|
103 try: |
104 try: |
104 self.cnx.repo.close(self.sessionid) |
105 self.cnx.repo.close(self.sessionid) |
105 except BadConnectionId: |
106 except BadConnectionId: |
106 pass # already closed |
107 pass # already closed |
107 |
108 |
108 |
109 |
109 class CloseDeletedUserSessionsHook(SyncSessionHook): |
110 class CloseDeletedUserSessionsHook(SyncSessionHook): |
110 __regid__ = 'closession' |
111 __regid__ = 'closession' |
111 __select__ = SyncSessionHook.__select__ & is_instance('CWUser') |
112 __select__ = SyncSessionHook.__select__ & is_instance('CWUser') |
112 events = ('after_delete_entity',) |
113 events = ('after_delete_entity',) |
113 |
114 |
114 def __call__(self): |
115 def __call__(self): |
115 """modify user permission, need to update users""" |
|
116 for session in get_user_sessions(self._cw.repo, self.entity.eid): |
116 for session in get_user_sessions(self._cw.repo, self.entity.eid): |
117 _DelUserOp(self._cw, session.sessionid) |
117 _DelUserOp(self._cw, session.sessionid) |
118 |
118 |
119 |
119 |
120 # CWProperty hooks ############################################################# |
120 # CWProperty hooks ############################################################# |
209 class DeleteCWPropertyHook(AddCWPropertyHook): |
209 class DeleteCWPropertyHook(AddCWPropertyHook): |
210 __regid__ = 'delcwprop' |
210 __regid__ = 'delcwprop' |
211 events = ('before_delete_entity',) |
211 events = ('before_delete_entity',) |
212 |
212 |
213 def __call__(self): |
213 def __call__(self): |
214 eid = self.entity.eid |
|
215 cnx = self._cw |
214 cnx = self._cw |
216 for eidfrom, rtype, eidto in cnx.transaction_data.get('pendingrelations', ()): |
215 for eidfrom, rtype, eidto in cnx.transaction_data.get('pendingrelations', ()): |
217 if rtype == 'for_user' and eidfrom == self.entity.eid: |
216 if rtype == 'for_user' and eidfrom == self.entity.eid: |
218 # if for_user was set, delete has already been handled |
217 # if for_user was set, delete already handled by hook on for_user deletion |
219 break |
218 break |
220 else: |
219 else: |
221 _DelCWPropertyOp(cnx, cwpropdict=cnx.vreg['propertyvalues'], |
220 _DelCWPropertyOp(cnx, cwpropdict=cnx.vreg['propertyvalues'], |
222 key=self.entity.pkey) |
221 key=self.entity.pkey) |
223 |
222 |
231 cnx = self._cw |
230 cnx = self._cw |
232 eidfrom = self.eidfrom |
231 eidfrom = self.eidfrom |
233 if not cnx.entity_metas(eidfrom)['type'] == 'CWProperty': |
232 if not cnx.entity_metas(eidfrom)['type'] == 'CWProperty': |
234 return |
233 return |
235 key, value = cnx.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V', |
234 key, value = cnx.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V', |
236 {'x': eidfrom})[0] |
235 {'x': eidfrom})[0] |
237 if cnx.vreg.property_info(key)['sitewide']: |
236 if cnx.vreg.property_info(key)['sitewide']: |
238 msg = _("site-wide property can't be set for user") |
237 msg = _("site-wide property can't be set for user") |
239 raise validation_error(eidfrom, {('for_user', 'subject'): msg}) |
238 raise validation_error(eidfrom, {('for_user', 'subject'): msg}) |
240 for session in get_user_sessions(cnx.repo, self.eidto): |
239 for session in get_user_sessions(cnx.repo, self.eidto): |
241 _ChangeCWPropertyOp(cnx, cwpropdict=session.user.properties, |
240 _ChangeCWPropertyOp(cnx, cwpropdict=session.user.properties, |
246 __regid__ = 'delcwpropforuser' |
245 __regid__ = 'delcwpropforuser' |
247 events = ('after_delete_relation',) |
246 events = ('after_delete_relation',) |
248 |
247 |
249 def __call__(self): |
248 def __call__(self): |
250 cnx = self._cw |
249 cnx = self._cw |
251 key = cnx.execute('Any K WHERE P eid %(x)s, P pkey K', |
250 key = cnx.execute('Any K WHERE P eid %(x)s, P pkey K', {'x': self.eidfrom})[0][0] |
252 {'x': self.eidfrom})[0][0] |
|
253 cnx.transaction_data.setdefault('pendingrelations', []).append( |
251 cnx.transaction_data.setdefault('pendingrelations', []).append( |
254 (self.eidfrom, self.rtype, self.eidto)) |
252 (self.eidfrom, self.rtype, self.eidto)) |
255 for session in get_user_sessions(cnx.repo, self.eidto): |
253 for session in get_user_sessions(cnx.repo, self.eidto): |
256 _DelCWPropertyOp(cnx, cwpropdict=session.user.properties, key=key) |
254 _DelCWPropertyOp(cnx, cwpropdict=session.user.properties, key=key) |