Add basic support for per-user session timeout

This commit is contained in:
Lance Edgar 2017-02-02 21:44:13 -06:00
parent 4659d3473b
commit b2e21b8e74
5 changed files with 189 additions and 6 deletions

View file

@ -26,7 +26,9 @@ Auth Views
from __future__ import unicode_literals, absolute_import
from rattail.db.auth import authenticate_user, set_user_password
import logging
from rattail.db.auth import authenticate_user, set_user_password, has_permission
import formencode as fe
from pyramid.httpexceptions import HTTPForbidden
@ -39,6 +41,9 @@ from tailbone.db import Session
from tailbone.views import View
log = logging.getLogger(__name__)
class UserLogin(fe.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -106,11 +111,17 @@ class AuthenticationView(View):
user = self.authenticate_user(form.data['username'],
form.data['password'])
if user:
# okay now they're truly logged in
headers = remember(self.request, user.uuid)
timeout = self.get_session_timeout_for_user(user) or None
log.debug("setting session timeout for '{}' to {}".format(user.username, timeout))
self.set_session_timeout(timeout)
# treat URL from session as referrer, if available
referrer = self.request.session.pop('next_url', referrer)
return self.redirect(referrer, headers=headers)
else:
self.request.session.flash("Invalid username or password", 'error')
@ -123,6 +134,33 @@ class AuthenticationView(View):
def authenticate_user(self, username, password):
return authenticate_user(Session(), username, password)
def get_session_timeout_for_user(self, user):
"""
Must return a value to be used to set the session timeout for the given
user. By default this will return ``None`` if the user has the
"forever session" permission, otherwise will try to read a default
value from config:
.. code-block:: ini
[tailbone]
# set session timeout to 10 minutes:
session.default_timeout = 600
# or, set to 0 to disable:
#session.default_timeout = 0
"""
if not has_permission(Session(), user, 'general.forever_session'):
return self.rattail_config.getint('tailbone', 'session.default_timeout',
default=300) # 5 minutes
def set_session_timeout(self, timeout):
"""
Set the server-side session timeout to the given value.
"""
self.request.session['_timeout'] = timeout or None
def mobile_login(self):
return self.login(mobile=True)

View file

@ -118,6 +118,11 @@ class CommonView(View):
# auto-correct URLs which require trailing slash
config.add_notfound_view(cls, attr='notfound', append_slash=True)
# general permissions
config.add_tailbone_permission_group('general', "(General)", overwrite=False)
config.add_tailbone_permission('general', 'general.forever_session',
"Never expire sessions on server")
# home
config.add_route('home', '/')
config.add_view(cls, attr='home', route_name='home', renderer='/home.mako')