Commit Graph

3 Commits

Author SHA1 Message Date
Damir Radulić bd3773434e CC2 R4 #6: real TOTP 2FA (setup + verify + disable + login flow)
- auth/auth_v2.py:
  - pyotp-based TOTP (RFC 6238, base32 secret, ±30s window)
  - new pgz_sport.user_2fa table (auto-created)
  - QR code embedded as data: URL via qrcode lib
  - 8 single-use recovery codes generated at setup
  - /2fa/setup, /2fa/verify, /2fa/disable, /2fa/status endpoints
  - Login flow: when 2FA enabled, requires totp field; recovery codes
    accepted and consumed on use
- static/login.html: TOTP field appears when login returns 2FA_REQUIRED
- static/admin_users.html: full 2FA panel in Sigurnost tab
  (status badge, QR + secret + recovery code display, verify input)

Live tests pass:
  T1 status (no setup) → enabled:false
  T2 setup → secret + 1.5KB QR PNG + 8 recovery codes
  T3 verify wrong code → 401
  T4 verify real TOTP → enabled:true
  T5 login w/o TOTP after enable → 401 detail=2FA_REQUIRED
  T6 login w/ TOTP → 200
2026-05-05 00:50:28 +02:00
Damir Radulić cb3faee731 CC3 R3 M4+: avatar upload, PUT /api/auth/me, /uploads mount
Backend (auth/auth_v2.py + pgz_sport_api.py):
- POST /api/auth/me/avatar  (multipart, jpeg/png/webp ≤5 MB) -> /uploads/avatars/{userid}_{ts}.ext
- DELETE /api/auth/me/avatar  (uklanja datoteku + briše users.avatar_url)
- PUT /api/auth/me  (UpdateMeReq: ime/prezime/full_name/telefon/phone/preferred_language/oib)
- GET /api/auth/me  proširen s avatar_url, two_factor_enabled, gdpr_consent_at, google_picture
- StaticFiles mount /uploads -> /opt/pgz-sport/uploads
- DB: ALTER TABLE pgz_sport.users ADD COLUMN avatar_url TEXT
- Audit: profile.update, profile.avatar_upload, profile.avatar_delete

Backups: _backups/auth_v2.py.cc3_pre_avatar.*, pgz_sport_api.py.cc3_pre_avatar.*

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 00:44:14 +02:00
Damir Radulić 492c8fdd87 M1+M2+M10 (CC2 R3): JWT auth + admin users + GDPR backend
- auth/auth_v2.py: JWT login/refresh/logout/me + bcrypt + tenant_id/role/tier claims
- auth/admin_users.py: /api/admin/users CRUD + invite/role/suspend + bulk CSV
- auth/gdpr.py: cookie consent + Art.20 export + Art.17 erasure + admin queue
- auth/seed_demo.py: 3 demo tenants + 4 users (damir@pgz.hr / PGZ2026!)
- Removed legacy /api/auth/login + /api/auth/me from pgz_sport_api.py
- Wired auth/admin/gdpr routers into FastAPI

5/5 live curl tests pass: damir@pgz.hr login → JWT with tenant_id=1, role=pgz_admin, tier=0
2026-05-05 00:09:09 +02:00