forked from gergely/calendar-social
Make it possible to list and invalidate active sessions
This commit is contained in:
parent
8d71edae5e
commit
cb9a62cd88
@ -17,7 +17,7 @@
|
|||||||
"""Main module for the Calendar.social app
|
"""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 flask_security import current_user, login_required
|
||||||
|
|
||||||
from sqlalchemy.orm.exc import NoResultFound
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
@ -197,3 +197,38 @@ class AccountBlueprint(Blueprint, RoutedMixin):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return redirect(url_for('account.follow_requests'))
|
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/<string:sid>')
|
||||||
|
@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'))
|
||||||
|
@ -27,6 +27,7 @@ from flask_sqlalchemy import SQLAlchemy
|
|||||||
from sqlalchemy.orm.exc import NoResultFound
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
from sqlalchemy_utils.types.choice import ChoiceType
|
from sqlalchemy_utils.types.choice import ChoiceType
|
||||||
|
|
||||||
|
from .cache import cache
|
||||||
from .utils import force_locale
|
from .utils import force_locale
|
||||||
|
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
@ -219,6 +220,21 @@ class User(db.Model, UserMixin):
|
|||||||
|
|
||||||
return current_app.timezone
|
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):
|
def __repr__(self):
|
||||||
return f'<User {self.id}({self.username})>'
|
return f'<User {self.id}({self.username})>'
|
||||||
|
|
||||||
|
15
calsocial/templates/account/active-sessions.html
Normal file
15
calsocial/templates/account/active-sessions.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{% extends 'account/settings-base.html' %}
|
||||||
|
|
||||||
|
{% block settings_content %}
|
||||||
|
<h2>{% trans %}Active sessions{% endtrans %}</h2>
|
||||||
|
<ul>
|
||||||
|
{% for sess in sessions %}
|
||||||
|
<li>
|
||||||
|
{{ sess['ip'] }}
|
||||||
|
{% if sess.sid != session.sid %}
|
||||||
|
<a href="{{ url_for('account.invalidate_session', sid=sess.sid) }}">{% trans %}Invalidate{% endtrans %}</a>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endblock settings_content %}
|
@ -6,6 +6,7 @@
|
|||||||
<div class="ui secondary pointing vertical menu">
|
<div class="ui secondary pointing vertical menu">
|
||||||
<a class="item{% if request.endpoint == 'account.edit_profile' %} active{% endif %}" href="{{ url_for('account.edit_profile') }}">{% trans %}Edit profile{% endtrans %}</a>
|
<a class="item{% if request.endpoint == 'account.edit_profile' %} active{% endif %}" href="{{ url_for('account.edit_profile') }}">{% trans %}Edit profile{% endtrans %}</a>
|
||||||
<a class="item{% if request.endpoint == 'account.settings' %} active{% endif %}" href="{{ url_for('account.settings') }}">{% trans %}Settings{% endtrans %}</a>
|
<a class="item{% if request.endpoint == 'account.settings' %} active{% endif %}" href="{{ url_for('account.settings') }}">{% trans %}Settings{% endtrans %}</a>
|
||||||
|
<a class="item{% if request.endpoint == 'account.active_sessions' %} active{% endif %}" href="{{ url_for('account.active_sessions') }}">{% trans %}Active sessions{% endtrans %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="twelve wide stretched column">
|
<div class="twelve wide stretched column">
|
||||||
|
Loading…
Reference in New Issue
Block a user