Collapse the Role enum from viewer/editor/admin to two kinds (admin/user);
non-admin access now comes entirely from permission groups + overrides.
Backend:
- Role -> StrEnum {USER, ADMIN}, VARCHAR-backed (native_enum=False); Role.coerce
maps legacy/unknown strings (incl. in-flight invites) to USER.
- Resolver: group-less users fall back to the default group (dropped the
role-based legacy fallback); kiosk caps all non-admins to read-only.
- OIDC editor/viewer claims both map to USER (env var names unchanged).
- Migration 0092 converts the native enum to VARCHAR and normalizes
ADMIN->admin, VIEWER/EDITOR->user.
- Updated endpoints, conftest fixtures, role/oidc/parity/db-handler tests, tools.
Frontend:
- v2 + v1 user management now use admin/user (dropdowns, defaults, getRoleIcon).
- Regenerated types (Role = 'user' | 'admin'); added role-user i18n to all locales.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gate automatic account creation on OIDC login behind a new OIDC_ALLOW_REGISTRATION environment variable. Defaults to true, preserving the current auto-provisioning behavior; set it to false to run OIDC in an "existing users only" mode, where a login from an email without an existing RomM account is rejected with a 403 instead of silently creating one. Existing users are unaffected either way.
Adds the config constant, env.template and docs entries, and tests covering the enabled/disabled and existing-user paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Use atomic getdel for pairing code exchange
- Add cascade="all, delete-orphan" to User.client_tokens
- Move generate/hash_client_token into AuthHandler as static methods
- Extract endpoint helpers to utils/client_tokens.py
Three tests were also implemented to check initial implementation that now invalidates expired access and refresh tokens and also rotating refresh tokens.
Since I introduced wrapper functions for create_oauth_token to distinguish between access and refresh token there is no need to set the token type in the data dict, since the type is now enforced in the wrapper functions create_access_token and create_refresh_token.
By convention I renamed create_oauth_token to _create_oauth_token as it is considered a private helper function now.
The OIDC email verified check now fails if the email is explicitly
unverified, or if the `email_verified` claim is supported and the email
is not explicitly verified.
Previously, the OIDC implementation failed for any OIDC provider that
did not include the `email_verified` claim in the userinfo response.
Providers like Synology do not include this claim, so the check always
failed with error "Email is not verified."
I haven't found a formal specification for the `email_verified` claim,
and how it should be handled, but this implementation should be more
robust and work with more OIDC providers.
Fixes#1446.