fix migration when upgrading from cw < 3.6 to cw 3.7
"""user authentication component:organization: Logilab:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromlogilab.common.decoratorsimportclear_cachefromcubicwebimportAuthenticationError,BadConnectionIdfromcubicweb.viewimportComponentfromcubicweb.dbapiimportrepo_connect,ConnectionPropertiesfromcubicweb.webimportExplicitLogin,InvalidSessionfromcubicweb.web.applicationimportAbstractAuthenticationManagerclassNoAuthInfo(Exception):passclassWebAuthInfoRetreiver(Component):__registry__='webauth'order=Nonedefauthentication_information(self,req):"""retreive authentication information from the given request, raise NoAuthInfo if expected information is not found. """raiseNotImplementedError()defauthenticated(self,req,cnx,retreiver):"""callback when return authentication information have opened a repository connection successfully """passclassLoginPasswordRetreiver(WebAuthInfoRetreiver):__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}classRepositoryAuthenticationManager(AbstractAuthenticationManager):"""authenticate user associated to a request and check session validity"""def__init__(self,vreg):super(RepositoryAuthenticationManager,self).__init__(vreg)self.repo=vreg.config.repository(vreg)self.log_queries=vreg.config['query-log-file']self.authinforetreivers=sorted(vreg['webauth'].possible_objects(vreg),key=lambdax:x.order)assertself.authinforetreiversself.anoninfo=vreg.config.anonymous_user()defvalidate_session(self,req,session):"""check session validity, and return eventually hijacked session :raise InvalidSession: if session is corrupted for a reason or another and should be closed """# with this authentication manager, session is actually a dbapi# connectioncnx=sessionlogin=req.get_authorization()[0]try:# calling cnx.user() check connection validity, raise# BadConnectionId on failureuser=cnx.user(req)# check cnx.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 loginifloginandcnx.login!=login:cnx.close()raiseInvalidSession('login mismatch')exceptBadConnectionId:# check if a connection should be automatically restablishedif(loginisNoneorlogin==cnx.login):cnx=self._authenticate(req,cnx.login,cnx.authinfo)user=cnx.user(req)# backport session's datacnx.data=session.dataelse:raiseInvalidSession('bad connection id')# associate the connection to the current requestreq.set_connection(cnx,user)returncnxdefauthenticate(self,req):"""authenticate user and return corresponding user object :raise ExplicitLogin: if authentication is required (no authentication info found or wrong user/password) Note: this method is violating AuthenticationManager interface by returning a session instance instead of the user. This is expected by the InMemoryRepositorySessionManager. """forretreiverinself.authinforetreivers:try:login,authinfo=retreiver.authentication_information(req)exceptNoAuthInfo:continuetry:cnx=self._authenticate(req,login,authinfo)exceptExplicitLogin:continue# the next one may succeedforretreiver_inself.authinforetreivers:retreiver_.authenticated(req,cnx,retreiver)breakelse:# false if no authentication info found, eg this is not an# authentication failureif'login'inlocals():req.set_message(req._('authentication failure'))cnx=self._open_anonymous_connection(req)returncnxdef_authenticate(self,req,login,authinfo):cnxprops=ConnectionProperties(self.vreg.config.repo_method,close=False,log=self.log_queries)try:cnx=repo_connect(self.repo,login,cnxprops=cnxprops,**authinfo)exceptAuthenticationError:raiseExplicitLogin()self._init_cnx(cnx,login,authinfo)# associate the connection to the current requestreq.set_connection(cnx)returncnxdef_open_anonymous_connection(self,req):# restore an anonymous connection if possiblelogin,password=self.anoninfoiflogin:cnx=self._authenticate(req,login,{'password':password})cnx.anonymous_connection=TruereturncnxraiseExplicitLogin()def_init_cnx(self,cnx,login,authinfo):# decorate connectioncnx.vreg=self.vregcnx.login=logincnx.authinfo=authinfo