Commit b00c4623 authored by Marcel Rieger's avatar Marcel Rieger
Browse files

Refactor user tool, works as expected with ajax requests now.

parent b7ae1a3c
......@@ -116,6 +116,7 @@ class Server(object):
'tools.private_parameters.on': True,
'tools.user.on': True,
'tools.user.redirect_url': vispa.url.dynamic('/login'),
'tools.user.redirect_url_reverse': vispa.url.dynamic('/'),
'tools.workspace.on': False,
'tools.sessions.on': True,
'tools.sessions.path': urlparse(base_dynamic).path,
......@@ -25,8 +25,8 @@ class AjaxTool(cherrypy.Tool):
def __init__(self, point="before_handler", **kwargs):
super(AjaxTool, self).__init__(point, self.callable, **kwargs)
def __init__(self):
super(AjaxTool, self).__init__("before_handler", self.callable, priority=50)
def callable(self, encoded=False):
# -*- coding: utf-8 -*-
Definition of the vispa user tool.
# imports
import cherrypy
import vispa
import os
from vispa.models.user import User
import logging
import vispa
from vispa import AjaxException
from vispa.models.user import User
logger = logging.getLogger(__name__)
class UserTool(cherrypy.Tool):
The user tool checks whether the session contains the field "user_id". If it exists, a reference
to the corresponding user is stored as "cherrypy.request.user". Otherwise, the request is either
redirected or a 401 error is returned using the ajax tool.
def __init__(self):
The user tool takes care of fetching the current
logged in user to then associating it with
the request.
cherrypy.Tool.__init__(self, 'before_handler', self._fetch, priority=65)
super(UserTool, self).__init__("before_handler", self._fetch, priority=65)
def _setup(self):
cherrypy.request.hooks.attach('before_finalize', self._cleanup, priority=35)
def _fetch(self, path=None, reverse=False, **conf):
Redirects a request dependent on 'reverse':
False ->
Redirect to 'path' or self.redir_path_nonuser when
a non-user performed the request. The original requested
path is stored as 'requested_path' in the session and may
be used for redirection e.g. after a successful login.
True ->
Redirect to 'path' when a logged-in user
performed the request. In this case, "path" should be set,
otherwise the index page url is used.
super(UserTool, self)._setup()
cherrypy.request.hooks.attach("before_finalize", self._cleanup, priority=35)
# to avoid loops, 'path' has to be set when reverse is True!
# otherwise 'path' points to the index page
if reverse and not path:
path = ""
# convert the path to inlcude our base path
if path:
# cut trailing slash to work with os.path.join
path = path[1:] if path.startswith('/') else path
path = os.path.join(vispa.url.dynamic('/'), path)
# store if there should be a redirect at the end of this function
redirect = False
if 'user_id' not in cherrypy.session.keys():
def _fetch(self, redirect_url, redirect_url_reverse, redirect=True, reverse=False):
Actual tool logic. If a user is not logged-in, i.e. no valid user id can be found in the
session, access to the requested resource is refused (401). Then, the user is redirected to
*redirect_url* if *redirect* is *True*, or a json formatted error is returned otherwise.
When *reverse* is *True*, the above rules flip and *redirect_url_reverse* is used instead.
However, in this case *redirect* is treated as *True* regardless of the value passed in the
# prepare some values
if reverse:
redirect = True
url = redirect_url_reverse
uid = cherrypy.session['user_id'].decode('utf-8')
user = User.get_by_id(cherrypy.request.db, uid)
if not user:
redirect = True
# store the user object inside the request
url = redirect_url
# get the user id and determine wheter access is granted or forbidden
user_id = cherrypy.session.get("user_id", None)
has_access = False
if reverse and user_id is None:
has_access = True
elif user_id is not None:
user = User.get_by_id(cherrypy.request.db, user_id.decode("utf-8"))
if isinstance(user, User):
has_access = True
cherrypy.request.user = user
# update the time of the last request
User.update_last_request(cherrypy.request.db, uid)
# update the users last request time
# when access is forbidden, create a handler that replaces the original
# one in order to stop the request via raise an exception
if not has_access:
def handler(*args, **kwargs):
if redirect:
logger.debug("Redirect %s" % url)
raise cherrypy.HTTPRedirect(url)
raise AjaxException("Unauthorized", code=401)
# redirect? depends on 'reverse'
if (redirect and not reverse) or (not redirect and reverse):
# store the requested path (w/o base) in the session
# when reverse is False
if not reverse:
if not 'requested_path' in cherrypy.session.keys():
cherrypy.session['requested_path'] = cherrypy.request.path_info
if not 'query_string' in cherrypy.session.keys():
cherrypy.session['query_string'] = cherrypy.request.query_string
redir_path_nonuser = conf.pop("redirect_url", "/login")
logger.debug("Redirect: %s or %s" % (path, redir_path_nonuser))
raise cherrypy.HTTPRedirect(path or redir_path_nonuser)
cherrypy.serving.request.handler = handler
def _cleanup(self):
cherrypy.request.user = None
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment