feat(admin): API gestione ruoli utenti /admin/users (backend #235 Fase 2) - #240
Conversation
Superficie admin-only (require_admin):
- GET /admin/users — elenco utenti (filtro per ruolo, paginazione), newest-first.
- PATCH /admin/users/{id}/role — cambia ruolo (validato su VALID_ROLES), 404 se
utente inesistente, guardia anti-lockout (l'admin non può auto-degradarsi).
- repo: list_users, get_by_id, set_role_by_id.
- router registrato in main.py.
Autenticazione resta all'IdP; il ruolo vive in opendata.users.role. Suite 504 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: b7753ccebf
ℹ️ 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".
| stmt = stmt.where(User.deleted_at.is_(None)) | ||
| if role: | ||
| stmt = stmt.where(User.role == role) | ||
| stmt = stmt.order_by(User.created_at.desc()).limit(limit).offset(offset) |
There was a problem hiding this comment.
Add a deterministic tie-breaker to pagination
When multiple users have the same created_at value (for example rows inserted in one transaction, since the model uses a database now() default), this ordering leaves their relative order undefined. With limit/offset pagination on /admin/users, page boundaries can then repeat or skip users between requests; add a stable tie-breaker such as User.id.desc() after created_at.desc().
Useful? React with 👍 / 👎.
Fase 2 della gestione utenti: la API admin che alimenterà la dashboard admin (Fase 4).
Endpoint (tutti
require_admin)/admin/users— elenco utenti registrati (id, email, display_name, role, tier, created_at), newest-first, con filtro?role=e paginazionelimit/offset./admin/users/{id}/role— cambia il ruolo (validato suadmin/regione/comune/cittadino),404se utente sconosciuto, guardia anti-lockout: un admin non può auto-degradarsi.Note
opendata.users.role(Fase 1). Un non-admin riceve 403 su entrambi.list_users,get_by_id,set_role_by_id.Test (
tests/test_admin_users.py)403 per non-admin, list+filtro (+422 ruolo ignoto), cambio ruolo persistito, 422/404 su PATCH, guardia auto-degrado. Suite backend 504 passed, 2 skipped; lint pulito.
Prossime fasi (#235)
/admin; 5) UI registrazione SPID + email-OTP; 6) frontend OIDC.Parte di #235.
🤖 Generated with Claude Code