Some checks failed
continuous-integration/drone/push Build is failing
- Create Admin role if it doesn't exist - Assign Admin role to admin@mv.local user - Remove separate create_admin_role script (integrated into seeds)
104 lines
2.9 KiB
Elixir
104 lines
2.9 KiB
Elixir
defmodule MvWeb.RoleLive.Index do
|
|
@moduledoc """
|
|
LiveView for displaying and managing the role list.
|
|
|
|
## Features
|
|
- List all roles with name, description, permission_set_name, is_system_role
|
|
- Create new roles
|
|
- Navigate to role details and edit forms
|
|
- Delete non-system roles
|
|
|
|
## Events
|
|
- `delete` - Remove a role from the database (only non-system roles)
|
|
|
|
## Security
|
|
Only admins can access this page (enforced by authorization).
|
|
"""
|
|
use MvWeb, :live_view
|
|
|
|
alias Mv.Authorization
|
|
|
|
@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
|
|
|
|
# Load role if not already loaded (check for Ash.NotLoaded struct)
|
|
user_with_role =
|
|
case Map.get(user, :role) do
|
|
%Ash.NotLoaded{} ->
|
|
case Ash.load(user, :role, domain: Mv.Accounts) do
|
|
{:ok, loaded_user} -> loaded_user
|
|
{:error, _} -> user
|
|
end
|
|
|
|
nil ->
|
|
case Ash.load(user, :role, domain: Mv.Accounts) do
|
|
{:ok, loaded_user} -> loaded_user
|
|
{:error, _} -> user
|
|
end
|
|
|
|
role when not is_nil(role) ->
|
|
user
|
|
end
|
|
|
|
assign(socket, :current_user, user_with_role)
|
|
else
|
|
socket
|
|
end
|
|
|
|
roles = load_roles()
|
|
|
|
{:ok,
|
|
socket
|
|
|> assign(:page_title, gettext("Listing Roles"))
|
|
|> assign(:roles, roles)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("delete", %{"id" => id}, socket) do
|
|
{:ok, role} = Authorization.get_role(id)
|
|
|
|
case Authorization.destroy_role(role) do
|
|
:ok ->
|
|
updated_roles = Enum.reject(socket.assigns.roles, &(&1.id == id))
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(:roles, updated_roles)
|
|
|> put_flash(:info, gettext("Role deleted successfully"))}
|
|
|
|
{:error, error} ->
|
|
error_message = format_error(error)
|
|
|
|
{:noreply,
|
|
put_flash(
|
|
socket,
|
|
:error,
|
|
gettext("Failed to delete role: %{error}", error: error_message)
|
|
)}
|
|
end
|
|
end
|
|
|
|
defp load_roles do
|
|
case Authorization.list_roles() do
|
|
{:ok, roles} -> Enum.sort_by(roles, & &1.name)
|
|
{:error, _} -> []
|
|
end
|
|
end
|
|
|
|
defp format_error(%Ash.Error.Invalid{} = error) do
|
|
Enum.map_join(error.errors, ", ", fn e -> e.message end)
|
|
end
|
|
|
|
defp format_error(error) when is_binary(error), do: error
|
|
defp format_error(_error), do: gettext("An error occurred")
|
|
|
|
defp permission_set_badge_class("own_data"), do: "badge badge-neutral badge-sm"
|
|
defp permission_set_badge_class("read_only"), do: "badge badge-info badge-sm"
|
|
defp permission_set_badge_class("normal_user"), do: "badge badge-success badge-sm"
|
|
defp permission_set_badge_class("admin"), do: "badge badge-error badge-sm"
|
|
defp permission_set_badge_class(_), do: "badge badge-ghost badge-sm"
|
|
end
|