194 lines
5.8 KiB
Elixir
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
|