From cb9a62cd88adcf334bb8990c0656a354498181ff Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Thu, 19 Jul 2018 15:14:00 +0200 Subject: [PATCH] Make it possible to list and invalidate active sessions --- calsocial/account.py | 37 ++++++++++++++++++- calsocial/models.py | 16 ++++++++ .../templates/account/active-sessions.html | 15 ++++++++ .../templates/account/settings-base.html | 1 + 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 calsocial/templates/account/active-sessions.html diff --git a/calsocial/account.py b/calsocial/account.py index 52dbbd7..389917f 100644 --- a/calsocial/account.py +++ b/calsocial/account.py @@ -17,7 +17,7 @@ """Main module for the Calendar.social app """ -from flask import Blueprint, abort, current_app, redirect, render_template, url_for +from flask import Blueprint, abort, current_app, flash, redirect, render_template, session, url_for from flask_security import current_user, login_required from sqlalchemy.orm.exc import NoResultFound @@ -197,3 +197,38 @@ class AccountBlueprint(Blueprint, RoutedMixin): db.session.commit() return redirect(url_for('account.follow_requests')) + + @staticmethod + @RoutedMixin.route('/sessions') + @login_required + def active_sessions(): + """View the list of active sessions + """ + + sessions = [] + + for sid in current_user.active_sessions: + session = current_app.session_interface.load_session(sid) + sessions.append(session) + + return render_template('account/active-sessions.html', sessions=sessions) + + @staticmethod + @RoutedMixin.route('/sessions/invalidate/') + @login_required + def invalidate_session(sid): + """View to invalidate a session + """ + + sess = current_app.session_interface.load_session(sid) + + if not sess or sess.user != current_user: + abort(404) + + if sess.sid == session.sid: + flash(_('Can’t invalidate your current session')) + else: + current_app.session_interface.delete_session(sid) + current_user.active_sessions = [sess_id for sess_id in current_user.active_sessions if sess_id != sid] + + return redirect(url_for('account.active_sessions')) diff --git a/calsocial/models.py b/calsocial/models.py index fce8bcd..c5802f0 100644 --- a/calsocial/models.py +++ b/calsocial/models.py @@ -27,6 +27,7 @@ from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.exc import NoResultFound from sqlalchemy_utils.types.choice import ChoiceType +from .cache import cache from .utils import force_locale db = SQLAlchemy() @@ -219,6 +220,21 @@ class User(db.Model, UserMixin): return current_app.timezone + @property + def session_list_key(self): + """The cache key of this user’s session list + """ + + return f'open_sessions:{self.id}' + + @property + def active_sessions(self): + return cache.get(self.session_list_key) or [] + + @active_sessions.setter + def active_sessions(self, value): + cache.set(self.session_list_key, list(value)) + def __repr__(self): return f'' diff --git a/calsocial/templates/account/active-sessions.html b/calsocial/templates/account/active-sessions.html new file mode 100644 index 0000000..a0aaaae --- /dev/null +++ b/calsocial/templates/account/active-sessions.html @@ -0,0 +1,15 @@ +{% extends 'account/settings-base.html' %} + +{% block settings_content %} +

{% trans %}Active sessions{% endtrans %}

+ +{% endblock settings_content %} diff --git a/calsocial/templates/account/settings-base.html b/calsocial/templates/account/settings-base.html index 46122b2..329d5dd 100644 --- a/calsocial/templates/account/settings-base.html +++ b/calsocial/templates/account/settings-base.html @@ -6,6 +6,7 @@