feat: add approval ui for join requests
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
50433e607f
commit
86d9242d83
22 changed files with 1624 additions and 12 deletions
|
|
@ -40,6 +40,13 @@ defmodule Mv.Membership.JoinRequest do
|
|||
change Mv.Membership.JoinRequest.Changes.FilterFormDataByAllowlist
|
||||
end
|
||||
|
||||
# Internal/seeding only: create with status submitted (no policy allows; use authorize?: false).
|
||||
create :create_submitted do
|
||||
description "Create a join request with status submitted (seeds, internal use only)"
|
||||
accept [:email, :first_name, :last_name, :form_data, :schema_version]
|
||||
change Mv.Membership.JoinRequest.Changes.SetSubmittedForSeeding
|
||||
end
|
||||
|
||||
read :get_by_confirmation_token_hash do
|
||||
description "Find a join request by confirmation token hash (for confirm flow only)"
|
||||
argument :confirmation_token_hash, :string, allow_nil?: false
|
||||
|
|
@ -56,25 +63,64 @@ defmodule Mv.Membership.JoinRequest do
|
|||
|
||||
change Mv.Membership.JoinRequest.Changes.ConfirmRequest
|
||||
end
|
||||
|
||||
update :approve do
|
||||
description "Approve a submitted join request and promote to Member"
|
||||
require_atomic? false
|
||||
|
||||
change Mv.Membership.JoinRequest.Changes.ApproveRequest
|
||||
end
|
||||
|
||||
update :reject do
|
||||
description "Reject a submitted join request"
|
||||
require_atomic? false
|
||||
|
||||
change Mv.Membership.JoinRequest.Changes.RejectRequest
|
||||
end
|
||||
end
|
||||
|
||||
policies do
|
||||
policy action(:submit) do
|
||||
# Use :strict so unauthorized access returns Forbidden (not empty list).
|
||||
# Default :filter would silently return [] for unauthorized reads instead of Forbidden.
|
||||
default_access_type :strict
|
||||
|
||||
# Public actions: bypass so nil actor is immediately authorized (skips all remaining policies).
|
||||
# Using bypass (not policy) avoids AND-combination with the read policy below.
|
||||
bypass action(:submit) do
|
||||
description "Allow unauthenticated submit (public join form)"
|
||||
authorize_if Mv.Authorization.Checks.ActorIsNil
|
||||
end
|
||||
|
||||
policy action(:get_by_confirmation_token_hash) do
|
||||
bypass action(:get_by_confirmation_token_hash) do
|
||||
description "Allow unauthenticated lookup by token hash for confirm"
|
||||
authorize_if Mv.Authorization.Checks.ActorIsNil
|
||||
end
|
||||
|
||||
policy action(:confirm) do
|
||||
bypass action(:confirm) do
|
||||
description "Allow unauthenticated confirm (confirmation link click)"
|
||||
authorize_if Mv.Authorization.Checks.ActorIsNil
|
||||
end
|
||||
|
||||
# Default read/destroy: no policy for actor nil → Forbidden
|
||||
# READ: bypass for authorized roles (normal_user, admin).
|
||||
# Uses a SimpleCheck (HasJoinRequestAccess) to avoid HasPermission.auto_filter returning
|
||||
# expr(false), which would silently produce an empty list instead of Forbidden for
|
||||
# unauthorized actors. See docs/policy-bypass-vs-haspermission.md.
|
||||
# Unauthorized actors fall through to no matching policy → Ash default deny (Forbidden).
|
||||
bypass action_type(:read) do
|
||||
description "Allow normal_user and admin to read join requests (SimpleCheck bypass)"
|
||||
authorize_if Mv.Authorization.Checks.HasJoinRequestAccess
|
||||
end
|
||||
|
||||
# Approve/Reject: only actors with JoinRequest update permission
|
||||
policy action(:approve) do
|
||||
description "Allow authenticated users with JoinRequest update permission to approve"
|
||||
authorize_if Mv.Authorization.Checks.HasPermission
|
||||
end
|
||||
|
||||
policy action(:reject) do
|
||||
description "Allow authenticated users with JoinRequest update permission to reject"
|
||||
authorize_if Mv.Authorization.Checks.HasPermission
|
||||
end
|
||||
end
|
||||
|
||||
validations do
|
||||
|
|
@ -135,6 +181,13 @@ defmodule Mv.Membership.JoinRequest do
|
|||
update_timestamp :updated_at
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :reviewed_by_user, Mv.Accounts.User do
|
||||
define_attribute? false
|
||||
source_attribute :reviewed_by_user_id
|
||||
end
|
||||
end
|
||||
|
||||
# Public helpers (used by SetConfirmationToken change and domain confirm_join_request)
|
||||
|
||||
@doc """
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue