--- a/_exceptions.py Mon Mar 01 11:26:14 2010 +0100
+++ b/_exceptions.py Tue Mar 16 16:32:36 2010 +0100
@@ -49,7 +49,11 @@
class AuthenticationError(ConnectionError):
"""raised when a bad connection id is given or when an attempt to establish
- a connection failed"""
+ a connection failed
+ """
+ def __init__(self, *args, **kwargs):
+ super(AuthenticationError, self).__init__(*args)
+ self.__dict__.update(kwargs)
class BadConnectionId(ConnectionError):
"""raised when a bad connection id is given or when an attempt to establish
--- a/etwist/server.py Mon Mar 01 11:26:14 2010 +0100
+++ b/etwist/server.py Tue Mar 16 16:32:36 2010 +0100
@@ -99,15 +99,11 @@
def __init__(self, config, debug=None):
self.debugmode = debug
self.config = config
- self.base_url = config['base-url'] or config.default_base_url()
- if self.base_url[-1] != '/':
- self.base_url += '/'
- self.https_url = config['https-url']
- if self.https_url and self.https_url[-1] != '/':
- self.https_url += '/'
# instantiate publisher here and not in init_publisher to get some
# checks done before daemonization (eg versions consistency)
self.appli = CubicWebPublisher(config, debug=self.debugmode)
+ self.base_url = config['base-url']
+ self.https_url = config['https-url']
self.versioned_datadir = 'data%s' % config.instance_md5_version()
def init_publisher(self):
@@ -250,21 +246,12 @@
headers=req.headers_out or None)
except ExplicitLogin: # must be before AuthenticationError
return self.request_auth(req)
- except AuthenticationError:
- if self.config['auth-mode'] == 'cookie':
- # in cookie mode redirecting to the index view is enough :
- # either anonymous connection is allowed and the page will
- # be displayed or we'll be redirected to the login form
- msg = req._('you have been logged out')
- if req.https:
- req._base_url = self.base_url
- req.https = False
- url = req.build_url('view', vid='index', __message=msg)
- return self.redirect(req, url)
- else:
- # in http we have to request auth to flush current http auth
- # information
- return self.request_auth(req, loggedout=True)
+ except AuthenticationError, ex:
+ if self.config['auth-mode'] == 'cookie' and getattr(ex, 'url', None):
+ return self.redirect(req, ex.url)
+ # in http we have to request auth to flush current http auth
+ # information
+ return self.request_auth(req, loggedout=True)
except Redirect, ex:
return self.redirect(req, ex.location)
# request may be referenced by "onetime callback", so clear its entity
--- a/web/application.py Mon Mar 01 11:26:14 2010 +0100
+++ b/web/application.py Tue Mar 16 16:32:36 2010 +0100
@@ -217,13 +217,13 @@
path = 'view'
raise Redirect(req.build_url(path, **args))
- def logout(self, req):
+ def logout(self, req, goto_url):
"""logout from the instance by cleaning the session and raising
`AuthenticationError`
"""
self.session_manager.close_session(req.cnx)
req.remove_cookie(req.get_cookie(), self.SESSION_VAR)
- raise AuthenticationError()
+ raise AuthenticationError(url=goto_url)
class CubicWebPublisher(object):
--- a/web/views/authentication.py Mon Mar 01 11:26:14 2010 +0100
+++ b/web/views/authentication.py Tue Mar 16 16:32:36 2010 +0100
@@ -39,19 +39,13 @@
__regid__ = 'loginpwdauth'
order = 10
- def __init__(self, vreg):
- self.anoninfo = vreg.config.anonymous_user()
-
def authentication_information(self, req):
"""retreive authentication information from the given request, raise
NoAuthInfo if expected information is not found.
"""
login, password = req.get_authorization()
if not login:
- # No session and no login -> try anonymous
- login, password = self.anoninfo
- if not login: # anonymous not authorized
- raise NoAuthInfo()
+ raise NoAuthInfo()
return login, {'password': password}
@@ -65,6 +59,7 @@
self.authinforetreivers = sorted(vreg['webauth'].possible_objects(vreg),
key=lambda x: x.order)
assert self.authinforetreivers
+ self.anoninfo = vreg.config.anonymous_user()
def validate_session(self, req, session):
"""check session validity, and return eventually hijacked session
@@ -116,37 +111,38 @@
continue
try:
cnx = self._authenticate(req, login, authinfo)
- break
except ExplicitLogin:
continue # the next one may succeed
+ for retreiver_ in self.authinforetreivers:
+ retreiver_.authenticated(req, cnx, retreiver)
+ break
else:
- raise ExplicitLogin()
- for retreiver_ in self.authinforetreivers:
- retreiver_.authenticated(req, cnx, retreiver)
+ # false if no authentication info found, eg this is not an
+ # authentication failure
+ if 'login' in locals():
+ req.set_message(req._('authentication failure'))
+ cnx = self._open_anonymous_connection(req)
return cnx
def _authenticate(self, req, login, authinfo):
- # remove possibly cached cursor coming from closed connection
cnxprops = ConnectionProperties(self.vreg.config.repo_method,
close=False, log=self.log_queries)
try:
cnx = repo_connect(self.repo, login, cnxprops=cnxprops, **authinfo)
except AuthenticationError:
- req.set_message(req._('authentication failure'))
- # restore an anonymous connection if possible
- anonlogin, anonpassword = self.vreg.config.anonymous_user()
- if anonlogin and anonlogin != login:
- cnx = repo_connect(self.repo, anonlogin, password=anonpassword,
- cnxprops=cnxprops)
- self._init_cnx(cnx, anonlogin, {'password': anonpassword})
- else:
- raise ExplicitLogin()
- else:
- self._init_cnx(cnx, login, authinfo)
+ raise ExplicitLogin()
+ self._init_cnx(cnx, login, authinfo)
# associate the connection to the current request
req.set_connection(cnx)
return cnx
+ def _open_anonymous_connection(self, req):
+ # restore an anonymous connection if possible
+ login, password = self.anoninfo
+ if login:
+ return self._authenticate(req, login, {'password': password})
+ raise ExplicitLogin()
+
def _init_cnx(self, cnx, login, authinfo):
# decorate connection
if login == self.vreg.config.anonymous_user()[0]:
--- a/web/views/basecontrollers.py Mon Mar 01 11:26:14 2010 +0100
+++ b/web/views/basecontrollers.py Tue Mar 16 16:32:36 2010 +0100
@@ -83,8 +83,19 @@
def publish(self, rset=None):
"""logout from the instance"""
- return self.appli.session_handler.logout(self._cw)
+ return self.appli.session_handler.logout(self._cw, self.goto_url())
+ def goto_url(self):
+ # * in http auth mode, url will be ignored
+ # * in cookie mode redirecting to the index view is enough : either
+ # anonymous connection is allowed and the page will be displayed or
+ # we'll be redirected to the login form
+ msg = self._cw._('you have been logged out')
+ if self._cw.https:
+ # XXX hack to generate an url on the http version of the site
+ self._cw._base_url = self._cw.vreg.config['base-url']
+ self._cw.https = False
+ return self._cw.build_url('view', vid='index', __message=msg)
class ViewController(Controller):
"""standard entry point :
--- a/web/webconfig.py Mon Mar 01 11:26:14 2010 +0100
+++ b/web/webconfig.py Tue Mar 16 16:32:36 2010 +0100
@@ -300,10 +300,10 @@
def _init_base_url(self):
# normalize base url(s)
- baseurl = self['base-url']
+ baseurl = self['base-url'] or self.default_base_url()
if baseurl and baseurl[-1] != '/':
baseurl += '/'
- self.global_set_option('base-url', baseurl)
+ self.global_set_option('base-url', baseurl)
httpsurl = self['https-url']
if httpsurl and httpsurl[-1] != '/':
httpsurl += '/'