From 2818a00548eb72c322fde944ca11ed2c4ab833ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Eppl=C3=A9e?= Date: Thu, 17 Jul 2025 14:48:17 +0200 Subject: [PATCH 01/11] docs: Add .env.example file --- .env.example | 1 + 1 file changed, 1 insertion(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ccbd6ed --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +OIDC_CLIENT_SECRET= From 1782210950787e1991461b857a67f4223a82054a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Eppl=C3=A9e?= Date: Thu, 17 Jul 2025 14:48:17 +0200 Subject: [PATCH 02/11] docs: Add docs for testing SSO --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 24419c7..38013f4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ # mitgliederverwaltung +## Testing SSO with rauthy + +1. `just run` +1. go to [localhost:8080](http://localhost:8080), go to the Admin area +1. Login with "admin@localhost" and password from `BOOTSTRAP_ADMIN_PASSWORD_PLAIN` in docker-compose.yml +1. add client from the admin panel + - Client ID: mv + - redirect uris: http://localhost:4000/auth/user/rauthy/callback + - Authorization Flows: authorization_code + - allowed origins: http://localhost:4000 + - access/id token algortihm: RS256 (EDDSA did not work for me, found just few infos in the ashauthentication docs) +1. copy client secret to `.env` file +1. abort and run `just run` again + + + From 96defae986b72029a7517c52f48443f73b0825b3 Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 Aug 2025 15:02:54 +0200 Subject: [PATCH 03/11] feat: add overrides for sign in page --- assets/css/app.css | 2 +- assets/tailwind.config.js | 1 + lib/mv_web/auth_overrides.ex | 11 ++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 0417463..ea63a2d 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1,7 +1,7 @@ /* See the Tailwind configuration guide for advanced usage https://tailwindcss.com/docs/configuration */ -@import "tailwindcss" source(none); +@import "tailwindcss"; @source "../css"; @source "../js"; @source "../../lib/mv_web"; diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index 873d6d6..d87d46f 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,6 +12,7 @@ module.exports = { "../lib/mv_web.ex", "../lib/mv_web/**/*.*ex" ], + safelist: ['h-screen', 'px-6', 'h-screen', 'place-items-center', 'px-20', 'px-24'], // Classes that are used by AshAuthentication Sign-In Page are otherwise purged theme: { extend: { colors: { diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index bec3354..fab8653 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -14,7 +14,12 @@ defmodule MvWeb.AuthOverrides do # set :text_class, "bg-red-500" # end - # override AshAuthentication.Phoenix.Components.SignIn do - # set :show_banner, false - # end + override AshAuthentication.Phoenix.Components.SignIn do + set :root_class, "min-w-md" + end + + override AshAuthentication.Phoenix.Components.Banner do + set :text, "Mitgliederverwaltung" + set :image_url, nil + end end From 01dc20af6e65ad7c269e9685c8f2fbd2bce360de Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 6 Aug 2025 12:42:17 +0200 Subject: [PATCH 04/11] feat: add translation --- Justfile | 2 +- lib/mv_web/auth_overrides.ex | 19 ++++-- lib/mv_web/components/layouts/root.html.heex | 2 +- lib/mv_web/live_helpers.ex | 2 +- lib/mv_web/live_user_auth.ex | 3 + lib/mv_web/router.ex | 14 ++--- priv/gettext/auth.pot | 64 +++++++++++++++++++ priv/gettext/de/LC_MESSAGES/auth.po | 66 ++++++++++++++++++++ priv/gettext/de/LC_MESSAGES/default.po | 21 ++++--- priv/gettext/default.pot | 21 ++++--- priv/gettext/en/LC_MESSAGES/auth.po | 63 +++++++++++++++++++ priv/gettext/en/LC_MESSAGES/default.po | 21 ++++--- 12 files changed, 260 insertions(+), 38 deletions(-) create mode 100644 priv/gettext/auth.pot create mode 100644 priv/gettext/de/LC_MESSAGES/auth.po create mode 100644 priv/gettext/en/LC_MESSAGES/auth.po diff --git a/Justfile b/Justfile index 21e54fb..1874b67 100644 --- a/Justfile +++ b/Justfile @@ -23,7 +23,7 @@ ci-dev: lint audit test gettext: mix gettext.extract - mix gettext.merge priv/gettext + mix gettext.merge priv/gettext --on-obsolete=mark_as_obsolete lint: mix format --check-formatted diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index fab8653..367982e 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -1,5 +1,6 @@ defmodule MvWeb.AuthOverrides do use AshAuthentication.Phoenix.Overrides + use Gettext, backend: MvWeb.Gettext # configure your UI overrides here @@ -14,12 +15,22 @@ defmodule MvWeb.AuthOverrides do # set :text_class, "bg-red-500" # end - override AshAuthentication.Phoenix.Components.SignIn do + # Avoid full-width for the Sign In Form + override AshAuthentication.Phoenix.Components.SignIn do set :root_class, "min-w-md" - end + end - override AshAuthentication.Phoenix.Components.Banner do + # Replace banner logo with text + override AshAuthentication.Phoenix.Components.Banner do set :text, "Mitgliederverwaltung" set :image_url, nil - end + end + + # Translate the or in the horizontal rule to German + override AshAuthentication.Phoenix.Components.HorizontalRule do + set :text, + Gettext.with_locale(MvWeb.Gettext, "de", fn -> + Gettext.gettext(MvWeb.Gettext, "or") + end) + end end diff --git a/lib/mv_web/components/layouts/root.html.heex b/lib/mv_web/components/layouts/root.html.heex index 5ee0fef..e1b639d 100644 --- a/lib/mv_web/components/layouts/root.html.heex +++ b/lib/mv_web/components/layouts/root.html.heex @@ -1,5 +1,5 @@ - + {Application.get_env(:live_debugger, :live_debugger_tags)} diff --git a/lib/mv_web/live_helpers.ex b/lib/mv_web/live_helpers.ex index 03d7d45..331bb5c 100644 --- a/lib/mv_web/live_helpers.ex +++ b/lib/mv_web/live_helpers.ex @@ -1,6 +1,6 @@ defmodule MvWeb.LiveHelpers do def on_mount(:default, _params, session, socket) do - locale = session["locale"] || "en" + locale = session["locale"] || "de" Gettext.put_locale(locale) {:cont, socket} end diff --git a/lib/mv_web/live_user_auth.ex b/lib/mv_web/live_user_auth.ex index 67bef70..d211245 100644 --- a/lib/mv_web/live_user_auth.ex +++ b/lib/mv_web/live_user_auth.ex @@ -37,6 +37,9 @@ defmodule MvWeb.LiveUserAuth do end def on_mount(:live_no_user, _params, _session, socket) do + Gettext.put_locale(MvWeb.Gettext, "de") + {:cont, assign(socket, :locale, "de")} + if socket.assigns[:current_user] do {:halt, Phoenix.LiveView.redirect(socket, to: ~p"/")} else diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 696a491..82e9f00 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -85,19 +85,19 @@ defmodule MvWeb.Router do reset_path: "/reset", auth_routes_prefix: "/auth", on_mount: [{MvWeb.LiveUserAuth, :live_no_user}], - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not want to use the reset password feature reset_route auth_routes_prefix: "/auth", - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not use the confirmation strategy confirm_route Mv.Accounts.User, :confirm_new_user, auth_routes_prefix: "/auth", - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not use the magic link strategy. # magic_sign_in_route(Mv.Accounts.User, :magic_link, @@ -139,7 +139,7 @@ defmodule MvWeb.Router do end defp set_locale(conn, _opts) do - locale = get_session(conn, :locale) || "en" + locale = get_session(conn, :locale) || "de" Gettext.put_locale(MvWeb.Gettext, locale) conn end diff --git a/priv/gettext/auth.pot b/priv/gettext/auth.pot new file mode 100644 index 0000000..29ee991 --- /dev/null +++ b/priv/gettext/auth.pot @@ -0,0 +1,64 @@ +## This file is a PO Template file. +## +## "msgid"s here are often extracted from source code. +## Add new messages manually only if they're dynamic +## messages that can't be statically extracted. +## +## Leave "msgstr"s empty as changing them here has no +## effect: edit them in PO (.po) files instead. +# +msgid "" +msgstr "" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "" + +msgid "Email or password was incorrect" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Forgot your password?" +msgstr "" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "" + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "" + +msgid "Need an account?" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password Confirmation" +msgstr "" + +msgid "Request magic link" +msgstr "" + +msgid "Request password reset token" +msgstr "" + +msgid "Requesting ..." +msgstr "" + +msgid "Reset password with token" +msgstr "" + +msgid "Sign in" +msgstr "" + +msgid "Signing in ..." +msgstr "" + +msgid "Your password has successfully been reset" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/auth.po b/priv/gettext/de/LC_MESSAGES/auth.po new file mode 100644 index 0000000..0f2202d --- /dev/null +++ b/priv/gettext/de/LC_MESSAGES/auth.po @@ -0,0 +1,66 @@ +## "msgid"s in this file come from POT (.pot) files. +### +### Do not add, change, or remove "msgid"s manually here as +### they're tied to the ones in the corresponding POT file +### (with the same domain). +### +### Use "mix gettext.extract --merge" or "mix gettext.merge" +### to merge POT files into PO files. +msgid "" +msgstr "" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "Bereit zum Anmelden?" + +msgid "Email or password was incorrect" +msgstr "Email oder Passwort nicht korrekt" + +msgid "Email" +msgstr "Email" + +msgid "Forgot your password?" +msgstr "Passwort vergessen?" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit Anmelde-Link versendet." + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit einer Anleitung zum Zurücksetzen versendet." + +msgid "Need an account?" +msgstr "Konto anlegen?" + +msgid "Password" +msgstr "Passwort" + +msgid "Password Confirmation" +msgstr "Passwort Wiederholung" + +msgid "Request magic link" +msgstr "Magischen Link anfordern" + +msgid "Request password reset token" +msgstr "Passwort zurücksetzen" + +msgid "Requesting ..." +msgstr "Anfrage låuft..." + +msgid "Reset password with token" +msgstr "Neues Passwort setzen" + +msgid "Sign in" +msgstr "Anmelden" + +msgid "Signing in ..." +msgstr "Anmelden..." + +msgid "Your password has successfully been reset" +msgstr "Das Passwort wurde erfolgreich zurückgesetzt" + +msgid "Sign in with Rauthy" +msgstr "Anmelden mit der Vereinscloud" diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 45723e7..1a7cf7e 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -16,7 +16,7 @@ msgid "Actions" msgstr "Aktionen" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "Bist du sicher?" @@ -35,14 +35,14 @@ msgid "City" msgstr "Stadt" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "Löschen" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "Bearbeite" @@ -57,7 +57,7 @@ msgstr "Mitglied bearbeiten" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -88,7 +88,7 @@ msgid "New Member" msgstr "Neues Mitglied" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "Anzeigen" @@ -351,7 +351,7 @@ msgstr "Nicht gesetzt" msgid "Note" msgstr "Hinweis" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -533,12 +533,12 @@ msgstr "Passwort" msgid "Password requirements" msgstr "Passwort-Anforderungen" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format msgid "Select all users" msgstr "Alle Benutzer auswählen" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format msgid "Select user" msgstr "Benutzer auswählen" @@ -552,3 +552,8 @@ msgstr "Passwort setzen" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "Benutzer wird ohne Passwort erstellt. Aktivieren Sie 'Passwort setzen', um eines hinzuzufügen." + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "oder" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index fd064d2..a9bfb08 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -17,7 +17,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "" @@ -36,14 +36,14 @@ msgid "City" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "" @@ -58,7 +58,7 @@ msgstr "" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -89,7 +89,7 @@ msgid "New Member" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "" @@ -352,7 +352,7 @@ msgstr "" msgid "Note" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -534,12 +534,12 @@ msgstr "" msgid "Password requirements" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format msgid "Select all users" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format msgid "Select user" msgstr "" @@ -553,3 +553,8 @@ msgstr "" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "" + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/auth.po b/priv/gettext/en/LC_MESSAGES/auth.po new file mode 100644 index 0000000..1e4e801 --- /dev/null +++ b/priv/gettext/en/LC_MESSAGES/auth.po @@ -0,0 +1,63 @@ +## "msgid"s in this file come from POT (.pot) files. +### +### Do not add, change, or remove "msgid"s manually here as +### they're tied to the ones in the corresponding POT file +### (with the same domain). +### +### Use "mix gettext.extract --merge" or "mix gettext.merge" +### to merge POT files into PO files. +msgid "" +msgstr "" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "" + +msgid "Email or password was incorrect" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Forgot your password?" +msgstr "" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "" + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "" + +msgid "Need an account?" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password Confirmation" +msgstr "" + +msgid "Request magic link" +msgstr "" + +msgid "Request password reset token" +msgstr "" + +msgid "Requesting ..." +msgstr "" + +msgid "Reset password with token" +msgstr "" + +msgid "Sign in" +msgstr "" + +msgid "Signing in ..." +msgstr "" + +msgid "Your password has successfully been reset" +msgstr "" + +msgid "Sign in with Rauthy" +msgstr "Sign in with Vereinscloud" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 41a35b4..2f09378 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -17,7 +17,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "" @@ -36,14 +36,14 @@ msgid "City" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "" @@ -58,7 +58,7 @@ msgstr "" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -89,7 +89,7 @@ msgid "New Member" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "" @@ -352,7 +352,7 @@ msgstr "" msgid "Note" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -534,12 +534,12 @@ msgstr "Password" msgid "Password requirements" msgstr "Password requirements" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format, fuzzy msgid "Select all users" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format, fuzzy msgid "Select user" msgstr "" @@ -553,3 +553,8 @@ msgstr "Set Password" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "User will be created without a password. Check 'Set Password' to add one." + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "" From a05e8641fe64a286fde8fc9e8b298d0f09dc5e21 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 6 Aug 2025 12:46:34 +0200 Subject: [PATCH 05/11] feat: memberslist as landing page --- lib/mv_web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 82e9f00..4a6e3d9 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -47,7 +47,7 @@ defmodule MvWeb.Router do """ ash_authentication_live_session :authentication_required, on_mount: {MvWeb.LiveUserAuth, :live_user_required} do - get "/", PageController, :home + live "/", MemberLive.Index, :index live "/members", MemberLive.Index, :index live "/members/new", MemberLive.Form, :new From afdb5f06471ca684e694f29d29821b174f46490f Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 14 Aug 2025 16:22:36 +0200 Subject: [PATCH 06/11] feat: set users locale --- assets/tailwind.config.js | 1 - lib/mv_web/auth_overrides.ex | 2 +- lib/mv_web/live_user_auth.ex | 8 ++++--- lib/mv_web/router.ex | 41 +++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index d87d46f..873d6d6 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,7 +12,6 @@ module.exports = { "../lib/mv_web.ex", "../lib/mv_web/**/*.*ex" ], - safelist: ['h-screen', 'px-6', 'h-screen', 'place-items-center', 'px-20', 'px-24'], // Classes that are used by AshAuthentication Sign-In Page are otherwise purged theme: { extend: { colors: { diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index 367982e..63cdcf9 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -17,7 +17,7 @@ defmodule MvWeb.AuthOverrides do # Avoid full-width for the Sign In Form override AshAuthentication.Phoenix.Components.SignIn do - set :root_class, "min-w-md" + set :root_class, "md:min-w-md" end # Replace banner logo with text diff --git a/lib/mv_web/live_user_auth.ex b/lib/mv_web/live_user_auth.ex index d211245..9b2a1a7 100644 --- a/lib/mv_web/live_user_auth.ex +++ b/lib/mv_web/live_user_auth.ex @@ -36,9 +36,11 @@ defmodule MvWeb.LiveUserAuth do end end - def on_mount(:live_no_user, _params, _session, socket) do - Gettext.put_locale(MvWeb.Gettext, "de") - {:cont, assign(socket, :locale, "de")} + def on_mount(:live_no_user, _params, session, socket) do + # Set the locale for not logged in user to set the language + locale = session["locale"] || "en" + Gettext.put_locale(MvWeb.Gettext, locale) + {:cont, assign(socket, :locale, locale)} if socket.assigns[:current_user] do {:halt, Phoenix.LiveView.redirect(socket, to: ~p"/")} diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 4a6e3d9..bf2c071 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -139,8 +139,47 @@ defmodule MvWeb.Router do end defp set_locale(conn, _opts) do - locale = get_session(conn, :locale) || "de" + locale = + get_session(conn, :locale) || + extract_locale_from_headers(conn.req_headers) + Gettext.put_locale(MvWeb.Gettext, locale) + conn + |> put_session(:locale, locale) + |> assign(:locale, locale) end + + # Get locale from user + defp extract_locale_from_headers(headers) do + headers + |> Enum.find_value(fn + {"accept-language", value} -> value + _ -> nil + end) + |> parse_accept_language() + |> Enum.find(&supported_locale?/1) + |> fallback_locale() + end + + defp parse_accept_language(nil), do: [] + + defp parse_accept_language(header) do + header + |> String.split(",") + |> Enum.map(&String.trim/1) + |> Enum.map(fn lang -> + lang + # we only want the first part + |> String.split(";") + |> hd() + |> String.split("-") + |> hd() + end) + end + + # Our supported languages for now are german and english, english as fallback language + defp supported_locale?(locale), do: locale in ["en", "de"] + defp fallback_locale(nil), do: "en" + defp fallback_locale(locale), do: locale end From dd77be038843232fb30354f3f87c9df816fee4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Eppl=C3=A9e?= Date: Mon, 4 Aug 2025 14:03:26 +0200 Subject: [PATCH 07/11] Add seed script for admin user --- lib/accounts/user.ex | 1 + mix.lock | 2 +- priv/repo/seeds.exs | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/accounts/user.ex b/lib/accounts/user.ex index d8c7a66..9294526 100644 --- a/lib/accounts/user.ex +++ b/lib/accounts/user.ex @@ -65,6 +65,7 @@ defmodule Mv.Accounts.User do create :create_user do accept [:email] + upsert? true end update :update_user do diff --git a/mix.lock b/mix.lock index 4392c65..6599c01 100644 --- a/mix.lock +++ b/mix.lock @@ -28,7 +28,7 @@ "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"}, "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"}, - "fine": {:hex, :fine, "0.1.2", "85cf7dd190c7c6c54c2840754ae977c9acc0417316255b674fad9f2678e4ecc7", [], [], "hexpm", "9113531982c2b60dbea6c7233917ddf16806947cd7104b5d03011bf436ca3072"}, + "fine": {:hex, :fine, "0.1.2", "85cf7dd190c7c6c54c2840754ae977c9acc0417316255b674fad9f2678e4ecc7", [:mix], [], "hexpm", "9113531982c2b60dbea6c7233917ddf16806947cd7104b5d03011bf436ca3072"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, "glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"}, "heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized", depth: 1]}, diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 1497096..306b627 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -4,6 +4,7 @@ # alias Mv.Membership +alias Mv.Accounts for attrs <- [ %{ @@ -41,3 +42,8 @@ for attrs <- [ upsert_identity: :unique_name ) end + +# Create admin user for testing +Accounts.create_user!(%{email: "admin@mv.local"}, upsert?: true, upsert_identity: :unique_email) +|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"}) +|> Ash.update!() From ddf9348eb865c4b9f9a03c0f35f643e263391407 Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 4 Aug 2025 15:02:54 +0200 Subject: [PATCH 08/11] feat: add overrides for sign in page --- assets/css/app.css | 2 +- assets/tailwind.config.js | 1 + lib/mv_web/auth_overrides.ex | 11 ++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 0417463..ea63a2d 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1,7 +1,7 @@ /* See the Tailwind configuration guide for advanced usage https://tailwindcss.com/docs/configuration */ -@import "tailwindcss" source(none); +@import "tailwindcss"; @source "../css"; @source "../js"; @source "../../lib/mv_web"; diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index 873d6d6..d87d46f 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,6 +12,7 @@ module.exports = { "../lib/mv_web.ex", "../lib/mv_web/**/*.*ex" ], + safelist: ['h-screen', 'px-6', 'h-screen', 'place-items-center', 'px-20', 'px-24'], // Classes that are used by AshAuthentication Sign-In Page are otherwise purged theme: { extend: { colors: { diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index bec3354..fab8653 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -14,7 +14,12 @@ defmodule MvWeb.AuthOverrides do # set :text_class, "bg-red-500" # end - # override AshAuthentication.Phoenix.Components.SignIn do - # set :show_banner, false - # end + override AshAuthentication.Phoenix.Components.SignIn do + set :root_class, "min-w-md" + end + + override AshAuthentication.Phoenix.Components.Banner do + set :text, "Mitgliederverwaltung" + set :image_url, nil + end end From 2a6f1ccf80e038501974adb44f33d94222643628 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 6 Aug 2025 12:42:17 +0200 Subject: [PATCH 09/11] feat: add translation --- Justfile | 2 +- lib/mv_web/auth_overrides.ex | 19 ++++-- lib/mv_web/components/layouts/root.html.heex | 2 +- lib/mv_web/live_helpers.ex | 2 +- lib/mv_web/live_user_auth.ex | 3 + lib/mv_web/router.ex | 14 ++--- priv/gettext/auth.pot | 64 +++++++++++++++++++ priv/gettext/de/LC_MESSAGES/auth.po | 66 ++++++++++++++++++++ priv/gettext/de/LC_MESSAGES/default.po | 21 ++++--- priv/gettext/default.pot | 21 ++++--- priv/gettext/en/LC_MESSAGES/auth.po | 63 +++++++++++++++++++ priv/gettext/en/LC_MESSAGES/default.po | 21 ++++--- 12 files changed, 260 insertions(+), 38 deletions(-) create mode 100644 priv/gettext/auth.pot create mode 100644 priv/gettext/de/LC_MESSAGES/auth.po create mode 100644 priv/gettext/en/LC_MESSAGES/auth.po diff --git a/Justfile b/Justfile index 21e54fb..1874b67 100644 --- a/Justfile +++ b/Justfile @@ -23,7 +23,7 @@ ci-dev: lint audit test gettext: mix gettext.extract - mix gettext.merge priv/gettext + mix gettext.merge priv/gettext --on-obsolete=mark_as_obsolete lint: mix format --check-formatted diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index fab8653..367982e 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -1,5 +1,6 @@ defmodule MvWeb.AuthOverrides do use AshAuthentication.Phoenix.Overrides + use Gettext, backend: MvWeb.Gettext # configure your UI overrides here @@ -14,12 +15,22 @@ defmodule MvWeb.AuthOverrides do # set :text_class, "bg-red-500" # end - override AshAuthentication.Phoenix.Components.SignIn do + # Avoid full-width for the Sign In Form + override AshAuthentication.Phoenix.Components.SignIn do set :root_class, "min-w-md" - end + end - override AshAuthentication.Phoenix.Components.Banner do + # Replace banner logo with text + override AshAuthentication.Phoenix.Components.Banner do set :text, "Mitgliederverwaltung" set :image_url, nil - end + end + + # Translate the or in the horizontal rule to German + override AshAuthentication.Phoenix.Components.HorizontalRule do + set :text, + Gettext.with_locale(MvWeb.Gettext, "de", fn -> + Gettext.gettext(MvWeb.Gettext, "or") + end) + end end diff --git a/lib/mv_web/components/layouts/root.html.heex b/lib/mv_web/components/layouts/root.html.heex index 5ee0fef..e1b639d 100644 --- a/lib/mv_web/components/layouts/root.html.heex +++ b/lib/mv_web/components/layouts/root.html.heex @@ -1,5 +1,5 @@ - + {Application.get_env(:live_debugger, :live_debugger_tags)} diff --git a/lib/mv_web/live_helpers.ex b/lib/mv_web/live_helpers.ex index 03d7d45..331bb5c 100644 --- a/lib/mv_web/live_helpers.ex +++ b/lib/mv_web/live_helpers.ex @@ -1,6 +1,6 @@ defmodule MvWeb.LiveHelpers do def on_mount(:default, _params, session, socket) do - locale = session["locale"] || "en" + locale = session["locale"] || "de" Gettext.put_locale(locale) {:cont, socket} end diff --git a/lib/mv_web/live_user_auth.ex b/lib/mv_web/live_user_auth.ex index 67bef70..d211245 100644 --- a/lib/mv_web/live_user_auth.ex +++ b/lib/mv_web/live_user_auth.ex @@ -37,6 +37,9 @@ defmodule MvWeb.LiveUserAuth do end def on_mount(:live_no_user, _params, _session, socket) do + Gettext.put_locale(MvWeb.Gettext, "de") + {:cont, assign(socket, :locale, "de")} + if socket.assigns[:current_user] do {:halt, Phoenix.LiveView.redirect(socket, to: ~p"/")} else diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 696a491..82e9f00 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -85,19 +85,19 @@ defmodule MvWeb.Router do reset_path: "/reset", auth_routes_prefix: "/auth", on_mount: [{MvWeb.LiveUserAuth, :live_no_user}], - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not want to use the reset password feature reset_route auth_routes_prefix: "/auth", - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not use the confirmation strategy confirm_route Mv.Accounts.User, :confirm_new_user, auth_routes_prefix: "/auth", - overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default], - gettext_backend: {MvWeb.Gettext, "default"} + overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.DaisyUI], + gettext_backend: {MvWeb.Gettext, "auth"} # Remove this if you do not use the magic link strategy. # magic_sign_in_route(Mv.Accounts.User, :magic_link, @@ -139,7 +139,7 @@ defmodule MvWeb.Router do end defp set_locale(conn, _opts) do - locale = get_session(conn, :locale) || "en" + locale = get_session(conn, :locale) || "de" Gettext.put_locale(MvWeb.Gettext, locale) conn end diff --git a/priv/gettext/auth.pot b/priv/gettext/auth.pot new file mode 100644 index 0000000..29ee991 --- /dev/null +++ b/priv/gettext/auth.pot @@ -0,0 +1,64 @@ +## This file is a PO Template file. +## +## "msgid"s here are often extracted from source code. +## Add new messages manually only if they're dynamic +## messages that can't be statically extracted. +## +## Leave "msgstr"s empty as changing them here has no +## effect: edit them in PO (.po) files instead. +# +msgid "" +msgstr "" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "" + +msgid "Email or password was incorrect" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Forgot your password?" +msgstr "" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "" + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "" + +msgid "Need an account?" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password Confirmation" +msgstr "" + +msgid "Request magic link" +msgstr "" + +msgid "Request password reset token" +msgstr "" + +msgid "Requesting ..." +msgstr "" + +msgid "Reset password with token" +msgstr "" + +msgid "Sign in" +msgstr "" + +msgid "Signing in ..." +msgstr "" + +msgid "Your password has successfully been reset" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/auth.po b/priv/gettext/de/LC_MESSAGES/auth.po new file mode 100644 index 0000000..0f2202d --- /dev/null +++ b/priv/gettext/de/LC_MESSAGES/auth.po @@ -0,0 +1,66 @@ +## "msgid"s in this file come from POT (.pot) files. +### +### Do not add, change, or remove "msgid"s manually here as +### they're tied to the ones in the corresponding POT file +### (with the same domain). +### +### Use "mix gettext.extract --merge" or "mix gettext.merge" +### to merge POT files into PO files. +msgid "" +msgstr "" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "Bereit zum Anmelden?" + +msgid "Email or password was incorrect" +msgstr "Email oder Passwort nicht korrekt" + +msgid "Email" +msgstr "Email" + +msgid "Forgot your password?" +msgstr "Passwort vergessen?" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit Anmelde-Link versendet." + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "Falls dieser Benutzer bekannt ist, wird jetzt eine Email mit einer Anleitung zum Zurücksetzen versendet." + +msgid "Need an account?" +msgstr "Konto anlegen?" + +msgid "Password" +msgstr "Passwort" + +msgid "Password Confirmation" +msgstr "Passwort Wiederholung" + +msgid "Request magic link" +msgstr "Magischen Link anfordern" + +msgid "Request password reset token" +msgstr "Passwort zurücksetzen" + +msgid "Requesting ..." +msgstr "Anfrage låuft..." + +msgid "Reset password with token" +msgstr "Neues Passwort setzen" + +msgid "Sign in" +msgstr "Anmelden" + +msgid "Signing in ..." +msgstr "Anmelden..." + +msgid "Your password has successfully been reset" +msgstr "Das Passwort wurde erfolgreich zurückgesetzt" + +msgid "Sign in with Rauthy" +msgstr "Anmelden mit der Vereinscloud" diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 45723e7..1a7cf7e 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -16,7 +16,7 @@ msgid "Actions" msgstr "Aktionen" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "Bist du sicher?" @@ -35,14 +35,14 @@ msgid "City" msgstr "Stadt" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "Löschen" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "Bearbeite" @@ -57,7 +57,7 @@ msgstr "Mitglied bearbeiten" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -88,7 +88,7 @@ msgid "New Member" msgstr "Neues Mitglied" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "Anzeigen" @@ -351,7 +351,7 @@ msgstr "Nicht gesetzt" msgid "Note" msgstr "Hinweis" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -533,12 +533,12 @@ msgstr "Passwort" msgid "Password requirements" msgstr "Passwort-Anforderungen" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format msgid "Select all users" msgstr "Alle Benutzer auswählen" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format msgid "Select user" msgstr "Benutzer auswählen" @@ -552,3 +552,8 @@ msgstr "Passwort setzen" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "Benutzer wird ohne Passwort erstellt. Aktivieren Sie 'Passwort setzen', um eines hinzuzufügen." + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "oder" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index fd064d2..a9bfb08 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -17,7 +17,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "" @@ -36,14 +36,14 @@ msgid "City" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "" @@ -58,7 +58,7 @@ msgstr "" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -89,7 +89,7 @@ msgid "New Member" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "" @@ -352,7 +352,7 @@ msgstr "" msgid "Note" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -534,12 +534,12 @@ msgstr "" msgid "Password requirements" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format msgid "Select all users" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format msgid "Select user" msgstr "" @@ -553,3 +553,8 @@ msgstr "" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "" + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/auth.po b/priv/gettext/en/LC_MESSAGES/auth.po new file mode 100644 index 0000000..1e4e801 --- /dev/null +++ b/priv/gettext/en/LC_MESSAGES/auth.po @@ -0,0 +1,63 @@ +## "msgid"s in this file come from POT (.pot) files. +### +### Do not add, change, or remove "msgid"s manually here as +### they're tied to the ones in the corresponding POT file +### (with the same domain). +### +### Use "mix gettext.extract --merge" or "mix gettext.merge" +### to merge POT files into PO files. +msgid "" +msgstr "" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Already have an account?" +msgstr "" + +msgid "Email or password was incorrect" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Forgot your password?" +msgstr "" + +msgid "If this user exists in our database you will contacted with a sign-in link shortly." +msgstr "" + +msgid "If this user exists in our system, you will be contacted with reset instructions shortly." +msgstr "" + +msgid "Need an account?" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password Confirmation" +msgstr "" + +msgid "Request magic link" +msgstr "" + +msgid "Request password reset token" +msgstr "" + +msgid "Requesting ..." +msgstr "" + +msgid "Reset password with token" +msgstr "" + +msgid "Sign in" +msgstr "" + +msgid "Signing in ..." +msgstr "" + +msgid "Your password has successfully been reset" +msgstr "" + +msgid "Sign in with Rauthy" +msgstr "Sign in with Vereinscloud" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 41a35b4..2f09378 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -17,7 +17,7 @@ msgid "Actions" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:77 -#: lib/mv_web/live/user_live/index.html.heex:69 +#: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" msgstr "" @@ -36,14 +36,14 @@ msgid "City" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:79 -#: lib/mv_web/live/user_live/index.html.heex:71 +#: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:71 #: lib/mv_web/live/user_live/form.ex:109 -#: lib/mv_web/live/user_live/index.html.heex:63 +#: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format msgid "Edit" msgstr "" @@ -58,7 +58,7 @@ msgstr "" #: lib/mv_web/live/member_live/index.html.heex:58 #: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 -#: lib/mv_web/live/user_live/index.html.heex:48 +#: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:24 #, elixir-autogen, elixir-format msgid "Email" @@ -89,7 +89,7 @@ msgid "New Member" msgstr "" #: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/user_live/index.html.heex:60 +#: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" msgstr "" @@ -352,7 +352,7 @@ msgstr "" msgid "Note" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:56 +#: lib/mv_web/live/user_live/index.html.heex:52 #: lib/mv_web/live/user_live/show.ex:25 #, elixir-autogen, elixir-format msgid "OIDC ID" @@ -534,12 +534,12 @@ msgstr "Password" msgid "Password requirements" msgstr "Password requirements" -#: lib/mv_web/live/user_live/index.html.heex:25 +#: lib/mv_web/live/user_live/index.html.heex:21 #, elixir-autogen, elixir-format, fuzzy msgid "Select all users" msgstr "" -#: lib/mv_web/live/user_live/index.html.heex:39 +#: lib/mv_web/live/user_live/index.html.heex:35 #, elixir-autogen, elixir-format, fuzzy msgid "Select user" msgstr "" @@ -553,3 +553,8 @@ msgstr "Set Password" #, elixir-autogen, elixir-format msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "User will be created without a password. Check 'Set Password' to add one." + +#: lib/mv_web/auth_overrides.ex:30 +#, elixir-autogen, elixir-format +msgid "or" +msgstr "" From 992addf0eaa7d3170483db96cf71fcae8c659fe7 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 6 Aug 2025 12:46:34 +0200 Subject: [PATCH 10/11] feat: memberslist as landing page --- lib/mv_web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 82e9f00..4a6e3d9 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -47,7 +47,7 @@ defmodule MvWeb.Router do """ ash_authentication_live_session :authentication_required, on_mount: {MvWeb.LiveUserAuth, :live_user_required} do - get "/", PageController, :home + live "/", MemberLive.Index, :index live "/members", MemberLive.Index, :index live "/members/new", MemberLive.Form, :new From f0b0de000865a5bf8e3de846312d8757668edd24 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 14 Aug 2025 16:22:36 +0200 Subject: [PATCH 11/11] feat: set users locale --- assets/tailwind.config.js | 1 - lib/mv_web/auth_overrides.ex | 2 +- lib/mv_web/live_user_auth.ex | 8 ++++--- lib/mv_web/router.ex | 41 +++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index d87d46f..873d6d6 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -12,7 +12,6 @@ module.exports = { "../lib/mv_web.ex", "../lib/mv_web/**/*.*ex" ], - safelist: ['h-screen', 'px-6', 'h-screen', 'place-items-center', 'px-20', 'px-24'], // Classes that are used by AshAuthentication Sign-In Page are otherwise purged theme: { extend: { colors: { diff --git a/lib/mv_web/auth_overrides.ex b/lib/mv_web/auth_overrides.ex index 367982e..63cdcf9 100644 --- a/lib/mv_web/auth_overrides.ex +++ b/lib/mv_web/auth_overrides.ex @@ -17,7 +17,7 @@ defmodule MvWeb.AuthOverrides do # Avoid full-width for the Sign In Form override AshAuthentication.Phoenix.Components.SignIn do - set :root_class, "min-w-md" + set :root_class, "md:min-w-md" end # Replace banner logo with text diff --git a/lib/mv_web/live_user_auth.ex b/lib/mv_web/live_user_auth.ex index d211245..9b2a1a7 100644 --- a/lib/mv_web/live_user_auth.ex +++ b/lib/mv_web/live_user_auth.ex @@ -36,9 +36,11 @@ defmodule MvWeb.LiveUserAuth do end end - def on_mount(:live_no_user, _params, _session, socket) do - Gettext.put_locale(MvWeb.Gettext, "de") - {:cont, assign(socket, :locale, "de")} + def on_mount(:live_no_user, _params, session, socket) do + # Set the locale for not logged in user to set the language + locale = session["locale"] || "en" + Gettext.put_locale(MvWeb.Gettext, locale) + {:cont, assign(socket, :locale, locale)} if socket.assigns[:current_user] do {:halt, Phoenix.LiveView.redirect(socket, to: ~p"/")} diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 4a6e3d9..bf2c071 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -139,8 +139,47 @@ defmodule MvWeb.Router do end defp set_locale(conn, _opts) do - locale = get_session(conn, :locale) || "de" + locale = + get_session(conn, :locale) || + extract_locale_from_headers(conn.req_headers) + Gettext.put_locale(MvWeb.Gettext, locale) + conn + |> put_session(:locale, locale) + |> assign(:locale, locale) end + + # Get locale from user + defp extract_locale_from_headers(headers) do + headers + |> Enum.find_value(fn + {"accept-language", value} -> value + _ -> nil + end) + |> parse_accept_language() + |> Enum.find(&supported_locale?/1) + |> fallback_locale() + end + + defp parse_accept_language(nil), do: [] + + defp parse_accept_language(header) do + header + |> String.split(",") + |> Enum.map(&String.trim/1) + |> Enum.map(fn lang -> + lang + # we only want the first part + |> String.split(";") + |> hd() + |> String.split("-") + |> hd() + end) + end + + # Our supported languages for now are german and english, english as fallback language + defp supported_locale?(locale), do: locale in ["en", "de"] + defp fallback_locale(nil), do: "en" + defp fallback_locale(locale), do: locale end