defmodule PhoenixKitWeb.Live.Settings.Authorization do @moduledoc """ Authorization settings management LiveView for PhoenixKit. Manages login page branding and authentication methods including magic links and OAuth provider configuration. """ use PhoenixKitWeb, :live_view use Gettext, backend: PhoenixKitWeb.Gettext alias PhoenixKit.Modules.Storage.URLSigner alias PhoenixKit.Settings alias PhoenixKit.Users.OAuthConfig alias PhoenixKit.Utils.CssValue require Logger def mount(_params, _session, socket) do current_settings = Settings.list_all_settings() defaults = Settings.get_defaults() merged_settings = Map.merge(defaults, current_settings) changeset = Settings.change_settings(merged_settings) socket = socket |> assign(:page_title, "Authorization Settings") |> assign(:settings, merged_settings) |> assign(:saved_settings, merged_settings) |> assign(:changeset, changeset) |> assign(:saving, false) |> assign( :project_title, merged_settings["project_title"] || PhoenixKit.Config.get(:project_title, "PhoenixKit") ) |> assign(:show_media_selector, false) |> assign(:media_selection_target, nil) {:ok, socket} end def handle_params(_params, _url, socket) do {:noreply, socket} end def handle_event("validate_settings", %{"settings" => settings_params}, socket) do changeset = Settings.validate_settings(settings_params) socket = socket |> assign(:settings, settings_params) |> assign(:changeset, changeset) {:noreply, socket} end def handle_event("save_settings", %{"settings" => settings_params}, socket) do socket = assign(socket, :saving, true) case validate_background_color(settings_params) do :ok -> do_save_settings(socket, settings_params) {:error, message} -> {:noreply, socket |> assign(:saving, false) |> put_flash(:error, message)} end end def handle_event("test_oauth", %{"provider" => provider}, socket) do provider_atom = String.to_existing_atom(provider) credentials = oauth_credentials_from_settings(provider_atom, socket.assigns.settings) case OAuthConfig.test_connection(provider_atom, credentials) do {:ok, message} -> {:noreply, put_flash(socket, :info, message)} {:error, message} -> {:noreply, put_flash(socket, :error, message)} end end def handle_event("reload_oauth_config", _params, socket) do OAuthConfig.configure_providers() {:noreply, put_flash(socket, :info, "OAuth configuration reloaded from database")} end def handle_event("open_media_selector", %{"target" => target}, socket) do {:noreply, socket |> assign(:show_media_selector, true) |> assign(:media_selection_target, String.to_existing_atom(target))} end def handle_event("clear_branding_image", %{"target" => target}, socket) do key = case target do "logo" -> "auth_logo_file_uuid" "background" -> "auth_background_image_file_uuid" "background_mobile" -> "auth_background_image_mobile_file_uuid" end settings = Map.put(socket.assigns.settings, key, "") {:noreply, assign(socket, :settings, settings)} end ## Media selector callbacks def handle_info({:media_selected, file_uuids}, socket) do file_uuid = List.first(file_uuids) || "" key = case socket.assigns.media_selection_target do :logo -> "auth_logo_file_uuid" :background -> "auth_background_image_file_uuid" :background_mobile -> "auth_background_image_mobile_file_uuid" end settings = Map.put(socket.assigns.settings, key, file_uuid) {:noreply, socket |> assign(:settings, settings) |> assign(:show_media_selector, false) |> assign(:media_selection_target, nil)} end def handle_info({:media_selector_closed}, socket) do {:noreply, socket |> assign(:show_media_selector, false) |> assign(:media_selection_target, nil)} end # Helper functions # The background colour lands in a `