feat: allow disabling registration
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
eb18209669
commit
09e4b64663
14 changed files with 344 additions and 5 deletions
|
|
@ -35,6 +35,19 @@ defmodule MvWeb.AuthOverrides do
|
|||
end
|
||||
end
|
||||
|
||||
defmodule MvWeb.AuthOverridesRegistrationDisabled do
|
||||
@moduledoc """
|
||||
When direct registration is disabled in global settings, this override is
|
||||
prepended in SignInLive so the Password component hides the "Need an account?"
|
||||
toggle (register_toggle_text: nil disables the register link per library docs).
|
||||
"""
|
||||
use AshAuthentication.Phoenix.Overrides
|
||||
|
||||
override AshAuthentication.Phoenix.Components.Password do
|
||||
set :register_toggle_text, nil
|
||||
end
|
||||
end
|
||||
|
||||
defmodule MvWeb.AuthOverridesDE do
|
||||
@moduledoc """
|
||||
German locale-specific overrides for AshAuthentication Phoenix components.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ defmodule MvWeb.SignInLive do
|
|||
|
||||
alias AshAuthentication.Phoenix.Components
|
||||
alias Mv.Config
|
||||
alias MvWeb.{AuthOverridesDE, Layouts}
|
||||
alias MvWeb.{AuthOverridesDE, AuthOverridesRegistrationDisabled, Layouts}
|
||||
|
||||
@impl true
|
||||
def mount(_params, session, socket) do
|
||||
|
|
@ -36,7 +36,18 @@ defmodule MvWeb.SignInLive do
|
|||
# without _gettext support (e.g. HorizontalRule) still render in German.
|
||||
base_overrides = Map.get(session, "overrides", [AshAuthentication.Phoenix.Overrides.Default])
|
||||
locale_overrides = if locale == "de", do: [AuthOverridesDE], else: []
|
||||
overrides = locale_overrides ++ base_overrides
|
||||
|
||||
registration_disabled =
|
||||
if session["registration_enabled"] == false,
|
||||
do: [AuthOverridesRegistrationDisabled],
|
||||
else: []
|
||||
|
||||
# When registration is disabled: hide register link (register_path: nil) and hide
|
||||
# "Need an account?" toggle (override register_toggle_text: nil so it takes precedence).
|
||||
overrides = registration_disabled ++ locale_overrides ++ base_overrides
|
||||
|
||||
register_path =
|
||||
if session["registration_enabled"] == false, do: nil, else: session["register_path"]
|
||||
|
||||
socket =
|
||||
socket
|
||||
|
|
@ -44,7 +55,7 @@ defmodule MvWeb.SignInLive do
|
|||
|> assign_new(:otp_app, fn -> nil end)
|
||||
|> assign(:path, session["path"] || "/")
|
||||
|> assign(:reset_path, session["reset_path"])
|
||||
|> assign(:register_path, session["register_path"])
|
||||
|> assign(:register_path, register_path)
|
||||
|> assign(:current_tenant, session["tenant"])
|
||||
|> assign(:resources, session["resources"])
|
||||
|> assign(:context, session["context"] || %{})
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
|
||||
## Settings
|
||||
- `club_name` - The name of the association/club (required)
|
||||
- `registration_enabled` - Whether direct registration via /register is allowed
|
||||
- `join_form_enabled` - Whether the public /join page is active
|
||||
- `join_form_field_ids` - Ordered list of field IDs shown on the join form
|
||||
- `join_form_field_required` - Map of field ID => required boolean
|
||||
|
||||
## Events
|
||||
- `validate` / `save` - Club settings form
|
||||
- `toggle_registration_enabled` - Enable/disable direct registration (/register)
|
||||
- `toggle_join_form_enabled` - Enable/disable the join form
|
||||
- `add_join_form_field` / `remove_join_form_field` - Manage join form fields
|
||||
- `toggle_join_form_field_required` - Toggle required flag per field
|
||||
|
|
@ -80,6 +82,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
|> assign(:oidc_only_env_set, Mv.Config.oidc_only_env_set?())
|
||||
|> assign(:oidc_configured, Mv.Config.oidc_configured?())
|
||||
|> assign(:oidc_client_secret_set, Mv.Config.oidc_client_secret_set?())
|
||||
|> assign(:registration_enabled, settings.registration_enabled != false)
|
||||
|> assign(:smtp_env_configured, Mv.Config.smtp_env_configured?())
|
||||
|> assign(:smtp_host_env_set, Mv.Config.smtp_host_env_set?())
|
||||
|> assign(:smtp_port_env_set, Mv.Config.smtp_port_env_set?())
|
||||
|
|
@ -607,8 +610,29 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
<% end %>
|
||||
</.form>
|
||||
</.form_section>
|
||||
<%!-- OIDC Section --%>
|
||||
<.form_section title={gettext("OIDC (Single Sign-On)")}>
|
||||
<%!-- Authentication: Direct registration + OIDC --%>
|
||||
<.form_section title={gettext("Authentication")}>
|
||||
<h3 class="font-medium mb-3">{gettext("Direct registration")}</h3>
|
||||
<p class="text-sm text-base-content/70 mb-4">
|
||||
{gettext(
|
||||
"If disabled, users cannot sign up via /register; sign-in and the join form remain available."
|
||||
)}
|
||||
</p>
|
||||
<div class="flex items-center gap-3 mb-6">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="registration-enabled-checkbox"
|
||||
class="checkbox checkbox-sm"
|
||||
checked={@registration_enabled}
|
||||
phx-click="toggle_registration_enabled"
|
||||
aria-label={gettext("Allow direct registration (/register)")}
|
||||
/>
|
||||
<label for="registration-enabled-checkbox" class="cursor-pointer font-medium">
|
||||
{gettext("Allow direct registration (/register)")}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h3 class="font-medium mb-3">{gettext("OIDC (Single Sign-On)")}</h3>
|
||||
<%= if @oidc_env_configured do %>
|
||||
<p class="text-sm text-base-content/70 mb-4">
|
||||
{gettext("Some values are set via environment variables. Those fields are read-only.")}
|
||||
|
|
@ -853,6 +877,7 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
socket =
|
||||
socket
|
||||
|> assign(:settings, fresh_settings)
|
||||
|> assign(:registration_enabled, fresh_settings.registration_enabled != false)
|
||||
|> assign(:vereinfacht_api_key_set, present?(fresh_settings.vereinfacht_api_key))
|
||||
|> assign(:oidc_client_secret_set, Mv.Config.oidc_client_secret_set?())
|
||||
|> assign(:oidc_configured, Mv.Config.oidc_configured?())
|
||||
|
|
@ -889,6 +914,24 @@ defmodule MvWeb.GlobalSettingsLive do
|
|||
{:noreply, persist_join_form_settings(socket)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("toggle_registration_enabled", _params, socket) do
|
||||
settings = socket.assigns.settings
|
||||
new_value = not socket.assigns.registration_enabled
|
||||
|
||||
case Membership.update_settings(settings, %{registration_enabled: new_value}) do
|
||||
{:ok, updated_settings} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:settings, updated_settings)
|
||||
|> assign(:registration_enabled, updated_settings.registration_enabled != false)
|
||||
|> assign_form()}
|
||||
|
||||
{:error, _} ->
|
||||
{:noreply, put_flash(socket, :error, gettext("Failed to update setting."))}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("toggle_add_field_dropdown", _params, socket) do
|
||||
{:noreply,
|
||||
|
|
|
|||
55
lib/mv_web/plugs/registration_enabled.ex
Normal file
55
lib/mv_web/plugs/registration_enabled.ex
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
defmodule MvWeb.Plugs.RegistrationEnabled do
|
||||
@moduledoc """
|
||||
When direct registration is disabled in settings:
|
||||
- GET /register is redirected to /sign-in with a flash message.
|
||||
Puts registration_enabled from settings into session for /sign-in and /register
|
||||
so the sign-in LiveView can show or hide the register link.
|
||||
"""
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
|
||||
alias Mv.Membership
|
||||
|
||||
def init(opts), do: opts
|
||||
|
||||
def call(conn, _opts) do
|
||||
conn
|
||||
|> maybe_redirect_register()
|
||||
|> maybe_put_registration_enabled_in_session()
|
||||
end
|
||||
|
||||
defp maybe_redirect_register(conn) do
|
||||
if conn.request_path == "/register" and conn.method == "GET" do
|
||||
case Membership.get_settings() do
|
||||
{:ok, %{registration_enabled: true}} ->
|
||||
conn
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> put_flash(:info, get_flash_message(conn))
|
||||
|> redirect(to: "/sign-in")
|
||||
|> halt()
|
||||
end
|
||||
else
|
||||
conn
|
||||
end
|
||||
end
|
||||
|
||||
defp get_flash_message(_conn) do
|
||||
Gettext.dgettext(MvWeb.Gettext, "default", "Registration is disabled.")
|
||||
end
|
||||
|
||||
defp maybe_put_registration_enabled_in_session(conn) do
|
||||
if conn.request_path in ["/sign-in", "/register"] do
|
||||
enabled =
|
||||
case Membership.get_settings() do
|
||||
{:ok, %{registration_enabled: enabled?}} -> enabled?
|
||||
_ -> true
|
||||
end
|
||||
|
||||
put_session(conn, "registration_enabled", enabled)
|
||||
else
|
||||
conn
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -16,6 +16,7 @@ defmodule MvWeb.Router do
|
|||
plug :set_locale
|
||||
plug MvWeb.Plugs.CheckPagePermission
|
||||
plug MvWeb.Plugs.JoinFormEnabled
|
||||
plug MvWeb.Plugs.RegistrationEnabled
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue