[rql, security] fix buggy rqlstr cleanup when some introduced snippet create an unresolvable query. Closes #2142041
# copyright 2010-2011 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/>."""hooks for repository sources synchronization"""fromsocketimportgethostnamefromlogilab.common.decoratorsimportclear_cachefromyams.schemaimportrole_namefromcubicwebimportValidationErrorfromcubicweb.selectorsimportis_instancefromcubicweb.serverimportSOURCE_TYPES,hookclassSourceHook(hook.Hook):__abstract__=Truecategory='cw.sources'# repo sources synchronization #################################################classSourceAddedOp(hook.Operation):entity=None# make pylint happydefpostcommit_event(self):self.session.repo.add_source(self.entity)classSourceAddedHook(SourceHook):__regid__='cw.sources.added'__select__=SourceHook.__select__&is_instance('CWSource')events=('after_add_entity',)def__call__(self):try:sourcecls=SOURCE_TYPES[self.entity.type]exceptKeyError:msg=self._cw._('unknown source type')raiseValidationError(self.entity.eid,{role_name('type','subject'):msg})sourcecls.check_conf_dict(self.entity.eid,self.entity.host_config,fail_if_unknown=notself._cw.vreg.config.repairing)SourceAddedOp(self._cw,entity=self.entity)classSourceRemovedOp(hook.Operation):uri=None# make pylint happydefpostcommit_event(self):self.session.repo.remove_source(self.uri)classSourceRemovedHook(SourceHook):__regid__='cw.sources.removed'__select__=SourceHook.__select__&is_instance('CWSource')events=('before_delete_entity',)def__call__(self):ifself.entity.name=='system':raiseValidationError(self.entity.eid,{None:'cant remove system source'})SourceRemovedOp(self._cw,uri=self.entity.name)classSourceConfigUpdatedOp(hook.DataOperationMixIn,hook.Operation):defprecommit_event(self):self.__processed=[]forsourceinself.get_data():ifnotself.session.deleted_in_transaction(source.eid):conf=source.repo_source.check_config(source)self.__processed.append((source,conf))defpostcommit_event(self):forsource,confinself.__processed:source.repo_source.update_config(source,conf)classSourceRenamedOp(hook.LateOperation):oldname=newname=None# make pylint happydefprecommit_event(self):source=self.session.repo.sources_by_uri[self.oldname]ifsource.copy_based_source:sql='UPDATE entities SET asource=%(newname)s WHERE asource=%(oldname)s'else:sql='UPDATE entities SET source=%(newname)s, asource=%(newname)s WHERE source=%(oldname)s'self.session.system_sql(sql,{'oldname':self.oldname,'newname':self.newname})defpostcommit_event(self):repo=self.session.repo# XXX race conditionsource=repo.sources_by_uri.pop(self.oldname)source.uri=self.newnamesource.public_config['uri']=self.newnamerepo.sources_by_uri[self.newname]=sourcerepo._type_source_cache.clear()clear_cache(repo,'source_defs')ifnotsource.copy_based_source:repo._extid_cache.clear()repo._clear_planning_caches()forcnxsetinrepo.cnxsets:cnxset.source_cnxs[self.oldname]=cnxset.source_cnxs.pop(self.oldname)classSourceUpdatedHook(SourceHook):__regid__='cw.sources.configupdate'__select__=SourceHook.__select__&is_instance('CWSource')events=('before_update_entity',)def__call__(self):if'config'inself.entity.cw_edited:SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity)if'name'inself.entity.cw_edited:oldname,newname=self.entity.cw_edited.oldnewvalue('name')SourceRenamedOp(self._cw,oldname=oldname,newname=newname)classSourceHostConfigUpdatedHook(SourceHook):__regid__='cw.sources.hostconfigupdate'__select__=SourceHook.__select__&is_instance('CWSourceHostConfig')events=('after_add_entity','after_update_entity','before_delete_entity',)def__call__(self):ifself.entity.match(gethostname()):ifself.event=='after_update_entity'and \not'config'inself.entity.cw_edited:returntry:SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity.cwsource)exceptIndexError:# XXX no source linked to the host config yetpass# source mapping synchronization ################################################# Expect cw_for_source/cw_schema are immutable relations (i.e. can't change from# a source or schema to another).classSourceMappingImmutableHook(SourceHook):"""check cw_for_source and cw_schema are immutable relations XXX empty delete perms would be enough? """__regid__='cw.sources.mapping.immutable'__select__=SourceHook.__select__&hook.match_rtype('cw_for_source','cw_schema')events=('before_add_relation',)def__call__(self):ifnotself._cw.added_in_transaction(self.eidfrom):msg=self._cw._("can't change this relation")raiseValidationError(self.eidfrom,{self.rtype:msg})classSourceMappingChangedOp(hook.DataOperationMixIn,hook.Operation):defcheck_or_update(self,checkonly):session=self.session# take care, can't call get_data() twicetry:data=self.__dataexceptAttributeError:data=self.__data=self.get_data()forschemacfg,sourceindata:ifsourceisNone:source=schemacfg.cwsource.repo_sourceifsession.added_in_transaction(schemacfg.eid):ifnotsession.deleted_in_transaction(schemacfg.eid):source.add_schema_config(schemacfg,checkonly=checkonly)elifsession.deleted_in_transaction(schemacfg.eid):source.del_schema_config(schemacfg,checkonly=checkonly)else:source.update_schema_config(schemacfg,checkonly=checkonly)defprecommit_event(self):self.check_or_update(True)defpostcommit_event(self):self.check_or_update(False)classSourceMappingChangedHook(SourceHook):__regid__='cw.sources.schemaconfig'__select__=SourceHook.__select__&is_instance('CWSourceSchemaConfig')events=('after_add_entity','after_update_entity')def__call__(self):ifself.event=='after_add_entity'or(self.event=='after_update_entity'and'options'inself.entity.cw_edited):SourceMappingChangedOp.get_instance(self._cw).add_data((self.entity,None))classSourceMappingDeleteHook(SourceHook):__regid__='cw.sources.delschemaconfig'__select__=SourceHook.__select__&hook.match_rtype('cw_for_source')events=('before_delete_relation',)def__call__(self):SourceMappingChangedOp.get_instance(self._cw).add_data((self._cw.entity_from_eid(self.eidfrom),self._cw.entity_from_eid(self.eidto).repo_source))