cubicweb/hooks/syncsession.py
changeset 11348 70337ad23145
parent 11129 97095348b3ee
child 11699 b48020a80dc3
equal deleted inserted replaced
11347:b4dcfd734686 11348:70337ad23145
     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)