auth: validate_new_password helper (min length 8)

Single source of truth for the password policy, to be reused by the
upcoming /profile/password endpoint and (optionally) the create-user
CLI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-11 21:45:03 +02:00
parent 2353378b23
commit a5982941df
No known key found for this signature in database
2 changed files with 27 additions and 0 deletions

View file

@ -21,6 +21,17 @@ def verify_password(raw: str, digest: str) -> bool:
return check_password_hash(digest, raw)
MIN_PASSWORD_LENGTH = 8
def validate_new_password(raw: str) -> str | None:
if raw == "":
return "password must not be empty"
if len(raw) < MIN_PASSWORD_LENGTH:
return f"password must be at least {MIN_PASSWORD_LENGTH} characters"
return None
def load_current_user() -> None:
user_id = session.get("user_id")
if user_id is None:

View file

@ -163,6 +163,22 @@ def test_create_user_cli_rejects_empty_environment_password(tmp_path, monkeypatc
assert "password must not be empty" in result.output
def test_validate_new_password_rejects_empty():
from l4d2web.auth import validate_new_password
assert validate_new_password("") == "password must not be empty"
def test_validate_new_password_rejects_short():
from l4d2web.auth import MIN_PASSWORD_LENGTH, validate_new_password
assert MIN_PASSWORD_LENGTH == 8
assert validate_new_password("a" * 7) == "password must be at least 8 characters"
def test_validate_new_password_accepts_min_length():
from l4d2web.auth import validate_new_password
assert validate_new_password("a" * 8) is None
def test_create_user_cli_rejects_duplicate_username(tmp_path, monkeypatch) -> None:
db_url = f"sqlite:///{tmp_path/'duplicate_user.db'}"
monkeypatch.setenv("DATABASE_URL", db_url)