All checks were successful
continuous-integration/drone/push Build is passing
## Description of the implemented changes The changes were: - [x] Bugfixing - [x] New Feature - [ ] Breaking Change - [x] Refactoring **OIDC-only mode improvements and UX tweaks (success toasts, unauthenticated redirect).** ## What has been changed? ### OIDC-only mode (new feature) - **Admin settings:** "Only OIDC sign-in" is an immediate toggle at the top of the OIDC section (no save button). Enabling it also turns off "Allow direct registration". When OIDC-only is on, the registration checkbox is disabled and shows a tooltip (DaisyUI `<.tooltip>`). - **Backend:** Password sign-in is forbidden via Ash policy (`OidcOnlyActive` check). Password registration is blocked via validation `OidcOnlyBlocksPasswordRegistration`. New plug `OidcOnlySignInRedirect`: when OIDC-only and OIDC are configured, GET `/sign-in` redirects to the OIDC flow; GET `/auth/user/password/sign_in_with_token` is rejected with redirect + flash. `AuthController.success/4` also rejects password sign-in when OIDC-only. - **Tests:** GlobalSettingsLive (OIDC-only UI), AuthController (redirect and password sign-in rejection), User authentication (register_with_password blocked when OIDC-only). ### UX / behaviour (no new feature flag) - **Success toasts:** Success flash messages auto-dismiss after 5 seconds via JS hook `FlashAutoDismiss` and optional `auto_clear_ms` on `<.flash>` (used for success in root layout and `flash_group`). - **Unauthenticated users:** Redirect to sign-in without the "You don't have permission to access this page" flash; that message is only shown to logged-in users who lack access. Logic in `LiveHelpers` and `CheckPagePermission` plug; test updated accordingly. ### Other - Layouts: comment about unprocessed join-request count no longer uses "TODO" (Credo). - Gettext: German translation for "Home" (Startseite); POT/PO kept in sync. - CHANGELOG: Unreleased section updated with the above. ## Definition of Done ### Code Quality - [x] No new technical depths - [x] Linting passed - [x] Documentation is added where needed (module docs, comments where non-obvious) ### Accessibility - [x] New elements are properly defined with html-tags (labels, aria-label on checkboxes) - [x] Colour contrast follows WCAG criteria (unchanged) - [x] Aria labels are added when needed (e.g. oidc-only and registration checkboxes) - [x] Everything is accessible by keyboard (toggles and buttons unchanged) - [x] Tab-Order is comprehensible - [x] All interactive elements have a visible focus (existing patterns) ### Testing - [x] Tests for new code are written (OIDC-only UI, auth controller, user auth; SMTP config builder and mailer) - [x] All tests pass - [ ] axe-core dev tools show no critical or major issues (not re-run for this PR; suggest spot-check on settings and sign-in) ## Additional Notes - **OIDC-only:** When the `OIDC_ONLY` env var is set, the toggle is read-only and shows "(From OIDC_ONLY)". When OIDC is not configured, the toggle is disabled. - **Invalidation:** Enabling OIDC-only sets `registration_enabled: false` in one update; disabling OIDC-only only updates `oidc_only` (registration left as-is). - **Review focus:** Plug order in router (OidcOnlySignInRedirect), policy/validation order in User, and that all OIDC-only paths (form, plug, controller) stay consistent. Reviewed-on: #474 Co-authored-by: Simon <s.thiessen@local-it.org> Co-committed-by: Simon <s.thiessen@local-it.org>
3.4 KiB
3.4 KiB
Admin Bootstrap and OIDC Role Sync
Overview
- Admin bootstrap: In production, the Docker entrypoint runs migrate, then
Mv.Release.run_seeds/0(bootstrap seeds; setRUN_DEV_SEEDS=trueto also run dev seeds), thenseed_admin/0from ENV, then the server. Password can be changed without redeploy viabin/mv eval "Mv.Release.seed_admin()". - OIDC role sync: Optional mapping from OIDC groups (e.g. from Authentik profile scope) to the Admin role. Users in the configured admin group get the Admin role on registration and on each sign-in.
Admin Bootstrap (Part A)
Environment Variables
RUN_DEV_SEEDS– If set to"true",run_seeds/0also runs dev seeds (members, groups, sample data). Otherwise only bootstrap seeds run.ADMIN_EMAIL– Email of the admin user to create/update. If unset, seed_admin/0 does nothing.ADMIN_PASSWORD– Password for the admin user. If unset (and no file), no new user is created; if a user with ADMIN_EMAIL already exists (e.g. OIDC-only), their role is set to Admin (no password change).ADMIN_PASSWORD_FILE– Path to a file containing the password (e.g. Docker secret).
Release Tasks
Mv.Release.run_seeds/0– Runs bootstrap seeds (fee types, custom fields, roles, settings). IfRUN_DEV_SEEDSenv is"true", also runs dev seeds (members, groups, sample data). Idempotent.Mv.Release.seed_admin/0– Reads ADMIN_EMAIL and password from ADMIN_PASSWORD or ADMIN_PASSWORD_FILE. If both email and password are set: creates or updates the user with the Admin role. If only ADMIN_EMAIL is set: sets the Admin role on an existing user with that email (for OIDC-only admins); does not create a user. Idempotent.
Entrypoint
- rel/overlays/bin/docker-entrypoint.sh – After migrate, runs run_seeds(), then seed_admin(), then starts the server.
Seeds (Dev/Test)
- priv/repo/seeds.exs – Uses ADMIN_PASSWORD or ADMIN_PASSWORD_FILE when set; otherwise fallback "testpassword" only in dev/test.
OIDC Role Sync (Part B)
Configuration
OIDC_ADMIN_GROUP_NAME– OIDC group name that maps to the Admin role. If unset, no role sync.OIDC_GROUPS_CLAIM– JWT claim name for group list (default "groups").- Module: Mv.OidcRoleSyncConfig (oidc_admin_group_name/0, oidc_groups_claim/0).
Sign-in page (OIDC-only mode)
OIDC_ONLY(or Settings → OIDC → "Only OIDC sign-in") – When set to true/1/yes and OIDC is configured, the sign-in page shows only the Single Sign-On button (password login is hidden). ENV takes precedence over Settings.- Redirect loop fix: After an OIDC failure (e.g. provider down), the app redirects to
/sign-in?oidc_failed=1. The plugOidcOnlySignInRedirectdoes not redirect that request back to OIDC, so the sign-in page is shown with the error (no endless redirect).
Sync Logic
- Mv.OidcRoleSync.apply_admin_role_from_user_info(user, user_info) – If admin group configured, sets user role to Admin or Mitglied based on user_info groups.
Where It Runs
- Registration: register_with_oidc after_action calls OidcRoleSync.
- Sign-in: sign_in_with_oidc prepare after_action calls OidcRoleSync for each user.
Internal Action
- User.set_role_from_oidc_sync – Internal update (role_id only). Used by OidcRoleSync; not exposed.
See Also
- .env.example – Admin and OIDC group env vars.
- lib/mv/release.ex – seed_admin/0.
- lib/mv/oidc_role_sync.ex – Sync implementation.
- docs/oidc-account-linking.md – OIDC account linking.