Current section
Files
Jump to
Current section
Files
lib/securex_web/controllers/role_controller.ex
defmodule SecureXWeb.RoleController do
@moduledoc false
import Macro, only: [camelize: 1]
use SecureXWeb, :controller
alias SecureX.Common
alias SecureX.SecureXContext, as: Context
@doc """
Create a Role,
## Examples
iex> create(%{"role" => "Super Admin"})
%Role{
id: "super_admin",
name: "Super Admin",
permission: [] || :no_resources_found || :permissions_already_set
}
"""
@spec create(map()) :: struct()
def create(params) when params !== %{} do
case params do
%{role: role} -> create_role_sage(role)
%{"role" => role} -> create_role_sage(role)
_-> {:error, :bad_input}
end
end
def create(_), do: {:error, :bad_input}
defp create_role_sage(role) do
with nil <- Context.get_role_by(role),
{:ok, new_role} <- create_role(role),
{:ok, permissions} <- create_permissions(role) do
{:ok, Map.merge(new_role, %{permissions: permissions})}
else
%{__struct__: _} -> {:error, :alrady_exist}
{:error, error} -> {:error, error}
end
end
defp create_role(role) do
name = role |> String.trim
role = name
|> String.downcase
|> String.replace(" ", "_")
Context.create_role(%{id: role, name: camelize(name)})
end
defp create_permissions(role_id) do
case Context.get_permission_by([role_id]) do
[] ->
case Context.list_resources() do
[] -> {:ok, :no_resources_found}
resources ->
{:ok,
Enum.each(resources, fn %{id: res_id} ->
Context.create_permission(%{resource_id: res_id, role_id: role_id, permission: -1})
end)
}
end
_-> {:ok, :permissions_already_set}
end
end
@doc """
Update Role,
## Examples
iex> update(%{"id" => "super_admin", "role" => "Admin", "permissions" => [%{"resource_id" => "users", "permission" => 4}]})
%Role{
id: admin,
name: "Admin",
permissions: [] || :updated
}
"""
@spec update(map()) :: struct()
def update(params) when params !== %{} do
case params do
%{id: role_id} -> update_role_sage(role_id, params)
%{"id" => role_id} ->
params = Common.keys_to_atoms(params)
update_role_sage(role_id, params)
_-> {:error, :bad_input}
end
end
def update(_), do: {:error, :bad_input}
defp update_role_sage(role_id, params) do
with %{__struct__: _} = prev_role <- Context.get_role_by(role_id),
{:ok, new_role} <- update_role(prev_role, params),
{:ok, new_role} <- update_permissions(new_role, params) do
{:ok, new_role}
else
nil -> {:error, :alrady_exist}
{:error, error} -> {:error, error}
end
end
defp update_role(prev_role, %{role: new_role}) do
name = new_role |> String.trim
updated_role = name
|> String.downcase
|> String.replace(" ", "_")
if(prev_role.id !== updated_role) do
new_role = Context.create_role(%{id: updated_role, name: camelize(name)})
case Context.get_permissions(prev_role.id) do
[] -> :nothing
permissions -> Enum.map(permissions, fn per -> Context.update_permission(per, %{role_id: updated_role}) end)
end
case Context.get_user_roles_by(%{role_id: prev_role.id}) do
[] -> :nothing
user_roles -> Enum.map(user_roles, fn user_role -> Context.update_user_role(user_role, %{role_id: updated_role}) end)
end
Context.delete_role(prev_role)
new_role
else
{:ok, prev_role}
end
end
defp update_permissions(role, %{permissions: permissions}) when permissions !== [] do
permissions = Enum.map(
permissions,
fn per ->
case per do
%{"resource_id" => resource_id, "permission" => permission} ->
update_permission(resource_id, permission, role.id)
%{resource_id: resource_id, permission: permission} ->
update_permission(resource_id, permission, role.id)
_-> :bad_input
end
end)
{:ok, Map.merge(role, %{permissions: permissions})}
end
defp update_permissions(role, _), do: {:ok, role}
defp update_permission(resource_id, updated_permission, role_id) do
case Context.get_permission(resource_id, role_id) do
nil -> :nothing
permission -> Context.update_permission(permission, %{permission: updated_permission, role_id: role_id})
end
end
@doc """
Delete Role,
## Examples
iex> delete(%{"id" => "admin")
%Role{
id: "admin",
name: "Admin",
permissions: :successfully_removed_permissions,
user_roles: :successfully_removed_user_roles
}
"""
@spec delete(map()) :: struct()
def delete(params) when params !== %{} do
case params do
%{id: role_id} -> delete_role_sage(role_id)
%{"id" => role_id} -> delete_role_sage(role_id)
_-> {:error, :bad_input}
end
end
def delete(_), do: {:error, :bad_input}
defp delete_role_sage(role_id) do
with %{__struct__: _} = role <- Context.get_role_by(role_id),
{:ok, permission} <- remove_permissions(role),
{:ok, user_role} <- remove_user_roles(role),
{:ok, role} <- delete_role(role) do
{:ok, Map.merge(role, %{permissions: permission, user_roles: user_role})}
else
nil -> {:error, :doesnt_exist}
{:error, error} -> {:error, error}
end
end
defp remove_permissions(%{id: role_id}) do
case Context.get_permissions(role_id) do
[] -> {:ok, :already_removed}
permissions ->
Enum.map(permissions, fn per -> Context.delete_permission(per) end)
{:ok, :successfully_removed_permissions}
end
end
defp remove_permissions(_), do: {:ok, :invalid_role_id}
defp remove_user_roles(%{id: role_id}) do
case Context.get_user_roles_by(%{role_id: role_id}) do
[] -> {:ok, :already_removed}
user_roles ->
Enum.map(user_roles, fn user_role -> Context.delete_user_role(user_role) end)
{:ok, :successfully_removed_user_roles}
end
end
defp remove_user_roles(_), do: {:ok, :invalid_role_id}
defp delete_role(role) do
case Context.delete_role(role) do
{:error, error} -> {:error, error}
{:ok, role} -> {:ok, role}
end
end
end