Change password

This commit is contained in:
2025-12-02 15:07:54 +01:00
parent 9547465661
commit e2dbdb49ea
3 changed files with 140 additions and 22 deletions

51
app.py
View File

@@ -11,6 +11,8 @@ from flask import (
) )
from functools import wraps from functools import wraps
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from werkzeug.security import generate_password_hash, check_password_hash
DATABASE = os.path.join(os.path.dirname(__file__), "avent.db") DATABASE = os.path.join(os.path.dirname(__file__), "avent.db")
UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), "static", "uploads") UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), "static", "uploads")
@@ -44,7 +46,9 @@ def init_db():
cur = db.execute("SELECT COUNT(*) AS c FROM user") cur = db.execute("SELECT COUNT(*) AS c FROM user")
if cur.fetchone()['c'] == 0: if cur.fetchone()['c'] == 0:
db.execute("INSERT INTO user (username, password) VALUES (?, ?)", ("admin", "admin")) hashed_admin = generate_password_hash("admin")
db.execute("INSERT INTO user (username, password) VALUES (?, ?)", ("admin", hashed_admin))
cur = db.execute("SELECT COUNT(*) AS c FROM project") cur = db.execute("SELECT COUNT(*) AS c FROM project")
if cur.fetchone()['c'] == 0: if cur.fetchone()['c'] == 0:
@@ -70,10 +74,11 @@ def get_user_by_username(username):
def check_login(username, password): def check_login(username, password):
user = get_user_by_username(username) user = get_user_by_username(username)
if user and user["password"] == password: if user and check_password_hash(user["password"], password):
return user return user
return None return None
def login_required(fn): def login_required(fn):
@wraps(fn) @wraps(fn)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
@@ -310,6 +315,48 @@ def admin_projects():
projects = get_project() projects = get_project()
return render_template("admin_projects.html", projects=projects) return render_template("admin_projects.html", projects=projects)
@app.route("/admin/change-password", methods=["GET", "POST"])
@login_required
def admin_change_password():
"""Page admin pour changer le mot de passe"""
db = get_db()
if request.method == "POST":
current_password = request.form.get("current_password")
new_password = request.form.get("new_password")
confirm_password = request.form.get("confirm_password")
# Récupérer l'utilisateur connecté
user_id = session.get("user_id")
cur = db.execute("SELECT password FROM user WHERE id = ?", (user_id,))
user = cur.fetchone()
if not user:
flash("Erreur utilisateur.")
return render_template("admin_change_password.html")
# Vérifier mot de passe actuel
if not check_password_hash(user["password"], current_password):
flash("Mot de passe actuel incorrect.")
return render_template("admin_change_password.html")
# Vérifications
if new_password != confirm_password:
flash("Les nouveaux mots de passe ne correspondent pas.")
return render_template("admin_change_password.html")
if len(new_password) < 6:
flash("Le nouveau mot de passe doit faire au moins 6 caractères.")
return render_template("admin_change_password.html")
# Hash et mise à jour
hashed_password = generate_password_hash(new_password)
db.execute("UPDATE user SET password = ? WHERE id = ?", (hashed_password, user_id))
db.commit()
flash("✅ Mot de passe changé avec succès !")
return redirect(url_for("admin_projects"))
return render_template("admin_change_password.html")
@app.route("/admin/project/<int:project_id>/people", methods=["GET", "POST"]) @app.route("/admin/project/<int:project_id>/people", methods=["GET", "POST"])
@login_required @login_required

View File

@@ -0,0 +1,65 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Changer mot de passe - Admin</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow-lg">
<div class="card-header bg-primary text-white text-center">
<h2 class="mb-0">
<i class="fas fa-key me-2"></i>Changer mot de passe
</h2>
</div>
<div class="card-body p-4">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-info alert-dismissible fade show mb-4">
{% for msg in messages %}
<div>{{ msg }}</div>
{% endfor %}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endif %}
{% endwith %}
<form method="post">
<div class="mb-3">
<label class="form-label fw-bold">Mot de passe actuel</label>
<input type="password" name="current_password" class="form-control" required autocomplete="current-password">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-bold">Nouveau mot de passe</label>
<input type="password" name="new_password" class="form-control" minlength="6" required autocomplete="new-password">
<small class="text-muted">Minimum 6 caractères</small>
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-bold">Confirmer nouveau</label>
<input type="password" name="confirm_password" class="form-control" minlength="6" required autocomplete="new-password">
</div>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{{ url_for('admin_projects') }}" class="btn btn-outline-secondary me-md-2">
<i class="fas fa-arrow-left me-1"></i>Retour
</a>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-1"></i>Changer mot de passe
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -3,29 +3,37 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Administration des projets</title> <title>Administration des projets</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet" />
</head> </head>
<body class="bg-light"> <body class="bg-light">
<div class="container py-5"> <div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4"> <div class="d-flex justify-content-between align-items-center mb-4">
<h1>Gestion des projets</h1> <h1>Gestion des projets</h1>
<a href="{{ url_for('dashboard') }}" class="btn btn-outline-primary"> <div>
<i class="fas fa-arrow-left me-2"></i>Tableau de bord <span class="badge bg-success me-3">Connecté: {{ session.username }}</span>
</a> <a href="{{ url_for('admin_change_password') }}" class="btn btn-outline-warning btn-sm me-2">
<i class="fas fa-key me-1"></i>Changer mot de passe
</a>
<a href="{{ url_for('logout') }}" class="btn btn-outline-danger btn-sm">
<i class="fas fa-sign-out-alt me-1"></i>Déconnexion
</a>
</div>
</div> </div>
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div class="alert alert-info alert-dismissible fade show"> <div class="alert alert-info alert-dismissible fade show">
{% for m in messages %} {% for m in messages %}
<div><i class="fas fa-info-circle me-2"></i>{{ m }}</div> <div><i class="fas fa-info-circle me-2"></i>{{ m }}</div>
{% endfor %} {% endfor %}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button> <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div> </div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<!-- Formulaire ajout projet -->
<div class="card mb-5"> <div class="card mb-5">
<div class="card-header bg-primary text-white"> <div class="card-header bg-primary text-white">
<h3 class="mb-0"><i class="fas fa-plus me-2"></i>Ajouter un projet</h3> <h3 class="mb-0"><i class="fas fa-plus me-2"></i>Ajouter un projet</h3>
@@ -44,7 +52,7 @@
<small class="text-muted">PNG, JPG, GIF (max 5 Mo)</small> <small class="text-muted">PNG, JPG, GIF (max 5 Mo)</small>
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<input type="number" name="total_days" class="form-control" value="24" min="1" max="365" required /> <input type="number" name="total_days" class="form-control" placeholder="Nombre de jours" value="24" min="1" max="365" required />
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<button class="btn btn-primary w-100" type="submit"> <button class="btn btn-primary w-100" type="submit">
@@ -55,6 +63,7 @@
</div> </div>
</div> </div>
<!-- Liste projets -->
<h3>Projets existants ({{ projects|length }})</h3> <h3>Projets existants ({{ projects|length }})</h3>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">
@@ -76,7 +85,7 @@
<td>{{ proj.id }}</td> <td>{{ proj.id }}</td>
<td> <td>
{% if proj.image_url %} {% if proj.image_url %}
<img src="{{ proj.image_url }}" alt="Illustration" style="width:50px; height:50px; object-fit:cover; border-radius:5px;"> <img src="{{ proj.image_url }}" alt="Illustration" style="width:50px; height:50px; object-fit:cover; border-radius:5px;" />
{% else %} {% else %}
<span class="text-muted"></span> <span class="text-muted"></span>
{% endif %} {% endif %}
@@ -95,8 +104,7 @@
<button name="action" value="update" class="btn btn-sm btn-success me-2" type="submit"> <button name="action" value="update" class="btn btn-sm btn-success me-2" type="submit">
<i class="fas fa-save"></i> Sauvegarder <i class="fas fa-save"></i> Sauvegarder
</button> </button>
<button name="action" value="delete" class="btn btn-sm btn-danger me-2" type="submit" <button name="action" value="delete" class="btn btn-sm btn-danger me-2" type="submit" onclick="return confirm('Supprimer ce projet ?');">
onclick="return confirm('Supprimer ce projet ?');">
<i class="fas fa-trash"></i> Supprimer <i class="fas fa-trash"></i> Supprimer
</button> </button>
<a href="{{ url_for('admin_project_people', project_id=proj.id) }}" class="btn btn-sm btn-primary" title="Gérer utilisateurs"> <a href="{{ url_for('admin_project_people', project_id=proj.id) }}" class="btn btn-sm btn-primary" title="Gérer utilisateurs">
@@ -110,9 +118,7 @@
</table> </table>
</div> </div>
<a href="{{ url_for('dashboard') }}" class="btn btn-link mt-3">Retour au tableau de bord</a>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body> </body>
</html> </html>