proper field's role handling: may be 'subject' / 'object' *in case
of entity's relation*, but None in other case. So you should correctly
specify it to field_by_name
"""user authentication component:organization: Logilab:copyright: 2001-2009 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=10def__init__(self,vreg):self.anoninfo=vreg.config.anonymous_user()defauthentication_information(self,req):"""retreive authentication information from the given request, raise NoAuthInfo if expected information is not found. """login,password=req.get_authorization()ifnotlogin:# No session and no login -> try anonymouslogin,password=self.anoninfoifnotlogin:# anonymous not authorizedraiseNoAuthInfo()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.authinforetreiversdefvalidate_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:continuecnx=self._authenticate(req,login,authinfo)breakelse:raiseExplicitLogin()forretreiver_inself.authinforetreivers:retreiver_.authenticated(req,cnx,retreiver)returncnxdef_authenticate(self,req,login,authinfo):# remove possibly cached cursor coming from closed connectionclear_cache(req,'cursor')cnxprops=ConnectionProperties(self.vreg.config.repo_method,close=False,log=self.log_queries)try:cnx=repo_connect(self.repo,login,cnxprops=cnxprops,**authinfo)exceptAuthenticationError:req.set_message(req._('authentication failure'))# restore an anonymous connection if possibleanonlogin,anonpassword=self.vreg.config.anonymous_user()ifanonloginandanonlogin!=login:cnx=repo_connect(self.repo,anonlogin,password=anonpassword,cnxprops=cnxprops)self._init_cnx(cnx,anonlogin,{'password':anonpassword})else:raiseExplicitLogin()else:self._init_cnx(cnx,login,authinfo)# associate the connection to the current requestreq.set_connection(cnx)returncnxdef_init_cnx(self,cnx,login,authinfo):# decorate connectioniflogin==self.vreg.config.anonymous_user()[0]:cnx.anonymous_connection=Truecnx.vreg=self.vregcnx.login=logincnx.authinfo=authinfo