CRITICAL: - Membership: remove :role/:org_id/:user_id from mass-assignment cast; use explicit create_changeset/4 and role_update_changeset/2 - GraphQL member resolver: add authorize_invite/3 checking admin/owner role and role hierarchy - REST invitations controller: add auth check for invite creation HIGH: - ApiToken: remove :organization_id/:user_id from cast; use explicit create_changeset/4 MEDIUM: - Move 8 LiveView Ecto queries into context modules (Admin, Alerts, Coverages, OnCall, Snmp) - Replace Process.put/Process.get with socket assigns for unresolved_alert_count (user_auth + layouts + 50 templates) - Add batch get_utilization_for_interfaces/1 to eliminate N+1 capacity queries in device show - Replace Process.sleep with Process.monitor/assert_receive or Process.send_after in 5 test files LOW: - Add handle_params/3 to UserResetPasswordLive, UserRegistrationLive, StatusPageLive - Remove redundant Repo.preload calls; add preloads to list_site_devices/1 - Fix @impl annotations and credo nesting warnings
56 lines
1.9 KiB
Elixir
56 lines
1.9 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
|
|
alias Towerops.Devices
|
|
alias Towerops.Devices.Device
|
|
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.
|
|
"""
|
|
@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.
|
|
"""
|
|
@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.
|
|
"""
|
|
@spec verify_alert_access(binary(), binary()) ::
|
|
{:ok, Alert.t()} | {:error, :not_found | :unauthorized}
|
|
def verify_alert_access(alert_id, organization_id) do
|
|
Alerts.get_verified_alert(alert_id, organization_id)
|
|
end
|
|
end
|