Commit f94329f7 authored by Pietro Albini's avatar Pietro Albini

Add session handling

parent 168ecda9
Pipeline #75 passed with stage
in 0 seconds
...@@ -66,6 +66,38 @@ class Sessions: ...@@ -66,6 +66,38 @@ class Sessions:
"""Delete a session""" """Delete a session"""
self.db.update("DELETE FROM auth_sessions WHERE id = ?;", id) self.db.update("DELETE FROM auth_sessions WHERE id = ?;", id)
def delete_all(self, except_id):
"""Delete every session except this one"""
self.db.update("DELETE FROM auth_sessions WHERE id != ?;", except_id)
def all(self):
"""Return all the sessions"""
rows = self.db.query("SELECT id, nickname, teams, ip FROM auth_sessions;")
result = []
for row in rows:
result.append({
"id": row[0],
"nickname": row[1],
"teams": row[2].split(","),
"ip": row[3],
})
return result
def get(self, id):
"""Return details about a session"""
row = self.db.query("SELECT nickname, teams, ip FROM auth_sessions WHERE id = ?;", id)
if row:
return {
"id": id,
"nickname": row[0][0],
"teams": row[0][1].split(","),
"ip": row[0][2],
}
def count(self):
"""Return the number of active sessions"""
return self.db.query("SELECT COUNT(*) FROM auth_sessions;")[0][0]
class Permissions: class Permissions:
...@@ -99,9 +131,12 @@ def prepare_blueprint(app): ...@@ -99,9 +131,12 @@ def prepare_blueprint(app):
flask.flash(str(e), "error") flask.flash(str(e), "error")
return return
flask.g.auth_id = flask.session["auth"]
flask.g.auth_name = data["nickname"] flask.g.auth_name = data["nickname"]
flask.g.auth_teams = data["teams"] flask.g.auth_teams = data["teams"]
flask.g.auth_sessions_count = sessions.count()
@oid.after_login @oid.after_login
def receive_openid(resp): def receive_openid(resp):
teams = resp.extensions["lp"].is_member teams = resp.extensions["lp"].is_member
...@@ -136,4 +171,41 @@ def prepare_blueprint(app): ...@@ -136,4 +171,41 @@ def prepare_blueprint(app):
flask.flash("La sessione è stata terminata correttamente.", "success") flask.flash("La sessione è stata terminata correttamente.", "success")
return flask.redirect(flask.url_for("pages.index")) return flask.redirect(flask.url_for("pages.index"))
@bp.route("/sessions")
def sessions_list():
return flask.render_template(
"auth/sessions.html",
sessions=sessions.all(),
)
@bp.route("/sessions/+all/revoke")
def sessions_revoke_all():
sessions.delete_all(flask.g.auth_id)
return flask.redirect(flask.url_for(".sessions_list"))
@bp.route("/sessions/<id>")
def sessions_show(id):
data = sessions.get(id)
if data is None:
return flask.abort(404)
all = sessions.all()
others = []
for session in all:
if session["id"] == id or session["nickname"] != data["nickname"]:
continue
others.append(session)
return flask.render_template(
"auth/session.html",
session=data,
others=others,
)
@bp.route("/sessions/<id>/revoke")
def sessions_revoke(id):
sessions.delete(id)
return flask.redirect(flask.url_for(".sessions_list"))
return bp return bp
{# Source code of the Ubuntu-it website
# Copyright (C) 2018 Pietro Albini <pietroalbini@ubuntu.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; witout even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "layout.html" %}
{% block title %}Dettagli sessione{% endblock %}
{% block content %}
<div class="page">
<div class="row">
<div class="col">
<h1>Dettagli sessione</h1>
<div class="table">
<table>
<tr>
<td>Nome utente</td>
<td><b>{{ session.nickname }}</b></td>
</tr>
<tr>
<td>Indirizzo IP</td>
<td>{{ session.ip }}</td>
</tr>
<tr>
<td>Team</td>
<td>
{% for team in session.teams %}
<a href="https://launchpad.net/~{{ team }}">
~{{ team -}}
</a>
{%- if not loop.last %},{% endif %}
{% endfor %}
</td>
</tr>
</table>
</div>
{% if g.auth_id != session.id %}
<a class="btn" href="{{ url_for(".sessions_revoke", id=session.id) }}">
Disabilita sessione
</a>
{% endif %}
</div>
</div>
{% if others %}
<div class="row">
<div class="col">
<h2>Altre sessioni dell'utente</h2>
<div class="table">
<table>
<tr>
<th>Indirizzo IP</th>
<th></th>
<th></th>
</tr>
{% for session in others %}
<tr>
<td>{{ session.ip }}</td>
<td>
<a href="{{ url_for(".sessions_show", id=session.id) }}">
Dettagli
</a>
</td>
<td>
{% if session.id == g.auth_id %}
Sessione corrente
{% else %}
<a href="{{ url_for(".sessions_revoke", id=session.id) }}">
Disabilita sessione
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
{# Source code of the Ubuntu-it website
# Copyright (C) 2018 Pietro Albini <pietroalbini@ubuntu.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; witout even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "layout.html" %}
{% block title %}Sessioni attive{% endblock %}
{% block content %}
<div class="page">
<div class="row">
<div class="col">
<h1>Sessioni attive</h1>
{% if g.auth_sessions_count > 1 %}
<p>
<a class="btn" href="{{ url_for(".sessions_revoke_all") }}">
Disabilita ogni altra sessione
</a>
</p>
{% endif %}
</div>
</div>
<div class="row">
<div class="col">
<div class="table">
<table>
<tr>
<th>Nome utente</th>
<th>Indirizzo IP</th>
<th></th>
<th></th>
</tr>
{% for session in sessions %}
<tr>
<td>{{ session.nickname }}</td>
<td>{{ session.ip }}</td>
<td>
<a href="{{ url_for(".sessions_show", id=session.id) }}">
Dettagli
</a>
</td>
<td>
{% if session.id == g.auth_id %}
Sessione corrente
{% else %}
<a href="{{ url_for(".sessions_revoke", id=session.id) }}">
Disabilita sessione
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% endblock %}
...@@ -47,7 +47,15 @@ ...@@ -47,7 +47,15 @@
{% if g.auth_name %} {% if g.auth_name %}
<nav class="sites-list"> <nav class="sites-list">
<div class="container"> <div class="container">
<ul class="left">
<li><a href="{{ url_for("auth.sessions_list") }}">
Sessioni attive: {{ g.auth_sessions_count }}
</a></li>
</ul>
<ul class="right"> <ul class="right">
<li><a href="{{ url_for("auth.sessions_show", id=g.auth_id) }}">
{{ g.auth_name }}
</a></li>
<li><a href="{{ url_for("auth.logout") }}">Esci</a></li> <li><a href="{{ url_for("auth.logout") }}">Esci</a></li>
</ul> </ul>
</div> </div>
......
Markdown is supported
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