Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
Nuovo sito
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
16
Issues
16
List
Boards
Labels
Milestones
Merge Requests
2
Merge Requests
2
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gruppo Web
Nuovo sito
Commits
db1a1c78
Commit
db1a1c78
authored
May 10, 2018
by
Pietro Albini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add actions logging
parent
565f65c7
Pipeline
#87
passed with stage
in 0 seconds
Changes
9
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
257 additions
and
8 deletions
+257
-8
uitwww/__init__.py
uitwww/__init__.py
+6
-7
uitwww/actions.py
uitwww/actions.py
+107
-0
uitwww/auth.py
uitwww/auth.py
+16
-1
uitwww/data/permissions.yml
uitwww/data/permissions.yml
+1
-0
uitwww/db.py
uitwww/db.py
+8
-0
uitwww/templates/actions/macros.html
uitwww/templates/actions/macros.html
+70
-0
uitwww/templates/actions/show.html
uitwww/templates/actions/show.html
+32
-0
uitwww/templates/auth/session.html
uitwww/templates/auth/session.html
+12
-0
uitwww/templates/layout.html
uitwww/templates/layout.html
+5
-0
No files found.
uitwww/__init__.py
View file @
db1a1c78
...
@@ -18,13 +18,14 @@ import os
...
@@ -18,13 +18,14 @@ import os
import
flask
import
flask
from
.
import
actions
from
.
import
auth
from
.
import
auth
from
.
import
cache
from
.
import
cache
from
.
import
db
from
.
import
db
from
.
import
pages
from
.
import
utils
from
.
import
download
from
.
import
download
from
.
import
navbar
from
.
import
navbar
from
.
import
pages
from
.
import
utils
from
.
import
utils
from
.
import
utils
...
@@ -55,12 +56,10 @@ def create_app(data_path):
...
@@ -55,12 +56,10 @@ def create_app(data_path):
utils
.
prepare_app
(
app
)
utils
.
prepare_app
(
app
)
app
.
download
=
download
.
Downloads
(
data_path
)
app
.
download
=
download
.
Downloads
(
data_path
)
app
.
register_blueprint
(
app
.
download
.
prepare_blueprint
(
app
),
url_prefix
=
"/download"
,
)
app
.
register_blueprint
(
auth
.
prepare_blueprint
(
app
),
url_prefix
=
"/+auth"
)
app
.
register_blueprint
(
app
.
download
.
prepare_blueprint
(
app
),
url_prefix
=
"/download"
)
app
.
register_blueprint
(
actions
.
prepare_blueprint
(
app
),
url_prefix
=
"/+actions"
)
app
.
register_blueprint
(
auth
.
prepare_blueprint
(
app
),
url_prefix
=
"/+auth"
)
app
.
register_blueprint
(
pages
.
prepare_blueprint
(
app
))
app
.
register_blueprint
(
pages
.
prepare_blueprint
(
app
))
nav
=
navbar
.
Navbar
()
nav
=
navbar
.
Navbar
()
...
...
uitwww/actions.py
0 → 100644
View file @
db1a1c78
# 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/>.
import
time
import
flask
from
uitwww
import
auth
ACTIONS_PER_PAGE
=
5
class
PageNotFoundError
(
BaseException
):
pass
def
log
(
message
,
session
=
None
):
"""Log an action into the database"""
date
=
int
(
time
.
time
())
if
session
is
None
:
session
=
flask
.
g
.
auth_id
flask
.
current_app
.
db
.
update
(
"INSERT INTO actions (session, date, message) VALUES (?, ?, ?);"
,
session
,
date
,
message
,
)
def
list_actions
(
page
=
None
,
session
=
None
):
"""List all the available actions"""
result
=
{
"actions"
:
[]
}
args
=
[]
where
=
""
if
session
is
not
None
:
where
=
"WHERE a.session = ?"
args
.
append
(
session
)
limit
=
""
if
page
is
not
None
:
page
=
page
-
1
total
=
flask
.
current_app
.
db
.
query
(
"SELECT COUNT(*) FROM actions %s;"
%
where
,
*
args
)[
0
][
0
]
if
page
<
0
or
page
>
total
%
ACTIONS_PER_PAGE
:
raise
PageNotFoundError
result
[
"current_page"
]
=
page
+
1
result
[
"has_prev"
]
=
page
!=
0
result
[
"has_next"
]
=
page
<
total
%
ACTIONS_PER_PAGE
limit
=
"LIMIT ? OFFSET ?"
args
+=
[
ACTIONS_PER_PAGE
,
page
*
ACTIONS_PER_PAGE
]
rows
=
flask
.
current_app
.
db
.
query
(
"SELECT s.nickname, s.ip, s.id, a.date, a.message FROM actions AS a "
"INNER JOIN auth_sessions AS s ON (s.id = a.session) %s "
"ORDER BY date DESC %s;"
%
(
where
,
limit
),
*
args
)
for
row
in
rows
:
result
[
"actions"
].
append
({
"nickname"
:
row
[
0
],
"ip"
:
row
[
1
],
"session"
:
row
[
2
],
"date"
:
row
[
3
],
"message"
:
row
[
4
],
})
return
result
def
prepare_blueprint
(
app
):
"""Prepare the auth blueprint"""
bp
=
flask
.
Blueprint
(
"actions"
,
__name__
)
@
bp
.
route
(
"/"
)
@
bp
.
route
(
"/<int:page>"
)
@
auth
.
permission
(
"actions.show"
)
def
show
(
page
=
1
):
try
:
actions
=
list_actions
(
page
=
page
)
except
PageNotFoundError
:
return
flask
.
abort
(
404
)
return
flask
.
render_template
(
"actions/show.html"
,
actions
=
actions
,
)
return
bp
uitwww/auth.py
View file @
db1a1c78
...
@@ -95,7 +95,7 @@ class Sessions:
...
@@ -95,7 +95,7 @@ class Sessions:
self
.
db
.
update
(
self
.
db
.
update
(
"UPDATE auth_sessions SET expires_at = ? WHERE id != ? AND "
"UPDATE auth_sessions SET expires_at = ? WHERE id != ? AND "
"expires_at IS NOT NULL AND expires_at >= ?;"
,
"expires_at IS NOT NULL AND expires_at >= ?;"
,
now
,
id
,
now
,
now
,
except_
id
,
now
,
)
)
def
all
(
self
):
def
all
(
self
):
...
@@ -205,6 +205,8 @@ def permission(perms):
...
@@ -205,6 +205,8 @@ def permission(perms):
def
prepare_blueprint
(
app
):
def
prepare_blueprint
(
app
):
"""Prepare the auth blueprint"""
"""Prepare the auth blueprint"""
from
uitwww
import
actions
bp
=
flask
.
Blueprint
(
"auth"
,
__name__
)
bp
=
flask
.
Blueprint
(
"auth"
,
__name__
)
oid
=
flask_openid
.
OpenID
(
oid
=
flask_openid
.
OpenID
(
...
@@ -246,6 +248,9 @@ def prepare_blueprint(app):
...
@@ -246,6 +248,9 @@ def prepare_blueprint(app):
flask
.
session
[
"auth"
]
=
sessions
.
create
(
resp
.
nickname
,
teams
)
flask
.
session
[
"auth"
]
=
sessions
.
create
(
resp
.
nickname
,
teams
)
flask
.
flash
(
"Benvenuto %s!"
%
resp
.
nickname
,
"success"
)
flask
.
flash
(
"Benvenuto %s!"
%
resp
.
nickname
,
"success"
)
actions
.
log
(
"Accesso effettuato"
,
session
=
flask
.
session
[
"auth"
])
return
flask
.
redirect
(
flask
.
url_for
(
"pages.index"
))
return
flask
.
redirect
(
flask
.
url_for
(
"pages.index"
))
@
bp
.
route
(
"/login"
)
@
bp
.
route
(
"/login"
)
...
@@ -284,6 +289,7 @@ def prepare_blueprint(app):
...
@@ -284,6 +289,7 @@ def prepare_blueprint(app):
@
bp
.
route
(
"/sessions/+all/revoke"
)
@
bp
.
route
(
"/sessions/+all/revoke"
)
@
permission
(
"auth.sessions.manage"
)
@
permission
(
"auth.sessions.manage"
)
def
sessions_revoke_all
():
def
sessions_revoke_all
():
actions
.
log
(
"Disabilitate tutte le altre sessioni"
)
sessions
.
disable_all
(
flask
.
g
.
auth_id
)
sessions
.
disable_all
(
flask
.
g
.
auth_id
)
return
flask
.
redirect
(
flask
.
url_for
(
".sessions_list"
))
return
flask
.
redirect
(
flask
.
url_for
(
".sessions_list"
))
...
@@ -304,10 +310,15 @@ def prepare_blueprint(app):
...
@@ -304,10 +310,15 @@ def prepare_blueprint(app):
continue
continue
others
.
append
(
session
)
others
.
append
(
session
)
user_actions
=
[]
if
app
.
permissions
.
check
(
"actions.show"
):
user_actions
=
actions
.
list_actions
(
session
=
id
)
return
flask
.
render_template
(
return
flask
.
render_template
(
"auth/session.html"
,
"auth/session.html"
,
session
=
data
,
session
=
data
,
others
=
others
,
others
=
others
,
actions
=
user_actions
,
)
)
@
bp
.
route
(
"/sessions/<id>/revoke"
)
@
bp
.
route
(
"/sessions/<id>/revoke"
)
...
@@ -316,6 +327,10 @@ def prepare_blueprint(app):
...
@@ -316,6 +327,10 @@ def prepare_blueprint(app):
"auth.sessions.own"
:
lambda
id
:
flask
.
g
.
auth_id
==
id
,
"auth.sessions.own"
:
lambda
id
:
flask
.
g
.
auth_id
==
id
,
})
})
def
sessions_revoke
(
id
):
def
sessions_revoke
(
id
):
actions
.
log
(
'Disabilitata <a href="%s">una sessione</a>'
%
flask
.
url_for
(
"auth.sessions_show"
,
id
=
id
)
)
sessions
.
disable
(
id
)
sessions
.
disable
(
id
)
return
flask
.
redirect
(
flask
.
url_for
(
".sessions_list"
))
return
flask
.
redirect
(
flask
.
url_for
(
".sessions_list"
))
...
...
uitwww/data/permissions.yml
View file @
db1a1c78
permissions
:
permissions
:
-
actions.show
-
auth.logout
-
auth.logout
-
auth.sessions.manage
-
auth.sessions.manage
-
auth.sessions.own
-
auth.sessions.own
...
...
uitwww/db.py
View file @
db1a1c78
...
@@ -89,4 +89,12 @@ MIGRATIONS = [
...
@@ -89,4 +89,12 @@ MIGRATIONS = [
(
"add_auth_sessions_created_at_column"
,
"""
(
"add_auth_sessions_created_at_column"
,
"""
ALTER TABLE auth_sessions ADD COLUMN created_at INTEGER;
ALTER TABLE auth_sessions ADD COLUMN created_at INTEGER;
"""
),
"""
),
(
"add_actions_table"
,
"""
CREATE TABLE actions (
session TEXT NOT NULL,
date INTEGER NOT NULL,
message TEXT NOT NULL
);
"""
),
]
]
uitwww/templates/actions/macros.html
0 → 100644
View file @
db1a1c78
{# 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
/>
.
#}
{% macro render_actions(actions, own=False) %}
<div
class=
"table"
>
<table>
<tr>
<th></th>
{% if not own %}
<th>
Nome utente
</th>
{% endif %}
<th>
Data e ora
</th>
{% if not own %}
<th>
Indirizzo IP
</th>
{% endif %}
</tr>
{% for action in actions.actions %}
<tr>
<td>
{{ action.message|safe }}
</td>
{% if not own %}
<td>
{{ action.nickname }}
</td>
{% endif %}
<td>
{{ action["date"]|format_timestamp }}
</td>
{% if not own %}
<td>
{% if (g.auth_name == action.nickname and permission("auth.sessions.own")) or permission("auth.sessions.manage") %}
<a
href=
"{{ url_for("
auth
.
sessions_show
",
id=
action.session)
}}"
>
{{ action.ip }}
</a>
{% else %}
{{ action.ip }}
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
<p
class=
"text-center"
>
{% if actions.current_page %}
{% if actions.has_prev %}
<a
href=
"{{ url_for(request.endpoint, page=actions.current_page - 1) }}"
>
Pagina precedente
</a>
-
{% endif %}
<b>
Pagina {{ actions.current_page }}
</b>
{% if actions.has_next %}
-
<a
href=
"{{ url_for(request.endpoint, page=actions.current_page + 1) }}"
>
Pagina successiva
</a>
{% endif %}
{% endif %}
</p>
{% endmacro %}
uitwww/templates/actions/show.html
0 → 100644
View file @
db1a1c78
{# 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" %}
{% from "actions/macros.html" import render_actions with context %}
{% block title %}Azioni recenti{% endblock %}
{% block content %}
<div
class=
"page"
>
<div
class=
"row"
>
<div
class=
"col"
>
<h1>
Azioni recenti
</h1>
{{ render_actions(actions) }}
</div>
</div>
</div>
{% endblock %}
uitwww/templates/auth/session.html
View file @
db1a1c78
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
#}
#}
{% extends "layout.html" %}
{% extends "layout.html" %}
{% from "actions/macros.html" import render_actions with context %}
{% block title %}Dettagli sessione{% endblock %}
{% block title %}Dettagli sessione{% endblock %}
...
@@ -116,4 +117,15 @@
...
@@ -116,4 +117,15 @@
</div>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% if permission("actions.show") and actions %}
<div
class=
"page"
>
<div
class=
"row"
>
<div
class=
"col"
>
<h2>
Azioni eseguite in questa sessione
</h2>
{{ render_actions(actions, own=True) }}
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% endblock %}
uitwww/templates/layout.html
View file @
db1a1c78
...
@@ -53,6 +53,11 @@
...
@@ -53,6 +53,11 @@
Sessioni attive: {{ g.auth_sessions_count }}
Sessioni attive: {{ g.auth_sessions_count }}
</a></li>
</a></li>
{% endif %}
{% endif %}
{% if permission("actions.show") %}
<li><a
href=
"{{ url_for("
actions
.
show
")
}}"
>
Azioni recenti
</a></li>
{% endif %}
</ul>
</ul>
<ul
class=
"right"
>
<ul
class=
"right"
>
{% if permission("auth.sessions.own") %}
{% if permission("auth.sessions.own") %}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment