Class ResolvedAuthorizationPath
Pre-computed navigation path from a leaf resource to an owner resource for indirect (multi-hop) resource authorization. Constructed at registration time (either by the assembly-scanning resolver or by an explicit registration helper) and passed to ResourceAuthorizationViaBehavior<TMessage, TLeaf, TOwner, TResponse>.
public sealed class ResolvedAuthorizationPath
- Inheritance
-
ResolvedAuthorizationPath
- Inherited Members
- Extension Methods
Remarks
Per-message registration. Each command has its own ResolvedAuthorizationPath. Do not register ResolvedAuthorizationPath as an unkeyed DI service — that would silently share a single path across all via-authorized commands, allowing one command's authorization rules to apply to another. Use one of the supported registration paths instead:
- Assembly scanning:
services.AddResourceAuthorization(typeof(MyCommand).Assembly)discovers via-commands, runs the resolver, and registers each path as a typed ResolvedAuthorizationPathHolder<TMessage, TLeaf, TOwner, TResponse>. - Explicit (AOT-friendly):
services.AddRelatedResourceAuthorization<TMessage, TLeaf, TLeafId, TOwner, TOwnerId, TResponse>(extractOwnerId)for single-hop, orservices.AddRelatedResourceAuthorization<TMessage, TLeaf, TOwner, TResponse>(path)accepting a hand-built path. Both overloads register the path as a closed-generic ResolvedAuthorizationPathHolder<TMessage, TLeaf, TOwner, TResponse> and the behavior as a typed descriptor — preserving relocation beforeValidationBehavior.
As a defense-in-depth measure, the behavior's constructor validates that the path's MessageType, LeafType, and OwnerType agree with its own generic arguments and fails fast when they do not.
Each ResolvedAuthorizationHop in Hops describes a single load step: starting from one or more instances of FromType, the pipeline extracts the IDs of related instances of type ToType, de-duplicates them, and loads each via the delegate carried on the hop.
Topology invariants enforced at construction time:
- Hops must be non-empty.
- For all adjacent hops,
hops[i].ToTypemust equalhops[i+1].FromType(chain continuity). - The first hop's FromType must equal LeafType.
- The terminal hop's ToType must equal OwnerType.
- At most one hop is plural, and if present it must be the terminal hop. Plural-in-middle (fan-out cartesian expansion) is intentionally out of scope for v1; use
IResourceLoader<TMessage, TProjection>with a projection type instead.
Constructors
ResolvedAuthorizationPath(Type, Type, Type, IReadOnlyList<ResolvedAuthorizationHop>)
Creates a new resolved authorization path.
public ResolvedAuthorizationPath(Type messageType, Type leafType, Type ownerType, IReadOnlyList<ResolvedAuthorizationHop> hops)
Parameters
messageTypeTypeThe command/query type this path serves.
leafTypeTypeThe leaf resource type the command identifies.
ownerTypeTypeThe owner resource type authorization is evaluated against.
hopsIReadOnlyList<ResolvedAuthorizationHop>The ordered list of hops from leaf to owner. The list is copied defensively, so subsequent mutation of the caller's collection cannot alter the path after construction.
Exceptions
- ArgumentNullException
Thrown when any argument is null.
- ArgumentException
Thrown when
hopsis empty, when adjacent hops do not chain (hops[i].ToType != hops[i+1].FromType), when the first hop's FromType does not equalleafType, when the terminal hop's ToType does not equalownerType, or when a plural hop appears at a non-terminal position.
Properties
Hops
Gets the ordered list of hops from leaf to owner.
public IReadOnlyList<ResolvedAuthorizationHop> Hops { get; }
Property Value
LeafType
Gets the leaf resource type the command identifies.
public Type LeafType { get; }
Property Value
MessageType
Gets the command/query type this path serves.
public Type MessageType { get; }
Property Value
OwnerType
Gets the owner resource type authorization is evaluated against.
public Type OwnerType { get; }