hooks/syncsession.py
changeset 2841 107ba1c45227
parent 2835 04034421b072
child 2847 c2ee28f4d4b1
equal deleted inserted replaced
2840:06daf13195d4 2841:107ba1c45227
     7 """
     7 """
     8 __docformat__ = "restructuredtext en"
     8 __docformat__ = "restructuredtext en"
     9 
     9 
    10 from cubicweb import UnknownProperty, ValidationError, BadConnectionId
    10 from cubicweb import UnknownProperty, ValidationError, BadConnectionId
    11 from cubicweb.selectors import entity_implements
    11 from cubicweb.selectors import entity_implements
    12 from cubicweb.server.hook import Hook, match_rtype
    12 from cubicweb.server import hook
    13 from cubicweb.server.pool import Operation
    13 
    14 from cubicweb.server.hookhelper import get_user_sessions
    14 
       
    15 def get_user_sessions(repo, ueid):
       
    16     for session in repo._sessions.values():
       
    17         if ueid == session.user.eid:
       
    18             yield session
       
    19 
       
    20 
       
    21 class SyncSessionHook(hook.Hook):
       
    22     __abstract__ = True
       
    23     category = 'syncsession'
    15 
    24 
    16 
    25 
    17 # user/groups synchronisation #################################################
    26 # user/groups synchronisation #################################################
    18 
    27 
    19 class _GroupOperation(Operation):
    28 class _GroupOperation(hook.Operation):
    20     """base class for group operation"""
    29     """base class for group operation"""
    21     geid = None
    30     geid = None
    22     def __init__(self, session, *args, **kwargs):
    31     def __init__(self, session, *args, **kwargs):
    23         """override to get the group name before actual groups manipulation:
    32         """override to get the group name before actual groups manipulation:
    24 
    33 
    25         we may temporarily loose right access during a commit event, so
    34         we may temporarily loose right access during a commit event, so
    26         no query should be emitted while comitting
    35         no query should be emitted while comitting
    27         """
    36         """
    28         rql = 'Any N WHERE G eid %(x)s, G name N'
    37         rql = 'Any N WHERE G eid %(x)s, G name N'
    29         result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False)
    38         result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False)
    30         Operation.__init__(self, session, *args, **kwargs)
    39         hook.Operation.__init__(self, session, *args, **kwargs)
    31         self.group = result[0][0]
    40         self.group = result[0][0]
    32 
    41 
    33 
    42 
    34 class _DeleteGroupOp(_GroupOperation):
    43 class _DeleteGroupOp(_GroupOperation):
    35     """synchronize user when a in_group relation has been deleted"""
    44     """synchronize user when a in_group relation has been deleted"""
    53                          self.group)
    62                          self.group)
    54             return
    63             return
    55         groups.add(self.group)
    64         groups.add(self.group)
    56 
    65 
    57 
    66 
    58 class SyncInGroupHook(Hook):
    67 class SyncInGroupHook(SyncSessionHook):
    59     __id__ = 'syncingroup'
    68     __id__ = 'syncingroup'
    60     __select__ = Hook.__select__ & match_rtype('in_group')
    69     __select__ = SyncSessionHook.__select__ & hook.match_rtype('in_group')
    61     events = ('after_delete_relation', 'after_add_relation')
    70     events = ('after_delete_relation', 'after_add_relation')
    62     category = 'syncsession'
       
    63 
    71 
    64     def __call__(self):
    72     def __call__(self):
    65         if self.event == 'after_delete_relation':
    73         if self.event == 'after_delete_relation':
    66             opcls = _DeleteGroupOp
    74             opcls = _DeleteGroupOp
    67         else:
    75         else:
    68             opcls = _AddGroupOp
    76             opcls = _AddGroupOp
    69         for session in get_user_sessions(self.cw_req.repo, self.eidfrom):
    77         for session in get_user_sessions(self.cw_req.repo, self.eidfrom):
    70             opcls(self.cw_req, cnxuser=session.user, geid=self.eidto)
    78             opcls(self.cw_req, cnxuser=session.user, geid=self.eidto)
    71 
    79 
    72 
    80 
    73 class _DelUserOp(Operation):
    81 class _DelUserOp(hook.Operation):
    74     """close associated user's session when it is deleted"""
    82     """close associated user's session when it is deleted"""
    75     def __init__(self, session, cnxid):
    83     def __init__(self, session, cnxid):
    76         self.cnxid = cnxid
    84         self.cnxid = cnxid
    77         Operation.__init__(self, session)
    85         hook.Operation.__init__(self, session)
    78 
    86 
    79     def commit_event(self):
    87     def commit_event(self):
    80         """the observed connections pool has been commited"""
    88         """the observed connections pool has been commited"""
    81         try:
    89         try:
    82             self.repo.close(self.cnxid)
    90             self.repo.close(self.cnxid)
    83         except BadConnectionId:
    91         except BadConnectionId:
    84             pass # already closed
    92             pass # already closed
    85 
    93 
    86 
    94 
    87 class CloseDeletedUserSessionsHook(Hook):
    95 class CloseDeletedUserSessionsHook(SyncSessionHook):
    88     __id__ = 'closession'
    96     __id__ = 'closession'
    89     __select__ = Hook.__select__ & entity_implements('CWUser')
    97     __select__ = SyncSessionHook.__select__ & entity_implements('CWUser')
    90     events = ('after_delete_entity',)
    98     events = ('after_delete_entity',)
    91     category = 'syncsession'
       
    92 
    99 
    93     def __call__(self):
   100     def __call__(self):
    94         """modify user permission, need to update users"""
   101         """modify user permission, need to update users"""
    95         for session in get_user_sessions(self.cw_req.repo, self.entity.eid):
   102         for session in get_user_sessions(self.cw_req.repo, self.entity.eid):
    96             _DelUserOp(self.cw_req, session.id)
   103             _DelUserOp(self.cw_req, session.id)
    97 
   104 
    98 
   105 
    99 # CWProperty hooks #############################################################
   106 # CWProperty hooks #############################################################
   100 
   107 
   101 
   108 
   102 class _DelCWPropertyOp(Operation):
   109 class _DelCWPropertyOp(hook.Operation):
   103     """a user's custom properties has been deleted"""
   110     """a user's custom properties has been deleted"""
   104 
   111 
   105     def commit_event(self):
   112     def commit_event(self):
   106         """the observed connections pool has been commited"""
   113         """the observed connections pool has been commited"""
   107         try:
   114         try:
   108             del self.epropdict[self.key]
   115             del self.epropdict[self.key]
   109         except KeyError:
   116         except KeyError:
   110             self.error('%s has no associated value', self.key)
   117             self.error('%s has no associated value', self.key)
   111 
   118 
   112 
   119 
   113 class _ChangeCWPropertyOp(Operation):
   120 class _ChangeCWPropertyOp(hook.Operation):
   114     """a user's custom properties has been added/changed"""
   121     """a user's custom properties has been added/changed"""
   115 
   122 
   116     def commit_event(self):
   123     def commit_event(self):
   117         """the observed connections pool has been commited"""
   124         """the observed connections pool has been commited"""
   118         self.epropdict[self.key] = self.value
   125         self.epropdict[self.key] = self.value
   119 
   126 
   120 
   127 
   121 class _AddCWPropertyOp(Operation):
   128 class _AddCWPropertyOp(hook.Operation):
   122     """a user's custom properties has been added/changed"""
   129     """a user's custom properties has been added/changed"""
   123 
   130 
   124     def commit_event(self):
   131     def commit_event(self):
   125         """the observed connections pool has been commited"""
   132         """the observed connections pool has been commited"""
   126         eprop = self.eprop
   133         eprop = self.eprop
   127         if not eprop.for_user:
   134         if not eprop.for_user:
   128             self.repo.vreg.eprop_values[eprop.pkey] = eprop.value
   135             self.repo.vreg.eprop_values[eprop.pkey] = eprop.value
   129         # if for_user is set, update is handled by a ChangeCWPropertyOp operation
   136         # if for_user is set, update is handled by a ChangeCWPropertyOp operation
   130 
   137 
   131 
   138 
   132 class AddCWPropertyHook(Hook):
   139 class AddCWPropertyHook(SyncSessionHook):
   133     __id__ = 'addcwprop'
   140     __id__ = 'addcwprop'
   134     __select__ = Hook.__select__ & entity_implements('CWProperty')
   141     __select__ = SyncSessionHook.__select__ & entity_implements('CWProperty')
   135     category = 'syncsession'
       
   136     events = ('after_add_entity',)
   142     events = ('after_add_entity',)
   137 
   143 
   138     def __call__(self):
   144     def __call__(self):
   139         key, value = self.entity.pkey, self.entity.value
   145         key, value = self.entity.pkey, self.entity.value
   140         session = self.cw_req
   146         session = self.cw_req
   192                 break
   198                 break
   193         else:
   199         else:
   194             _DelCWPropertyOp(session, epropdict=session.vreg.eprop_values, key=entity.pkey)
   200             _DelCWPropertyOp(session, epropdict=session.vreg.eprop_values, key=entity.pkey)
   195 
   201 
   196 
   202 
   197 class AddForUserRelationHook(Hook):
   203 class AddForUserRelationHook(SyncSessionHook):
   198     __id__ = 'addcwpropforuser'
   204     __id__ = 'addcwpropforuser'
   199     __select__ = Hook.__select__ & match_rtype('for_user')
   205     __select__ = SyncSessionHook.__select__ & hook.match_rtype('for_user')
   200     events = ('after_add_relation',)
   206     events = ('after_add_relation',)
   201     category = 'syncsession'
       
   202 
   207 
   203     def __call__(self):
   208     def __call__(self):
   204         session = self.cw_req
   209         session = self.cw_req
   205         eidfrom = self.eidfrom
   210         eidfrom = self.eidfrom
   206         if not session.describe(eidfrom)[0] == 'CWProperty':
   211         if not session.describe(eidfrom)[0] == 'CWProperty':