@holo-js/authorization 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-WPHPV4WY.mjs +82 -0
- package/dist/chunk-WPHPV4WY.mjs.map +1 -0
- package/dist/contracts.d.ts +202 -0
- package/dist/contracts.mjs +3 -0
- package/dist/contracts.mjs.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.mjs +511 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/contracts.ts
|
|
2
|
+
var AUTHORIZATION_POLICY_MARKER = /* @__PURE__ */ Symbol.for("holo-js.authorization.policy");
|
|
3
|
+
var AUTHORIZATION_ABILITY_MARKER = /* @__PURE__ */ Symbol.for("holo-js.authorization.ability");
|
|
4
|
+
var AuthorizationError = class extends Error {
|
|
5
|
+
decision;
|
|
6
|
+
constructor(message, decision) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "AuthorizationError";
|
|
9
|
+
this.decision = decision;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var AuthorizationPolicyNotFoundError = class extends Error {
|
|
13
|
+
constructor(message = "[@holo-js/authorization] Policy definition was not found.") {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "AuthorizationPolicyNotFoundError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var AuthorizationAbilityNotFoundError = class extends Error {
|
|
19
|
+
constructor(message = "[@holo-js/authorization] Ability definition was not found.") {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "AuthorizationAbilityNotFoundError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var AuthorizationAuthIntegrationMissingError = class extends Error {
|
|
25
|
+
constructor(message = "[@holo-js/authorization] Auth integration is not configured yet.") {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "AuthorizationAuthIntegrationMissingError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var AuthorizationGuardNotFoundError = class extends Error {
|
|
31
|
+
constructor(message = "[@holo-js/authorization] Guard was not found.") {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "AuthorizationGuardNotFoundError";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
function allow(message) {
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
allowed: true,
|
|
39
|
+
status: 200,
|
|
40
|
+
...message ? { message } : {}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function deny(message = "You are not authorized to perform this action.") {
|
|
44
|
+
return Object.freeze({
|
|
45
|
+
allowed: false,
|
|
46
|
+
status: 403,
|
|
47
|
+
message
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function denyAsNotFound(message = "Resource not found.") {
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
allowed: false,
|
|
53
|
+
status: 404,
|
|
54
|
+
message
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function isAuthorizationDecision(value) {
|
|
58
|
+
if (!value || typeof value !== "object") {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const decision = value;
|
|
62
|
+
return typeof decision.allowed === "boolean" && (decision.status === 200 || decision.status === 403 || decision.status === 404);
|
|
63
|
+
}
|
|
64
|
+
function isAuthorizationPolicyDefinition(value) {
|
|
65
|
+
return !!value && typeof value === "object" && value[AUTHORIZATION_POLICY_MARKER] === true;
|
|
66
|
+
}
|
|
67
|
+
function isAuthorizationAbilityDefinition(value) {
|
|
68
|
+
return !!value && typeof value === "object" && value[AUTHORIZATION_ABILITY_MARKER] === true;
|
|
69
|
+
}
|
|
70
|
+
function normalizeAuthorizationDecision(outcome, fallbackMessage = "You are not authorized to perform this action.") {
|
|
71
|
+
if (typeof outcome === "boolean") {
|
|
72
|
+
return outcome ? allow() : deny(fallbackMessage);
|
|
73
|
+
}
|
|
74
|
+
if (isAuthorizationDecision(outcome)) {
|
|
75
|
+
return outcome;
|
|
76
|
+
}
|
|
77
|
+
return deny(fallbackMessage);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { AUTHORIZATION_ABILITY_MARKER, AUTHORIZATION_POLICY_MARKER, AuthorizationAbilityNotFoundError, AuthorizationAuthIntegrationMissingError, AuthorizationError, AuthorizationGuardNotFoundError, AuthorizationPolicyNotFoundError, allow, deny, denyAsNotFound, isAuthorizationAbilityDefinition, isAuthorizationDecision, isAuthorizationPolicyDefinition, normalizeAuthorizationDecision };
|
|
81
|
+
//# sourceMappingURL=chunk-WPHPV4WY.mjs.map
|
|
82
|
+
//# sourceMappingURL=chunk-WPHPV4WY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts.ts"],"names":[],"mappings":";AAAA,IAAM,2BAAA,mBAA8B,MAAA,CAAO,GAAA,CAAI,8BAA8B;AAC7E,IAAM,4BAAA,mBAA+B,MAAA,CAAO,GAAA,CAAI,+BAA+B;AAiWxE,IAAM,kBAAA,GAAN,cAAiC,KAAA,CAAM;AAAA,EACnC,QAAA;AAAA,EAET,WAAA,CAAY,SAAiB,QAAA,EAAiC;AAC5D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EAClB;AACF;AAEO,IAAM,gCAAA,GAAN,cAA+C,KAAA,CAAM;AAAA,EAC1D,WAAA,CAAY,UAAU,2DAAA,EAA6D;AACjF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,kCAAA;AAAA,EACd;AACF;AAEO,IAAM,iCAAA,GAAN,cAAgD,KAAA,CAAM;AAAA,EAC3D,WAAA,CAAY,UAAU,4DAAA,EAA8D;AAClF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mCAAA;AAAA,EACd;AACF;AAEO,IAAM,wCAAA,GAAN,cAAuD,KAAA,CAAM;AAAA,EAClE,WAAA,CAAY,UAAU,kEAAA,EAAoE;AACxF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,0CAAA;AAAA,EACd;AACF;AAEO,IAAM,+BAAA,GAAN,cAA8C,KAAA,CAAM;AAAA,EACzD,WAAA,CAAY,UAAU,+CAAA,EAAiD;AACrE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iCAAA;AAAA,EACd;AACF;AAEO,SAAS,MAAM,OAAA,EAAyC;AAC7D,EAAA,OAAO,OAAO,MAAA,CAAO;AAAA,IACnB,OAAA,EAAS,IAAA;AAAA,IACT,MAAA,EAAQ,GAAA;AAAA,IACR,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY;AAAC,GAC9B,CAAA;AACH;AAEO,SAAS,IAAA,CAAK,UAAU,gDAAA,EAAyE;AACtG,EAAA,OAAO,OAAO,MAAA,CAAO;AAAA,IACnB,OAAA,EAAS,KAAA;AAAA,IACT,MAAA,EAAQ,GAAA;AAAA,IACR;AAAA,GACD,CAAA;AACH;AAEO,SAAS,cAAA,CAAe,UAAU,qBAAA,EAA8C;AACrF,EAAA,OAAO,OAAO,MAAA,CAAO;AAAA,IACnB,OAAA,EAAS,KAAA;AAAA,IACT,MAAA,EAAQ,GAAA;AAAA,IACR;AAAA,GACD,CAAA;AACH;AAEO,SAAS,wBAAwB,KAAA,EAAgD;AACtF,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,KAAA;AACjB,EAAA,OAAO,OAAO,QAAA,CAAS,OAAA,KAAY,SAAA,KAC7B,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,QAAA,CAAS,MAAA,KAAW,GAAA,CAAA;AAClF;AAEO,SAAS,gCAAgC,KAAA,EAAwD;AACtG,EAAA,OAAO,CAAC,CAAC,KAAA,IACJ,OAAO,UAAU,QAAA,IAChB,KAAA,CAA+D,2BAA2B,CAAA,KAAM,IAAA;AACxG;AAEO,SAAS,iCAAiC,KAAA,EAAyD;AACxG,EAAA,OAAO,CAAC,CAAC,KAAA,IACJ,OAAO,UAAU,QAAA,IAChB,KAAA,CAAgE,4BAA4B,CAAA,KAAM,IAAA;AAC1G;AAEO,SAAS,8BAAA,CACd,OAAA,EACA,eAAA,GAAkB,gDAAA,EACK;AACvB,EAAA,IAAI,OAAO,YAAY,SAAA,EAAW;AAChC,IAAA,OAAO,OAAA,GAAU,KAAA,EAAM,GAAI,IAAA,CAAK,eAAe,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,uBAAA,CAAwB,OAAO,CAAA,EAAG;AACpC,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,OAAO,KAAK,eAAe,CAAA;AAC7B","file":"chunk-WPHPV4WY.mjs","sourcesContent":["const AUTHORIZATION_POLICY_MARKER = Symbol.for('holo-js.authorization.policy')\nconst AUTHORIZATION_ABILITY_MARKER = Symbol.for('holo-js.authorization.ability')\ndeclare const AUTHORIZATION_POLICY_REGISTRY_MARKER: unique symbol\ndeclare const AUTHORIZATION_ABILITY_REGISTRY_MARKER: unique symbol\ndeclare const AUTHORIZATION_GUARD_REGISTRY_MARKER: unique symbol\n\nexport type AuthorizationDecisionStatus = 200 | 403 | 404\n\nexport interface AuthorizationDecision {\n readonly allowed: boolean\n readonly status: AuthorizationDecisionStatus\n readonly message?: string\n readonly code?: string\n}\n\nexport interface AuthorizationActorContext<TActor = object> {\n readonly user: TActor | null\n readonly authenticated: boolean\n}\n\nexport interface AuthorizationGuardActorContext<TActor = object, TGuardName extends string = string> extends AuthorizationActorContext<TActor> {\n readonly guard: TGuardName\n}\n\nexport interface AuthorizationAuthorizationContext<\n TActor = object,\n TGuardName extends string = string,\n> extends AuthorizationActorContext<TActor> {\n readonly guard?: TGuardName\n}\n\nexport type AuthorizationDecisionInput = AuthorizationDecision | boolean\n\nexport interface AuthorizationTargetConstructor<TInstance = object> {\n readonly prototype: TInstance\n}\n\nexport interface AuthorizationTargetModelDefinition {\n readonly name: string\n readonly table?: {\n readonly tableName?: string\n }\n}\n\nexport interface AuthorizationTargetModel<TInstance extends object = object> {\n readonly definition: AuthorizationTargetModelDefinition\n query(): {\n first(): Promise<TInstance | undefined>\n firstOrFail(): Promise<TInstance>\n }\n}\n\nexport type AuthorizationPolicyTarget<TInstance extends object = object>\n = | AuthorizationTargetConstructor<TInstance>\n | AuthorizationTargetModel<TInstance>\n\nexport type AuthorizationTargetInstance<TTarget extends AuthorizationPolicyTarget> = TTarget extends AuthorizationTargetConstructor<infer TInstance>\n ? TInstance\n : TTarget extends AuthorizationTargetModel<infer TInstance>\n ? TInstance\n : object\n\nexport interface AuthorizationPolicyClassHandler<\n TActor = object,\n TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget,\n> {\n (\n context: AuthorizationAuthorizationContext<TActor>,\n target: TTarget,\n ): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>\n}\n\nexport interface AuthorizationPolicyRecordHandler<\n TActor = object,\n TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget,\n> {\n (\n context: AuthorizationAuthorizationContext<TActor>,\n target: AuthorizationTargetInstance<TTarget>,\n ): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>\n}\n\nexport interface AuthorizationPolicyBeforeHandler<\n TActor = object,\n TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget,\n> {\n (\n context: AuthorizationAuthorizationContext<TActor>,\n target: TTarget | AuthorizationTargetInstance<TTarget>,\n ): AuthorizationDecisionInput | void | Promise<AuthorizationDecisionInput | void>\n}\n\nexport interface AuthorizationPolicyDefinition<\n TName extends string = string,\n TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget,\n TClassActions extends string = string,\n TRecordActions extends string = string,\n TActor = object,\n> {\n readonly [AUTHORIZATION_POLICY_MARKER]: true\n readonly name: TName\n readonly target: TTarget\n readonly before?: AuthorizationPolicyBeforeHandler<TActor, TTarget>\n readonly class?: Readonly<Record<TClassActions, AuthorizationPolicyClassHandler<TActor, TTarget>>>\n readonly record?: Readonly<Record<TRecordActions, AuthorizationPolicyRecordHandler<TActor, TTarget>>>\n}\n\nexport interface AuthorizationAbilityDefinition<\n TName extends string = string,\n TInput extends object = object,\n TActor = object,\n> {\n readonly [AUTHORIZATION_ABILITY_MARKER]: true\n readonly name: TName\n readonly handle: AuthorizationAbilityHandler<TActor, TInput>\n}\n\nexport interface AuthorizationAbilityHandler<TActor = object, TInput extends object = object> {\n (\n context: AuthorizationAuthorizationContext<TActor>,\n input: TInput,\n ): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>\n}\n\nexport interface AuthorizationPolicyRegistryEntry<\n TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget,\n TClassActions extends string = string,\n TRecordActions extends string = string,\n TActor = object,\n> {\n readonly actor?: TActor\n readonly target: TTarget\n readonly classActions: Readonly<Record<TClassActions, AuthorizationPolicyClassHandler<TActor, TTarget>>>\n readonly recordActions: Readonly<Record<TRecordActions, AuthorizationPolicyRecordHandler<TActor, TTarget>>>\n readonly before?: AuthorizationPolicyBeforeHandler<TActor, TTarget>\n}\n\nexport interface AuthorizationPolicyRegistry {\n readonly [AUTHORIZATION_POLICY_REGISTRY_MARKER]?: true\n}\n\nexport interface AuthorizationAbilityRegistryEntry<TInput extends object = object, TActor = object> {\n readonly actor?: TActor\n readonly input: TInput\n readonly handler?: AuthorizationAbilityHandler<TActor, TInput>\n}\n\nexport interface AuthorizationAbilityRegistry {\n readonly [AUTHORIZATION_ABILITY_REGISTRY_MARKER]?: true\n}\n\nexport interface AuthorizationGuardRegistry {\n readonly [AUTHORIZATION_GUARD_REGISTRY_MARKER]?: true\n}\n\ntype FallbackRegistryName<TName extends string> = [TName] extends [never] ? string : TName\ntype FallbackRegistryAction<TAction extends string> = [TAction] extends [never] ? string : TAction\ntype FallbackRegistryInput<TInput extends object> = [TInput] extends [never] ? object : TInput\ntype FallbackRegistryActor<TActor> = [TActor] extends [never] ? object : TActor\n\nexport type HoloPolicyName = FallbackRegistryName<Extract<keyof AuthorizationPolicyRegistry, string>>\nexport type HoloAbilityName = FallbackRegistryName<Extract<keyof AuthorizationAbilityRegistry, string>>\nexport type HoloAuthorizationGuardName = FallbackRegistryName<Extract<keyof AuthorizationGuardRegistry, string>>\n\ntype RegisteredAuthorizationPolicyName = Extract<keyof AuthorizationPolicyRegistry, string>\ntype RegisteredAuthorizationAbilityName = Extract<keyof AuthorizationAbilityRegistry, string>\n\ntype RegisteredAuthorizationPolicyEntry<TPolicyName extends string> = AuthorizationPolicyRegistry[\n Extract<TPolicyName, RegisteredAuthorizationPolicyName>\n]\ntype RegisteredAuthorizationAbilityEntry<TAbilityName extends string> = AuthorizationAbilityRegistry[\n Extract<TAbilityName, RegisteredAuthorizationAbilityName>\n]\n\nexport type PolicyActorForName<TPolicyName extends string> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {\n actor?: infer TActor\n}\n ? FallbackRegistryActor<TActor>\n : object\n\nexport type AbilityActorForName<TAbilityName extends string> = RegisteredAuthorizationAbilityEntry<TAbilityName> extends {\n actor?: infer TActor\n}\n ? FallbackRegistryActor<TActor>\n : object\n\ntype RegisteredPolicyClassActionFor<TTarget> = {\n [TName in RegisteredAuthorizationPolicyName]: RegisteredAuthorizationPolicyEntry<TName> extends {\n target: infer TRegisteredTarget extends AuthorizationPolicyTarget\n classActions: infer TClassActions extends Record<string, unknown>\n recordActions: infer _TRecordActions extends Record<string, unknown>\n }\n ? TTarget extends AuthorizationPolicyTarget\n ? TTarget extends TRegisteredTarget\n ? FallbackRegistryAction<Extract<keyof TClassActions, string>>\n : never\n : never\n : never\n}[RegisteredAuthorizationPolicyName]\n\ntype RegisteredPolicyRecordActionFor<TTarget> = {\n [TName in RegisteredAuthorizationPolicyName]: RegisteredAuthorizationPolicyEntry<TName> extends {\n target: infer TRegisteredTarget extends AuthorizationPolicyTarget\n classActions: infer _TClassActions extends Record<string, unknown>\n recordActions: infer TRecordActions extends Record<string, unknown>\n }\n ? TTarget extends AuthorizationPolicyTarget\n ? never\n : TTarget extends AuthorizationTargetInstance<TRegisteredTarget>\n ? FallbackRegistryAction<Extract<keyof TRecordActions, string>>\n : never\n : never\n}[RegisteredAuthorizationPolicyName]\n\nexport type PolicyClassActionFor<TTarget> = FallbackRegistryAction<RegisteredPolicyClassActionFor<TTarget>>\n\nexport type PolicyRecordActionFor<TTarget> = FallbackRegistryAction<RegisteredPolicyRecordActionFor<TTarget>>\n\nexport type PolicyActionFor<TTarget> = TTarget extends AuthorizationPolicyTarget\n ? PolicyClassActionFor<TTarget>\n : PolicyRecordActionFor<TTarget>\n\nexport type PolicyActionForPolicy<\n TPolicyName extends HoloPolicyName,\n TTarget,\n> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {\n target: infer _TRegisteredTarget extends AuthorizationPolicyTarget\n classActions: infer TClassActions extends Record<string, unknown>\n recordActions: infer TRecordActions extends Record<string, unknown>\n}\n ? TTarget extends AuthorizationPolicyTarget\n ? FallbackRegistryAction<Extract<keyof TClassActions, string>>\n : FallbackRegistryAction<Extract<keyof TRecordActions, string>>\n : string\n\nexport type PolicyTargetForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {\n target: infer TTarget extends AuthorizationPolicyTarget\n}\n ? TTarget\n : AuthorizationPolicyTarget\n\nexport type PolicyClassActionForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {\n classActions: infer TClassActions extends Record<string, unknown>\n}\n ? FallbackRegistryAction<Extract<keyof TClassActions, string>>\n : string\n\nexport type PolicyRecordActionForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {\n recordActions: infer TRecordActions extends Record<string, unknown>\n}\n ? FallbackRegistryAction<Extract<keyof TRecordActions, string>>\n : string\n\nexport type PolicyInstanceForPolicy<TPolicyName extends HoloPolicyName> = AuthorizationTargetInstance<PolicyTargetForPolicy<TPolicyName>>\n\nexport type AbilityInput<TAbilityName extends HoloAbilityName> = RegisteredAuthorizationAbilityEntry<TAbilityName> extends AuthorizationAbilityRegistryEntry<\n infer TInput,\n object\n>\n ? FallbackRegistryInput<TInput>\n : object\n\nexport interface AuthorizationPolicyBuilder<TPolicyName extends HoloPolicyName> {\n authorize(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<void>\n authorize(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<void>\n can(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<boolean>\n can(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<boolean>\n cannot(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<boolean>\n cannot(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<boolean>\n inspect(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<AuthorizationDecision>\n inspect(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<AuthorizationDecision>\n}\n\nexport interface AuthorizationAbilityBuilder<TAbilityName extends HoloAbilityName> {\n authorize(input: AbilityInput<TAbilityName>): Promise<void>\n can(input: AbilityInput<TAbilityName>): Promise<boolean>\n cannot(input: AbilityInput<TAbilityName>): Promise<boolean>\n inspect(input: AbilityInput<TAbilityName>): Promise<AuthorizationDecision>\n}\n\nexport interface AuthorizationActorBuilder {\n authorize<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<void>\n authorize<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<void>\n can<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n can<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n cannot<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n cannot<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n inspect<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<AuthorizationDecision>\n inspect<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<AuthorizationDecision>\n policy<TPolicyName extends HoloPolicyName>(name: TPolicyName): AuthorizationPolicyBuilder<TPolicyName>\n ability<TAbilityName extends HoloAbilityName>(name: TAbilityName): AuthorizationAbilityBuilder<TAbilityName>\n}\n\nexport interface AuthorizationFacade {\n forUser<TActor extends object>(actor: TActor | null): AuthorizationActorBuilder\n guard<TGuardName extends HoloAuthorizationGuardName>(name: TGuardName): AuthorizationActorBuilder\n authorize<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<void>\n authorize<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<void>\n can<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n can<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n cannot<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n cannot<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<boolean>\n inspect<TTarget extends AuthorizationPolicyTarget>(\n action: PolicyClassActionFor<TTarget>,\n target: TTarget,\n ): Promise<AuthorizationDecision>\n inspect<TTarget extends object>(\n action: PolicyRecordActionFor<TTarget>,\n target: TTarget,\n ): Promise<AuthorizationDecision>\n}\n\nexport class AuthorizationError extends Error {\n readonly decision: AuthorizationDecision\n\n constructor(message: string, decision: AuthorizationDecision) {\n super(message)\n this.name = 'AuthorizationError'\n this.decision = decision\n }\n}\n\nexport class AuthorizationPolicyNotFoundError extends Error {\n constructor(message = '[@holo-js/authorization] Policy definition was not found.') {\n super(message)\n this.name = 'AuthorizationPolicyNotFoundError'\n }\n}\n\nexport class AuthorizationAbilityNotFoundError extends Error {\n constructor(message = '[@holo-js/authorization] Ability definition was not found.') {\n super(message)\n this.name = 'AuthorizationAbilityNotFoundError'\n }\n}\n\nexport class AuthorizationAuthIntegrationMissingError extends Error {\n constructor(message = '[@holo-js/authorization] Auth integration is not configured yet.') {\n super(message)\n this.name = 'AuthorizationAuthIntegrationMissingError'\n }\n}\n\nexport class AuthorizationGuardNotFoundError extends Error {\n constructor(message = '[@holo-js/authorization] Guard was not found.') {\n super(message)\n this.name = 'AuthorizationGuardNotFoundError'\n }\n}\n\nexport function allow(message?: string): AuthorizationDecision {\n return Object.freeze({\n allowed: true,\n status: 200 as const,\n ...(message ? { message } : {}),\n })\n}\n\nexport function deny(message = 'You are not authorized to perform this action.'): AuthorizationDecision {\n return Object.freeze({\n allowed: false,\n status: 403 as const,\n message,\n })\n}\n\nexport function denyAsNotFound(message = 'Resource not found.'): AuthorizationDecision {\n return Object.freeze({\n allowed: false,\n status: 404 as const,\n message,\n })\n}\n\nexport function isAuthorizationDecision(value: unknown): value is AuthorizationDecision {\n if (!value || typeof value !== 'object') {\n return false\n }\n\n const decision = value as Partial<AuthorizationDecision>\n return typeof decision.allowed === 'boolean'\n && (decision.status === 200 || decision.status === 403 || decision.status === 404)\n}\n\nexport function isAuthorizationPolicyDefinition(value: unknown): value is AuthorizationPolicyDefinition {\n return !!value\n && typeof value === 'object'\n && (value as { readonly [AUTHORIZATION_POLICY_MARKER]?: unknown })[AUTHORIZATION_POLICY_MARKER] === true\n}\n\nexport function isAuthorizationAbilityDefinition(value: unknown): value is AuthorizationAbilityDefinition {\n return !!value\n && typeof value === 'object'\n && (value as { readonly [AUTHORIZATION_ABILITY_MARKER]?: unknown })[AUTHORIZATION_ABILITY_MARKER] === true\n}\n\nexport function normalizeAuthorizationDecision(\n outcome: AuthorizationDecisionInput | undefined,\n fallbackMessage = 'You are not authorized to perform this action.',\n): AuthorizationDecision {\n if (typeof outcome === 'boolean') {\n return outcome ? allow() : deny(fallbackMessage)\n }\n\n if (isAuthorizationDecision(outcome)) {\n return outcome\n }\n\n return deny(fallbackMessage)\n}\n\nexport { AUTHORIZATION_POLICY_MARKER, AUTHORIZATION_ABILITY_MARKER }\n"]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
declare const AUTHORIZATION_POLICY_MARKER: unique symbol;
|
|
2
|
+
declare const AUTHORIZATION_ABILITY_MARKER: unique symbol;
|
|
3
|
+
declare const AUTHORIZATION_POLICY_REGISTRY_MARKER: unique symbol;
|
|
4
|
+
declare const AUTHORIZATION_ABILITY_REGISTRY_MARKER: unique symbol;
|
|
5
|
+
declare const AUTHORIZATION_GUARD_REGISTRY_MARKER: unique symbol;
|
|
6
|
+
type AuthorizationDecisionStatus = 200 | 403 | 404;
|
|
7
|
+
interface AuthorizationDecision {
|
|
8
|
+
readonly allowed: boolean;
|
|
9
|
+
readonly status: AuthorizationDecisionStatus;
|
|
10
|
+
readonly message?: string;
|
|
11
|
+
readonly code?: string;
|
|
12
|
+
}
|
|
13
|
+
interface AuthorizationActorContext<TActor = object> {
|
|
14
|
+
readonly user: TActor | null;
|
|
15
|
+
readonly authenticated: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface AuthorizationGuardActorContext<TActor = object, TGuardName extends string = string> extends AuthorizationActorContext<TActor> {
|
|
18
|
+
readonly guard: TGuardName;
|
|
19
|
+
}
|
|
20
|
+
interface AuthorizationAuthorizationContext<TActor = object, TGuardName extends string = string> extends AuthorizationActorContext<TActor> {
|
|
21
|
+
readonly guard?: TGuardName;
|
|
22
|
+
}
|
|
23
|
+
type AuthorizationDecisionInput = AuthorizationDecision | boolean;
|
|
24
|
+
interface AuthorizationTargetConstructor<TInstance = object> {
|
|
25
|
+
readonly prototype: TInstance;
|
|
26
|
+
}
|
|
27
|
+
interface AuthorizationTargetModelDefinition {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly table?: {
|
|
30
|
+
readonly tableName?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
interface AuthorizationTargetModel<TInstance extends object = object> {
|
|
34
|
+
readonly definition: AuthorizationTargetModelDefinition;
|
|
35
|
+
query(): {
|
|
36
|
+
first(): Promise<TInstance | undefined>;
|
|
37
|
+
firstOrFail(): Promise<TInstance>;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
type AuthorizationPolicyTarget<TInstance extends object = object> = AuthorizationTargetConstructor<TInstance> | AuthorizationTargetModel<TInstance>;
|
|
41
|
+
type AuthorizationTargetInstance<TTarget extends AuthorizationPolicyTarget> = TTarget extends AuthorizationTargetConstructor<infer TInstance> ? TInstance : TTarget extends AuthorizationTargetModel<infer TInstance> ? TInstance : object;
|
|
42
|
+
interface AuthorizationPolicyClassHandler<TActor = object, TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget> {
|
|
43
|
+
(context: AuthorizationAuthorizationContext<TActor>, target: TTarget): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>;
|
|
44
|
+
}
|
|
45
|
+
interface AuthorizationPolicyRecordHandler<TActor = object, TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget> {
|
|
46
|
+
(context: AuthorizationAuthorizationContext<TActor>, target: AuthorizationTargetInstance<TTarget>): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>;
|
|
47
|
+
}
|
|
48
|
+
interface AuthorizationPolicyBeforeHandler<TActor = object, TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget> {
|
|
49
|
+
(context: AuthorizationAuthorizationContext<TActor>, target: TTarget | AuthorizationTargetInstance<TTarget>): AuthorizationDecisionInput | void | Promise<AuthorizationDecisionInput | void>;
|
|
50
|
+
}
|
|
51
|
+
interface AuthorizationPolicyDefinition<TName extends string = string, TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget, TClassActions extends string = string, TRecordActions extends string = string, TActor = object> {
|
|
52
|
+
readonly [AUTHORIZATION_POLICY_MARKER]: true;
|
|
53
|
+
readonly name: TName;
|
|
54
|
+
readonly target: TTarget;
|
|
55
|
+
readonly before?: AuthorizationPolicyBeforeHandler<TActor, TTarget>;
|
|
56
|
+
readonly class?: Readonly<Record<TClassActions, AuthorizationPolicyClassHandler<TActor, TTarget>>>;
|
|
57
|
+
readonly record?: Readonly<Record<TRecordActions, AuthorizationPolicyRecordHandler<TActor, TTarget>>>;
|
|
58
|
+
}
|
|
59
|
+
interface AuthorizationAbilityDefinition<TName extends string = string, TInput extends object = object, TActor = object> {
|
|
60
|
+
readonly [AUTHORIZATION_ABILITY_MARKER]: true;
|
|
61
|
+
readonly name: TName;
|
|
62
|
+
readonly handle: AuthorizationAbilityHandler<TActor, TInput>;
|
|
63
|
+
}
|
|
64
|
+
interface AuthorizationAbilityHandler<TActor = object, TInput extends object = object> {
|
|
65
|
+
(context: AuthorizationAuthorizationContext<TActor>, input: TInput): AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>;
|
|
66
|
+
}
|
|
67
|
+
interface AuthorizationPolicyRegistryEntry<TTarget extends AuthorizationPolicyTarget = AuthorizationPolicyTarget, TClassActions extends string = string, TRecordActions extends string = string, TActor = object> {
|
|
68
|
+
readonly actor?: TActor;
|
|
69
|
+
readonly target: TTarget;
|
|
70
|
+
readonly classActions: Readonly<Record<TClassActions, AuthorizationPolicyClassHandler<TActor, TTarget>>>;
|
|
71
|
+
readonly recordActions: Readonly<Record<TRecordActions, AuthorizationPolicyRecordHandler<TActor, TTarget>>>;
|
|
72
|
+
readonly before?: AuthorizationPolicyBeforeHandler<TActor, TTarget>;
|
|
73
|
+
}
|
|
74
|
+
interface AuthorizationPolicyRegistry {
|
|
75
|
+
readonly [AUTHORIZATION_POLICY_REGISTRY_MARKER]?: true;
|
|
76
|
+
}
|
|
77
|
+
interface AuthorizationAbilityRegistryEntry<TInput extends object = object, TActor = object> {
|
|
78
|
+
readonly actor?: TActor;
|
|
79
|
+
readonly input: TInput;
|
|
80
|
+
readonly handler?: AuthorizationAbilityHandler<TActor, TInput>;
|
|
81
|
+
}
|
|
82
|
+
interface AuthorizationAbilityRegistry {
|
|
83
|
+
readonly [AUTHORIZATION_ABILITY_REGISTRY_MARKER]?: true;
|
|
84
|
+
}
|
|
85
|
+
interface AuthorizationGuardRegistry {
|
|
86
|
+
readonly [AUTHORIZATION_GUARD_REGISTRY_MARKER]?: true;
|
|
87
|
+
}
|
|
88
|
+
type FallbackRegistryName<TName extends string> = [TName] extends [never] ? string : TName;
|
|
89
|
+
type FallbackRegistryAction<TAction extends string> = [TAction] extends [never] ? string : TAction;
|
|
90
|
+
type FallbackRegistryInput<TInput extends object> = [TInput] extends [never] ? object : TInput;
|
|
91
|
+
type FallbackRegistryActor<TActor> = [TActor] extends [never] ? object : TActor;
|
|
92
|
+
type HoloPolicyName = FallbackRegistryName<Extract<keyof AuthorizationPolicyRegistry, string>>;
|
|
93
|
+
type HoloAbilityName = FallbackRegistryName<Extract<keyof AuthorizationAbilityRegistry, string>>;
|
|
94
|
+
type HoloAuthorizationGuardName = FallbackRegistryName<Extract<keyof AuthorizationGuardRegistry, string>>;
|
|
95
|
+
type RegisteredAuthorizationPolicyName = Extract<keyof AuthorizationPolicyRegistry, string>;
|
|
96
|
+
type RegisteredAuthorizationAbilityName = Extract<keyof AuthorizationAbilityRegistry, string>;
|
|
97
|
+
type RegisteredAuthorizationPolicyEntry<TPolicyName extends string> = AuthorizationPolicyRegistry[Extract<TPolicyName, RegisteredAuthorizationPolicyName>];
|
|
98
|
+
type RegisteredAuthorizationAbilityEntry<TAbilityName extends string> = AuthorizationAbilityRegistry[Extract<TAbilityName, RegisteredAuthorizationAbilityName>];
|
|
99
|
+
type PolicyActorForName<TPolicyName extends string> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {
|
|
100
|
+
actor?: infer TActor;
|
|
101
|
+
} ? FallbackRegistryActor<TActor> : object;
|
|
102
|
+
type AbilityActorForName<TAbilityName extends string> = RegisteredAuthorizationAbilityEntry<TAbilityName> extends {
|
|
103
|
+
actor?: infer TActor;
|
|
104
|
+
} ? FallbackRegistryActor<TActor> : object;
|
|
105
|
+
type RegisteredPolicyClassActionFor<TTarget> = {
|
|
106
|
+
[TName in RegisteredAuthorizationPolicyName]: RegisteredAuthorizationPolicyEntry<TName> extends {
|
|
107
|
+
target: infer TRegisteredTarget extends AuthorizationPolicyTarget;
|
|
108
|
+
classActions: infer TClassActions extends Record<string, unknown>;
|
|
109
|
+
recordActions: infer _TRecordActions extends Record<string, unknown>;
|
|
110
|
+
} ? TTarget extends AuthorizationPolicyTarget ? TTarget extends TRegisteredTarget ? FallbackRegistryAction<Extract<keyof TClassActions, string>> : never : never : never;
|
|
111
|
+
}[RegisteredAuthorizationPolicyName];
|
|
112
|
+
type RegisteredPolicyRecordActionFor<TTarget> = {
|
|
113
|
+
[TName in RegisteredAuthorizationPolicyName]: RegisteredAuthorizationPolicyEntry<TName> extends {
|
|
114
|
+
target: infer TRegisteredTarget extends AuthorizationPolicyTarget;
|
|
115
|
+
classActions: infer _TClassActions extends Record<string, unknown>;
|
|
116
|
+
recordActions: infer TRecordActions extends Record<string, unknown>;
|
|
117
|
+
} ? TTarget extends AuthorizationPolicyTarget ? never : TTarget extends AuthorizationTargetInstance<TRegisteredTarget> ? FallbackRegistryAction<Extract<keyof TRecordActions, string>> : never : never;
|
|
118
|
+
}[RegisteredAuthorizationPolicyName];
|
|
119
|
+
type PolicyClassActionFor<TTarget> = FallbackRegistryAction<RegisteredPolicyClassActionFor<TTarget>>;
|
|
120
|
+
type PolicyRecordActionFor<TTarget> = FallbackRegistryAction<RegisteredPolicyRecordActionFor<TTarget>>;
|
|
121
|
+
type PolicyActionFor<TTarget> = TTarget extends AuthorizationPolicyTarget ? PolicyClassActionFor<TTarget> : PolicyRecordActionFor<TTarget>;
|
|
122
|
+
type PolicyActionForPolicy<TPolicyName extends HoloPolicyName, TTarget> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {
|
|
123
|
+
target: infer _TRegisteredTarget extends AuthorizationPolicyTarget;
|
|
124
|
+
classActions: infer TClassActions extends Record<string, unknown>;
|
|
125
|
+
recordActions: infer TRecordActions extends Record<string, unknown>;
|
|
126
|
+
} ? TTarget extends AuthorizationPolicyTarget ? FallbackRegistryAction<Extract<keyof TClassActions, string>> : FallbackRegistryAction<Extract<keyof TRecordActions, string>> : string;
|
|
127
|
+
type PolicyTargetForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {
|
|
128
|
+
target: infer TTarget extends AuthorizationPolicyTarget;
|
|
129
|
+
} ? TTarget : AuthorizationPolicyTarget;
|
|
130
|
+
type PolicyClassActionForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {
|
|
131
|
+
classActions: infer TClassActions extends Record<string, unknown>;
|
|
132
|
+
} ? FallbackRegistryAction<Extract<keyof TClassActions, string>> : string;
|
|
133
|
+
type PolicyRecordActionForPolicy<TPolicyName extends HoloPolicyName> = RegisteredAuthorizationPolicyEntry<TPolicyName> extends {
|
|
134
|
+
recordActions: infer TRecordActions extends Record<string, unknown>;
|
|
135
|
+
} ? FallbackRegistryAction<Extract<keyof TRecordActions, string>> : string;
|
|
136
|
+
type PolicyInstanceForPolicy<TPolicyName extends HoloPolicyName> = AuthorizationTargetInstance<PolicyTargetForPolicy<TPolicyName>>;
|
|
137
|
+
type AbilityInput<TAbilityName extends HoloAbilityName> = RegisteredAuthorizationAbilityEntry<TAbilityName> extends AuthorizationAbilityRegistryEntry<infer TInput, object> ? FallbackRegistryInput<TInput> : object;
|
|
138
|
+
interface AuthorizationPolicyBuilder<TPolicyName extends HoloPolicyName> {
|
|
139
|
+
authorize(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<void>;
|
|
140
|
+
authorize(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<void>;
|
|
141
|
+
can(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<boolean>;
|
|
142
|
+
can(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<boolean>;
|
|
143
|
+
cannot(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<boolean>;
|
|
144
|
+
cannot(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<boolean>;
|
|
145
|
+
inspect(action: PolicyClassActionForPolicy<TPolicyName>, target: PolicyTargetForPolicy<TPolicyName>): Promise<AuthorizationDecision>;
|
|
146
|
+
inspect(action: PolicyRecordActionForPolicy<TPolicyName>, target: PolicyInstanceForPolicy<TPolicyName>): Promise<AuthorizationDecision>;
|
|
147
|
+
}
|
|
148
|
+
interface AuthorizationAbilityBuilder<TAbilityName extends HoloAbilityName> {
|
|
149
|
+
authorize(input: AbilityInput<TAbilityName>): Promise<void>;
|
|
150
|
+
can(input: AbilityInput<TAbilityName>): Promise<boolean>;
|
|
151
|
+
cannot(input: AbilityInput<TAbilityName>): Promise<boolean>;
|
|
152
|
+
inspect(input: AbilityInput<TAbilityName>): Promise<AuthorizationDecision>;
|
|
153
|
+
}
|
|
154
|
+
interface AuthorizationActorBuilder {
|
|
155
|
+
authorize<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<void>;
|
|
156
|
+
authorize<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<void>;
|
|
157
|
+
can<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
158
|
+
can<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
159
|
+
cannot<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
160
|
+
cannot<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
161
|
+
inspect<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision>;
|
|
162
|
+
inspect<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision>;
|
|
163
|
+
policy<TPolicyName extends HoloPolicyName>(name: TPolicyName): AuthorizationPolicyBuilder<TPolicyName>;
|
|
164
|
+
ability<TAbilityName extends HoloAbilityName>(name: TAbilityName): AuthorizationAbilityBuilder<TAbilityName>;
|
|
165
|
+
}
|
|
166
|
+
interface AuthorizationFacade {
|
|
167
|
+
forUser<TActor extends object>(actor: TActor | null): AuthorizationActorBuilder;
|
|
168
|
+
guard<TGuardName extends HoloAuthorizationGuardName>(name: TGuardName): AuthorizationActorBuilder;
|
|
169
|
+
authorize<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<void>;
|
|
170
|
+
authorize<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<void>;
|
|
171
|
+
can<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
172
|
+
can<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
173
|
+
cannot<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
174
|
+
cannot<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
175
|
+
inspect<TTarget extends AuthorizationPolicyTarget>(action: PolicyClassActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision>;
|
|
176
|
+
inspect<TTarget extends object>(action: PolicyRecordActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision>;
|
|
177
|
+
}
|
|
178
|
+
declare class AuthorizationError extends Error {
|
|
179
|
+
readonly decision: AuthorizationDecision;
|
|
180
|
+
constructor(message: string, decision: AuthorizationDecision);
|
|
181
|
+
}
|
|
182
|
+
declare class AuthorizationPolicyNotFoundError extends Error {
|
|
183
|
+
constructor(message?: string);
|
|
184
|
+
}
|
|
185
|
+
declare class AuthorizationAbilityNotFoundError extends Error {
|
|
186
|
+
constructor(message?: string);
|
|
187
|
+
}
|
|
188
|
+
declare class AuthorizationAuthIntegrationMissingError extends Error {
|
|
189
|
+
constructor(message?: string);
|
|
190
|
+
}
|
|
191
|
+
declare class AuthorizationGuardNotFoundError extends Error {
|
|
192
|
+
constructor(message?: string);
|
|
193
|
+
}
|
|
194
|
+
declare function allow(message?: string): AuthorizationDecision;
|
|
195
|
+
declare function deny(message?: string): AuthorizationDecision;
|
|
196
|
+
declare function denyAsNotFound(message?: string): AuthorizationDecision;
|
|
197
|
+
declare function isAuthorizationDecision(value: unknown): value is AuthorizationDecision;
|
|
198
|
+
declare function isAuthorizationPolicyDefinition(value: unknown): value is AuthorizationPolicyDefinition;
|
|
199
|
+
declare function isAuthorizationAbilityDefinition(value: unknown): value is AuthorizationAbilityDefinition;
|
|
200
|
+
declare function normalizeAuthorizationDecision(outcome: AuthorizationDecisionInput | undefined, fallbackMessage?: string): AuthorizationDecision;
|
|
201
|
+
|
|
202
|
+
export { AUTHORIZATION_ABILITY_MARKER, AUTHORIZATION_POLICY_MARKER, type AbilityActorForName, type AbilityInput, type AuthorizationAbilityBuilder, type AuthorizationAbilityDefinition, type AuthorizationAbilityHandler, AuthorizationAbilityNotFoundError, type AuthorizationAbilityRegistry, type AuthorizationAbilityRegistryEntry, type AuthorizationActorBuilder, type AuthorizationActorContext, AuthorizationAuthIntegrationMissingError, type AuthorizationAuthorizationContext, type AuthorizationDecision, type AuthorizationDecisionInput, type AuthorizationDecisionStatus, AuthorizationError, type AuthorizationFacade, type AuthorizationGuardActorContext, AuthorizationGuardNotFoundError, type AuthorizationGuardRegistry, type AuthorizationPolicyBeforeHandler, type AuthorizationPolicyBuilder, type AuthorizationPolicyClassHandler, type AuthorizationPolicyDefinition, AuthorizationPolicyNotFoundError, type AuthorizationPolicyRecordHandler, type AuthorizationPolicyRegistry, type AuthorizationPolicyRegistryEntry, type AuthorizationPolicyTarget, type AuthorizationTargetConstructor, type AuthorizationTargetInstance, type AuthorizationTargetModel, type AuthorizationTargetModelDefinition, type HoloAbilityName, type HoloAuthorizationGuardName, type HoloPolicyName, type PolicyActionFor, type PolicyActionForPolicy, type PolicyActorForName, type PolicyClassActionFor, type PolicyClassActionForPolicy, type PolicyInstanceForPolicy, type PolicyRecordActionFor, type PolicyRecordActionForPolicy, type PolicyTargetForPolicy, allow, deny, denyAsNotFound, isAuthorizationAbilityDefinition, isAuthorizationDecision, isAuthorizationPolicyDefinition, normalizeAuthorizationDecision };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { AUTHORIZATION_ABILITY_MARKER, AUTHORIZATION_POLICY_MARKER, AuthorizationAbilityNotFoundError, AuthorizationAuthIntegrationMissingError, AuthorizationError, AuthorizationGuardNotFoundError, AuthorizationPolicyNotFoundError, allow, deny, denyAsNotFound, isAuthorizationAbilityDefinition, isAuthorizationDecision, isAuthorizationPolicyDefinition, normalizeAuthorizationDecision } from './chunk-WPHPV4WY.mjs';
|
|
2
|
+
//# sourceMappingURL=contracts.mjs.map
|
|
3
|
+
//# sourceMappingURL=contracts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"contracts.mjs"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AuthorizationPolicyDefinition, AuthorizationPolicyTarget, AuthorizationAbilityDefinition, AuthorizationDecision, PolicyActionFor, AuthorizationAbilityHandler, AuthorizationAbilityRegistry, AbilityActorForName, AuthorizationPolicyBeforeHandler, AuthorizationPolicyRegistry, PolicyActorForName, AuthorizationPolicyClassHandler, AuthorizationPolicyRecordHandler, AuthorizationActorBuilder, HoloAuthorizationGuardName, AuthorizationFacade } from './contracts.js';
|
|
2
|
+
export { AbilityInput, AuthorizationAbilityBuilder, AuthorizationAbilityNotFoundError, AuthorizationAbilityRegistryEntry, AuthorizationActorContext, AuthorizationAuthIntegrationMissingError, AuthorizationDecisionInput, AuthorizationDecisionStatus, AuthorizationError, AuthorizationGuardActorContext, AuthorizationGuardNotFoundError, AuthorizationPolicyBuilder, AuthorizationPolicyNotFoundError, AuthorizationPolicyRegistryEntry, AuthorizationTargetConstructor, AuthorizationTargetInstance, AuthorizationTargetModel, AuthorizationTargetModelDefinition, HoloAbilityName, HoloPolicyName, PolicyActionForPolicy, PolicyClassActionFor, PolicyClassActionForPolicy, PolicyInstanceForPolicy, PolicyRecordActionFor, PolicyRecordActionForPolicy, PolicyTargetForPolicy, allow, deny, denyAsNotFound, isAuthorizationAbilityDefinition, isAuthorizationDecision, isAuthorizationPolicyDefinition, normalizeAuthorizationDecision } from './contracts.js';
|
|
3
|
+
|
|
4
|
+
type RegisteredPolicy = AuthorizationPolicyDefinition<string, AuthorizationPolicyTarget, string, string, object>;
|
|
5
|
+
type RegisteredAbility = AuthorizationAbilityDefinition<string, object, object>;
|
|
6
|
+
type FallbackAuthorizationActor<TActor> = [TActor] extends [never] ? object : Extract<TActor, object>;
|
|
7
|
+
type PolicyActorForDefinition<TName extends string> = [Extract<TName, keyof AuthorizationPolicyRegistry & string>] extends [never] ? object : FallbackAuthorizationActor<PolicyActorForName<Extract<TName, keyof AuthorizationPolicyRegistry & string>>>;
|
|
8
|
+
type AbilityActorForDefinition<TName extends string> = [Extract<TName, keyof AuthorizationAbilityRegistry & string>] extends [never] ? object : FallbackAuthorizationActor<AbilityActorForName<Extract<TName, keyof AuthorizationAbilityRegistry & string>>>;
|
|
9
|
+
type AuthorizationAuthIntegration = {
|
|
10
|
+
hasGuard(guardName: string): boolean;
|
|
11
|
+
resolveDefaultActor(): Promise<object | null> | object | null;
|
|
12
|
+
resolveGuardActor(guardName: string): Promise<object | null> | object | null;
|
|
13
|
+
};
|
|
14
|
+
type AuthorizationRuntimeState = {
|
|
15
|
+
policiesByName: Map<string, RegisteredPolicy>;
|
|
16
|
+
policiesByTargetObject: WeakMap<object, RegisteredPolicy>;
|
|
17
|
+
policiesByDefinitionKey: Map<string, RegisteredPolicy>;
|
|
18
|
+
abilitiesByName: Map<string, RegisteredAbility>;
|
|
19
|
+
authIntegration: AuthorizationAuthIntegration | null;
|
|
20
|
+
};
|
|
21
|
+
declare function getAuthorizationRuntimeState(): AuthorizationRuntimeState;
|
|
22
|
+
declare function resetAuthorizationRuntimeState(): void;
|
|
23
|
+
declare function configureAuthorizationAuthIntegration(integration?: AuthorizationAuthIntegration): void;
|
|
24
|
+
declare function resetAuthorizationAuthIntegration(): void;
|
|
25
|
+
declare function getAuthorizationAuthIntegration(): AuthorizationAuthIntegration;
|
|
26
|
+
declare function registerPolicyDefinition<TDefinition extends RegisteredPolicy>(definition: TDefinition): TDefinition;
|
|
27
|
+
declare function registerAbilityDefinition<TDefinition extends RegisteredAbility>(definition: TDefinition): TDefinition;
|
|
28
|
+
declare function unregisterPolicyDefinition(name: string): void;
|
|
29
|
+
declare function unregisterAbilityDefinition(name: string): void;
|
|
30
|
+
declare function definePolicy<TName extends string, TTarget extends AuthorizationPolicyTarget, TDefinition extends {
|
|
31
|
+
readonly before?: AuthorizationPolicyBeforeHandler<PolicyActorForDefinition<TName>, TTarget>;
|
|
32
|
+
readonly class?: Readonly<Record<string, AuthorizationPolicyClassHandler<PolicyActorForDefinition<TName>, TTarget>>>;
|
|
33
|
+
readonly record?: Readonly<Record<string, AuthorizationPolicyRecordHandler<PolicyActorForDefinition<TName>, TTarget>>>;
|
|
34
|
+
}>(name: TName, target: TTarget, definition: TDefinition & {
|
|
35
|
+
readonly before?: AuthorizationPolicyBeforeHandler<PolicyActorForDefinition<TName>, TTarget>;
|
|
36
|
+
readonly class?: Readonly<Record<string, AuthorizationPolicyClassHandler<PolicyActorForDefinition<TName>, TTarget>>>;
|
|
37
|
+
readonly record?: Readonly<Record<string, AuthorizationPolicyRecordHandler<PolicyActorForDefinition<TName>, TTarget>>>;
|
|
38
|
+
}): AuthorizationPolicyDefinition<TName, TTarget, Extract<keyof NonNullable<TDefinition['class']>, string>, Extract<keyof NonNullable<TDefinition['record']>, string>, PolicyActorForDefinition<TName>>;
|
|
39
|
+
declare function defineAbility<TName extends string, TInput extends object>(name: TName, handle: AuthorizationAbilityHandler<AbilityActorForDefinition<TName>, TInput>): AuthorizationAbilityDefinition<TName, TInput>;
|
|
40
|
+
declare function getPolicyByName(name: string): RegisteredPolicy;
|
|
41
|
+
declare function getAbilityByName(name: string): RegisteredAbility;
|
|
42
|
+
declare function getPolicyByTarget(target: AuthorizationPolicyTarget | object): RegisteredPolicy;
|
|
43
|
+
declare function evaluatePolicyByTarget(actor: object | null, action: string, target: AuthorizationPolicyTarget | object, guard?: string): Promise<AuthorizationDecision>;
|
|
44
|
+
declare function evaluatePolicyByName(actor: object | null, policyName: string, action: string, target: AuthorizationPolicyTarget | object, guard?: string): Promise<AuthorizationDecision>;
|
|
45
|
+
declare function evaluateAbility<TInput extends object>(actor: object | null, abilityName: string, input: TInput, guard?: string): Promise<AuthorizationDecision>;
|
|
46
|
+
declare function forUser<TActor extends object>(actor: TActor | null): AuthorizationActorBuilder;
|
|
47
|
+
declare function authorize<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<void>;
|
|
48
|
+
declare function can<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
49
|
+
declare function cannot<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<boolean>;
|
|
50
|
+
declare function inspect<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision>;
|
|
51
|
+
declare function guard<TGuardName extends HoloAuthorizationGuardName>(name: TGuardName): AuthorizationActorBuilder;
|
|
52
|
+
declare const authorizationInternals: Readonly<{
|
|
53
|
+
getAuthorizationRuntimeState: typeof getAuthorizationRuntimeState;
|
|
54
|
+
resetAuthorizationRuntimeState: typeof resetAuthorizationRuntimeState;
|
|
55
|
+
configureAuthorizationAuthIntegration: typeof configureAuthorizationAuthIntegration;
|
|
56
|
+
resetAuthorizationAuthIntegration: typeof resetAuthorizationAuthIntegration;
|
|
57
|
+
getAuthorizationAuthIntegration: typeof getAuthorizationAuthIntegration;
|
|
58
|
+
getPolicyByName: typeof getPolicyByName;
|
|
59
|
+
getAbilityByName: typeof getAbilityByName;
|
|
60
|
+
getPolicyByTarget: typeof getPolicyByTarget;
|
|
61
|
+
evaluatePolicyByTarget: typeof evaluatePolicyByTarget;
|
|
62
|
+
evaluatePolicyByName: typeof evaluatePolicyByName;
|
|
63
|
+
evaluateAbility: typeof evaluateAbility;
|
|
64
|
+
registerPolicyDefinition: typeof registerPolicyDefinition;
|
|
65
|
+
registerAbilityDefinition: typeof registerAbilityDefinition;
|
|
66
|
+
unregisterPolicyDefinition: typeof unregisterPolicyDefinition;
|
|
67
|
+
unregisterAbilityDefinition: typeof unregisterAbilityDefinition;
|
|
68
|
+
}>;
|
|
69
|
+
|
|
70
|
+
declare const authorization: AuthorizationFacade;
|
|
71
|
+
|
|
72
|
+
export { AuthorizationAbilityHandler, AuthorizationAbilityRegistry, AuthorizationActorBuilder, AuthorizationDecision, AuthorizationFacade, AuthorizationPolicyBeforeHandler, AuthorizationPolicyClassHandler, AuthorizationPolicyDefinition, AuthorizationPolicyRecordHandler, AuthorizationPolicyRegistry, AuthorizationPolicyTarget, HoloAuthorizationGuardName, PolicyActionFor, authorizationInternals, authorize, can, cannot, authorization as default, defineAbility, definePolicy, forUser, guard, inspect };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import { AuthorizationError, deny, AuthorizationGuardNotFoundError, AuthorizationPolicyNotFoundError, AuthorizationAbilityNotFoundError, AuthorizationAuthIntegrationMissingError, AUTHORIZATION_POLICY_MARKER, AUTHORIZATION_ABILITY_MARKER, normalizeAuthorizationDecision } from './chunk-WPHPV4WY.mjs';
|
|
2
|
+
export { AuthorizationAbilityNotFoundError, AuthorizationAuthIntegrationMissingError, AuthorizationError, AuthorizationGuardNotFoundError, AuthorizationPolicyNotFoundError, allow, deny, denyAsNotFound, isAuthorizationAbilityDefinition, isAuthorizationDecision, isAuthorizationPolicyDefinition, normalizeAuthorizationDecision } from './chunk-WPHPV4WY.mjs';
|
|
3
|
+
|
|
4
|
+
// src/runtime.ts
|
|
5
|
+
function createAuthorizationRuntimeState() {
|
|
6
|
+
return {
|
|
7
|
+
policiesByName: /* @__PURE__ */ new Map(),
|
|
8
|
+
policiesByTargetObject: /* @__PURE__ */ new WeakMap(),
|
|
9
|
+
policiesByDefinitionKey: /* @__PURE__ */ new Map(),
|
|
10
|
+
abilitiesByName: /* @__PURE__ */ new Map(),
|
|
11
|
+
authIntegration: null
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function getAuthorizationRuntimeState() {
|
|
15
|
+
const runtime = globalThis;
|
|
16
|
+
runtime.__holoAuthorizationRuntime__ ??= createAuthorizationRuntimeState();
|
|
17
|
+
return runtime.__holoAuthorizationRuntime__;
|
|
18
|
+
}
|
|
19
|
+
function resetAuthorizationRuntimeState() {
|
|
20
|
+
const runtime = globalThis;
|
|
21
|
+
runtime.__holoAuthorizationRuntime__ = createAuthorizationRuntimeState();
|
|
22
|
+
}
|
|
23
|
+
function configureAuthorizationAuthIntegration(integration) {
|
|
24
|
+
const state = getAuthorizationRuntimeState();
|
|
25
|
+
state.authIntegration = integration ?? null;
|
|
26
|
+
}
|
|
27
|
+
function resetAuthorizationAuthIntegration() {
|
|
28
|
+
getAuthorizationRuntimeState().authIntegration = null;
|
|
29
|
+
}
|
|
30
|
+
function getAuthorizationAuthIntegration() {
|
|
31
|
+
const integration = getAuthorizationRuntimeState().authIntegration;
|
|
32
|
+
if (!integration) {
|
|
33
|
+
throw new AuthorizationAuthIntegrationMissingError("[@holo-js/authorization] Auth integration is not configured yet.");
|
|
34
|
+
}
|
|
35
|
+
return integration;
|
|
36
|
+
}
|
|
37
|
+
function normalizePolicyName(name) {
|
|
38
|
+
const trimmed = name.trim();
|
|
39
|
+
if (!trimmed) {
|
|
40
|
+
throw new TypeError("[@holo-js/authorization] Policy name must be a non-empty string.");
|
|
41
|
+
}
|
|
42
|
+
return trimmed;
|
|
43
|
+
}
|
|
44
|
+
function normalizeAbilityName(name) {
|
|
45
|
+
const trimmed = name.trim();
|
|
46
|
+
if (!trimmed) {
|
|
47
|
+
throw new TypeError("[@holo-js/authorization] Ability name must be a non-empty string.");
|
|
48
|
+
}
|
|
49
|
+
return trimmed;
|
|
50
|
+
}
|
|
51
|
+
function normalizeTarget(target) {
|
|
52
|
+
if (typeof target === "function") {
|
|
53
|
+
return target;
|
|
54
|
+
}
|
|
55
|
+
if (isAuthorizationTargetModel(target)) {
|
|
56
|
+
return target;
|
|
57
|
+
}
|
|
58
|
+
throw new TypeError("[@holo-js/authorization] Policy targets must be class constructors or model references.");
|
|
59
|
+
}
|
|
60
|
+
function normalizeHandlerMap(value, label) {
|
|
61
|
+
if (typeof value === "undefined") {
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
65
|
+
throw new TypeError(`[@holo-js/authorization] ${label} must be a plain object when provided.`);
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
function validateHandlerMap(value, label) {
|
|
70
|
+
if (!value) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const [name, handler] of Object.entries(value)) {
|
|
74
|
+
if (typeof handler !== "function") {
|
|
75
|
+
throw new TypeError(`[@holo-js/authorization] ${label}.${name} must be a function.`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function validatePolicyDefinition(definition) {
|
|
80
|
+
validateHandlerMap(definition.class, "policy.class");
|
|
81
|
+
validateHandlerMap(definition.record, "policy.record");
|
|
82
|
+
if (definition.before && typeof definition.before !== "function") {
|
|
83
|
+
throw new TypeError("[@holo-js/authorization] policy.before must be a function when provided.");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function validateAbilityDefinition(definition) {
|
|
87
|
+
if (typeof definition.handle !== "function") {
|
|
88
|
+
throw new TypeError("[@holo-js/authorization] Ability handler must be a function.");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function registerPolicyDefinition(definition) {
|
|
92
|
+
const state = getAuthorizationRuntimeState();
|
|
93
|
+
if (state.policiesByName.has(definition.name)) {
|
|
94
|
+
throw new Error(`[@holo-js/authorization] Policy "${definition.name}" is already registered.`);
|
|
95
|
+
}
|
|
96
|
+
if (state.policiesByTargetObject.get(definition.target)) {
|
|
97
|
+
throw new Error("[@holo-js/authorization] A policy is already registered for this target.");
|
|
98
|
+
}
|
|
99
|
+
const definitionKey = getDefinitionKeyForTarget(definition.target);
|
|
100
|
+
if (definitionKey && state.policiesByDefinitionKey.has(definitionKey)) {
|
|
101
|
+
throw new Error(`[@holo-js/authorization] A policy is already registered for target definition "${definitionKey}".`);
|
|
102
|
+
}
|
|
103
|
+
state.policiesByName.set(definition.name, definition);
|
|
104
|
+
state.policiesByTargetObject.set(definition.target, definition);
|
|
105
|
+
if (definitionKey) {
|
|
106
|
+
state.policiesByDefinitionKey.set(definitionKey, definition);
|
|
107
|
+
}
|
|
108
|
+
return definition;
|
|
109
|
+
}
|
|
110
|
+
function registerAbilityDefinition(definition) {
|
|
111
|
+
const state = getAuthorizationRuntimeState();
|
|
112
|
+
if (state.abilitiesByName.has(definition.name)) {
|
|
113
|
+
throw new Error(`[@holo-js/authorization] Ability "${definition.name}" is already registered.`);
|
|
114
|
+
}
|
|
115
|
+
state.abilitiesByName.set(definition.name, definition);
|
|
116
|
+
return definition;
|
|
117
|
+
}
|
|
118
|
+
function unregisterPolicyDefinition(name) {
|
|
119
|
+
const state = getAuthorizationRuntimeState();
|
|
120
|
+
const definition = state.policiesByName.get(name);
|
|
121
|
+
if (!definition) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
state.policiesByName.delete(name);
|
|
125
|
+
state.policiesByTargetObject.delete(definition.target);
|
|
126
|
+
const definitionKey = getDefinitionKeyForTarget(definition.target);
|
|
127
|
+
if (definitionKey) {
|
|
128
|
+
state.policiesByDefinitionKey.delete(definitionKey);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function unregisterAbilityDefinition(name) {
|
|
132
|
+
getAuthorizationRuntimeState().abilitiesByName.delete(name);
|
|
133
|
+
}
|
|
134
|
+
function freezePolicyDefinition(definition) {
|
|
135
|
+
return Object.freeze({
|
|
136
|
+
...definition,
|
|
137
|
+
class: definition.class ? Object.freeze({ ...definition.class }) : definition.class,
|
|
138
|
+
record: definition.record ? Object.freeze({ ...definition.record }) : definition.record
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function freezeAbilityDefinition(definition) {
|
|
142
|
+
return Object.freeze(definition);
|
|
143
|
+
}
|
|
144
|
+
function definePolicy(name, target, definition) {
|
|
145
|
+
const normalizedName = normalizePolicyName(name);
|
|
146
|
+
const normalizedTarget = normalizeTarget(target);
|
|
147
|
+
const normalizedClass = normalizeHandlerMap(definition.class, "policy.class");
|
|
148
|
+
const normalizedRecord = normalizeHandlerMap(definition.record, "policy.record");
|
|
149
|
+
const runtimeDefinition = {
|
|
150
|
+
[AUTHORIZATION_POLICY_MARKER]: true,
|
|
151
|
+
name: normalizedName,
|
|
152
|
+
target: normalizedTarget,
|
|
153
|
+
before: definition.before,
|
|
154
|
+
class: normalizedClass,
|
|
155
|
+
record: normalizedRecord
|
|
156
|
+
};
|
|
157
|
+
validatePolicyDefinition(runtimeDefinition);
|
|
158
|
+
const registered = registerPolicyDefinition(freezePolicyDefinition(runtimeDefinition));
|
|
159
|
+
return registered;
|
|
160
|
+
}
|
|
161
|
+
function defineAbility(name, handle) {
|
|
162
|
+
const normalizedName = normalizeAbilityName(name);
|
|
163
|
+
const runtimeDefinition = {
|
|
164
|
+
[AUTHORIZATION_ABILITY_MARKER]: true,
|
|
165
|
+
name: normalizedName,
|
|
166
|
+
handle
|
|
167
|
+
};
|
|
168
|
+
validateAbilityDefinition(runtimeDefinition);
|
|
169
|
+
const registered = registerAbilityDefinition(freezeAbilityDefinition(runtimeDefinition));
|
|
170
|
+
return registered;
|
|
171
|
+
}
|
|
172
|
+
function getPolicyByName(name) {
|
|
173
|
+
const policy = getAuthorizationRuntimeState().policiesByName.get(name);
|
|
174
|
+
if (!policy) {
|
|
175
|
+
throw new AuthorizationPolicyNotFoundError(`[@holo-js/authorization] Policy "${name}" was not found.`);
|
|
176
|
+
}
|
|
177
|
+
return policy;
|
|
178
|
+
}
|
|
179
|
+
function getAbilityByName(name) {
|
|
180
|
+
const ability = getAuthorizationRuntimeState().abilitiesByName.get(name);
|
|
181
|
+
if (!ability) {
|
|
182
|
+
throw new AuthorizationAbilityNotFoundError(`[@holo-js/authorization] Ability "${name}" was not found.`);
|
|
183
|
+
}
|
|
184
|
+
return ability;
|
|
185
|
+
}
|
|
186
|
+
function getPolicyByTarget(target) {
|
|
187
|
+
const state = getAuthorizationRuntimeState();
|
|
188
|
+
if (typeof target === "function" || isAuthorizationTargetModel(target)) {
|
|
189
|
+
const directPolicy = state.policiesByTargetObject.get(target);
|
|
190
|
+
if (directPolicy) {
|
|
191
|
+
return directPolicy;
|
|
192
|
+
}
|
|
193
|
+
const directDefinitionKey = getDefinitionKeyForTarget(target);
|
|
194
|
+
if (directDefinitionKey) {
|
|
195
|
+
const definitionPolicy = state.policiesByDefinitionKey.get(directDefinitionKey);
|
|
196
|
+
if (definitionPolicy) {
|
|
197
|
+
return definitionPolicy;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const targetConstructor = getTargetConstructor(target);
|
|
202
|
+
if (targetConstructor) {
|
|
203
|
+
const constructorPolicy = state.policiesByTargetObject.get(targetConstructor);
|
|
204
|
+
if (constructorPolicy) {
|
|
205
|
+
return constructorPolicy;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const instanceDefinitionKey = getDefinitionKeyForTargetInstance(target);
|
|
209
|
+
if (instanceDefinitionKey) {
|
|
210
|
+
const definitionPolicy = state.policiesByDefinitionKey.get(instanceDefinitionKey);
|
|
211
|
+
if (definitionPolicy) {
|
|
212
|
+
return definitionPolicy;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
throw new AuthorizationPolicyNotFoundError("[@holo-js/authorization] Policy definition was not found for the target.");
|
|
216
|
+
}
|
|
217
|
+
function getTargetConstructor(target) {
|
|
218
|
+
const candidate = target.constructor;
|
|
219
|
+
return isAuthorizationTargetConstructor(candidate) ? candidate : null;
|
|
220
|
+
}
|
|
221
|
+
function isAuthorizationTargetConstructor(value) {
|
|
222
|
+
return typeof value === "function" && "prototype" in value;
|
|
223
|
+
}
|
|
224
|
+
function isAuthorizationTargetModel(value) {
|
|
225
|
+
return !!value && typeof value === "object" && "definition" in value && isAuthorizationTargetModelDefinition(value.definition);
|
|
226
|
+
}
|
|
227
|
+
function isAuthorizationTargetModelDefinition(value) {
|
|
228
|
+
return !!value && typeof value === "object" && "name" in value && typeof value.name === "string";
|
|
229
|
+
}
|
|
230
|
+
function getDefinitionKeyForTarget(target) {
|
|
231
|
+
if (!isAuthorizationTargetModel(target)) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return buildDefinitionKey(target.definition);
|
|
235
|
+
}
|
|
236
|
+
function getDefinitionKeyForTargetInstance(target) {
|
|
237
|
+
const candidate = target;
|
|
238
|
+
if (typeof candidate.getRepository !== "function") {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
const repository = candidate.getRepository();
|
|
242
|
+
if (!repository || typeof repository !== "object" || !("definition" in repository)) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
const definition = repository.definition;
|
|
246
|
+
return isAuthorizationTargetModelDefinition(definition) ? buildDefinitionKey(definition) : null;
|
|
247
|
+
}
|
|
248
|
+
function buildDefinitionKey(definition) {
|
|
249
|
+
const tableName = definition.table?.tableName?.trim();
|
|
250
|
+
const modelName = definition.name.trim();
|
|
251
|
+
return tableName ? `${modelName}:${tableName}` : modelName;
|
|
252
|
+
}
|
|
253
|
+
function resolveContext(actor, guard2) {
|
|
254
|
+
const baseContext = {
|
|
255
|
+
user: actor,
|
|
256
|
+
authenticated: actor !== null
|
|
257
|
+
};
|
|
258
|
+
if (typeof guard2 === "string") {
|
|
259
|
+
return Object.freeze({
|
|
260
|
+
...baseContext,
|
|
261
|
+
guard: guard2
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
return Object.freeze(baseContext);
|
|
265
|
+
}
|
|
266
|
+
function createAuthorizationError(decision) {
|
|
267
|
+
return new AuthorizationError(
|
|
268
|
+
decision.message ?? "You are not authorized to perform this action.",
|
|
269
|
+
decision
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
function normalizeResult(outcome) {
|
|
273
|
+
return Promise.resolve(outcome).then((result) => normalizeAuthorizationDecision(result));
|
|
274
|
+
}
|
|
275
|
+
async function evaluateBeforeHook(before, context, target) {
|
|
276
|
+
if (!before) {
|
|
277
|
+
return void 0;
|
|
278
|
+
}
|
|
279
|
+
const outcome = await before(context, target);
|
|
280
|
+
if (typeof outcome === "undefined") {
|
|
281
|
+
return void 0;
|
|
282
|
+
}
|
|
283
|
+
return normalizeAuthorizationDecision(outcome);
|
|
284
|
+
}
|
|
285
|
+
async function evaluatePolicyByTarget(actor, action, target, guard2) {
|
|
286
|
+
const policy = getPolicyByTarget(target);
|
|
287
|
+
const context = typeof guard2 === "string" ? resolveContext(actor, guard2) : resolveContext(actor);
|
|
288
|
+
if (typeof target === "function" || isAuthorizationTargetModel(target)) {
|
|
289
|
+
const beforeDecision2 = await evaluateBeforeHook(policy.before, context, target);
|
|
290
|
+
if (beforeDecision2) {
|
|
291
|
+
return beforeDecision2;
|
|
292
|
+
}
|
|
293
|
+
const handler2 = policy.class?.[action];
|
|
294
|
+
if (!handler2) {
|
|
295
|
+
throw new AuthorizationError(
|
|
296
|
+
`[@holo-js/authorization] Policy action "${action}" is not defined for the selected target.`,
|
|
297
|
+
deny()
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
return await normalizeResult(handler2(context, target));
|
|
301
|
+
}
|
|
302
|
+
const beforeDecision = await evaluateBeforeHook(policy.before, context, target);
|
|
303
|
+
if (beforeDecision) {
|
|
304
|
+
return beforeDecision;
|
|
305
|
+
}
|
|
306
|
+
const handler = policy.record?.[action];
|
|
307
|
+
if (!handler) {
|
|
308
|
+
throw new AuthorizationError(
|
|
309
|
+
`[@holo-js/authorization] Policy action "${action}" is not defined for the selected target.`,
|
|
310
|
+
deny()
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
return await normalizeResult(handler(context, target));
|
|
314
|
+
}
|
|
315
|
+
async function evaluatePolicyByName(actor, policyName, action, target, guard2) {
|
|
316
|
+
const policy = getPolicyByName(policyName);
|
|
317
|
+
const context = typeof guard2 === "string" ? resolveContext(actor, guard2) : resolveContext(actor);
|
|
318
|
+
if (typeof target === "function" || isAuthorizationTargetModel(target)) {
|
|
319
|
+
const beforeDecision2 = await evaluateBeforeHook(policy.before, context, target);
|
|
320
|
+
if (beforeDecision2) {
|
|
321
|
+
return beforeDecision2;
|
|
322
|
+
}
|
|
323
|
+
const handler2 = policy.class?.[action];
|
|
324
|
+
if (!handler2) {
|
|
325
|
+
throw new AuthorizationError(
|
|
326
|
+
`[@holo-js/authorization] Policy action "${action}" is not defined for policy "${policyName}".`,
|
|
327
|
+
deny()
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
return await normalizeResult(handler2(context, target));
|
|
331
|
+
}
|
|
332
|
+
const beforeDecision = await evaluateBeforeHook(policy.before, context, target);
|
|
333
|
+
if (beforeDecision) {
|
|
334
|
+
return beforeDecision;
|
|
335
|
+
}
|
|
336
|
+
const handler = policy.record?.[action];
|
|
337
|
+
if (!handler) {
|
|
338
|
+
throw new AuthorizationError(
|
|
339
|
+
`[@holo-js/authorization] Policy action "${action}" is not defined for policy "${policyName}".`,
|
|
340
|
+
deny()
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
return await normalizeResult(handler(context, target));
|
|
344
|
+
}
|
|
345
|
+
async function evaluateAbility(actor, abilityName, input, guard2) {
|
|
346
|
+
const ability = getAbilityByName(abilityName);
|
|
347
|
+
const context = typeof guard2 === "string" ? resolveContext(actor, guard2) : resolveContext(actor);
|
|
348
|
+
return await normalizeResult(ability.handle(context, input));
|
|
349
|
+
}
|
|
350
|
+
function createPolicyBuilder(resolveActor, policyName, guard2) {
|
|
351
|
+
return Object.freeze({
|
|
352
|
+
async authorize(action, target) {
|
|
353
|
+
const actor = await resolveActor();
|
|
354
|
+
const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target, guard2);
|
|
355
|
+
if (!decision.allowed) {
|
|
356
|
+
throw createAuthorizationError(decision);
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
async can(action, target) {
|
|
360
|
+
const actor = await resolveActor();
|
|
361
|
+
const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target, guard2);
|
|
362
|
+
return decision.allowed;
|
|
363
|
+
},
|
|
364
|
+
async cannot(action, target) {
|
|
365
|
+
const actor = await resolveActor();
|
|
366
|
+
const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target, guard2);
|
|
367
|
+
return !decision.allowed;
|
|
368
|
+
},
|
|
369
|
+
async inspect(action, target) {
|
|
370
|
+
const actor = await resolveActor();
|
|
371
|
+
return await evaluatePolicyByName(actor, String(policyName), String(action), target, guard2);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function createAbilityBuilder(resolveActor, abilityName, guard2) {
|
|
376
|
+
return Object.freeze({
|
|
377
|
+
async authorize(input) {
|
|
378
|
+
const actor = await resolveActor();
|
|
379
|
+
const decision = await evaluateAbility(actor, String(abilityName), input, guard2);
|
|
380
|
+
if (!decision.allowed) {
|
|
381
|
+
throw createAuthorizationError(decision);
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
async can(input) {
|
|
385
|
+
const actor = await resolveActor();
|
|
386
|
+
const decision = await evaluateAbility(actor, String(abilityName), input, guard2);
|
|
387
|
+
return decision.allowed;
|
|
388
|
+
},
|
|
389
|
+
async cannot(input) {
|
|
390
|
+
const actor = await resolveActor();
|
|
391
|
+
const decision = await evaluateAbility(actor, String(abilityName), input, guard2);
|
|
392
|
+
return !decision.allowed;
|
|
393
|
+
},
|
|
394
|
+
async inspect(input) {
|
|
395
|
+
const actor = await resolveActor();
|
|
396
|
+
return await evaluateAbility(actor, String(abilityName), input, guard2);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function createActorAuthorization(resolveActor, guard2) {
|
|
401
|
+
return Object.freeze({
|
|
402
|
+
async authorize(action, target) {
|
|
403
|
+
const actor = await resolveActor();
|
|
404
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target, guard2);
|
|
405
|
+
if (!decision.allowed) {
|
|
406
|
+
throw createAuthorizationError(decision);
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
async can(action, target) {
|
|
410
|
+
const actor = await resolveActor();
|
|
411
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target, guard2);
|
|
412
|
+
return decision.allowed;
|
|
413
|
+
},
|
|
414
|
+
async cannot(action, target) {
|
|
415
|
+
const actor = await resolveActor();
|
|
416
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target, guard2);
|
|
417
|
+
return !decision.allowed;
|
|
418
|
+
},
|
|
419
|
+
async inspect(action, target) {
|
|
420
|
+
const actor = await resolveActor();
|
|
421
|
+
return await evaluatePolicyByTarget(actor, String(action), target, guard2);
|
|
422
|
+
},
|
|
423
|
+
policy(name) {
|
|
424
|
+
return createPolicyBuilder(resolveActor, name, guard2);
|
|
425
|
+
},
|
|
426
|
+
ability(name) {
|
|
427
|
+
return createAbilityBuilder(resolveActor, name, guard2);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
function forUser(actor) {
|
|
432
|
+
return createActorAuthorization(() => Promise.resolve(actor));
|
|
433
|
+
}
|
|
434
|
+
function getResolvedAuthActorContext() {
|
|
435
|
+
const integration = getAuthorizationAuthIntegration();
|
|
436
|
+
return {
|
|
437
|
+
resolveActor: () => Promise.resolve(integration.resolveDefaultActor()),
|
|
438
|
+
guard: void 0
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function getResolvedAuthGuardActorContext(name) {
|
|
442
|
+
const integration = getAuthorizationAuthIntegration();
|
|
443
|
+
if (!integration.hasGuard(name)) {
|
|
444
|
+
throw new AuthorizationGuardNotFoundError(`[@holo-js/authorization] Guard "${name}" was not found.`);
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
resolveActor: () => Promise.resolve(integration.resolveGuardActor(name)),
|
|
448
|
+
guard: name
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
async function authorize(action, target) {
|
|
452
|
+
const { resolveActor } = getResolvedAuthActorContext();
|
|
453
|
+
const actor = await resolveActor();
|
|
454
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target);
|
|
455
|
+
if (!decision.allowed) {
|
|
456
|
+
throw createAuthorizationError(decision);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
async function can(action, target) {
|
|
460
|
+
const { resolveActor } = getResolvedAuthActorContext();
|
|
461
|
+
const actor = await resolveActor();
|
|
462
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target);
|
|
463
|
+
return decision.allowed;
|
|
464
|
+
}
|
|
465
|
+
async function cannot(action, target) {
|
|
466
|
+
const { resolveActor } = getResolvedAuthActorContext();
|
|
467
|
+
const actor = await resolveActor();
|
|
468
|
+
const decision = await evaluatePolicyByTarget(actor, String(action), target);
|
|
469
|
+
return !decision.allowed;
|
|
470
|
+
}
|
|
471
|
+
async function inspect(action, target) {
|
|
472
|
+
const { resolveActor } = getResolvedAuthActorContext();
|
|
473
|
+
const actor = await resolveActor();
|
|
474
|
+
return await evaluatePolicyByTarget(actor, String(action), target);
|
|
475
|
+
}
|
|
476
|
+
function guard(name) {
|
|
477
|
+
const { resolveActor, guard: resolvedGuard } = getResolvedAuthGuardActorContext(String(name));
|
|
478
|
+
return createActorAuthorization(resolveActor, resolvedGuard);
|
|
479
|
+
}
|
|
480
|
+
var authorizationInternals = Object.freeze({
|
|
481
|
+
getAuthorizationRuntimeState,
|
|
482
|
+
resetAuthorizationRuntimeState,
|
|
483
|
+
configureAuthorizationAuthIntegration,
|
|
484
|
+
resetAuthorizationAuthIntegration,
|
|
485
|
+
getAuthorizationAuthIntegration,
|
|
486
|
+
getPolicyByName,
|
|
487
|
+
getAbilityByName,
|
|
488
|
+
getPolicyByTarget,
|
|
489
|
+
evaluatePolicyByTarget,
|
|
490
|
+
evaluatePolicyByName,
|
|
491
|
+
evaluateAbility,
|
|
492
|
+
registerPolicyDefinition,
|
|
493
|
+
registerAbilityDefinition,
|
|
494
|
+
unregisterPolicyDefinition,
|
|
495
|
+
unregisterAbilityDefinition
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// src/index.ts
|
|
499
|
+
var authorization = Object.freeze({
|
|
500
|
+
forUser,
|
|
501
|
+
guard,
|
|
502
|
+
authorize,
|
|
503
|
+
can,
|
|
504
|
+
cannot,
|
|
505
|
+
inspect
|
|
506
|
+
});
|
|
507
|
+
var src_default = authorization;
|
|
508
|
+
|
|
509
|
+
export { authorizationInternals, authorize, can, cannot, src_default as default, defineAbility, definePolicy, forUser, guard, inspect };
|
|
510
|
+
//# sourceMappingURL=index.mjs.map
|
|
511
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts","../src/index.ts"],"names":["guard","beforeDecision","handler"],"mappings":"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","file":"index.mjs","sourcesContent":["import type {\n AuthorizationAbilityDefinition,\n AuthorizationAbilityBuilder,\n AuthorizationAbilityHandler,\n AuthorizationActorContext,\n AuthorizationActorBuilder,\n AuthorizationDecision,\n AuthorizationDecisionInput,\n AuthorizationError,\n AuthorizationGuardActorContext,\n AuthorizationPolicyClassHandler,\n AuthorizationPolicyBeforeHandler,\n AuthorizationPolicyBuilder,\n AuthorizationPolicyDefinition,\n AuthorizationPolicyRecordHandler,\n AuthorizationPolicyTarget,\n AuthorizationTargetModel,\n AuthorizationTargetModelDefinition,\n AuthorizationTargetConstructor,\n AuthorizationAbilityRegistry,\n AuthorizationPolicyRegistry,\n AbilityInput,\n HoloAbilityName,\n HoloPolicyName,\n HoloAuthorizationGuardName,\n PolicyActionFor,\n PolicyActionForPolicy,\n AbilityActorForName,\n PolicyActorForName,\n} from './contracts'\nimport {\n allow,\n deny,\n denyAsNotFound,\n AuthorizationAbilityNotFoundError,\n AuthorizationAuthIntegrationMissingError,\n AuthorizationError as AuthorizationErrorClass,\n AuthorizationPolicyNotFoundError as PolicyNotFoundError,\n AuthorizationGuardNotFoundError,\n AUTHORIZATION_POLICY_MARKER,\n AUTHORIZATION_ABILITY_MARKER,\n normalizeAuthorizationDecision,\n} from './contracts'\n\ntype RegisteredPolicy = AuthorizationPolicyDefinition<string, AuthorizationPolicyTarget, string, string, object>\ntype RegisteredAbility = AuthorizationAbilityDefinition<string, object, object>\n\ntype FallbackAuthorizationActor<TActor> = [TActor] extends [never]\n ? object\n : Extract<TActor, object>\n\ntype PolicyActorForDefinition<TName extends string> = [Extract<TName, keyof AuthorizationPolicyRegistry & string>] extends [never]\n ? object\n : FallbackAuthorizationActor<PolicyActorForName<Extract<TName, keyof AuthorizationPolicyRegistry & string>>>\n\ntype AbilityActorForDefinition<TName extends string> = [Extract<TName, keyof AuthorizationAbilityRegistry & string>] extends [never]\n ? object\n : FallbackAuthorizationActor<AbilityActorForName<Extract<TName, keyof AuthorizationAbilityRegistry & string>>>\n\ntype AuthorizationAuthIntegration = {\n hasGuard(guardName: string): boolean\n resolveDefaultActor(): Promise<object | null> | object | null\n resolveGuardActor(guardName: string): Promise<object | null> | object | null\n}\n\ntype AuthorizationRuntimeState = {\n policiesByName: Map<string, RegisteredPolicy>\n policiesByTargetObject: WeakMap<object, RegisteredPolicy>\n policiesByDefinitionKey: Map<string, RegisteredPolicy>\n abilitiesByName: Map<string, RegisteredAbility>\n authIntegration: AuthorizationAuthIntegration | null\n}\n\nfunction createAuthorizationRuntimeState(): AuthorizationRuntimeState {\n return {\n policiesByName: new Map(),\n policiesByTargetObject: new WeakMap(),\n policiesByDefinitionKey: new Map(),\n abilitiesByName: new Map(),\n authIntegration: null,\n }\n}\n\nfunction getAuthorizationRuntimeState(): AuthorizationRuntimeState {\n const runtime = globalThis as typeof globalThis & {\n __holoAuthorizationRuntime__?: AuthorizationRuntimeState\n }\n\n runtime.__holoAuthorizationRuntime__ ??= createAuthorizationRuntimeState()\n return runtime.__holoAuthorizationRuntime__\n}\n\nfunction resetAuthorizationRuntimeState(): void {\n const runtime = globalThis as typeof globalThis & {\n __holoAuthorizationRuntime__?: AuthorizationRuntimeState\n }\n\n runtime.__holoAuthorizationRuntime__ = createAuthorizationRuntimeState()\n}\n\nfunction configureAuthorizationAuthIntegration(integration?: AuthorizationAuthIntegration): void {\n const state = getAuthorizationRuntimeState()\n state.authIntegration = integration ?? null\n}\n\nfunction resetAuthorizationAuthIntegration(): void {\n getAuthorizationRuntimeState().authIntegration = null\n}\n\nfunction getAuthorizationAuthIntegration(): AuthorizationAuthIntegration {\n const integration = getAuthorizationRuntimeState().authIntegration\n if (!integration) {\n throw new AuthorizationAuthIntegrationMissingError('[@holo-js/authorization] Auth integration is not configured yet.')\n }\n\n return integration\n}\n\nfunction normalizePolicyName<TName extends string>(name: TName): TName {\n const trimmed = name.trim()\n if (!trimmed) {\n throw new TypeError('[@holo-js/authorization] Policy name must be a non-empty string.')\n }\n\n return trimmed as TName\n}\n\nfunction normalizeAbilityName<TName extends string>(name: TName): TName {\n const trimmed = name.trim()\n if (!trimmed) {\n throw new TypeError('[@holo-js/authorization] Ability name must be a non-empty string.')\n }\n\n return trimmed as TName\n}\n\nfunction normalizeTarget<TTarget extends AuthorizationPolicyTarget>(target: TTarget): TTarget {\n if (typeof target === 'function') {\n return target\n }\n\n if (isAuthorizationTargetModel(target)) {\n return target\n }\n\n throw new TypeError('[@holo-js/authorization] Policy targets must be class constructors or model references.')\n}\n\nfunction normalizeHandlerMap<THandler extends Record<string, unknown> | undefined>(\n value: THandler,\n label: string,\n): THandler {\n if (typeof value === 'undefined') {\n return value\n }\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new TypeError(`[@holo-js/authorization] ${label} must be a plain object when provided.`)\n }\n\n return value\n}\n\nfunction validateHandlerMap(\n value: Readonly<Record<string, unknown>> | undefined,\n label: string,\n): void {\n if (!value) {\n return\n }\n\n for (const [name, handler] of Object.entries(value)) {\n if (typeof handler !== 'function') {\n throw new TypeError(`[@holo-js/authorization] ${label}.${name} must be a function.`)\n }\n }\n}\n\nfunction validatePolicyDefinition(definition: AuthorizationPolicyDefinition<string, AuthorizationPolicyTarget, string, string, object>): void {\n validateHandlerMap(definition.class, 'policy.class')\n validateHandlerMap(definition.record, 'policy.record')\n if (definition.before && typeof definition.before !== 'function') {\n throw new TypeError('[@holo-js/authorization] policy.before must be a function when provided.')\n }\n}\n\nfunction validateAbilityDefinition(definition: AuthorizationAbilityDefinition<string, object, object>): void {\n if (typeof definition.handle !== 'function') {\n throw new TypeError('[@holo-js/authorization] Ability handler must be a function.')\n }\n}\n\nfunction registerPolicyDefinition<TDefinition extends RegisteredPolicy>(definition: TDefinition): TDefinition {\n const state = getAuthorizationRuntimeState()\n if (state.policiesByName.has(definition.name)) {\n throw new Error(`[@holo-js/authorization] Policy \"${definition.name}\" is already registered.`)\n }\n\n if (state.policiesByTargetObject.get(definition.target)) {\n throw new Error('[@holo-js/authorization] A policy is already registered for this target.')\n }\n\n const definitionKey = getDefinitionKeyForTarget(definition.target)\n if (definitionKey && state.policiesByDefinitionKey.has(definitionKey)) {\n throw new Error(`[@holo-js/authorization] A policy is already registered for target definition \"${definitionKey}\".`)\n }\n\n state.policiesByName.set(definition.name, definition)\n state.policiesByTargetObject.set(definition.target, definition)\n if (definitionKey) {\n state.policiesByDefinitionKey.set(definitionKey, definition)\n }\n return definition\n}\n\nfunction registerAbilityDefinition<TDefinition extends RegisteredAbility>(definition: TDefinition): TDefinition {\n const state = getAuthorizationRuntimeState()\n if (state.abilitiesByName.has(definition.name)) {\n throw new Error(`[@holo-js/authorization] Ability \"${definition.name}\" is already registered.`)\n }\n\n state.abilitiesByName.set(definition.name, definition)\n return definition\n}\n\nfunction unregisterPolicyDefinition(name: string): void {\n const state = getAuthorizationRuntimeState()\n const definition = state.policiesByName.get(name)\n if (!definition) {\n return\n }\n\n state.policiesByName.delete(name)\n state.policiesByTargetObject.delete(definition.target)\n const definitionKey = getDefinitionKeyForTarget(definition.target)\n if (definitionKey) {\n state.policiesByDefinitionKey.delete(definitionKey)\n }\n}\n\nfunction unregisterAbilityDefinition(name: string): void {\n getAuthorizationRuntimeState().abilitiesByName.delete(name)\n}\n\nfunction freezePolicyDefinition<TDefinition extends RegisteredPolicy>(definition: TDefinition): TDefinition {\n return Object.freeze({\n ...definition,\n class: definition.class ? Object.freeze({ ...definition.class }) : definition.class,\n record: definition.record ? Object.freeze({ ...definition.record }) : definition.record,\n }) as TDefinition\n}\n\nfunction freezeAbilityDefinition<TDefinition extends RegisteredAbility>(definition: TDefinition): TDefinition {\n return Object.freeze(definition) as TDefinition\n}\n\nexport function definePolicy<\n TName extends string,\n TTarget extends AuthorizationPolicyTarget,\n TDefinition extends {\n readonly before?: AuthorizationPolicyBeforeHandler<PolicyActorForDefinition<TName>, TTarget>\n readonly class?: Readonly<Record<string, AuthorizationPolicyClassHandler<PolicyActorForDefinition<TName>, TTarget>>>\n readonly record?: Readonly<Record<string, AuthorizationPolicyRecordHandler<PolicyActorForDefinition<TName>, TTarget>>>\n },\n>(\n name: TName,\n target: TTarget,\n definition: TDefinition & {\n readonly before?: AuthorizationPolicyBeforeHandler<PolicyActorForDefinition<TName>, TTarget>\n readonly class?: Readonly<Record<string, AuthorizationPolicyClassHandler<PolicyActorForDefinition<TName>, TTarget>>>\n readonly record?: Readonly<Record<string, AuthorizationPolicyRecordHandler<PolicyActorForDefinition<TName>, TTarget>>>\n },\n): AuthorizationPolicyDefinition<\n TName,\n TTarget,\n Extract<keyof NonNullable<TDefinition['class']>, string>,\n Extract<keyof NonNullable<TDefinition['record']>, string>,\n PolicyActorForDefinition<TName>\n> {\n const normalizedName = normalizePolicyName(name)\n const normalizedTarget = normalizeTarget(target)\n const normalizedClass = normalizeHandlerMap(definition.class, 'policy.class')\n const normalizedRecord = normalizeHandlerMap(definition.record, 'policy.record')\n const runtimeDefinition = {\n [AUTHORIZATION_POLICY_MARKER]: true,\n name: normalizedName,\n target: normalizedTarget,\n before: definition.before,\n class: normalizedClass,\n record: normalizedRecord,\n } as RegisteredPolicy\n validatePolicyDefinition(runtimeDefinition)\n\n const registered = registerPolicyDefinition(freezePolicyDefinition(runtimeDefinition))\n\n return registered as AuthorizationPolicyDefinition<\n TName,\n TTarget,\n Extract<keyof NonNullable<TDefinition['class']>, string>,\n Extract<keyof NonNullable<TDefinition['record']>, string>,\n PolicyActorForDefinition<TName>\n >\n}\n\nexport function defineAbility<\n TName extends string,\n TInput extends object,\n>(\n name: TName,\n handle: AuthorizationAbilityHandler<AbilityActorForDefinition<TName>, TInput>,\n): AuthorizationAbilityDefinition<TName, TInput> {\n const normalizedName = normalizeAbilityName(name)\n const runtimeDefinition = {\n [AUTHORIZATION_ABILITY_MARKER]: true,\n name: normalizedName,\n handle,\n } as unknown as RegisteredAbility\n validateAbilityDefinition(runtimeDefinition)\n\n const registered = registerAbilityDefinition(freezeAbilityDefinition(runtimeDefinition))\n\n return registered as unknown as AuthorizationAbilityDefinition<TName, TInput>\n}\n\nfunction getPolicyByName(name: string): RegisteredPolicy {\n const policy = getAuthorizationRuntimeState().policiesByName.get(name)\n if (!policy) {\n throw new PolicyNotFoundError(`[@holo-js/authorization] Policy \"${name}\" was not found.`)\n }\n\n return policy\n}\n\nfunction getAbilityByName(name: string): RegisteredAbility {\n const ability = getAuthorizationRuntimeState().abilitiesByName.get(name)\n if (!ability) {\n throw new AuthorizationAbilityNotFoundError(`[@holo-js/authorization] Ability \"${name}\" was not found.`)\n }\n\n return ability\n}\n\nfunction getPolicyByTarget(target: AuthorizationPolicyTarget | object): RegisteredPolicy {\n const state = getAuthorizationRuntimeState()\n if (typeof target === 'function' || isAuthorizationTargetModel(target)) {\n const directPolicy = state.policiesByTargetObject.get(target)\n if (directPolicy) {\n return directPolicy\n }\n\n const directDefinitionKey = getDefinitionKeyForTarget(target)\n if (directDefinitionKey) {\n const definitionPolicy = state.policiesByDefinitionKey.get(directDefinitionKey)\n if (definitionPolicy) {\n return definitionPolicy\n }\n }\n }\n\n const targetConstructor = getTargetConstructor(target)\n if (targetConstructor) {\n const constructorPolicy = state.policiesByTargetObject.get(targetConstructor)\n if (constructorPolicy) {\n return constructorPolicy\n }\n }\n\n const instanceDefinitionKey = getDefinitionKeyForTargetInstance(target)\n if (instanceDefinitionKey) {\n const definitionPolicy = state.policiesByDefinitionKey.get(instanceDefinitionKey)\n if (definitionPolicy) {\n return definitionPolicy\n }\n }\n\n throw new PolicyNotFoundError('[@holo-js/authorization] Policy definition was not found for the target.')\n}\n\nfunction getTargetConstructor(target: object): AuthorizationTargetConstructor | null {\n const candidate = (target as { constructor?: AuthorizationTargetConstructor | undefined }).constructor\n return isAuthorizationTargetConstructor(candidate)\n ? candidate\n : null\n}\n\nfunction isAuthorizationTargetConstructor(value: unknown): value is AuthorizationTargetConstructor {\n return typeof value === 'function'\n && 'prototype' in value\n}\n\nfunction isAuthorizationTargetModel(value: unknown): value is AuthorizationTargetModel<object> {\n return !!value\n && typeof value === 'object'\n && 'definition' in value\n && isAuthorizationTargetModelDefinition((value as { definition?: unknown }).definition)\n}\n\nfunction isAuthorizationTargetModelDefinition(value: unknown): value is AuthorizationTargetModelDefinition {\n return !!value\n && typeof value === 'object'\n && 'name' in value\n && typeof (value as { name?: unknown }).name === 'string'\n}\n\nfunction getDefinitionKeyForTarget(target: AuthorizationPolicyTarget): string | null {\n if (!isAuthorizationTargetModel(target)) {\n return null\n }\n\n return buildDefinitionKey(target.definition)\n}\n\nfunction getDefinitionKeyForTargetInstance(target: object): string | null {\n const candidate = target as {\n getRepository?: (() => {\n definition?: unknown\n }) | undefined\n }\n\n if (typeof candidate.getRepository !== 'function') {\n return null\n }\n\n const repository = candidate.getRepository()\n if (!repository || typeof repository !== 'object' || !('definition' in repository)) {\n return null\n }\n\n const definition = (repository as { definition?: unknown }).definition\n return isAuthorizationTargetModelDefinition(definition)\n ? buildDefinitionKey(definition)\n : null\n}\n\nfunction buildDefinitionKey(definition: AuthorizationTargetModelDefinition): string {\n const tableName = definition.table?.tableName?.trim()\n const modelName = definition.name.trim()\n return tableName\n ? `${modelName}:${tableName}`\n : modelName\n}\n\nfunction resolveContext<TActor extends object>(actor: TActor | null): AuthorizationActorContext<TActor>\nfunction resolveContext<TActor extends object, TGuardName extends string>(\n actor: TActor | null,\n guard: TGuardName,\n): AuthorizationGuardActorContext<TActor, TGuardName>\nfunction resolveContext<TActor extends object, TGuardName extends string>(\n actor: TActor | null,\n guard?: TGuardName,\n): AuthorizationActorContext<TActor> | AuthorizationGuardActorContext<TActor, TGuardName> {\n const baseContext = {\n user: actor,\n authenticated: actor !== null,\n }\n\n if (typeof guard === 'string') {\n return Object.freeze({\n ...baseContext,\n guard,\n })\n }\n\n return Object.freeze(baseContext)\n}\n\nfunction createAuthorizationError(decision: AuthorizationDecision): AuthorizationError {\n return new AuthorizationErrorClass(\n decision.message ?? 'You are not authorized to perform this action.',\n decision,\n )\n}\n\nfunction normalizeResult(outcome: AuthorizationDecisionInput | Promise<AuthorizationDecisionInput>): Promise<AuthorizationDecision> {\n return Promise.resolve(outcome).then(result => normalizeAuthorizationDecision(result))\n}\n\nasync function evaluateBeforeHook(\n before: AuthorizationPolicyBeforeHandler<object, AuthorizationPolicyTarget> | undefined,\n context: AuthorizationActorContext<object> | AuthorizationGuardActorContext<object, string>,\n target: AuthorizationPolicyTarget | object,\n): Promise<AuthorizationDecision | undefined> {\n if (!before) {\n return undefined\n }\n\n const outcome = await before(context, target as AuthorizationPolicyTarget & object)\n if (typeof outcome === 'undefined') {\n return undefined\n }\n\n return normalizeAuthorizationDecision(outcome)\n}\n\nasync function evaluatePolicyByTarget(\n actor: object | null,\n action: string,\n target: AuthorizationPolicyTarget | object,\n guard?: string,\n): Promise<AuthorizationDecision> {\n const policy = getPolicyByTarget(target)\n const context = typeof guard === 'string'\n ? resolveContext(actor, guard)\n : resolveContext(actor)\n if (typeof target === 'function' || isAuthorizationTargetModel(target)) {\n const beforeDecision = await evaluateBeforeHook(policy.before, context, target)\n if (beforeDecision) {\n return beforeDecision\n }\n\n const handler = policy.class?.[action]\n if (!handler) {\n throw new AuthorizationErrorClass(\n `[@holo-js/authorization] Policy action \"${action}\" is not defined for the selected target.`,\n deny(),\n )\n }\n\n return await normalizeResult(handler(context, target))\n }\n\n const beforeDecision = await evaluateBeforeHook(policy.before, context, target)\n if (beforeDecision) {\n return beforeDecision\n }\n\n const handler = policy.record?.[action]\n if (!handler) {\n throw new AuthorizationErrorClass(\n `[@holo-js/authorization] Policy action \"${action}\" is not defined for the selected target.`,\n deny(),\n )\n }\n\n return await normalizeResult(handler(context, target))\n}\n\nasync function evaluatePolicyByName(\n actor: object | null,\n policyName: string,\n action: string,\n target: AuthorizationPolicyTarget | object,\n guard?: string,\n): Promise<AuthorizationDecision> {\n const policy = getPolicyByName(policyName)\n const context = typeof guard === 'string'\n ? resolveContext(actor, guard)\n : resolveContext(actor)\n if (typeof target === 'function' || isAuthorizationTargetModel(target)) {\n const beforeDecision = await evaluateBeforeHook(policy.before, context, target)\n if (beforeDecision) {\n return beforeDecision\n }\n\n const handler = policy.class?.[action]\n if (!handler) {\n throw new AuthorizationErrorClass(\n `[@holo-js/authorization] Policy action \"${action}\" is not defined for policy \"${policyName}\".`,\n deny(),\n )\n }\n\n return await normalizeResult(handler(context, target))\n }\n\n const beforeDecision = await evaluateBeforeHook(policy.before, context, target)\n if (beforeDecision) {\n return beforeDecision\n }\n\n const handler = policy.record?.[action]\n if (!handler) {\n throw new AuthorizationErrorClass(\n `[@holo-js/authorization] Policy action \"${action}\" is not defined for policy \"${policyName}\".`,\n deny(),\n )\n }\n\n return await normalizeResult(handler(context, target))\n}\n\nasync function evaluateAbility<TInput extends object>(\n actor: object | null,\n abilityName: string,\n input: TInput,\n guard?: string,\n): Promise<AuthorizationDecision> {\n const ability = getAbilityByName(abilityName)\n const context = typeof guard === 'string'\n ? resolveContext(actor, guard)\n : resolveContext(actor)\n return await normalizeResult(ability.handle(context, input))\n}\n\nfunction createPolicyBuilder<TPolicyName extends HoloPolicyName>(\n resolveActor: () => Promise<object | null> | object | null,\n policyName: TPolicyName,\n guard?: string,\n): AuthorizationPolicyBuilder<TPolicyName> {\n return Object.freeze({\n async authorize<TTarget>(action: PolicyActionForPolicy<TPolicyName, TTarget>, target: TTarget): Promise<void> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target as AuthorizationPolicyTarget | object, guard)\n if (!decision.allowed) {\n throw createAuthorizationError(decision)\n }\n },\n async can<TTarget>(action: PolicyActionForPolicy<TPolicyName, TTarget>, target: TTarget): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target as AuthorizationPolicyTarget | object, guard)\n return decision.allowed\n },\n async cannot<TTarget>(action: PolicyActionForPolicy<TPolicyName, TTarget>, target: TTarget): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByName(actor, String(policyName), String(action), target as AuthorizationPolicyTarget | object, guard)\n return !decision.allowed\n },\n async inspect<TTarget>(action: PolicyActionForPolicy<TPolicyName, TTarget>, target: TTarget): Promise<AuthorizationDecision> {\n const actor = await resolveActor()\n return await evaluatePolicyByName(actor, String(policyName), String(action), target as AuthorizationPolicyTarget | object, guard)\n },\n }) as unknown as AuthorizationPolicyBuilder<TPolicyName>\n}\n\nfunction createAbilityBuilder<TAbilityName extends HoloAbilityName>(\n resolveActor: () => Promise<object | null> | object | null,\n abilityName: TAbilityName,\n guard?: string,\n): AuthorizationAbilityBuilder<TAbilityName> {\n return Object.freeze({\n async authorize(input: AbilityInput<TAbilityName>): Promise<void> {\n const actor = await resolveActor()\n const decision = await evaluateAbility(actor, String(abilityName), input, guard)\n if (!decision.allowed) {\n throw createAuthorizationError(decision)\n }\n },\n async can(input: AbilityInput<TAbilityName>): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluateAbility(actor, String(abilityName), input, guard)\n return decision.allowed\n },\n async cannot(input: AbilityInput<TAbilityName>): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluateAbility(actor, String(abilityName), input, guard)\n return !decision.allowed\n },\n async inspect(input: AbilityInput<TAbilityName>): Promise<AuthorizationDecision> {\n const actor = await resolveActor()\n return await evaluateAbility(actor, String(abilityName), input, guard)\n },\n })\n}\n\nfunction createActorAuthorization(\n resolveActor: () => Promise<object | null> | object | null,\n guard?: string,\n): AuthorizationActorBuilder {\n return Object.freeze({\n async authorize<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<void> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object, guard)\n if (!decision.allowed) {\n throw createAuthorizationError(decision)\n }\n },\n async can<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object, guard)\n return decision.allowed\n },\n async cannot<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<boolean> {\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object, guard)\n return !decision.allowed\n },\n async inspect<TTarget extends AuthorizationPolicyTarget | object>(action: PolicyActionFor<TTarget>, target: TTarget): Promise<AuthorizationDecision> {\n const actor = await resolveActor()\n return await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object, guard)\n },\n policy<TPolicyName extends HoloPolicyName>(name: TPolicyName) {\n return createPolicyBuilder(resolveActor, name, guard)\n },\n ability<TAbilityName extends HoloAbilityName>(name: TAbilityName) {\n return createAbilityBuilder(resolveActor, name, guard)\n },\n }) as AuthorizationActorBuilder\n}\n\nexport function forUser<TActor extends object>(actor: TActor | null): AuthorizationActorBuilder {\n return createActorAuthorization(() => Promise.resolve(actor))\n}\n\nfunction getResolvedAuthActorContext(): {\n readonly resolveActor: () => Promise<object | null>\n readonly guard: string | undefined\n} {\n const integration = getAuthorizationAuthIntegration()\n return {\n resolveActor: () => Promise.resolve(integration.resolveDefaultActor()),\n guard: undefined,\n }\n}\n\nfunction getResolvedAuthGuardActorContext(name: string): {\n readonly resolveActor: () => Promise<object | null>\n readonly guard: string\n} {\n const integration = getAuthorizationAuthIntegration()\n if (!integration.hasGuard(name)) {\n throw new AuthorizationGuardNotFoundError(`[@holo-js/authorization] Guard \"${name}\" was not found.`)\n }\n\n return {\n resolveActor: () => Promise.resolve(integration.resolveGuardActor(name)),\n guard: name,\n }\n}\n\nexport async function authorize<TTarget extends AuthorizationPolicyTarget | object>(\n action: PolicyActionFor<TTarget>,\n target: TTarget,\n): Promise<void> {\n const { resolveActor } = getResolvedAuthActorContext()\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object)\n if (!decision.allowed) {\n throw createAuthorizationError(decision)\n }\n}\n\nexport async function can<TTarget extends AuthorizationPolicyTarget | object>(\n action: PolicyActionFor<TTarget>,\n target: TTarget,\n): Promise<boolean> {\n const { resolveActor } = getResolvedAuthActorContext()\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object)\n return decision.allowed\n}\n\nexport async function cannot<TTarget extends AuthorizationPolicyTarget | object>(\n action: PolicyActionFor<TTarget>,\n target: TTarget,\n): Promise<boolean> {\n const { resolveActor } = getResolvedAuthActorContext()\n const actor = await resolveActor()\n const decision = await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object)\n return !decision.allowed\n}\n\nexport async function inspect<TTarget extends AuthorizationPolicyTarget | object>(\n action: PolicyActionFor<TTarget>,\n target: TTarget,\n): Promise<AuthorizationDecision> {\n const { resolveActor } = getResolvedAuthActorContext()\n const actor = await resolveActor()\n return await evaluatePolicyByTarget(actor, String(action), target as AuthorizationPolicyTarget | object)\n}\n\nexport function guard<TGuardName extends HoloAuthorizationGuardName>(name: TGuardName): AuthorizationActorBuilder {\n const { resolveActor, guard: resolvedGuard } = getResolvedAuthGuardActorContext(String(name))\n return createActorAuthorization(resolveActor, resolvedGuard)\n}\n\nexport const authorizationInternals = Object.freeze({\n getAuthorizationRuntimeState,\n resetAuthorizationRuntimeState,\n configureAuthorizationAuthIntegration,\n resetAuthorizationAuthIntegration,\n getAuthorizationAuthIntegration,\n getPolicyByName,\n getAbilityByName,\n getPolicyByTarget,\n evaluatePolicyByTarget,\n evaluatePolicyByName,\n evaluateAbility,\n registerPolicyDefinition,\n registerAbilityDefinition,\n unregisterPolicyDefinition,\n unregisterAbilityDefinition,\n})\n\nexport {\n allow,\n deny,\n denyAsNotFound,\n AuthorizationAbilityNotFoundError,\n AuthorizationAuthIntegrationMissingError,\n AuthorizationErrorClass as AuthorizationError,\n PolicyNotFoundError as AuthorizationPolicyNotFoundError,\n}\n","import type { AuthorizationFacade } from './contracts'\n\nexport {\n allow,\n deny,\n denyAsNotFound,\n isAuthorizationAbilityDefinition,\n isAuthorizationDecision,\n isAuthorizationPolicyDefinition,\n normalizeAuthorizationDecision,\n AuthorizationAbilityNotFoundError,\n AuthorizationAuthIntegrationMissingError,\n AuthorizationError,\n AuthorizationGuardNotFoundError,\n AuthorizationPolicyNotFoundError,\n} from './contracts'\nexport type {\n AbilityInput,\n AuthorizationActorBuilder,\n AuthorizationActorContext,\n AuthorizationAbilityBuilder,\n AuthorizationAbilityHandler,\n AuthorizationAbilityRegistry,\n AuthorizationAbilityRegistryEntry,\n AuthorizationDecision,\n AuthorizationDecisionInput,\n AuthorizationDecisionStatus,\n AuthorizationFacade,\n AuthorizationGuardActorContext,\n AuthorizationPolicyBeforeHandler,\n AuthorizationPolicyBuilder,\n AuthorizationPolicyClassHandler,\n AuthorizationPolicyDefinition,\n AuthorizationPolicyRegistry,\n AuthorizationPolicyRecordHandler,\n AuthorizationPolicyRegistryEntry,\n AuthorizationPolicyTarget,\n AuthorizationTargetConstructor,\n AuthorizationTargetInstance,\n AuthorizationTargetModel,\n AuthorizationTargetModelDefinition,\n HoloAbilityName,\n HoloAuthorizationGuardName,\n HoloPolicyName,\n PolicyActionFor,\n PolicyActionForPolicy,\n PolicyClassActionFor,\n PolicyClassActionForPolicy,\n PolicyInstanceForPolicy,\n PolicyRecordActionFor,\n PolicyRecordActionForPolicy,\n PolicyTargetForPolicy,\n} from './contracts'\nexport {\n authorize,\n authorizationInternals,\n can,\n cannot,\n defineAbility,\n definePolicy,\n forUser,\n guard,\n inspect,\n} from './runtime'\n\nimport { authorize, can, cannot, forUser, guard, inspect } from './runtime'\n\nconst authorization: AuthorizationFacade = Object.freeze({\n forUser,\n guard,\n authorize,\n can,\n cannot,\n inspect,\n})\n\nexport default authorization\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@holo-js/authorization",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Holo-JS Framework - policy contracts, abilities, and typed authorization surfaces",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/cobraprojects/holo-js.git"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"default": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./contracts": {
|
|
19
|
+
"types": "./dist/contracts.d.ts",
|
|
20
|
+
"import": "./dist/contracts.mjs",
|
|
21
|
+
"default": "./dist/contracts.mjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/index.mjs",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"stub": "tsup",
|
|
32
|
+
"stub:watch": "tsup --watch",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
34
|
+
"test": "vitest --run"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.10.2",
|
|
38
|
+
"tsup": "^8.3.5",
|
|
39
|
+
"typescript": "^5.7.2",
|
|
40
|
+
"vitest": "^2.1.8"
|
|
41
|
+
}
|
|
42
|
+
}
|