Add /settings

This commit is contained in:
augustin64 2024-02-25 15:28:51 +01:00
parent 3f83f1c44a
commit b9a5f92a56
11 changed files with 310 additions and 62 deletions

View File

@ -92,8 +92,9 @@ pybabel update -i partitioncloud/translations/messages.pot -d partitioncloud/tra
```
## TODO
- [ ] Modifier son mot de passe
- [ ] Supprimer un utilisateur
- [x] Modifier son mot de passe
- [x] Supprimer un utilisateur
- [ ] Ajouter config:DISABLE_DARK_MODE
- [x] Ajouter config:DISABLE_REGISTER
- [ ] Ajouter config:ONLINE_SEARCH_BASE_QUERY pour la recherche google, actuellement 'filetype:pdf partition'
- [ ] Ajouter un Dockerfile

View File

@ -13,7 +13,7 @@ from werkzeug.security import generate_password_hash
from flask_babel import Babel, _
from .modules.utils import User, Album, get_all_albums, user_count, partition_count
from .modules import albums, auth, partition, admin, groupe, thumbnails, logging
from .modules import albums, auth, partition, admin, groupe, thumbnails, logging, settings
from .modules.auth import admin_required, login_required
from .modules.db import get_db
@ -91,6 +91,7 @@ app.register_blueprint(auth.bp)
app.register_blueprint(admin.bp)
app.register_blueprint(groupe.bp)
app.register_blueprint(albums.bp)
app.register_blueprint(settings.bp)
app.register_blueprint(partition.bp)
app.register_blueprint(thumbnails.bp)

View File

@ -19,7 +19,6 @@ def index():
Admin panel home page
"""
current_user = User(user_id=session.get("user_id"))
current_user.get_albums() # We need to do that before we close the db
db = get_db()
users_id = db.execute(
"""
@ -37,6 +36,23 @@ def index():
user=current_user
)
@bp.route("/user/<user_id>")
@admin_required
def user_inspect(user_id):
"""
Inspect user
"""
current_user = User(user_id=session.get("user_id"))
db = get_db()
inspected_user = User(user_id=user_id)
return render_template(
"settings/index.html",
skip_old_password=True,
inspected_user=inspected_user,
user=current_user
)
@bp.route("/logs")
@admin_required

View File

@ -1,4 +1,5 @@
from flask import current_app
from werkzeug.security import generate_password_hash
from ..db import get_db
from .album import Album
@ -28,6 +29,7 @@ class User():
def __init__(self, user_id=None, name=None):
self.id = user_id
self.username = name
self.password = None
self.albums = None
self.groupes = None
self.partitions = None
@ -58,6 +60,7 @@ class User():
self.id = data["id"]
self.username = data["username"]
self.password = data["password"]
self.access_level = data["access_level"]
self.color = self.get_color()
if self.access_level == 1:
@ -198,12 +201,10 @@ class User():
db.execute(
"""
DELETE FROM contient_user
JOIN album
ON album.id = album_id
WHERE user_id = ?
AND album.uuid = ?
WHERE album_id IN (SELECT id FROM album WHERE uuid = ?)
AND user_id = ?
""",
(self.id, album_uuid)
(album_uuid, self.id)
)
db.commit()
@ -221,6 +222,49 @@ class User():
)
db.commit()
def update_password(self, new_password):
db = get_db()
db.execute(
"""
UPDATE user SET password=?
WHERE id=?
""",
(generate_password_hash(new_password), self.id)
)
db.commit()
def delete(self):
instance_path = current_app.config["INSTANCE_PATH"]
for groupe in self.get_groupes():
self.quit_groupe(groupe.uuid)
if groupe.get_users() == []:
groupe.delete(instance_path)
for album_data in self.get_albums():
uuid = album_data["uuid"]
self.quit_album(uuid)
album = Album(uuid=uuid)
if album.get_users() == []:
album.delete(instance_path)
db = get_db()
db.execute(
"""
DELETE FROM user
WHERE id=?
""",
(self.id,)
)
db.commit()
def get_color(self):
if len(colors) == 0:

View File

@ -0,0 +1,90 @@
#!/usr/bin/python3
"""
User Settings
"""
import os
from flask import Blueprint, render_template, session, current_app, send_file, request, flash, redirect
from werkzeug.security import check_password_hash
from flask_babel import _
from .db import get_db
from .auth import login_required
from .utils import User
bp = Blueprint("settings", __name__, url_prefix="/settings")
@bp.route("/")
@login_required
def index():
"""
Settings page
"""
user = User(user_id=session.get("user_id"))
return render_template(
"settings/index.html",
inspected_user=user,
user=user
)
@bp.route("/delete-account", methods=["POST"])
@login_required
def delete_account():
if "user_id" not in request.form:
flash(_("Missing user id."))
return redirect(request.referrer)
cur_user = User(user_id=session.get("user_id"))
user_id = request.form["user_id"]
mod_user = User(user_id=user_id)
if cur_user.access_level != 1:
if cur_user.id != mod_user.id:
flash(_("Missing rights."))
return redirect(request.referrer)
mod_user.delete()
flash(_("User successfully deleted."))
if cur_user.id == mod_user.id:
return redirect("/")
return redirect("/admin")
@bp.route("/change-password", methods=["POST"])
@login_required
def change_password():
if "user_id" not in request.form:
flash(_("Missing user id."))
return redirect(request.referrer)
cur_user = User(user_id=session.get("user_id"))
user_id = request.form["user_id"]
mod_user = User(user_id=user_id)
if cur_user.access_level != 1:
if cur_user.id != mod_user.id:
flash(_("Missing rights."))
return redirect(request.referrer)
if "old_password" not in request.form:
flash(_("Missing old password."))
return redirect(request.referrer)
if not check_password_hash(mod_user.password, request.form["old_password"]):
flash(_("Incorrect password."))
return redirect(request.referrer)
if "new_password" not in request.form or "confirm_new_password" not in request.form:
flash(_("Missing password."))
return redirect(request.referrer)
if request.form["new_password"] != request.form["confirm_new_password"]:
flash(_("Password and its confirmation differ."))
return redirect(request.referrer)
mod_user.update_password(request.form["new_password"])
flash(_("Successfully updated password."))
return redirect(request.referrer)

View File

@ -4,7 +4,7 @@
/** Various settings (variables) */
:root {
--sidebar-size: max(10vw, 160px);
--sidebar-size: max(10vw, 250px);
--sidebar-sz-plus10: calc(var(--sidebar-size) + 10px);
--sidebar-sz-moins20: calc(var(--sidebar-size) - 20px);
}
@ -333,6 +333,7 @@ img.partition-thumbnail {
.user {
display: flex;
color: var(--color-text);
}
.username {
@ -387,12 +388,13 @@ a#delete-album {
transform: translateY(-17%);
}
#settings-container>.user {
#settings-container > a > .user {
margin-top: 6px;
border-radius: 3px;
padding: 3px;
}
#settings-container>.user:hover {
#settings-container > a > .user:hover {
background-color: var(--color-mantle);
}
@ -538,6 +540,8 @@ input[type="file"] {
/** Dangerous buttons */
button#logout:hover,
a#delete-album:hover,
.red-confirm,
input[type="submit"].red-confirm,
#delete-partition {
background-color: var(--color-red);
color: var(--color-mantle);

View File

@ -34,7 +34,9 @@
title="{{ user.username }}">
{{ user.username[0] | upper }}
</div>
<div class="table-username">{{ user.username }}</div>
<div class="table-username">
<a href="/admin/user/{{ user.id }}">{{ user.username }}</a>
</div>
</div>
</td>
<td>{{ user.albums | length }}</td>

View File

@ -157,13 +157,13 @@
</svg>{{ _("Admin Panel") }}
</button></a><br/>
{% endif %}
<div class="user">
<a href="/settings"><div class="user">
<div class="user-profile-picture" style="background-color:{{ user.color }};"
title="{{ user.username }}">
{{ user.username[0] | upper }}
</div>
<div class="username">{{ user.username }}</div>
</div>
</div></a>
{% else %}
{% if not config.DISABLE_REGISTER %}
<a href="{{ url_for('auth.register') }}"><button>{{ _("Create account") }}</button></a>

View File

@ -0,0 +1,42 @@
{% extends 'base.html' %}
{% block title %}{{ _("Settings") }}{% endblock %}
{% block dialogs %}
<dialog id="delete-account">
<h2>{{ _("Delete account") }}</h2>
{% set username %}
<b>{{ inspected_user.username }}</b>
{% endset %}
{% set irreversible_bold %}
<b>irreversible</b>
{% endset %}
{{ _("Do you really want to delete %(username)s's account ? This action is %(irreversible_bold)s.", username=username, irreversible_bold=irreversible_bold) }}
<br/><br/>
<form method="post" action="/settings/delete-account">
<input type="hidden" id="user_id" name="user_id" value="{{ inspected_user.id }}">
<input type="submit" class="red-confirm" value="{{ _('Delete') }}">
</form>
<a href="#!" class="close-dialog">Close</a>
</dialog>
{% endblock %}
{% block content %}
{{ _("User %(username)s has %(album_count)s albums"), username=inspected_user.username, album_count=len(inspected_user.get_albums()) }}
<form action="/settings/change-password" method="post">
<h3>{{ _("Change password") }}</h3>
{% if not skip_old_password %}
<input type="password" id="old-password" name="old_password" placeholder="{{ _('old password') }}"/><br/>
{% endif %}
<input type="password" id="new-password" name="new_password" placeholder="{{ _('new password') }}"/><br/>
<input type="password" id="confirm-new-password" name="confirm_new_password" placeholder="{{ _('confirm new password') }}"/><br/>
<input type="hidden" id="user_id" name="user_id" value="{{ inspected_user.id }}">
<input type="Submit" value="{{ _('confirm') }}">
</form>
<h3>{{ _("Delete account") }}</h3>
<a href="#delete-account"><button class="red-confirm">{{ _("Delete account") }}</button></a>
{% endblock %}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-01-29 18:32+0100\n"
"POT-Creation-Date: 2024-02-25 15:18+0100\n"
"PO-Revision-Date: 2024-01-22 15:38+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
@ -18,12 +18,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"
#: partitioncloud/__init__.py:147
#: partitioncloud/__init__.py:148
#, python-format
msgid "Created user %(username)s"
msgstr "Created user %(username)s"
#: partitioncloud/__init__.py:150
#: partitioncloud/__init__.py:151
#, python-format
msgid "This album does not exists, but user %(username)s has been created"
msgstr "This album does not exists, but user %(username)s has been created"
@ -116,7 +116,8 @@ msgstr "Unknown score type."
msgid "You need to login to access this resource."
msgstr "You need to login to access this resource."
#: partitioncloud/modules/auth.py:59
#: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:46
#: partitioncloud/modules/settings.py:69
msgid "Missing rights."
msgstr "Missing rights."
@ -124,7 +125,7 @@ msgstr "Missing rights."
msgid "Missing username."
msgstr "Missing username."
#: partitioncloud/modules/auth.py:87
#: partitioncloud/modules/auth.py:87 partitioncloud/modules/settings.py:81
msgid "Missing password."
msgstr "Missing password."
@ -217,79 +218,103 @@ msgstr "You are not allowed to delete this score."
msgid "Score deleted."
msgstr "Score deleted."
#: partitioncloud/templates/base.html:25
#: partitioncloud/modules/settings.py:37 partitioncloud/modules/settings.py:60
msgid "Missing user id."
msgstr "Missing user id."
#: partitioncloud/modules/settings.py:50
msgid "User successfully deleted."
msgstr "User successfully deleted."
#: partitioncloud/modules/settings.py:73
msgid "Missing old password."
msgstr "Missing old password."
#: partitioncloud/modules/settings.py:77
msgid "Incorrect password."
msgstr "Incorrect password."
#: partitioncloud/modules/settings.py:85
msgid "Password and its confirmation differ."
msgstr "Password and its confirmation differ."
#: partitioncloud/modules/settings.py:89
msgid "Successfully updated password."
msgstr "Successfully updated password."
#: partitioncloud/templates/base.html:26
msgid "New Album"
msgstr "New Album"
#: partitioncloud/templates/base.html:27 partitioncloud/templates/base.html:38
#: partitioncloud/templates/base.html:28 partitioncloud/templates/base.html:39
#: partitioncloud/templates/groupe/index.html:10
#: partitioncloud/templates/partition/attachments.html:11
msgid "Name"
msgstr "Name"
#: partitioncloud/templates/base.html:28 partitioncloud/templates/base.html:39
#: partitioncloud/templates/base.html:29 partitioncloud/templates/base.html:40
msgid "Create"
msgstr "Create"
#: partitioncloud/templates/base.html:32
#: partitioncloud/templates/base.html:33
msgid "I want to create a collection of albums."
msgstr "I want to create a collection of albums."
#: partitioncloud/templates/base.html:32
#: partitioncloud/templates/base.html:33
msgid "Create group"
msgstr "Create group"
#: partitioncloud/templates/base.html:36
#: partitioncloud/templates/base.html:37
msgid "Create new group"
msgstr "Create new group"
#: partitioncloud/templates/base.html:63
#: partitioncloud/templates/base.html:64
msgid "Search"
msgstr "Search"
#: partitioncloud/templates/base.html:65
#: partitioncloud/templates/base.html:66
msgid "Number of online searches"
msgstr "Number of online searches"
#: partitioncloud/templates/admin/index.html:23
#: partitioncloud/templates/base.html:73
#: partitioncloud/templates/base.html:74
#: partitioncloud/templates/partition/details.html:41
msgid "Albums"
msgstr "Albums"
#: partitioncloud/templates/base.html:77
#: partitioncloud/templates/base.html:78
msgid "New album"
msgstr "New album"
#: partitioncloud/templates/base.html:94
#: partitioncloud/templates/base.html:95
msgid "No albums"
msgstr "No albums"
#: partitioncloud/templates/base.html:113
#: partitioncloud/templates/base.html:114
msgid "No album available"
msgstr "No album available"
#: partitioncloud/templates/base.html:127
#: partitioncloud/templates/base.html:128
msgid "Log in to see your albums"
msgstr "Log in to see your albums"
#: partitioncloud/templates/base.html:141
#: partitioncloud/templates/base.html:142
msgid "Log out"
msgstr "Log out"
#: partitioncloud/templates/base.html:156
#: partitioncloud/templates/base.html:157
msgid "Admin Panel"
msgstr "Admin Panel"
#: partitioncloud/templates/auth/register.html:5
#: partitioncloud/templates/auth/register.html:20
#: partitioncloud/templates/base.html:168
#: partitioncloud/templates/base.html:169
msgid "Create account"
msgstr "Create account"
#: partitioncloud/templates/auth/login.html:5
#: partitioncloud/templates/auth/login.html:10
#: partitioncloud/templates/base.html:170
#: partitioncloud/templates/base.html:171
#: partitioncloud/templates/launch.html:26
msgid "Log in"
msgstr "Log in"
@ -315,9 +340,7 @@ msgstr "Check code"
msgid ""
"This instance is used by %(users)s users with a total of %(scores)s "
"scores."
msgstr ""
"This instance has %(users)s users with a total of %(scores)s "
"scores."
msgstr "This instance has %(users)s users with a total of %(scores)s scores."
#: partitioncloud/templates/admin/index.html:5
msgid "Administration Panel"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-01-29 18:32+0100\n"
"POT-Creation-Date: 2024-02-25 15:18+0100\n"
"PO-Revision-Date: 2024-01-22 15:24+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n"
@ -18,12 +18,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"
#: partitioncloud/__init__.py:147
#: partitioncloud/__init__.py:148
#, python-format
msgid "Created user %(username)s"
msgstr "Utilisateur %(username)s créé"
#: partitioncloud/__init__.py:150
#: partitioncloud/__init__.py:151
#, python-format
msgid "This album does not exists, but user %(username)s has been created"
msgstr "Cet album n'existe pas. L'utilisateur %(username)s a été créé"
@ -116,7 +116,8 @@ msgstr "Type de partition inconnu."
msgid "You need to login to access this resource."
msgstr "Vous devez être connecté pour accéder à cette page."
#: partitioncloud/modules/auth.py:59
#: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:46
#: partitioncloud/modules/settings.py:69
msgid "Missing rights."
msgstr "Droits insuffisants."
@ -124,7 +125,7 @@ msgstr "Droits insuffisants."
msgid "Missing username."
msgstr "Un nom d'utilisateur est requis."
#: partitioncloud/modules/auth.py:87
#: partitioncloud/modules/auth.py:87 partitioncloud/modules/settings.py:81
msgid "Missing password."
msgstr "Un mot de passe est requis."
@ -219,81 +220,105 @@ msgstr "Vous n'êtes pas autorisé à supprimer cette partition."
msgid "Score deleted."
msgstr "Partition supprimée."
#: partitioncloud/templates/base.html:25
#: partitioncloud/modules/settings.py:37 partitioncloud/modules/settings.py:60
msgid "Missing user id."
msgstr "Identifiant d'utilisateur manquant."
#: partitioncloud/modules/settings.py:50
msgid "User successfully deleted."
msgstr "Utilisateur supprimée."
#: partitioncloud/modules/settings.py:73
msgid "Missing old password."
msgstr "Ancien mot de passe manquant."
#: partitioncloud/modules/settings.py:77
msgid "Incorrect password."
msgstr "Mot de passe incorrect."
#: partitioncloud/modules/settings.py:85
msgid "Password and its confirmation differ."
msgstr "Le mot de passe et sa confirmation diffèrent"
#: partitioncloud/modules/settings.py:89
msgid "Successfully updated password."
msgstr "Mot de passe mis à jour."
#: partitioncloud/templates/base.html:26
msgid "New Album"
msgstr "Créer un nouvel album"
#: partitioncloud/templates/base.html:27 partitioncloud/templates/base.html:38
#: partitioncloud/templates/base.html:28 partitioncloud/templates/base.html:39
#: partitioncloud/templates/groupe/index.html:10
#: partitioncloud/templates/partition/attachments.html:11
msgid "Name"
msgstr "Nom"
#: partitioncloud/templates/base.html:28 partitioncloud/templates/base.html:39
#: partitioncloud/templates/base.html:29 partitioncloud/templates/base.html:40
msgid "Create"
msgstr "Créer"
#: partitioncloud/templates/base.html:32
#: partitioncloud/templates/base.html:33
msgid "I want to create a collection of albums."
msgstr ""
"Je souhaite créer plusieurs albums et pouvoir tous les partager avec un "
"seul lien."
#: partitioncloud/templates/base.html:32
#: partitioncloud/templates/base.html:33
msgid "Create group"
msgstr "Créer un groupe"
#: partitioncloud/templates/base.html:36
#: partitioncloud/templates/base.html:37
msgid "Create new group"
msgstr "Créer un nouveau groupe"
#: partitioncloud/templates/base.html:63
#: partitioncloud/templates/base.html:64
msgid "Search"
msgstr "Rechercher"
#: partitioncloud/templates/base.html:65
#: partitioncloud/templates/base.html:66
msgid "Number of online searches"
msgstr "Nombre de recherches en ligne"
#: partitioncloud/templates/admin/index.html:23
#: partitioncloud/templates/base.html:73
#: partitioncloud/templates/base.html:74
#: partitioncloud/templates/partition/details.html:41
msgid "Albums"
msgstr "Albums"
#: partitioncloud/templates/base.html:77
#: partitioncloud/templates/base.html:78
msgid "New album"
msgstr "Créer un album"
#: partitioncloud/templates/base.html:94
#: partitioncloud/templates/base.html:95
msgid "No albums"
msgstr "Aucun album disponible"
#: partitioncloud/templates/base.html:113
#: partitioncloud/templates/base.html:114
msgid "No album available"
msgstr "Aucun album disponible"
#: partitioncloud/templates/base.html:127
#: partitioncloud/templates/base.html:128
msgid "Log in to see your albums"
msgstr "Connectez vous pour avoir accès à vos albums"
#: partitioncloud/templates/base.html:141
#: partitioncloud/templates/base.html:142
msgid "Log out"
msgstr "Déconnexion"
#: partitioncloud/templates/base.html:156
#: partitioncloud/templates/base.html:157
msgid "Admin Panel"
msgstr "Panneau admin"
#: partitioncloud/templates/auth/register.html:5
#: partitioncloud/templates/auth/register.html:20
#: partitioncloud/templates/base.html:168
#: partitioncloud/templates/base.html:169
msgid "Create account"
msgstr "Créer un compte"
#: partitioncloud/templates/auth/login.html:5
#: partitioncloud/templates/auth/login.html:10
#: partitioncloud/templates/base.html:170
#: partitioncloud/templates/base.html:171
#: partitioncloud/templates/launch.html:26
msgid "Log in"
msgstr "Se connecter"