Packages
phoenix_kit
1.7.96
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit/audit_log.ex
defmodule PhoenixKit.AuditLog do
@moduledoc """
Context for managing audit logs in PhoenixKit.
Provides functionality for logging administrative actions such as password resets,
user modifications, and other sensitive operations that require tracking.
## Examples
# Log an admin password reset
PhoenixKit.AuditLog.log_password_change(%{
target_user_uuid: 123,
admin_user_uuid: 1,
action: :admin_password_reset,
ip_address: "192.168.1.1",
user_agent: "Mozilla/5.0..."
})
# Query audit logs for a specific user
PhoenixKit.AuditLog.list_logs_for_user(123)
# Query audit logs by action type
PhoenixKit.AuditLog.list_logs_by_action(:admin_password_reset)
"""
import Ecto.Query, warn: false
alias PhoenixKit.AuditLog.Entry
alias PhoenixKit.RepoHelper, as: Repo
@doc """
Logs a password change action performed by an admin.
## Parameters
* `attrs` - Map containing:
* `:target_user_uuid` - ID of the user whose password was changed (required)
* `:admin_user_uuid` - ID of the admin who performed the action (required)
* `:action` - The action performed (default: `:admin_password_reset`)
* `:ip_address` - IP address of the admin (optional)
* `:user_agent` - User agent string of the admin (optional)
* `:metadata` - Additional metadata (optional)
## Examples
iex> log_password_change(%{
...> target_user_uuid: 123,
...> admin_user_uuid: 1,
...> action: :admin_password_reset,
...> ip_address: "192.168.1.1"
...> })
{:ok, %Entry{}}
"""
def log_password_change(attrs) do
attrs
|> Map.put_new(:action, :admin_password_reset)
|> create_log_entry()
end
@doc """
Creates a generic audit log entry.
## Parameters
* `attrs` - Map containing:
* `:target_user_uuid` - ID of the user affected by the action (required)
* `:admin_user_uuid` - ID of the admin who performed the action (required)
* `:action` - The action performed (required)
* `:ip_address` - IP address of the admin (optional)
* `:user_agent` - User agent string of the admin (optional)
* `:metadata` - Additional metadata (optional)
## Examples
iex> create_log_entry(%{
...> target_user_uuid: 123,
...> admin_user_uuid: 1,
...> action: :user_created,
...> ip_address: "192.168.1.1"
...> })
{:ok, %Entry{}}
"""
def create_log_entry(attrs) do
%Entry{}
|> Entry.changeset(attrs)
|> Repo.insert()
end
@doc """
Lists all audit log entries for a specific user.
Returns entries where the user is either the target or the admin.
## Examples
iex> list_logs_for_user(123)
[%Entry{}, ...]
"""
def list_logs_for_user(user_uuid, opts \\ []) when is_binary(user_uuid) do
limit = Keyword.get(opts, :limit, 100)
from(e in Entry,
where: e.target_user_uuid == ^user_uuid or e.admin_user_uuid == ^user_uuid,
order_by: [desc: e.inserted_at],
limit: ^limit
)
|> Repo.all()
end
@doc """
Lists all audit log entries by action type.
## Examples
iex> list_logs_by_action(:admin_password_reset)
[%Entry{}, ...]
"""
def list_logs_by_action(action, opts \\ []) do
action_string = to_string(action)
limit = Keyword.get(opts, :limit, 100)
from(e in Entry,
where: e.action == ^action_string,
order_by: [desc: e.inserted_at],
limit: ^limit
)
|> Repo.all()
end
@doc """
Lists all audit log entries with optional filters.
## Options
* `:limit` - Maximum number of entries to return (default: 100)
* `:offset` - Number of entries to skip (default: 0)
* `:action` - Filter by action type
* `:target_user_uuid` - Filter by target user ID
* `:admin_user_uuid` - Filter by admin user ID
* `:from_date` - Filter entries after this date
* `:to_date` - Filter entries before this date
## Examples
iex> list_logs(limit: 50, action: :admin_password_reset)
[%Entry{}, ...]
"""
def list_logs(opts \\ []) do
limit = Keyword.get(opts, :limit, 100)
offset = Keyword.get(opts, :offset, 0)
query = from(e in Entry, order_by: [desc: e.inserted_at])
query =
Enum.reduce(opts, query, fn
{:action, action}, query ->
from(e in query, where: e.action == ^to_string(action))
{:target_user_uuid, user_uuid}, query when is_binary(user_uuid) ->
from(e in query, where: e.target_user_uuid == ^user_uuid)
{:admin_user_uuid, user_uuid}, query when is_binary(user_uuid) ->
from(e in query, where: e.admin_user_uuid == ^user_uuid)
{:from_date, date}, query ->
from(e in query, where: e.inserted_at >= ^date)
{:to_date, date}, query ->
from(e in query, where: e.inserted_at <= ^date)
_other, query ->
query
end)
query
|> limit(^limit)
|> offset(^offset)
|> Repo.all()
end
@doc """
Gets a single audit log entry by ID.
## Examples
iex> get_log!(123)
%Entry{}
iex> get_log!(456)
** (Ecto.NoResultsError)
"""
def get_log!(uuid) when is_binary(uuid) do
Repo.get!(Entry, uuid)
end
@doc """
Counts audit log entries with optional filters.
## Options
Same options as `list_logs/1` except `:limit` and `:offset`
## Examples
iex> count_logs(action: :admin_password_reset)
42
"""
def count_logs(opts \\ []) do
query = from(e in Entry)
query =
Enum.reduce(opts, query, fn
{:action, action}, query ->
from(e in query, where: e.action == ^to_string(action))
{:target_user_uuid, user_uuid}, query when is_binary(user_uuid) ->
from(e in query, where: e.target_user_uuid == ^user_uuid)
{:admin_user_uuid, user_uuid}, query when is_binary(user_uuid) ->
from(e in query, where: e.admin_user_uuid == ^user_uuid)
{:from_date, date}, query ->
from(e in query, where: e.inserted_at >= ^date)
{:to_date, date}, query ->
from(e in query, where: e.inserted_at <= ^date)
_other, query ->
query
end)
Repo.aggregate(query, :count, :uuid)
end
end