199 lines
4.4 KiB
Elixir
199 lines
4.4 KiB
Elixir
defmodule Towerops.Admin do
|
|
@moduledoc """
|
|
The Admin context for superuser operations.
|
|
|
|
Provides functions for managing users, organizations, and audit logging.
|
|
"""
|
|
import Ecto.Query
|
|
|
|
alias Towerops.Accounts.User
|
|
alias Towerops.Admin.AuditLog
|
|
alias Towerops.Organizations.Organization
|
|
alias Towerops.Repo
|
|
|
|
## User Management
|
|
|
|
@doc """
|
|
Lists all users in the system with their organizations.
|
|
|
|
## Options
|
|
|
|
* `:limit` - Maximum number of users to return (default: 100)
|
|
* `:offset` - Number of users to skip (default: 0)
|
|
|
|
## Examples
|
|
|
|
iex> list_all_users()
|
|
[%User{}, ...]
|
|
|
|
iex> list_all_users(limit: 50, offset: 100)
|
|
[%User{}, ...]
|
|
"""
|
|
def list_all_users(opts \\ []) do
|
|
limit = Keyword.get(opts, :limit, 100)
|
|
offset = Keyword.get(opts, :offset, 0)
|
|
|
|
User
|
|
|> order_by([u], desc: u.inserted_at)
|
|
|> limit(^limit)
|
|
|> offset(^offset)
|
|
|> preload(:organizations)
|
|
|> Repo.all()
|
|
end
|
|
|
|
@doc """
|
|
Returns the total count of users in the system.
|
|
|
|
## Examples
|
|
|
|
iex> count_users()
|
|
42
|
|
"""
|
|
def count_users do
|
|
Repo.aggregate(User, :count)
|
|
end
|
|
|
|
@doc """
|
|
Deletes a user and creates an audit log entry.
|
|
|
|
## Examples
|
|
|
|
iex> delete_user(user_id, superuser_id, "127.0.0.1")
|
|
{:ok, %User{}}
|
|
|
|
iex> delete_user(invalid_id, superuser_id, "127.0.0.1")
|
|
** (Ecto.NoResultsError)
|
|
"""
|
|
def delete_user(user_id, superuser_id, ip_address) do
|
|
user = Repo.get!(User, user_id)
|
|
|
|
Repo.transaction(fn ->
|
|
# Create audit log before deletion
|
|
create_audit_log(%{
|
|
action: "user_delete",
|
|
superuser_id: superuser_id,
|
|
target_user_id: user_id,
|
|
metadata: %{email: user.email},
|
|
ip_address: ip_address
|
|
})
|
|
|
|
# Delete user (cascades to memberships and tokens)
|
|
Repo.delete!(user)
|
|
end)
|
|
end
|
|
|
|
## Organization Management
|
|
|
|
@doc """
|
|
Lists all organizations in the system with their memberships.
|
|
|
|
## Options
|
|
|
|
* `:limit` - Maximum number of organizations to return (default: 100)
|
|
* `:offset` - Number of organizations to skip (default: 0)
|
|
|
|
## Examples
|
|
|
|
iex> list_all_organizations()
|
|
[%Organization{}, ...]
|
|
|
|
iex> list_all_organizations(limit: 50, offset: 100)
|
|
[%Organization{}, ...]
|
|
"""
|
|
def list_all_organizations(opts \\ []) do
|
|
limit = Keyword.get(opts, :limit, 100)
|
|
offset = Keyword.get(opts, :offset, 0)
|
|
|
|
Organization
|
|
|> order_by([o], desc: o.inserted_at)
|
|
|> limit(^limit)
|
|
|> offset(^offset)
|
|
|> preload(memberships: :user)
|
|
|> Repo.all()
|
|
end
|
|
|
|
@doc """
|
|
Returns the total count of organizations in the system.
|
|
|
|
## Examples
|
|
|
|
iex> count_organizations()
|
|
15
|
|
"""
|
|
def count_organizations do
|
|
Repo.aggregate(Organization, :count)
|
|
end
|
|
|
|
@doc """
|
|
Deletes an organization and creates an audit log entry.
|
|
|
|
## Examples
|
|
|
|
iex> delete_organization(org_id, superuser_id, "127.0.0.1")
|
|
{:ok, %Organization{}}
|
|
|
|
iex> delete_organization(invalid_id, superuser_id, "127.0.0.1")
|
|
** (Ecto.NoResultsError)
|
|
"""
|
|
def delete_organization(org_id, superuser_id, ip_address) do
|
|
org = Repo.get!(Organization, org_id)
|
|
|
|
Repo.transaction(fn ->
|
|
# Create audit log before deletion
|
|
create_audit_log(%{
|
|
action: "org_delete",
|
|
superuser_id: superuser_id,
|
|
target_user_id: nil,
|
|
metadata: %{name: org.name, slug: org.slug},
|
|
ip_address: ip_address
|
|
})
|
|
|
|
# Delete organization (cascades to memberships, sites, device)
|
|
Repo.delete!(org)
|
|
end)
|
|
end
|
|
|
|
## Audit Logging
|
|
|
|
@doc """
|
|
Creates an audit log entry.
|
|
|
|
## Examples
|
|
|
|
iex> create_audit_log(%{action: "impersonate_start", superuser_id: superuser_id, target_user_id: user_id})
|
|
{:ok, %AuditLog{}}
|
|
|
|
iex> create_audit_log(%{action: "invalid"})
|
|
{:error, %Ecto.Changeset{}}
|
|
"""
|
|
def create_audit_log(attrs) do
|
|
%AuditLog{}
|
|
|> AuditLog.changeset(attrs)
|
|
|> Repo.insert()
|
|
end
|
|
|
|
@doc """
|
|
Lists recent audit logs with associated users.
|
|
|
|
## Options
|
|
|
|
* `:limit` - Maximum number of logs to return (default: 100)
|
|
|
|
## Examples
|
|
|
|
iex> list_audit_logs()
|
|
[%AuditLog{}, ...]
|
|
|
|
iex> list_audit_logs(limit: 50)
|
|
[%AuditLog{}, ...]
|
|
"""
|
|
def list_audit_logs(opts \\ []) do
|
|
limit = Keyword.get(opts, :limit, 100)
|
|
|
|
AuditLog
|
|
|> order_by([a], desc: a.inserted_at)
|
|
|> limit(^limit)
|
|
|> preload([:superuser, :target_user])
|
|
|> Repo.all()
|
|
end
|
|
end
|