feat(auth): RBAC ruoli + require_role + bootstrap admin (backend #235 Fase 1) - #239
Conversation
…ase 1) Autorizzazione separata dall'autenticazione (delegata all'IdP OIDC): - colonna opendata.users.role (migrazione 0016, default "cittadino") — R4. - auth/roles.py: ruoli admin/regione/comune/cittadino, resolve_role (sync utente al primo login + promozione bootstrap admin via BOOTSTRAP_ADMIN_EMAIL), require_role(*ruoli)/require_admin. Dev-bypass → admin. - ClerkUser.role (da claims["role"] popolato da resolve_role), users_repo.set_role. - .env.*.example: BOOTSTRAP_ADMIN_EMAIL. Prepara Fase 2 (admin API /admin/users) e la dashboard admin UI. Suite: 499 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a82390ee23
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| elif is_boot and row.role != ROLE_ADMIN: | ||
| row.role = ROLE_ADMIN | ||
| await session.commit() |
There was a problem hiding this comment.
Honor demotions for the bootstrap admin
When BOOTSTRAP_ADMIN_EMAIL remains configured after initial setup, any attempt to demote or revoke that account with set_role is undone on the next protected request because this branch re-promotes every matching existing row, not just newly-created users. That makes the bootstrap account permanently self-restoring unless operators edit the environment and restart, which conflicts with the documented first-login bootstrap flow.
Useful? React with 👍 / 👎.
|
|
||
| async def _dep( | ||
| user: ClerkUser = Depends(require_user), | ||
| session: AsyncSession = Depends(get_db_session), |
There was a problem hiding this comment.
Skip DB resolution before dev-bypass authz
When AUTH_ENABLED=false and DATABASE_URL is not configured or the session factory is not initialized, FastAPI resolves this get_db_session dependency before _dep can call resolve_role, so require_admin/require_role routes fail with the database initialization error instead of returning the intended dev admin. The app explicitly allows the database to be absent at boot, and this module documents dev-bypass as admin, so the DB session needs to be acquired lazily or bypassed in dev mode.
Useful? React with 👍 / 👎.
Prima fase della gestione utenti/ruoli confermata: autorizzazione nel nostro DB, autenticazione delegata all'IdP OIDC (Keycloak/SPID/email-OTP, step successivi).
Cosa fa
opendata.users.role(migrazione 0016, defaultcittadino) — R4, single head.admin/regione/comune/cittadino;resolve_role(sync utente al primo login + promozione bootstrap admin viaBOOTSTRAP_ADMIN_EMAIL);require_role(*ruoli)+require_admin. Dev-bypass → admin (UI admin usabile in locale).ClerkUser.role(daclaims["role"]popolato daresolve_role) +users_repo.set_role(pronto per l'admin PATCH)..env.*.example:BOOTSTRAP_ADMIN_EMAIL.Test (
tests/test_roles.py)dev-bypass→admin, default cittadino negato su rotta admin, bootstrap→admin, set_role + gate staff, persistenza al primo login. Suite backend 499 passed, 2 skipped; lint pulito;
alembic heads=0016unico.Prossime fasi (issue #235)
GET /admin/users+PATCH /admin/users/{id}/role; 3) sync Keycloak; 4) UI dashboard admin; 5) UI registrazione SPID + email-OTP; 6) frontend OIDC.Parte di #235.
🤖 Generated with Claude Code