[dbapi] retire repository transaction methods which were used by the dbapi
Related to #3933480.
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""Core hooks: synchronize living session on persistent data changes"""__docformat__="restructuredtext en"_=unicodefromcubicwebimportUnknownProperty,BadConnectionId,validation_errorfromcubicweb.predicatesimportis_instancefromcubicweb.serverimporthookdefget_user_sessions(repo,ueid):forsessioninrepo._sessions.itervalues():ifueid==session.user.eid:yieldsessionclassSyncSessionHook(hook.Hook):__abstract__=Truecategory='syncsession'# user/groups synchronisation #################################################class_GroupOperation(hook.Operation):"""base class for group operation"""cnxuser=None# make pylint happydef__init__(self,cnx,*args,**kwargs):"""override to get the group name before actual groups manipulation: we may temporarily loose right access during a commit event, so no query should be emitted while comitting """rql='Any N WHERE G eid %(x)s, G name N'result=cnx.execute(rql,{'x':kwargs['geid']},build_descr=False)hook.Operation.__init__(self,cnx,*args,**kwargs)self.group=result[0][0]class_DeleteGroupOp(_GroupOperation):"""synchronize user when a in_group relation has been deleted"""defpostcommit_event(self):"""the observed connections set has been commited"""groups=self.cnxuser.groupstry:groups.remove(self.group)exceptKeyError:self.error('user %s not in group %s',self.cnxuser,self.group)class_AddGroupOp(_GroupOperation):"""synchronize user when a in_group relation has been added"""defpostcommit_event(self):"""the observed connections set has been commited"""groups=self.cnxuser.groupsifself.groupingroups:self.warning('user %s already in group %s',self.cnxuser,self.group)else:groups.add(self.group)classSyncInGroupHook(SyncSessionHook):__regid__='syncingroup'__select__=SyncSessionHook.__select__&hook.match_rtype('in_group')events=('after_delete_relation','after_add_relation')def__call__(self):ifself.event=='after_delete_relation':opcls=_DeleteGroupOpelse:opcls=_AddGroupOpforsessioninget_user_sessions(self._cw.repo,self.eidfrom):opcls(self._cw,cnxuser=session.user,geid=self.eidto)class_DelUserOp(hook.Operation):"""close associated user's session when it is deleted"""def__init__(self,cnx,sessionid):self.sessionid=sessionidhook.Operation.__init__(self,cnx)defpostcommit_event(self):"""the observed connections set has been commited"""try:self.cnx.repo.close(self.sessionid)exceptBadConnectionId:pass# already closedclassCloseDeletedUserSessionsHook(SyncSessionHook):__regid__='closession'__select__=SyncSessionHook.__select__&is_instance('CWUser')events=('after_delete_entity',)def__call__(self):"""modify user permission, need to update users"""forsessioninget_user_sessions(self._cw.repo,self.entity.eid):_DelUserOp(self._cw,session.id)# CWProperty hooks #############################################################class_DelCWPropertyOp(hook.Operation):"""a user's custom properties has been deleted"""cwpropdict=key=None# make pylint happydefpostcommit_event(self):"""the observed connections set has been commited"""try:delself.cwpropdict[self.key]exceptKeyError:self.error('%s has no associated value',self.key)class_ChangeCWPropertyOp(hook.Operation):"""a user's custom properties has been added/changed"""cwpropdict=key=value=None# make pylint happydefpostcommit_event(self):"""the observed connections set has been commited"""self.cwpropdict[self.key]=self.valueclass_AddCWPropertyOp(hook.Operation):"""a user's custom properties has been added/changed"""cwprop=None# make pylint happydefpostcommit_event(self):"""the observed connections set has been commited"""cwprop=self.cwpropifnotcwprop.for_user:self.cnx.vreg['propertyvalues'][cwprop.pkey]=cwprop.value# if for_user is set, update is handled by a ChangeCWPropertyOp operationclassAddCWPropertyHook(SyncSessionHook):__regid__='addcwprop'__select__=SyncSessionHook.__select__&is_instance('CWProperty')events=('after_add_entity',)def__call__(self):key,value=self.entity.pkey,self.entity.valueifkey.startswith('sources.'):returncnx=self._cwtry:value=cnx.vreg.typed_value(key,value)exceptUnknownProperty:msg=_('unknown property key %s')raisevalidation_error(self.entity,{('pkey','subject'):msg},(key,))exceptValueErrorasex:raisevalidation_error(self.entity,{('value','subject'):str(ex)})ifnotcnx.user.matching_groups('managers'):cnx.add_relation(self.entity.eid,'for_user',cnx.user.eid)else:_AddCWPropertyOp(cnx,cwprop=self.entity)classUpdateCWPropertyHook(AddCWPropertyHook):__regid__='updatecwprop'events=('after_update_entity',)def__call__(self):entity=self.entityifnot('pkey'inentity.cw_editedor'value'inentity.cw_edited):returnkey,value=entity.pkey,entity.valueifkey.startswith('sources.'):returncnx=self._cwtry:value=cnx.vreg.typed_value(key,value)exceptUnknownProperty:returnexceptValueErrorasex:raisevalidation_error(entity,{('value','subject'):str(ex)})ifentity.for_user:forsessioninget_user_sessions(cnx.repo,entity.for_user[0].eid):_ChangeCWPropertyOp(cnx,cwpropdict=session.user.properties,key=key,value=value)else:# site wide properties_ChangeCWPropertyOp(cnx,cwpropdict=cnx.vreg['propertyvalues'],key=key,value=value)classDeleteCWPropertyHook(AddCWPropertyHook):__regid__='delcwprop'events=('before_delete_entity',)def__call__(self):eid=self.entity.eidcnx=self._cwforeidfrom,rtype,eidtoincnx.transaction_data.get('pendingrelations',()):ifrtype=='for_user'andeidfrom==self.entity.eid:# if for_user was set, delete has already been handledbreakelse:_DelCWPropertyOp(cnx,cwpropdict=cnx.vreg['propertyvalues'],key=self.entity.pkey)classAddForUserRelationHook(SyncSessionHook):__regid__='addcwpropforuser'__select__=SyncSessionHook.__select__&hook.match_rtype('for_user')events=('after_add_relation',)def__call__(self):cnx=self._cweidfrom=self.eidfromifnotcnx.entity_metas(eidfrom)['type']=='CWProperty':returnkey,value=cnx.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V',{'x':eidfrom})[0]ifcnx.vreg.property_info(key)['sitewide']:msg=_("site-wide property can't be set for user")raisevalidation_error(eidfrom,{('for_user','subject'):msg})forsessioninget_user_sessions(cnx.repo,self.eidto):_ChangeCWPropertyOp(cnx,cwpropdict=session.user.properties,key=key,value=value)classDelForUserRelationHook(AddForUserRelationHook):__regid__='delcwpropforuser'events=('after_delete_relation',)def__call__(self):cnx=self._cwkey=cnx.execute('Any K WHERE P eid %(x)s, P pkey K',{'x':self.eidfrom})[0][0]cnx.transaction_data.setdefault('pendingrelations',[]).append((self.eidfrom,self.rtype,self.eidto))forsessioninget_user_sessions(cnx.repo,self.eidto):_DelCWPropertyOp(cnx,cwpropdict=session.user.properties,key=key)