diff --git a/lib/mv_web/live/role_live/form.ex b/lib/mv_web/live/role_live/form.ex index 5646bd4..8fea5e1 100644 --- a/lib/mv_web/live/role_live/form.ex +++ b/lib/mv_web/live/role_live/form.ex @@ -88,37 +88,62 @@ defmodule MvWeb.RoleLive.Form do @impl true def mount(params, _session, socket) do # Ensure current_user has role loaded for authorization checks - socket = - if socket.assigns[:current_user] do - user = socket.assigns.current_user + socket = ensure_user_role_loaded(socket) - user_with_role = - case Map.get(user, :role) do - %Ash.NotLoaded{} -> Ash.load!(user, :role, domain: Mv.Accounts) - nil -> Ash.load!(user, :role, domain: Mv.Accounts) - role when not is_nil(role) -> user + case params["id"] do + nil -> + action = gettext("New") + page_title = action <> " " <> gettext("Role") + + {:ok, + socket + |> assign(:return_to, return_to(params["return_to"])) + |> assign(:role, nil) + |> assign(:page_title, page_title) + |> assign_form()} + + id -> + try do + case Ash.get( + Mv.Authorization.Role, + id, + domain: Mv.Authorization, + actor: socket.assigns[:current_user] + ) do + {:ok, role} -> + action = gettext("Edit") + page_title = action <> " " <> gettext("Role") + + {:ok, + socket + |> assign(:return_to, return_to(params["return_to"])) + |> assign(:role, role) + |> assign(:page_title, page_title) + |> assign_form()} + + {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]}} -> + {:ok, + socket + |> put_flash(:error, gettext("Role not found.")) + |> redirect(to: ~p"/admin/roles")} + + {:error, error} -> + raise error end + rescue + e in [Ash.Error.Invalid] -> + case e do + %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]} -> + {:ok, + socket + |> put_flash(:error, gettext("Role not found.")) + |> redirect(to: ~p"/admin/roles")} - assign(socket, :current_user, user_with_role) - else - socket - end - - role = - case params["id"] do - nil -> nil - id -> Ash.get!(Mv.Authorization.Role, id, domain: Mv.Authorization) - end - - action = if is_nil(role), do: gettext("New"), else: gettext("Edit") - page_title = action <> " " <> gettext("Role") - - {:ok, - socket - |> assign(:return_to, return_to(params["return_to"])) - |> assign(:role, role) - |> assign(:page_title, page_title) - |> assign_form()} + _ -> + reraise e, __STACKTRACE__ + end + end + end end @spec return_to(String.t() | nil) :: String.t() @@ -145,7 +170,7 @@ defmodule MvWeb.RoleLive.Form do socket = socket - |> put_flash(:info, gettext("Role saved successfully")) + |> put_flash(:info, gettext("Role saved successfully.")) |> push_navigate(to: redirect_path) {:noreply, socket} @@ -159,16 +184,21 @@ defmodule MvWeb.RoleLive.Form do defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) @spec assign_form(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t() - defp assign_form(%{assigns: %{role: role}} = socket) do + defp assign_form(%{assigns: %{role: role, current_user: actor}} = socket) do form = if role do - AshPhoenix.Form.for_update(role, :update_role, domain: Mv.Authorization, as: "role") + AshPhoenix.Form.for_update(role, :update_role, + domain: Mv.Authorization, + as: "role", + actor: actor + ) else AshPhoenix.Form.for_create( Mv.Authorization.Role, :create_role, domain: Mv.Authorization, - as: "role" + as: "role", + actor: actor ) end @@ -199,4 +229,29 @@ defmodule MvWeb.RoleLive.Form do defp return_path("show", _role), do: ~p"/admin/roles" defp return_path(_, role) when not is_nil(role), do: ~p"/admin/roles/#{role.id}" defp return_path(_, _role), do: ~p"/admin/roles" + + defp ensure_user_role_loaded(socket) do + if socket.assigns[:current_user] do + user = socket.assigns.current_user + user_with_role = load_user_role(user) + assign(socket, :current_user, user_with_role) + else + socket + end + end + + defp load_user_role(user) do + case Map.get(user, :role) do + %Ash.NotLoaded{} -> load_role_safely(user) + nil -> load_role_safely(user) + _role -> user + end + end + + defp load_role_safely(user) do + case Ash.load(user, :role, domain: Mv.Accounts) do + {:ok, loaded_user} -> loaded_user + {:error, _} -> user + end + end end