[server] add a db-namespace option in source definition (closes #1631339)
"namespace" is preferred to the postgresql term "schema" to try and
avoid confusion with cubicweb's schema.
cubicweb now depends on logilab-database >= 1.13.0
# 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/>."""user authentication component"""__docformat__="restructuredtext en"fromthreadingimportLockfromlogilab.common.decoratorsimportclear_cachefromlogilab.common.deprecationimportclass_renamedfromcubicwebimportAuthenticationError,BadConnectionIdfromcubicweb.viewimportComponentfromcubicweb.dbapiimport_repo_connect,ConnectionPropertiesfromcubicweb.webimportInvalidSessionfromcubicweb.web.applicationimportAbstractAuthenticationManagerclassNoAuthInfo(Exception):passclassWebAuthInfoRetriever(Component):__registry__='webauth'order=None__abstract__=Truedefauthentication_information(self,req):"""retrieve authentication information from the given request, raise NoAuthInfo if expected information is not found. """raiseNotImplementedError()defauthenticated(self,retriever,req,session,login,authinfo):"""callback when return authentication information have opened a repository connection successfully. Take care req has no session attached yet, hence req.execute isn't available. """passdefrequest_has_auth_info(self,req):"""tells from the request if it has enough information to proceed to authentication, would the current session be invalidated """raiseNotImplementedError()defrevalidate_login(self,req):"""returns a login string or None, for repository session validation purposes """raiseNotImplementedError()defcleanup_authentication_information(self,req):"""called when the retriever has returned some authentication information but we get an authentication error when using them, so it get a chance to clean things up (e.g. remove cookie) """passWebAuthInfoRetreiver=class_renamed('WebAuthInfoRetreiver',WebAuthInfoRetriever,'[3.17] WebAuthInfoRetreiver had been renamed into WebAuthInfoRetriever ''("ie" instead of "ei")')classLoginPasswordRetriever(WebAuthInfoRetriever):__regid__='loginpwdauth'order=10defauthentication_information(self,req):"""retreive authentication information from the given request, raise NoAuthInfo if expected information is not found. """login,password=req.get_authorization()ifnotlogin:raiseNoAuthInfo()returnlogin,{'password':password}defrequest_has_auth_info(self,req):returnreq.get_authorization()[0]isnotNonedefrevalidate_login(self,req):returnreq.get_authorization()[0]LoginPasswordRetreiver=class_renamed('LoginPasswordRetreiver',LoginPasswordRetriever,'[3.17] LoginPasswordRetreiver had been renamed into LoginPasswordRetriever ''("ie" instead of "ei")')classRepositoryAuthenticationManager(AbstractAuthenticationManager):"""authenticate user associated to a request and check session validity"""def__init__(self,repo):super(RepositoryAuthenticationManager,self).__init__(repo)self.repo=repovreg=repo.vregself.log_queries=vreg.config['query-log-file']self.authinforetrievers=sorted(vreg['webauth'].possible_objects(vreg),key=lambdax:x.order)# 2-uple login / password, login is None when no anonymous access# configuredself.anoninfo=vreg.config.anonymous_user()ifself.anoninfo[0]:self.anoninfo=(self.anoninfo[0],{'password':self.anoninfo[1]})defvalidate_session(self,req,session):"""check session validity and return the connected user on success. raise :exc:`InvalidSession` if session is corrupted for a reason or another and should be closed also invoked while going from anonymous to logged in """forretrieverinself.authinforetrievers:ifretriever.request_has_auth_info(req):login=retriever.revalidate_login(req)returnself._validate_session(req,session,login)# let's try with the current sessionreturnself._validate_session(req,session,None)def_validate_session(self,req,session,login):# check session.login and not user.login, since in case of login by# email, login and cnx.login are the email while user.login is the# actual user loginifloginandsession.login!=login:raiseInvalidSession('login mismatch')defauthenticate(self,req):"""authenticate user using connection information found in the request, and return corresponding a :class:`~cubicweb.dbapi.Connection` instance, as well as login used to open the connection. raise :exc:`cubicweb.AuthenticationError` if authentication failed (no authentication info found or wrong user/password) """has_auth=Falseforretrieverinself.authinforetrievers:try:login,authinfo=retriever.authentication_information(req)exceptNoAuthInfo:continuehas_auth=Truetry:session=self._authenticate(login,authinfo)exceptAuthenticationError:retriever.cleanup_authentication_information(req)continue# the next one may succeedforretriever_inself.authinforetrievers:retriever_.authenticated(retriever,req,session,login,authinfo)returnsession,login# false if no authentication info found, i.e. this is not an# authentication failureifhas_auth:req.set_message(req._('authentication failure'))login,authinfo=self.anoninfoiflogin:session=self._authenticate(login,authinfo)returnsession,loginraiseAuthenticationError()def_authenticate(self,login,authinfo):sessionid=self.repo.connect(login,**authinfo)returnself.repo._sessions[sessionid]