97 lines
3 KiB
Elixir
97 lines
3 KiB
Elixir
defmodule ToweropsWeb.Live.Helpers.AccessControl do
|
|
@moduledoc """
|
|
Centralized organization-based access control for LiveViews.
|
|
|
|
Provides functions to verify that users have access to resources
|
|
(devices, sites, alerts) within their organization scope.
|
|
"""
|
|
|
|
alias Towerops.Alerts.Alert
|
|
alias Towerops.Devices
|
|
alias Towerops.Devices.Device
|
|
alias Towerops.Repo
|
|
alias Towerops.Sites
|
|
alias Towerops.Sites.Site
|
|
|
|
@doc """
|
|
Verifies that a device belongs to the specified organization.
|
|
|
|
Returns `{:ok, device}` if access is granted, or an error tuple.
|
|
|
|
## Examples
|
|
|
|
iex> verify_device_access(device_id, org_id)
|
|
{:ok, %Device{}}
|
|
|
|
iex> verify_device_access(device_id, wrong_org_id)
|
|
{:error, :unauthorized}
|
|
|
|
iex> verify_device_access("nonexistent", org_id)
|
|
{:error, :not_found}
|
|
"""
|
|
@spec verify_device_access(binary(), binary()) ::
|
|
{:ok, Device.t()} | {:error, :not_found | :unauthorized}
|
|
def verify_device_access(device_id, organization_id) do
|
|
case Devices.get_device(device_id) do
|
|
%Device{organization_id: ^organization_id} = device -> {:ok, device}
|
|
nil -> {:error, :not_found}
|
|
%Device{} -> {:error, :unauthorized}
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Verifies that a site belongs to the specified organization.
|
|
|
|
Returns `{:ok, site}` if access is granted, or an error tuple.
|
|
|
|
## Examples
|
|
|
|
iex> verify_site_access(site_id, org_id)
|
|
{:ok, %Site{}}
|
|
|
|
iex> verify_site_access(site_id, wrong_org_id)
|
|
{:error, :unauthorized}
|
|
|
|
iex> verify_site_access("nonexistent", org_id)
|
|
{:error, :not_found}
|
|
"""
|
|
@spec verify_site_access(binary(), binary()) ::
|
|
{:ok, Site.t()} | {:error, :not_found | :unauthorized}
|
|
def verify_site_access(site_id, organization_id) do
|
|
case Sites.get_site(site_id) do
|
|
%Site{organization_id: ^organization_id} = site -> {:ok, site}
|
|
nil -> {:error, :not_found}
|
|
%Site{} -> {:error, :unauthorized}
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Verifies that an alert's device belongs to the specified organization.
|
|
|
|
Returns `{:ok, alert}` if access is granted, or an error tuple.
|
|
The alert is preloaded with `device: [site: :organization]` for access checking.
|
|
|
|
## Examples
|
|
|
|
iex> verify_alert_access(alert_id, org_id)
|
|
{:ok, %Alert{device: %Device{site: %Site{organization: %Organization{}}}}}
|
|
|
|
iex> verify_alert_access(alert_id, wrong_org_id)
|
|
{:error, :unauthorized}
|
|
|
|
iex> verify_alert_access("nonexistent", org_id)
|
|
{:error, :not_found}
|
|
"""
|
|
@spec verify_alert_access(binary(), binary()) ::
|
|
{:ok, Alert.t()} | {:error, :not_found | :unauthorized}
|
|
def verify_alert_access(alert_id, organization_id) do
|
|
with %Alert{} = alert <- Repo.get(Alert, alert_id),
|
|
alert = Repo.preload(alert, [:acknowledged_by, device: [site: :organization]]),
|
|
%Alert{device: %{site: %{organization_id: ^organization_id}}} <- alert do
|
|
{:ok, alert}
|
|
else
|
|
nil -> {:error, :not_found}
|
|
%Alert{} -> {:error, :unauthorized}
|
|
end
|
|
end
|
|
end
|