feat: implement authorization policies for Member resource
This commit is contained in:
parent
93190d558f
commit
4192922fd3
5 changed files with 169 additions and 17 deletions
|
|
@ -34,7 +34,8 @@ defmodule Mv.Membership.Member do
|
|||
"""
|
||||
use Ash.Resource,
|
||||
domain: Mv.Membership,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
authorizers: [Ash.Policy.Authorizer]
|
||||
|
||||
require Ash.Query
|
||||
import Ash.Expr
|
||||
|
|
@ -296,6 +297,40 @@ defmodule Mv.Membership.Member do
|
|||
end
|
||||
end
|
||||
|
||||
# Authorization Policies
|
||||
# Order matters: Most specific policies first, then general permission check
|
||||
policies do
|
||||
# SYSTEM OPERATIONS: Allow operations without actor (seeds, tests, system jobs)
|
||||
# This must come first to allow database seeding and test fixtures
|
||||
# IMPORTANT: Use bypass so this short-circuits and doesn't require other policies
|
||||
bypass action_type([:create, :read, :update, :destroy]) do
|
||||
description "Allow system operations without actor (seeds, tests)"
|
||||
authorize_if Mv.Authorization.Checks.NoActor
|
||||
end
|
||||
|
||||
# SPECIAL CASE: Users can always READ their linked member
|
||||
# This allows users with ANY permission set to read their own linked member
|
||||
# Check using the inverse relationship: User.member_id → Member.id
|
||||
bypass action_type(:read) do
|
||||
description "Users can always read member linked to their account"
|
||||
authorize_if expr(id == ^actor(:member_id))
|
||||
end
|
||||
|
||||
# GENERAL: Check permissions from user's role
|
||||
# HasPermission handles update permissions correctly:
|
||||
# - :own_data → can update linked member (scope :linked)
|
||||
# - :read_only → cannot update any member (no update permission)
|
||||
# - :normal_user → can update all members (scope :all)
|
||||
# - :admin → can update all members (scope :all)
|
||||
policy action_type([:read, :create, :update, :destroy]) do
|
||||
description "Check permissions from user's role and permission set"
|
||||
authorize_if Mv.Authorization.Checks.HasPermission
|
||||
end
|
||||
|
||||
# DEFAULT: Forbid if no policy matched
|
||||
# Ash implicitly forbids if no policy authorized
|
||||
end
|
||||
|
||||
@doc """
|
||||
Filters members list based on email match priority.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue