Packages
phoenix_kit
2.41.3
2.43.1
2.43.0
2.42.1
2.42.0
2.41.6
2.41.4
2.41.3
2.41.2
2.41.1
2.41.0
2.40.1
2.40.0
2.39.0
2.38.1
2.38.0
2.37.5
2.37.4
2.37.3
2.37.2
2.37.1
2.37.0
2.36.1
2.36.0
2.35.0
2.34.0
2.33.0
2.32.1
2.32.0
2.31.1
2.31.0
2.30.0
2.29.1
2.29.0
2.28.2
2.28.1
2.28.0
2.27.2
2.27.1
2.27.0
2.26.1
2.26.0
2.25.0
2.24.0
2.23.3
2.23.2
2.23.1
2.23.0
2.22.24
2.22.23
2.22.22
2.22.21
2.22.20
2.22.19
2.22.18
2.22.17
2.22.16
2.22.15
2.22.14
2.22.13
2.22.12
2.22.11
2.22.10
2.22.9
2.22.8
2.22.7
2.22.6
2.22.5
2.22.4
2.22.3
2.22.2
2.22.1
2.22.0
2.21.5
2.21.4
2.21.3
2.21.2
2.21.1
2.21.0
2.20.0
2.19.0
2.18.1
2.18.0
2.17.0
2.16.0
2.15.1
2.15.0
2.14.2
2.14.1
2.14.0
2.13.19
2.13.18
2.13.17
2.13.16
2.13.15
2.13.13
2.13.12
2.13.11
2.13.10
2.13.9
2.13.8
2.13.7
2.13.6
2.13.5
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.12.1
2.12.0
2.11.0
2.10.0
2.9.0
2.8.1
2.8.0
2.7.0
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.0
2.0.1
2.0.0
1.7.236
1.7.235
1.7.234
1.7.233
1.7.232
1.7.231
1.7.230
1.7.229
1.7.228
1.7.227
1.7.226
1.7.225
1.7.224
1.7.223
1.7.222
1.7.221
1.7.220
1.7.219
1.7.218
1.7.217
1.7.216
1.7.215
1.7.214
1.7.213
1.7.212
1.7.211
1.7.210
1.7.209
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_web/actor.ex
defmodule PhoenixKitWeb.Actor do
@moduledoc """
Who is acting, read from a LiveView socket, a `Plug.Conn` or an assigns
map — the one place modules ask, instead of each reading its own assign.
The admin `live_session` puts both `:phoenix_kit_current_scope` and
`:phoenix_kit_current_user` on the socket. The scope is the canonical
one (it is what permission checks read), so it wins; the bare user is
the fallback for callers that only have that — a test harness, a plain
controller. Modules used to pick one or the other, so the same action
could log an actor in one module and none in the next.
PhoenixKit.Activity.log("crm", "crm.company_updated",
PhoenixKitWeb.Actor.opts(socket) ++ [resource_uuid: company.uuid])
"""
alias PhoenixKit.Users.Auth.Scope
@typedoc "Anything that knows who is acting."
@type source :: Phoenix.LiveView.Socket.t() | Plug.Conn.t() | Scope.t() | map() | nil
@doc """
The acting user's uuid, or `nil` when nobody is signed in.
PhoenixKitWeb.Actor.uuid(socket)
PhoenixKitWeb.Actor.uuid(conn)
PhoenixKitWeb.Actor.uuid(scope)
PhoenixKitWeb.Actor.uuid(%{phoenix_kit_current_user: user})
"""
@spec uuid(source()) :: String.t() | nil
def uuid(%Scope{user: user}), do: user_uuid(user)
def uuid(%{assigns: %{} = assigns}), do: uuid(assigns)
def uuid(%{} = assigns) do
case Map.get(assigns, :phoenix_kit_current_scope) do
%Scope{} = scope -> uuid(scope)
_ -> nil
end || user_uuid(Map.get(assigns, :phoenix_kit_current_user))
end
def uuid(_), do: nil
@doc """
`[actor_uuid: uuid]` for a context call that logs, or `[]` when nobody
is signed in — so it can be appended to other options as is.
"""
@spec opts(source()) :: keyword()
def opts(source) do
case uuid(source) do
nil -> []
uuid -> [actor_uuid: uuid]
end
end
@doc """
The name of the role the user is acting as (not PII), or `nil` — for
audit metadata that wants to say which role acted. With the role
switcher on, that is the active role, not the always-on roles that ride
along with it; otherwise the first role held.
"""
@spec role(source()) :: String.t() | nil
def role(%Scope{} = scope) do
case Scope.active_role(scope) do
%{name: name} when is_binary(name) ->
name
_ ->
case Scope.user_roles(scope) do
[role | _] when is_binary(role) -> role
_ -> nil
end
end
end
def role(%{assigns: %{} = assigns}), do: role(assigns)
def role(%{} = assigns), do: role(Map.get(assigns, :phoenix_kit_current_scope))
def role(_), do: nil
defp user_uuid(%{uuid: uuid}) when is_binary(uuid), do: uuid
defp user_uuid(_), do: nil
end