Restrict User.update_user to admin; allow :update for email only
- Add ActorIsAdmin policy check (admin permission set only) - User: policy action(:update_user) forbid_unless + authorize_if ActorIsAdmin - User: primary :update action accept [:email] for non-admin profile edit
This commit is contained in:
parent
faee780aab
commit
14fa873640
2 changed files with 31 additions and 0 deletions
|
|
@ -103,6 +103,7 @@ defmodule Mv.Accounts.User do
|
||||||
# the specialized :update_user action below.
|
# the specialized :update_user action below.
|
||||||
update :update do
|
update :update do
|
||||||
primary? true
|
primary? true
|
||||||
|
accept [:email]
|
||||||
|
|
||||||
# Required because custom validation functions (email validation, member relationship validation)
|
# Required because custom validation functions (email validation, member relationship validation)
|
||||||
# cannot be executed atomically. These validations need to query the database and perform
|
# cannot be executed atomically. These validations need to query the database and perform
|
||||||
|
|
@ -310,6 +311,14 @@ defmodule Mv.Accounts.User do
|
||||||
authorize_if expr(id == ^actor(:id))
|
authorize_if expr(id == ^actor(:id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# update_user allows :member argument (link/unlink). Only admins may use it to prevent
|
||||||
|
# privilege escalation (own_data could otherwise link to any member and get :linked scope).
|
||||||
|
policy action(:update_user) do
|
||||||
|
description "Only admins can update user with member link/unlink"
|
||||||
|
forbid_unless Mv.Authorization.Checks.ActorIsAdmin
|
||||||
|
authorize_if Mv.Authorization.Checks.ActorIsAdmin
|
||||||
|
end
|
||||||
|
|
||||||
# UPDATE/DESTROY via HasPermission (evaluates PermissionSets scope)
|
# UPDATE/DESTROY via HasPermission (evaluates PermissionSets scope)
|
||||||
policy action_type([:read, :create, :update, :destroy]) do
|
policy action_type([:read, :create, :update, :destroy]) do
|
||||||
description "Check permissions from user's role and permission set"
|
description "Check permissions from user's role and permission set"
|
||||||
|
|
|
||||||
22
lib/mv/authorization/checks/actor_is_admin.ex
Normal file
22
lib/mv/authorization/checks/actor_is_admin.ex
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule Mv.Authorization.Checks.ActorIsAdmin do
|
||||||
|
@moduledoc """
|
||||||
|
Policy check: true when the actor's role has permission_set_name "admin".
|
||||||
|
|
||||||
|
Used to restrict actions (e.g. User.update_user for member link/unlink) to admins only.
|
||||||
|
"""
|
||||||
|
use Ash.Policy.SimpleCheck
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def describe(_opts), do: "actor has admin permission set"
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def match?(nil, _context, _opts), do: false
|
||||||
|
|
||||||
|
def match?(actor, _context, _opts) do
|
||||||
|
ps_name =
|
||||||
|
get_in(actor, [Access.key(:role), Access.key(:permission_set_name)]) ||
|
||||||
|
get_in(actor, [Access.key("role"), Access.key("permission_set_name")])
|
||||||
|
|
||||||
|
ps_name == "admin"
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue