feat(web): self-onboarding multi-tenant + auth sesiune (PRD 3.3a)
Canalul web trece de la 100% deschis (hardcodat cont 1) la autentificat si multi-tenant. Un service nou se inregistreaza din browser, primeste o cheie API (o singura data) si o sesiune; contul se creeaza "in asteptare" (active=0) si nu trimite la RAR pana la activarea de catre admin (tools/account.py activate). - users + app/users.py: parole scrypt (salt per-user, eticheta parametri onorata la verify pentru migrare cost), email unic case-insensitive - sesiune: SessionMiddleware (same_site=strict, https_only config) + app/web/session.py (current_account/web_account/require_login->LoginRequired, set_session clear-inainte) - CSRF (app/web/csrf.py) enforce in prod inclusiv pe login/signup + rate-limit in-proces (app/web/ratelimit.py) pe signup si login - signup/login/logout (app/web/auth_routes.py): signup tranzactie atomica, cheie-o-data, log SIGNUP pentru descoperire admin - dashboard + import scoped pe contul sesiunii (regula NULL->cont 1); toate rutele web care ating date sensibile sub require_login; nomenclator ramane global - banner "cont in asteptare" pentru conturi active=0 - gate worker: claim_one LEFT JOIN accounts COALESCE(active,1)=1 (account_id NULL=activ) VERIFY context curat (2 runde): leak cross-account /_fragments/mapari prins+reparat. /code-review high: csrf_token lipsa pe re-randari de eroare, scrypt_params ignorat, login fara rate-limit -- toate reparate. 361 teste pass (de la 313). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,25 @@ class Settings(BaseSettings):
|
||||
# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
creds_key: str | None = None
|
||||
|
||||
# --- Sesiuni web (US-002, PRD 3.3) ---
|
||||
# Secret semnat cookie sesiune. None -> efemer la fiecare restart (dev ok;
|
||||
# in prod seteaza persistent ca si creds_key, altfel cookieurile se invalideaza
|
||||
# la restart). Genereaza: python -c "import secrets; print(secrets.token_hex(32))"
|
||||
session_secret: str | None = None
|
||||
# True (prod): rutele web fara sesiune -> redirect /login. False (dev): fara
|
||||
# sesiune -> cont implicit id=1, back-compat (C12/§5 Q5).
|
||||
web_auth_required: bool = False
|
||||
# True (prod, in spatele Cloudflare Tunnel TLS): cookie cu Secure flag (C4).
|
||||
# False (dev): cookie fara Secure, functioneaza pe HTTP.
|
||||
session_https_only: bool = False
|
||||
|
||||
# --- Rate-limit signup + login (US-009, PRD 3.3 C5) ---
|
||||
# Max cereri POST /signup per IP in fereastra de timp (in-proces, fara dependinta noua).
|
||||
signup_rate_max: int = 5
|
||||
signup_rate_window_s: int = 3600
|
||||
# Max incercari POST /login per IP (brute-force parole). Fereastra impartita cu signup.
|
||||
login_rate_max: int = 10
|
||||
|
||||
# --- RAR ---
|
||||
rar_env: str = "test" # "test" | "prod"
|
||||
rar_base_url_test: str = "https://apps.rarom.ro/test-rar-autopass"
|
||||
|
||||
Reference in New Issue
Block a user