src/auth/routes.py : route /auth/change-password (#73)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+21
-1
@@ -1,6 +1,6 @@
|
|||||||
from email_validator import EmailNotValidError, validate_email
|
from email_validator import EmailNotValidError, validate_email
|
||||||
from flask import Blueprint, redirect, request
|
from flask import Blueprint, redirect, request
|
||||||
from flask_login import login_user, logout_user
|
from flask_login import current_user, login_required, login_user, logout_user
|
||||||
from werkzeug.security import check_password_hash, generate_password_hash
|
from werkzeug.security import check_password_hash, generate_password_hash
|
||||||
|
|
||||||
from src.auth import db, mailer, tokens
|
from src.auth import db, mailer, tokens
|
||||||
@@ -145,3 +145,23 @@ def reset_password():
|
|||||||
|
|
||||||
db.update_password_hash(consumed, generate_password_hash(password))
|
db.update_password_hash(consumed, generate_password_hash(password))
|
||||||
return redirect("/connexion?password_changed=1")
|
return redirect("/connexion?password_changed=1")
|
||||||
|
|
||||||
|
|
||||||
|
@auth_bp.route("/change-password", methods=["POST"])
|
||||||
|
@login_required
|
||||||
|
def change_password():
|
||||||
|
current_pw = request.form.get("current_password") or ""
|
||||||
|
password = request.form.get("password") or ""
|
||||||
|
password_confirm = request.form.get("password_confirm") or ""
|
||||||
|
|
||||||
|
row = db.get_user_by_id(current_user.id)
|
||||||
|
if not check_password_hash(row["password_hash"], current_pw):
|
||||||
|
return _redirect_with_error("/compte", "invalid_current_password")
|
||||||
|
|
||||||
|
if len(password) < MIN_PASSWORD_LENGTH:
|
||||||
|
return _redirect_with_error("/compte", "password_too_short")
|
||||||
|
if password != password_confirm:
|
||||||
|
return _redirect_with_error("/compte", "password_mismatch")
|
||||||
|
|
||||||
|
db.update_password_hash(current_user.id, generate_password_hash(password))
|
||||||
|
return redirect("/compte?password_changed=1")
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
from werkzeug.security import check_password_hash, generate_password_hash
|
||||||
|
|
||||||
|
from src.auth import db
|
||||||
|
|
||||||
|
|
||||||
|
def _login(client, email="a@b.c", password="old-password12"):
|
||||||
|
db.init_schema()
|
||||||
|
uid = db.create_user(email, generate_password_hash(password))
|
||||||
|
db.set_email_verified(uid)
|
||||||
|
client.post("/auth/login", data={"email": email, "password": password})
|
||||||
|
return uid
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_requires_login(client, users_db_path):
|
||||||
|
resp = client.post(
|
||||||
|
"/auth/change-password",
|
||||||
|
data={
|
||||||
|
"current_password": "whatever",
|
||||||
|
"password": "new-password12",
|
||||||
|
"password_confirm": "new-password12",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code in (302, 401)
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_success(client, users_db_path):
|
||||||
|
uid = _login(client)
|
||||||
|
resp = client.post(
|
||||||
|
"/auth/change-password",
|
||||||
|
data={
|
||||||
|
"current_password": "old-password12",
|
||||||
|
"password": "new-password12",
|
||||||
|
"password_confirm": "new-password12",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 302
|
||||||
|
assert "password_changed=1" in resp.headers["Location"]
|
||||||
|
row = db.get_user_by_id(uid)
|
||||||
|
assert check_password_hash(row["password_hash"], "new-password12")
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_wrong_current(client, users_db_path):
|
||||||
|
uid = _login(client)
|
||||||
|
resp = client.post(
|
||||||
|
"/auth/change-password",
|
||||||
|
data={
|
||||||
|
"current_password": "wrong",
|
||||||
|
"password": "new-password12",
|
||||||
|
"password_confirm": "new-password12",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert "error=invalid_current_password" in resp.headers["Location"]
|
||||||
|
row = db.get_user_by_id(uid)
|
||||||
|
assert check_password_hash(row["password_hash"], "old-password12")
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_short(client, users_db_path):
|
||||||
|
_login(client)
|
||||||
|
resp = client.post(
|
||||||
|
"/auth/change-password",
|
||||||
|
data={
|
||||||
|
"current_password": "old-password12",
|
||||||
|
"password": "short",
|
||||||
|
"password_confirm": "short",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert "error=password_too_short" in resp.headers["Location"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_password_mismatch(client, users_db_path):
|
||||||
|
_login(client)
|
||||||
|
resp = client.post(
|
||||||
|
"/auth/change-password",
|
||||||
|
data={
|
||||||
|
"current_password": "old-password12",
|
||||||
|
"password": "new-password12",
|
||||||
|
"password_confirm": "autre-password12",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert "error=password_mismatch" in resp.headers["Location"]
|
||||||
Reference in New Issue
Block a user