refactor(auth): centralize token hashing, email validation & admin gating
- app/utils.py: shared valid_email() + now_utc() (one email regex, was duplicated in auth.py and admin.py with a looser "@"-in check elsewhere). - security.hash_token(): one SHA-256 token hasher (was duplicated in auth.py + state.py). - auth.admin_user dependency + count_admins() helper, replacing the inline role checks and the last-admin count query repeated across admin.py/me.py/tags.py.
This commit is contained in:
parent
8ef748c7b8
commit
63701f5344
7 changed files with 84 additions and 65 deletions
|
|
@ -1,5 +1,4 @@
|
|||
"""Global admin-controlled app state (e.g. pausing background sync, first-run setup)."""
|
||||
import hashlib
|
||||
import logging
|
||||
import secrets
|
||||
|
||||
|
|
@ -7,6 +6,7 @@ from sqlalchemy.orm import Session
|
|||
|
||||
from app.config import settings
|
||||
from app.models import AppState
|
||||
from app.security import hash_token
|
||||
|
||||
log = logging.getLogger("siftlode.state")
|
||||
|
||||
|
|
@ -73,16 +73,12 @@ def mark_configured(db: Session) -> None:
|
|||
log.info("Instance marked configured; setup wizard disabled.")
|
||||
|
||||
|
||||
def _hash_token(raw: str) -> str:
|
||||
return hashlib.sha256(raw.encode()).hexdigest()
|
||||
|
||||
|
||||
def rotate_setup_token(db: Session) -> str:
|
||||
"""Generate a fresh one-time setup token, persist only its hash, and return the raw token
|
||||
(logged at startup so the admin can open the wizard)."""
|
||||
raw = secrets.token_urlsafe(24)
|
||||
row = _row(db)
|
||||
row.setup_token_hash = _hash_token(raw)
|
||||
row.setup_token_hash = hash_token(raw)
|
||||
db.add(row)
|
||||
db.commit()
|
||||
return raw
|
||||
|
|
@ -93,7 +89,7 @@ def check_setup_token(db: Session, raw: str | None) -> bool:
|
|||
if not raw:
|
||||
return False
|
||||
stored = _row(db).setup_token_hash
|
||||
return stored is not None and secrets.compare_digest(stored, _hash_token(raw))
|
||||
return stored is not None and secrets.compare_digest(stored, hash_token(raw))
|
||||
|
||||
|
||||
def get_maintenance_batch(db: Session) -> int:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue