towerops/test/towerops/admin_test.exs
2026-01-31 09:35:07 -06:00

194 lines
5.8 KiB
Elixir

defmodule Towerops.AdminTest do
use Towerops.DataCase
alias Towerops.Admin
describe "GDPR data access - list_audit_logs_for_user/2" do
import Towerops.AccountsFixtures
setup do
user = user_fixture()
superuser = user_fixture(%{superuser: true})
target_user = user_fixture()
%{user: user, superuser: superuser, target_user: target_user}
end
test "returns audit logs where user is the target", %{superuser: superuser, target_user: target_user} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(target_user.id)
assert length(result) == 1
assert hd(result).target_user_id == target_user.id
end
test "returns audit logs where user is the superuser", %{superuser: superuser, target_user: target_user} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(superuser.id)
assert length(result) == 1
assert hd(result).superuser_id == superuser.id
end
test "returns audit logs for both superuser and target actions", %{
superuser: superuser,
target_user: target_user,
user: user
} do
# User is target in one action
{:ok, _log1} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: user.id,
ip_address: "127.0.0.1"
})
# User is superuser in another action
{:ok, _log2} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: user.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(user.id)
assert length(result) == 2
end
test "does not return audit logs for other users", %{
superuser: superuser,
target_user: target_user,
user: user
} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
# User is not involved in this log
result = Admin.list_audit_logs_for_user(user.id)
assert result == []
end
test "respects limit parameter", %{superuser: superuser, target_user: target_user} do
# Create 5 audit logs
for _i <- 1..5 do
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
end
result = Admin.list_audit_logs_for_user(target_user.id, limit: 3)
assert length(result) == 3
end
test "defaults to limit 100", %{superuser: superuser, target_user: target_user} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
# Should not error with default limit
result = Admin.list_audit_logs_for_user(target_user.id)
assert length(result) == 1
end
test "orders logs by inserted_at descending", %{superuser: superuser, target_user: target_user} do
{:ok, _old_log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
# Sleep to ensure different timestamp (database uses second precision)
Process.sleep(1100)
{:ok, _new_log} =
Admin.create_audit_log(%{
action: "impersonate_end",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(target_user.id)
assert length(result) == 2
# Most recent should be first
[first, second] = result
# Verify ordering by timestamp
assert DateTime.after?(first.inserted_at, second.inserted_at)
# The newer log (impersonate_end) should come first
assert first.action == "impersonate_end"
assert second.action == "impersonate_start"
end
test "preloads superuser and target_user associations", %{
superuser: superuser,
target_user: target_user
} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "impersonate_start",
superuser_id: superuser.id,
target_user_id: target_user.id,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(target_user.id)
assert length(result) == 1
log = hd(result)
assert Ecto.assoc_loaded?(log.superuser)
assert Ecto.assoc_loaded?(log.target_user)
assert log.superuser.id == superuser.id
assert log.target_user.id == target_user.id
end
test "returns empty list when user has no audit logs", %{user: user} do
result = Admin.list_audit_logs_for_user(user.id)
assert result == []
end
test "handles audit logs with nil target_user_id", %{superuser: superuser} do
{:ok, _log} =
Admin.create_audit_log(%{
action: "user_data_exported",
superuser_id: superuser.id,
target_user_id: nil,
ip_address: "127.0.0.1"
})
result = Admin.list_audit_logs_for_user(superuser.id)
assert length(result) == 1
assert hd(result).target_user_id == nil
end
end
end