@jsango/auth 1.0.0
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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/base64url.d.ts +6 -0
- package/dist/internal/base64url.d.ts.map +1 -0
- package/dist/internal/base64url.js +21 -0
- package/dist/internal/base64url.js.map +1 -0
- package/dist/internal/crypto-utils.d.ts +11 -0
- package/dist/internal/crypto-utils.d.ts.map +1 -0
- package/dist/internal/crypto-utils.js +16 -0
- package/dist/internal/crypto-utils.js.map +1 -0
- package/dist/internal/timing.d.ts +5 -0
- package/dist/internal/timing.d.ts.map +1 -0
- package/dist/internal/timing.js +15 -0
- package/dist/internal/timing.js.map +1 -0
- package/dist/public/authentication/api-key.d.ts +17 -0
- package/dist/public/authentication/api-key.d.ts.map +1 -0
- package/dist/public/authentication/api-key.js +57 -0
- package/dist/public/authentication/api-key.js.map +1 -0
- package/dist/public/authentication/bearer.d.ts +27 -0
- package/dist/public/authentication/bearer.d.ts.map +1 -0
- package/dist/public/authentication/bearer.js +97 -0
- package/dist/public/authentication/bearer.js.map +1 -0
- package/dist/public/authentication/jwt.d.ts +60 -0
- package/dist/public/authentication/jwt.d.ts.map +1 -0
- package/dist/public/authentication/jwt.js +154 -0
- package/dist/public/authentication/jwt.js.map +1 -0
- package/dist/public/authentication/manager.d.ts +23 -0
- package/dist/public/authentication/manager.d.ts.map +1 -0
- package/dist/public/authentication/manager.js +64 -0
- package/dist/public/authentication/manager.js.map +1 -0
- package/dist/public/authentication/password.d.ts +24 -0
- package/dist/public/authentication/password.d.ts.map +1 -0
- package/dist/public/authentication/password.js +108 -0
- package/dist/public/authentication/password.js.map +1 -0
- package/dist/public/authentication/session.d.ts +31 -0
- package/dist/public/authentication/session.d.ts.map +1 -0
- package/dist/public/authentication/session.js +165 -0
- package/dist/public/authentication/session.js.map +1 -0
- package/dist/public/authentication/totp.d.ts +52 -0
- package/dist/public/authentication/totp.d.ts.map +1 -0
- package/dist/public/authentication/totp.js +138 -0
- package/dist/public/authentication/totp.js.map +1 -0
- package/dist/public/authorization/composite.d.ts +23 -0
- package/dist/public/authorization/composite.d.ts.map +1 -0
- package/dist/public/authorization/composite.js +79 -0
- package/dist/public/authorization/composite.js.map +1 -0
- package/dist/public/authorization/decision.d.ts +11 -0
- package/dist/public/authorization/decision.d.ts.map +1 -0
- package/dist/public/authorization/decision.js +19 -0
- package/dist/public/authorization/decision.js.map +1 -0
- package/dist/public/authorization/manager.d.ts +39 -0
- package/dist/public/authorization/manager.d.ts.map +1 -0
- package/dist/public/authorization/manager.js +138 -0
- package/dist/public/authorization/manager.js.map +1 -0
- package/dist/public/authorization/permission.d.ts +20 -0
- package/dist/public/authorization/permission.d.ts.map +1 -0
- package/dist/public/authorization/permission.js +46 -0
- package/dist/public/authorization/permission.js.map +1 -0
- package/dist/public/authorization/policy.d.ts +30 -0
- package/dist/public/authorization/policy.d.ts.map +1 -0
- package/dist/public/authorization/policy.js +93 -0
- package/dist/public/authorization/policy.js.map +1 -0
- package/dist/public/authorization/role.d.ts +17 -0
- package/dist/public/authorization/role.d.ts.map +1 -0
- package/dist/public/authorization/role.js +43 -0
- package/dist/public/authorization/role.js.map +1 -0
- package/dist/public/context/auth-context.d.ts +8 -0
- package/dist/public/context/auth-context.d.ts.map +1 -0
- package/dist/public/context/auth-context.js +33 -0
- package/dist/public/context/auth-context.js.map +1 -0
- package/dist/public/errors.d.ts +33 -0
- package/dist/public/errors.d.ts.map +1 -0
- package/dist/public/errors.js +89 -0
- package/dist/public/errors.js.map +1 -0
- package/dist/public/identity.d.ts +40 -0
- package/dist/public/identity.d.ts.map +1 -0
- package/dist/public/identity.js +102 -0
- package/dist/public/identity.js.map +1 -0
- package/dist/public/index.d.ts +23 -0
- package/dist/public/index.d.ts.map +1 -0
- package/dist/public/index.js +29 -0
- package/dist/public/index.js.map +1 -0
- package/dist/public/middleware/authenticate.d.ts +10 -0
- package/dist/public/middleware/authenticate.d.ts.map +1 -0
- package/dist/public/middleware/authenticate.js +65 -0
- package/dist/public/middleware/authenticate.js.map +1 -0
- package/dist/public/middleware/authorize.d.ts +11 -0
- package/dist/public/middleware/authorize.d.ts.map +1 -0
- package/dist/public/middleware/authorize.js +42 -0
- package/dist/public/middleware/authorize.js.map +1 -0
- package/dist/public/types.d.ts +75 -0
- package/dist/public/types.d.ts.map +1 -0
- package/dist/public/types.js +2 -0
- package/dist/public/types.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.js","sourceRoot":"","sources":["../../../src/public/authentication/totp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Identity, AuthContext, PolicyResult, IPolicy } from '../types.js';
|
|
2
|
+
export declare class AndPolicy<TResource = unknown> implements IPolicy<TResource> {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
private readonly policies;
|
|
5
|
+
constructor(...policies: readonly IPolicy<TResource>[]);
|
|
6
|
+
can(identity: Identity, action: string, resource?: TResource, context?: AuthContext): Promise<PolicyResult>;
|
|
7
|
+
}
|
|
8
|
+
export declare class OrPolicy<TResource = unknown> implements IPolicy<TResource> {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
private readonly policies;
|
|
11
|
+
constructor(...policies: readonly IPolicy<TResource>[]);
|
|
12
|
+
can(identity: Identity, action: string, resource?: TResource, context?: AuthContext): Promise<PolicyResult>;
|
|
13
|
+
}
|
|
14
|
+
export declare class NotPolicy<TResource = unknown> implements IPolicy<TResource> {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
private readonly policy;
|
|
17
|
+
constructor(policy: IPolicy<TResource>);
|
|
18
|
+
can(identity: Identity, action: string, resource?: TResource, context?: AuthContext): Promise<PolicyResult>;
|
|
19
|
+
}
|
|
20
|
+
export declare function andPolicy<TResource = unknown>(...policies: readonly IPolicy<TResource>[]): IPolicy<TResource>;
|
|
21
|
+
export declare function orPolicy<TResource = unknown>(...policies: readonly IPolicy<TResource>[]): IPolicy<TResource>;
|
|
22
|
+
export declare function notPolicy<TResource = unknown>(policy: IPolicy<TResource>): IPolicy<TResource>;
|
|
23
|
+
//# sourceMappingURL=composite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/composite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAiBhF,qBAAa,SAAS,CAAC,SAAS,GAAG,OAAO,CAAE,YAAW,OAAO,CAAC,SAAS,CAAC;IACvE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;gBAEtC,GAAG,QAAQ,EAAE,SAAS,OAAO,CAAC,SAAS,CAAC,EAAE;IAQhD,GAAG,CACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,YAAY,CAAC;CAczB;AAED,qBAAa,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAE,YAAW,OAAO,CAAC,SAAS,CAAC;IACtE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;gBAEtC,GAAG,QAAQ,EAAE,SAAS,OAAO,CAAC,SAAS,CAAC,EAAE;IAQhD,GAAG,CACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,YAAY,CAAC;CAsBzB;AAED,qBAAa,SAAS,CAAC,SAAS,GAAG,OAAO,CAAE,YAAW,OAAO,CAAC,SAAS,CAAC;IACvE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEzB,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC;IAKhC,GAAG,CACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,YAAY,CAAC;CAczB;AAED,wBAAgB,SAAS,CAAC,SAAS,GAAG,OAAO,EAC3C,GAAG,QAAQ,EAAE,SAAS,OAAO,CAAC,SAAS,CAAC,EAAE,GACzC,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAgB,QAAQ,CAAC,SAAS,GAAG,OAAO,EAC1C,GAAG,QAAQ,EAAE,SAAS,OAAO,CAAC,SAAS,CAAC,EAAE,GACzC,OAAO,CAAC,SAAS,CAAC,CAEpB;AAED,wBAAgB,SAAS,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAE7F"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { AuthDecision } from './decision.js';
|
|
2
|
+
function toDecision(result, policyName) {
|
|
3
|
+
if (typeof result === 'boolean') {
|
|
4
|
+
return result
|
|
5
|
+
? AuthDecision.allow('Policy allowed action.', policyName)
|
|
6
|
+
: AuthDecision.deny(`Access denied by policy "${policyName}".`, policyName);
|
|
7
|
+
}
|
|
8
|
+
return new AuthDecision(result.allowed, result.reason, result.policy ?? policyName, result.metadata);
|
|
9
|
+
}
|
|
10
|
+
export class AndPolicy {
|
|
11
|
+
name;
|
|
12
|
+
policies;
|
|
13
|
+
constructor(...policies) {
|
|
14
|
+
if (policies.length === 0) {
|
|
15
|
+
throw new Error('AndPolicy requires at least one policy.');
|
|
16
|
+
}
|
|
17
|
+
this.policies = Object.freeze([...policies]);
|
|
18
|
+
this.name = `(${this.policies.map((p) => p.name).join(' AND ')})`;
|
|
19
|
+
}
|
|
20
|
+
async can(identity, action, resource, context) {
|
|
21
|
+
for (const policy of this.policies) {
|
|
22
|
+
const res = await policy.can(identity, action, resource, context);
|
|
23
|
+
const decision = toDecision(res, policy.name);
|
|
24
|
+
if (!decision.allowed) {
|
|
25
|
+
return AuthDecision.deny(decision.reason ?? `Access denied by policy "${policy.name}" in composite AND.`, this.name, decision.metadata);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return AuthDecision.allow('All composite AND policies satisfied.', this.name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class OrPolicy {
|
|
32
|
+
name;
|
|
33
|
+
policies;
|
|
34
|
+
constructor(...policies) {
|
|
35
|
+
if (policies.length === 0) {
|
|
36
|
+
throw new Error('OrPolicy requires at least one policy.');
|
|
37
|
+
}
|
|
38
|
+
this.policies = Object.freeze([...policies]);
|
|
39
|
+
this.name = `(${this.policies.map((p) => p.name).join(' OR ')})`;
|
|
40
|
+
}
|
|
41
|
+
async can(identity, action, resource, context) {
|
|
42
|
+
let lastDenial;
|
|
43
|
+
for (const policy of this.policies) {
|
|
44
|
+
const res = await policy.can(identity, action, resource, context);
|
|
45
|
+
const decision = toDecision(res, policy.name);
|
|
46
|
+
if (decision.allowed) {
|
|
47
|
+
return AuthDecision.allow(decision.reason ?? `Access granted by policy "${policy.name}" in composite OR.`, this.name, decision.metadata);
|
|
48
|
+
}
|
|
49
|
+
lastDenial = decision;
|
|
50
|
+
}
|
|
51
|
+
return AuthDecision.deny(lastDenial?.reason ?? 'None of the composite OR policies were satisfied.', this.name, lastDenial?.metadata);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export class NotPolicy {
|
|
55
|
+
name;
|
|
56
|
+
policy;
|
|
57
|
+
constructor(policy) {
|
|
58
|
+
this.policy = policy;
|
|
59
|
+
this.name = `(NOT ${policy.name})`;
|
|
60
|
+
}
|
|
61
|
+
async can(identity, action, resource, context) {
|
|
62
|
+
const res = await this.policy.can(identity, action, resource, context);
|
|
63
|
+
const decision = toDecision(res, this.policy.name);
|
|
64
|
+
if (decision.allowed) {
|
|
65
|
+
return AuthDecision.deny(`Access denied by NOT policy inversion of "${this.policy.name}".`, this.name);
|
|
66
|
+
}
|
|
67
|
+
return AuthDecision.allow(`Access allowed by NOT policy inversion of "${this.policy.name}".`, this.name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function andPolicy(...policies) {
|
|
71
|
+
return new AndPolicy(...policies);
|
|
72
|
+
}
|
|
73
|
+
export function orPolicy(...policies) {
|
|
74
|
+
return new OrPolicy(...policies);
|
|
75
|
+
}
|
|
76
|
+
export function notPolicy(policy) {
|
|
77
|
+
return new NotPolicy(policy);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=composite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite.js","sourceRoot":"","sources":["../../../src/public/authorization/composite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AuthorizationDecision } from '../types.js';
|
|
2
|
+
export declare class AuthDecision implements AuthorizationDecision {
|
|
3
|
+
readonly allowed: boolean;
|
|
4
|
+
readonly reason?: string | undefined;
|
|
5
|
+
readonly policy?: string | undefined;
|
|
6
|
+
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
|
|
7
|
+
constructor(allowed: boolean, reason?: string | undefined, policy?: string | undefined, metadata?: Readonly<Record<string, unknown>> | undefined);
|
|
8
|
+
static allow(reason?: string, policy?: string, metadata?: Readonly<Record<string, unknown>>): AuthDecision;
|
|
9
|
+
static deny(reason?: string, policy?: string, metadata?: Readonly<Record<string, unknown>>): AuthDecision;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=decision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,qBAAa,YAAa,YAAW,qBAAqB;IACxD,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,SAAgB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,SAAgB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,SAAgB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;gBAGvE,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,EAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS;WAQ5C,KAAK,CACjB,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC3C,YAAY;WAID,IAAI,CAChB,MAAM,SAAmB,EACzB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC3C,YAAY;CAGhB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class AuthDecision {
|
|
2
|
+
allowed;
|
|
3
|
+
reason;
|
|
4
|
+
policy;
|
|
5
|
+
metadata;
|
|
6
|
+
constructor(allowed, reason, policy, metadata) {
|
|
7
|
+
this.allowed = allowed;
|
|
8
|
+
this.reason = reason;
|
|
9
|
+
this.policy = policy;
|
|
10
|
+
this.metadata = metadata ? Object.freeze({ ...metadata }) : undefined;
|
|
11
|
+
}
|
|
12
|
+
static allow(reason, policy, metadata) {
|
|
13
|
+
return new AuthDecision(true, reason, policy, metadata);
|
|
14
|
+
}
|
|
15
|
+
static deny(reason = 'Access denied.', policy, metadata) {
|
|
16
|
+
return new AuthDecision(false, reason, policy, metadata);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../../../src/public/authorization/decision.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,YAAY;IACP,OAAO,CAAU;IACjB,MAAM,CAAsB;IAC5B,MAAM,CAAsB;IAC5B,QAAQ,CAAiD;IAEzE,YACE,OAAgB,EAChB,MAA2B,EAC3B,MAA2B,EAC3B,QAAwD;QAExD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,CAAC;IAEM,MAAM,CAAC,KAAK,CACjB,MAAe,EACf,MAAe,EACf,QAA4C;QAE5C,OAAO,IAAI,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;IAEM,MAAM,CAAC,IAAI,CAChB,MAAM,GAAG,gBAAgB,EACzB,MAAe,EACf,QAA4C;QAE5C,OAAO,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Identity, AuthContext, AuthorizationDecision, IPolicy } from '../types.js';
|
|
2
|
+
import { PermissionRegistry } from './permission.js';
|
|
3
|
+
import { RoleRegistry } from './role.js';
|
|
4
|
+
import { PolicyRegistry } from './policy.js';
|
|
5
|
+
export interface AuthorizationManagerOptions {
|
|
6
|
+
readonly permissions?: PermissionRegistry | undefined;
|
|
7
|
+
readonly roles?: RoleRegistry | undefined;
|
|
8
|
+
readonly policies?: PolicyRegistry | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface AuthorizeOptions {
|
|
11
|
+
readonly throwOnDeny?: boolean | undefined;
|
|
12
|
+
readonly context?: AuthContext | undefined;
|
|
13
|
+
readonly policy?: string | IPolicy | undefined;
|
|
14
|
+
}
|
|
15
|
+
export declare class AuthorizationManager {
|
|
16
|
+
readonly permissions: PermissionRegistry;
|
|
17
|
+
readonly roles: RoleRegistry;
|
|
18
|
+
readonly policies: PolicyRegistry;
|
|
19
|
+
constructor(options?: AuthorizationManagerOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates whether an identity can perform an action on an optional resource.
|
|
22
|
+
* Centralizes superuser check, policy resolution, role-to-permission mapping, and fail-closed security.
|
|
23
|
+
*/
|
|
24
|
+
authorize(identity: Identity | undefined, action: string, resource?: unknown, options?: AuthorizeOptions): Promise<AuthorizationDecision>;
|
|
25
|
+
/**
|
|
26
|
+
* Helper that returns a boolean indicating whether the action is allowed.
|
|
27
|
+
*/
|
|
28
|
+
can(identity: Identity | undefined, action: string, resource?: unknown, context?: AuthContext): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Enforces that the action is allowed. Throws ForbiddenError if denied.
|
|
31
|
+
*/
|
|
32
|
+
enforce(identity: Identity | undefined, action: string, resource?: unknown, context?: AuthContext): Promise<AuthorizationDecision>;
|
|
33
|
+
/**
|
|
34
|
+
* Evaluates authorization for multiple resources in bulk (useful for Admin bulk actions).
|
|
35
|
+
*/
|
|
36
|
+
authorizeMany<T = unknown>(identity: Identity | undefined, action: string, resources: readonly T[], options?: AuthorizeOptions): Promise<readonly AuthorizationDecision[]>;
|
|
37
|
+
private normalizeResult;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,WAAW,EACX,qBAAqB,EAErB,OAAO,EACR,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CAChD;AAED,qBAAa,oBAAoB;IAC/B,SAAgB,WAAW,EAAE,kBAAkB,CAAC;IAChD,SAAgB,KAAK,EAAE,YAAY,CAAC;IACpC,SAAgB,QAAQ,EAAE,cAAc,CAAC;gBAEtB,OAAO,GAAE,2BAAgC;IAM5D;;;OAGG;IACU,SAAS,CACpB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,qBAAqB,CAAC;IAgHjC;;OAEG;IACU,GAAG,CACd,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,OAAO,CAAC;IAKnB;;OAEG;IACU,OAAO,CAClB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,qBAAqB,CAAC;IAIjC;;OAEG;IACU,aAAa,CAAC,CAAC,GAAG,OAAO,EACpC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,CAAC,EAAE,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC;IAS5C,OAAO,CAAC,eAAe;CAQxB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { AuthDecision } from './decision.js';
|
|
2
|
+
import { PermissionRegistry } from './permission.js';
|
|
3
|
+
import { RoleRegistry } from './role.js';
|
|
4
|
+
import { PolicyRegistry } from './policy.js';
|
|
5
|
+
import { ForbiddenError } from '../errors.js';
|
|
6
|
+
export class AuthorizationManager {
|
|
7
|
+
permissions;
|
|
8
|
+
roles;
|
|
9
|
+
policies;
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.permissions = options.permissions ?? new PermissionRegistry();
|
|
12
|
+
this.roles = options.roles ?? new RoleRegistry();
|
|
13
|
+
this.policies = options.policies ?? new PolicyRegistry();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Evaluates whether an identity can perform an action on an optional resource.
|
|
17
|
+
* Centralizes superuser check, policy resolution, role-to-permission mapping, and fail-closed security.
|
|
18
|
+
*/
|
|
19
|
+
async authorize(identity, action, resource, options = {}) {
|
|
20
|
+
// 1. Fail closed on missing identity
|
|
21
|
+
if (!identity) {
|
|
22
|
+
const decision = AuthDecision.deny('Identity is missing or unauthenticated.');
|
|
23
|
+
if (options.throwOnDeny) {
|
|
24
|
+
throw new ForbiddenError(decision.reason);
|
|
25
|
+
}
|
|
26
|
+
return decision;
|
|
27
|
+
}
|
|
28
|
+
// 2. Centralized superuser check (auditable)
|
|
29
|
+
if (identity.isSuperuser) {
|
|
30
|
+
return AuthDecision.allow('Superuser access granted.', 'SuperuserPolicy', {
|
|
31
|
+
isSuperuser: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// 3. Object-level / Resource-level policy evaluation
|
|
35
|
+
if (resource !== undefined && resource !== null) {
|
|
36
|
+
let policy;
|
|
37
|
+
if (typeof options.policy === 'string') {
|
|
38
|
+
policy =
|
|
39
|
+
this.policies.getByName(options.policy) ?? this.policies.getForTarget(options.policy);
|
|
40
|
+
}
|
|
41
|
+
else if (options.policy && typeof options.policy === 'object') {
|
|
42
|
+
policy = options.policy;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
policy = this.policies.resolvePolicy(resource);
|
|
46
|
+
}
|
|
47
|
+
if (policy) {
|
|
48
|
+
try {
|
|
49
|
+
const result = await policy.can(identity, action, resource, options.context);
|
|
50
|
+
const decision = this.normalizeResult(result, policy.name);
|
|
51
|
+
if (!decision.allowed && options.throwOnDeny) {
|
|
52
|
+
throw new ForbiddenError(decision.reason ?? `Access denied by policy "${policy.name}".`);
|
|
53
|
+
}
|
|
54
|
+
return decision;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof ForbiddenError) {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
const decision = AuthDecision.deny(`Policy evaluation error: ${error instanceof Error ? error.message : String(error)}`, policy.name);
|
|
61
|
+
if (options.throwOnDeny) {
|
|
62
|
+
throw new ForbiddenError(decision.reason);
|
|
63
|
+
}
|
|
64
|
+
return decision;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// If a resource was supplied but no policy was registered for it: FAIL CLOSED
|
|
68
|
+
const decision = AuthDecision.deny(`No authorization policy found for resource. Access denied.`, undefined, { action });
|
|
69
|
+
if (options.throwOnDeny) {
|
|
70
|
+
throw new ForbiddenError(decision.reason);
|
|
71
|
+
}
|
|
72
|
+
return decision;
|
|
73
|
+
}
|
|
74
|
+
// 4. Action / Permission level evaluation (when no specific resource instance is provided)
|
|
75
|
+
// 4a. Check direct identity permissions (supports wildcards)
|
|
76
|
+
if (identity.hasPermission(action)) {
|
|
77
|
+
return AuthDecision.allow(`Permission "${action}" granted directly to identity.`, 'PermissionRegistry', {
|
|
78
|
+
permission: action,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// 4b. Check role-mapped permissions
|
|
82
|
+
if (identity.roles.length > 0) {
|
|
83
|
+
const rolePermissions = this.roles.getPermissionsForRoles(identity.roles);
|
|
84
|
+
if (PermissionRegistry.matches(rolePermissions, action)) {
|
|
85
|
+
return AuthDecision.allow(`Permission "${action}" granted via identity roles [${identity.roles.join(', ')}].`, 'RoleRegistry', { permission: action, roles: identity.roles });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 4c. Check if a global policy is registered under the action name
|
|
89
|
+
const globalPolicy = this.policies.getByName(action);
|
|
90
|
+
if (globalPolicy) {
|
|
91
|
+
const result = await globalPolicy.can(identity, action, undefined, options.context);
|
|
92
|
+
const decision = this.normalizeResult(result, globalPolicy.name);
|
|
93
|
+
if (!decision.allowed && options.throwOnDeny) {
|
|
94
|
+
throw new ForbiddenError(decision.reason ?? `Access denied by policy "${globalPolicy.name}".`);
|
|
95
|
+
}
|
|
96
|
+
return decision;
|
|
97
|
+
}
|
|
98
|
+
// 5. Fail-closed default
|
|
99
|
+
const denyDecision = AuthDecision.deny(`Access denied: no matching permission, role, or policy allows action "${action}".`);
|
|
100
|
+
if (options.throwOnDeny) {
|
|
101
|
+
throw new ForbiddenError(denyDecision.reason);
|
|
102
|
+
}
|
|
103
|
+
return denyDecision;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Helper that returns a boolean indicating whether the action is allowed.
|
|
107
|
+
*/
|
|
108
|
+
async can(identity, action, resource, context) {
|
|
109
|
+
const decision = await this.authorize(identity, action, resource, { context });
|
|
110
|
+
return decision.allowed;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Enforces that the action is allowed. Throws ForbiddenError if denied.
|
|
114
|
+
*/
|
|
115
|
+
async enforce(identity, action, resource, context) {
|
|
116
|
+
return this.authorize(identity, action, resource, { throwOnDeny: true, context });
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Evaluates authorization for multiple resources in bulk (useful for Admin bulk actions).
|
|
120
|
+
*/
|
|
121
|
+
async authorizeMany(identity, action, resources, options = {}) {
|
|
122
|
+
const decisions = [];
|
|
123
|
+
for (const resource of resources) {
|
|
124
|
+
const decision = await this.authorize(identity, action, resource, options);
|
|
125
|
+
decisions.push(decision);
|
|
126
|
+
}
|
|
127
|
+
return Object.freeze(decisions);
|
|
128
|
+
}
|
|
129
|
+
normalizeResult(result, policyName) {
|
|
130
|
+
if (typeof result === 'boolean') {
|
|
131
|
+
return result
|
|
132
|
+
? AuthDecision.allow('Policy granted access.', policyName)
|
|
133
|
+
: AuthDecision.deny(`Access denied by policy "${policyName}".`, policyName);
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/public/authorization/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PermissionDefinition {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly description?: string | undefined;
|
|
4
|
+
readonly category?: string | undefined;
|
|
5
|
+
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare class PermissionRegistry {
|
|
8
|
+
private readonly permissions;
|
|
9
|
+
register(permission: PermissionDefinition): this;
|
|
10
|
+
registerMany(permissions: readonly PermissionDefinition[]): this;
|
|
11
|
+
get(name: string): PermissionDefinition | undefined;
|
|
12
|
+
has(name: string): boolean;
|
|
13
|
+
getAll(): readonly PermissionDefinition[];
|
|
14
|
+
/**
|
|
15
|
+
* Deterministically test if any granted permission matches the requested permission.
|
|
16
|
+
* Supports exact match, superuser wildcard '*', and namespace wildcards (e.g. 'users.*' matches 'users.read').
|
|
17
|
+
*/
|
|
18
|
+
static matches(grantedPermissions: readonly string[], requestedPermission: string): boolean;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=permission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/permission.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CACnE;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;IAEhE,QAAQ,CAAC,UAAU,EAAE,oBAAoB,GAAG,IAAI;IAQhD,YAAY,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI;IAOhE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAInD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,MAAM,IAAI,SAAS,oBAAoB,EAAE;IAIhD;;;OAGG;WACW,OAAO,CACnB,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,mBAAmB,EAAE,MAAM,GAC1B,OAAO;CAkBX"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export class PermissionRegistry {
|
|
2
|
+
permissions = new Map();
|
|
3
|
+
register(permission) {
|
|
4
|
+
if (this.permissions.has(permission.name)) {
|
|
5
|
+
throw new Error(`Permission "${permission.name}" is already registered.`);
|
|
6
|
+
}
|
|
7
|
+
this.permissions.set(permission.name, Object.freeze({ ...permission }));
|
|
8
|
+
return this;
|
|
9
|
+
}
|
|
10
|
+
registerMany(permissions) {
|
|
11
|
+
for (const permission of permissions) {
|
|
12
|
+
this.register(permission);
|
|
13
|
+
}
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
get(name) {
|
|
17
|
+
return this.permissions.get(name);
|
|
18
|
+
}
|
|
19
|
+
has(name) {
|
|
20
|
+
return this.permissions.has(name);
|
|
21
|
+
}
|
|
22
|
+
getAll() {
|
|
23
|
+
return Object.freeze(Array.from(this.permissions.values()));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Deterministically test if any granted permission matches the requested permission.
|
|
27
|
+
* Supports exact match, superuser wildcard '*', and namespace wildcards (e.g. 'users.*' matches 'users.read').
|
|
28
|
+
*/
|
|
29
|
+
static matches(grantedPermissions, requestedPermission) {
|
|
30
|
+
if (grantedPermissions.includes('*')) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (grantedPermissions.includes(requestedPermission)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const dotIndex = requestedPermission.indexOf('.');
|
|
37
|
+
if (dotIndex !== -1) {
|
|
38
|
+
const namespace = requestedPermission.slice(0, dotIndex);
|
|
39
|
+
if (grantedPermissions.includes(`${namespace}.*`)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=permission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../../../src/public/authorization/permission.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,kBAAkB;IACZ,WAAW,GAAG,IAAI,GAAG,EAAgC,CAAC;IAEhE,QAAQ,CAAC,UAAgC;QAC9C,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,YAAY,CAAC,WAA4C;QAC9D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEM,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAEM,MAAM;QACX,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,OAAO,CACnB,kBAAqC,EACrC,mBAA2B;QAE3B,IAAI,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzD,IAAI,kBAAkB,CAAC,QAAQ,CAAC,GAAG,SAAS,IAAI,CAAC,EAAE,CAAC;gBAClD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Identity, AuthContext, PolicyResult, IPolicy } from '../types.js';
|
|
2
|
+
export declare abstract class BasePolicy<TResource = unknown> implements IPolicy<TResource> {
|
|
3
|
+
abstract readonly name: string;
|
|
4
|
+
/**
|
|
5
|
+
* Evaluates if the given action is allowed for this identity and resource.
|
|
6
|
+
* By default, it dispatches to a method named after the action (e.g., `view`, `update`, `delete`).
|
|
7
|
+
* If no matching method exists, it defaults to `false` (fail-closed).
|
|
8
|
+
*/
|
|
9
|
+
can(identity: Identity, action: string, resource?: TResource, context?: AuthContext): Promise<PolicyResult>;
|
|
10
|
+
}
|
|
11
|
+
export type TargetConstructor = (new (...args: unknown[]) => unknown) | (abstract new (...args: unknown[]) => unknown) | ((...args: unknown[]) => unknown);
|
|
12
|
+
export declare class PolicyRegistry {
|
|
13
|
+
private readonly policiesByName;
|
|
14
|
+
private readonly policiesByTarget;
|
|
15
|
+
register(policy: IPolicy): this;
|
|
16
|
+
registerFor(target: string | TargetConstructor, policy: IPolicy): this;
|
|
17
|
+
getByName(name: string): IPolicy | undefined;
|
|
18
|
+
getForTarget(target: string | TargetConstructor): IPolicy | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a policy for a resource instance or model constructor/name.
|
|
21
|
+
* Inspects:
|
|
22
|
+
* 1. Exact target match in registered targets
|
|
23
|
+
* 2. Constructor match in registered targets
|
|
24
|
+
* 3. ModelMetadata name (`constructor.metadata.name` or `constructor.modelName`)
|
|
25
|
+
* 4. String name match
|
|
26
|
+
*/
|
|
27
|
+
resolvePolicy(resource: unknown): IPolicy | undefined;
|
|
28
|
+
getAll(): readonly IPolicy[];
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEhF,8BAAsB,UAAU,CAAC,SAAS,GAAG,OAAO,CAAE,YAAW,OAAO,CAAC,SAAS,CAAC;IACjF,kBAAyB,IAAI,EAAE,MAAM,CAAC;IAEtC;;;;OAIG;IACU,GAAG,CACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,YAAY,CAAC;CAOzB;AAED,MAAM,MAAM,iBAAiB,GACzB,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GACrC,CAAC,QAAQ,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAC9C,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;AAEtC,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+B;IAEzD,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK/B,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAMtE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI5C,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,OAAO,GAAG,SAAS;IAI5E;;;;;;;OAOG;IACI,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS;IAyDrD,MAAM,IAAI,SAAS,OAAO,EAAE;CAGpC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export class BasePolicy {
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates if the given action is allowed for this identity and resource.
|
|
4
|
+
* By default, it dispatches to a method named after the action (e.g., `view`, `update`, `delete`).
|
|
5
|
+
* If no matching method exists, it defaults to `false` (fail-closed).
|
|
6
|
+
*/
|
|
7
|
+
async can(identity, action, resource, context) {
|
|
8
|
+
const handler = this[action];
|
|
9
|
+
if (typeof handler === 'function') {
|
|
10
|
+
return handler.call(this, identity, resource, context);
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class PolicyRegistry {
|
|
16
|
+
policiesByName = new Map();
|
|
17
|
+
policiesByTarget = new Map();
|
|
18
|
+
register(policy) {
|
|
19
|
+
this.policiesByName.set(policy.name, policy);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
registerFor(target, policy) {
|
|
23
|
+
this.policiesByName.set(policy.name, policy);
|
|
24
|
+
this.policiesByTarget.set(target, policy);
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
getByName(name) {
|
|
28
|
+
return this.policiesByName.get(name);
|
|
29
|
+
}
|
|
30
|
+
getForTarget(target) {
|
|
31
|
+
return this.policiesByTarget.get(target);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves a policy for a resource instance or model constructor/name.
|
|
35
|
+
* Inspects:
|
|
36
|
+
* 1. Exact target match in registered targets
|
|
37
|
+
* 2. Constructor match in registered targets
|
|
38
|
+
* 3. ModelMetadata name (`constructor.metadata.name` or `constructor.modelName`)
|
|
39
|
+
* 4. String name match
|
|
40
|
+
*/
|
|
41
|
+
resolvePolicy(resource) {
|
|
42
|
+
if (resource === undefined || resource === null) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
// 1. Direct target match
|
|
46
|
+
const direct = this.policiesByTarget.get(resource);
|
|
47
|
+
if (direct) {
|
|
48
|
+
return direct;
|
|
49
|
+
}
|
|
50
|
+
// 2. If resource is a string name
|
|
51
|
+
if (typeof resource === 'string') {
|
|
52
|
+
const byName = this.policiesByName.get(resource) ?? this.policiesByTarget.get(resource);
|
|
53
|
+
if (byName) {
|
|
54
|
+
return byName;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 3. If resource is an object with a constructor
|
|
58
|
+
if (typeof resource === 'object') {
|
|
59
|
+
const ctor = resource.constructor;
|
|
60
|
+
if (ctor && typeof ctor === 'function') {
|
|
61
|
+
const byCtor = this.policiesByTarget.get(ctor);
|
|
62
|
+
if (byCtor) {
|
|
63
|
+
return byCtor;
|
|
64
|
+
}
|
|
65
|
+
// Inspect Phase 6 ModelMetadata stable identity
|
|
66
|
+
const meta = ctor.metadata;
|
|
67
|
+
const modelName = meta?.name ?? ctor.modelName;
|
|
68
|
+
if (modelName) {
|
|
69
|
+
const byModelName = this.policiesByTarget.get(modelName) ?? this.policiesByName.get(modelName);
|
|
70
|
+
if (byModelName) {
|
|
71
|
+
return byModelName;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Inspect object type hints ($type, resourceType, modelName)
|
|
75
|
+
const obj = resource;
|
|
76
|
+
const typeHint = (typeof obj['$type'] === 'string' ? obj['$type'] : undefined) ??
|
|
77
|
+
(typeof obj['resourceType'] === 'string' ? obj['resourceType'] : undefined) ??
|
|
78
|
+
(typeof obj['modelName'] === 'string' ? obj['modelName'] : undefined);
|
|
79
|
+
if (typeHint) {
|
|
80
|
+
const byHint = this.policiesByTarget.get(typeHint) ?? this.policiesByName.get(typeHint);
|
|
81
|
+
if (byHint) {
|
|
82
|
+
return byHint;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
getAll() {
|
|
90
|
+
return Object.freeze(Array.from(this.policiesByName.values()));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/public/authorization/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface RoleDefinition {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly permissions: readonly string[];
|
|
4
|
+
readonly description?: string | undefined;
|
|
5
|
+
readonly metadata?: Readonly<Record<string, unknown>> | undefined;
|
|
6
|
+
}
|
|
7
|
+
export declare class RoleRegistry {
|
|
8
|
+
private readonly roles;
|
|
9
|
+
register(role: RoleDefinition): this;
|
|
10
|
+
registerMany(roles: readonly RoleDefinition[]): this;
|
|
11
|
+
get(name: string): RoleDefinition | undefined;
|
|
12
|
+
has(name: string): boolean;
|
|
13
|
+
getPermissionsForRole(roleName: string): readonly string[];
|
|
14
|
+
getPermissionsForRoles(roleNames: readonly string[]): readonly string[];
|
|
15
|
+
getAll(): readonly RoleDefinition[];
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=role.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.d.ts","sourceRoot":"","sources":["../../../src/public/authorization/role.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;CACnE;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAEpD,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAcpC,YAAY,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI;IAOpD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE;IAK1D,sBAAsB,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE;IAWvE,MAAM,IAAI,SAAS,cAAc,EAAE;CAG3C"}
|