@c9up/warden 0.1.13 → 0.1.14
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/AuthManager.d.ts +45 -9
- package/dist/AuthManager.d.ts.map +1 -1
- package/dist/AuthManager.js +75 -23
- package/dist/AuthManager.js.map +1 -1
- package/dist/Authenticator.d.ts +128 -0
- package/dist/Authenticator.d.ts.map +1 -0
- package/dist/Authenticator.js +296 -0
- package/dist/Authenticator.js.map +1 -0
- package/dist/WardenProvider.d.ts.map +1 -1
- package/dist/WardenProvider.js +51 -23
- package/dist/WardenProvider.js.map +1 -1
- package/dist/bouncer/AbilitiesBuilder.d.ts +20 -0
- package/dist/bouncer/AbilitiesBuilder.d.ts.map +1 -0
- package/dist/bouncer/AbilitiesBuilder.js +32 -0
- package/dist/bouncer/AbilitiesBuilder.js.map +1 -0
- package/dist/bouncer/AuthorizationResponse.d.ts +18 -8
- package/dist/bouncer/AuthorizationResponse.d.ts.map +1 -1
- package/dist/bouncer/AuthorizationResponse.js +20 -8
- package/dist/bouncer/AuthorizationResponse.js.map +1 -1
- package/dist/bouncer/BasePolicy.d.ts +4 -3
- package/dist/bouncer/BasePolicy.d.ts.map +1 -1
- package/dist/bouncer/BasePolicy.js.map +1 -1
- package/dist/bouncer/Bouncer.d.ts +9 -2
- package/dist/bouncer/Bouncer.d.ts.map +1 -1
- package/dist/bouncer/Bouncer.js +59 -10
- package/dist/bouncer/Bouncer.js.map +1 -1
- package/dist/bouncer/PolicyAuthorizer.d.ts +2 -1
- package/dist/bouncer/PolicyAuthorizer.d.ts.map +1 -1
- package/dist/bouncer/PolicyAuthorizer.js +11 -3
- package/dist/bouncer/PolicyAuthorizer.js.map +1 -1
- package/dist/bouncer/evaluate.d.ts +1 -1
- package/dist/bouncer/evaluate.d.ts.map +1 -1
- package/dist/bouncer/evaluate.js +3 -2
- package/dist/bouncer/evaluate.js.map +1 -1
- package/dist/bouncer/types.d.ts +22 -1
- package/dist/bouncer/types.d.ts.map +1 -1
- package/dist/config.d.ts +34 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -1
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +15 -13
- package/dist/configure.js.map +1 -1
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +37 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/mfa/OtpProvider.d.ts.map +1 -1
- package/dist/mfa/OtpProvider.js +21 -3
- package/dist/mfa/OtpProvider.js.map +1 -1
- package/dist/mfa/WebauthnProvider.d.ts +24 -2
- package/dist/mfa/WebauthnProvider.d.ts.map +1 -1
- package/dist/mfa/WebauthnProvider.js +28 -8
- package/dist/mfa/WebauthnProvider.js.map +1 -1
- package/dist/middleware.d.ts +29 -6
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +85 -166
- package/dist/middleware.js.map +1 -1
- package/dist/standalone.d.ts.map +1 -1
- package/dist/standalone.js +21 -13
- package/dist/standalone.js.map +1 -1
- package/dist/strategies/ApiKeyStrategy.d.ts.map +1 -1
- package/dist/strategies/ApiKeyStrategy.js +4 -1
- package/dist/strategies/ApiKeyStrategy.js.map +1 -1
- package/dist/strategies/SessionStrategy.js +2 -2
- package/dist/strategies/SessionStrategy.js.map +1 -1
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +2 -1
- package/src/AuthManager.ts +125 -28
- package/src/Authenticator.ts +385 -0
- package/src/WardenProvider.ts +51 -25
- package/src/bouncer/AbilitiesBuilder.ts +41 -0
- package/src/bouncer/AuthorizationResponse.ts +24 -16
- package/src/bouncer/BasePolicy.ts +4 -2
- package/src/bouncer/Bouncer.ts +77 -14
- package/src/bouncer/PolicyAuthorizer.ts +14 -4
- package/src/bouncer/evaluate.ts +4 -2
- package/src/bouncer/types.ts +24 -1
- package/src/config.ts +47 -3
- package/src/configure.ts +15 -13
- package/src/errors.ts +43 -1
- package/src/index.ts +22 -2
- package/src/mfa/OtpProvider.ts +31 -3
- package/src/mfa/WebauthnProvider.ts +58 -12
- package/src/middleware.ts +112 -207
- package/src/standalone.ts +22 -14
- package/src/strategies/ApiKeyStrategy.ts +4 -1
- package/src/strategies/SessionStrategy.ts +2 -2
|
@@ -12,13 +12,20 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { UserPayload } from "../AuthManager.js";
|
|
14
14
|
import type { Scope } from "../rights/types.js";
|
|
15
|
+
import { AbilitiesBuilder } from "./AbilitiesBuilder.js";
|
|
15
16
|
import { AuthorizationResponse } from "./AuthorizationResponse.js";
|
|
16
17
|
import type { BasePolicy } from "./BasePolicy.js";
|
|
17
18
|
import { PolicyAuthorizer } from "./PolicyAuthorizer.js";
|
|
18
19
|
import type { Ability, AbilityOptions, AuthorizerResponse, BouncerContext } from "./types.js";
|
|
19
20
|
export declare class Bouncer {
|
|
20
21
|
#private;
|
|
21
|
-
constructor(user: UserPayload | null, abilities?: Record<string, Ability<never[]>>, policies?: Record<string, new () => BasePolicy>, context?: BouncerContext);
|
|
22
|
+
constructor(user: UserPayload | (() => UserPayload | null) | null, abilities?: Record<string, Ability<never[]>>, policies?: Record<string, new () => BasePolicy>, context?: BouncerContext);
|
|
23
|
+
/**
|
|
24
|
+
* Define an ability and open a chainable {@link AbilitiesBuilder} (Adonis
|
|
25
|
+
* `Bouncer.define`). Read `.abilities` off the returned builder to pass into a
|
|
26
|
+
* `new Bouncer(user, abilities)`.
|
|
27
|
+
*/
|
|
28
|
+
static define<Args extends unknown[]>(name: string, authorizer: (user: UserPayload, ...args: Args) => AuthorizerResponse, options?: AbilityOptions): AbilitiesBuilder;
|
|
22
29
|
/** The active resolution scope (default `"global"`). */
|
|
23
30
|
get scope(): Scope;
|
|
24
31
|
/**
|
|
@@ -29,7 +36,7 @@ export declare class Bouncer {
|
|
|
29
36
|
static ability<Args extends unknown[]>(options: AbilityOptions, callback: (user: UserPayload | null, ...args: Args) => AuthorizerResponse): Ability<Args>;
|
|
30
37
|
/** Convenience — equivalent to `AuthorizationResponse.deny` (Adonis `bouncer.deny`). */
|
|
31
38
|
deny(message?: string, status?: number): AuthorizationResponse;
|
|
32
|
-
/** Open a policy for checks (D8 — fresh
|
|
39
|
+
/** Open a policy for checks (D8 — fresh policy instance per check). */
|
|
33
40
|
with(policy: (new () => BasePolicy) | string): PolicyAuthorizer;
|
|
34
41
|
/** Run an ability check and resolve to the full response. */
|
|
35
42
|
execute<Args extends unknown[]>(ability: Ability<Args>, ...args: Args): Promise<AuthorizationResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Bouncer.d.ts","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,KAAK,EAAwB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EACX,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,cAAc,
|
|
1
|
+
{"version":3,"file":"Bouncer.d.ts","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"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"}
|
package/dist/bouncer/Bouncer.js
CHANGED
|
@@ -11,24 +11,52 @@
|
|
|
11
11
|
* the developer writes the predicate, exactly as Adonis does.
|
|
12
12
|
*/
|
|
13
13
|
import { WardenError } from "../errors.js";
|
|
14
|
+
import { AbilitiesBuilder } from "./AbilitiesBuilder.js";
|
|
14
15
|
import { AuthorizationResponse } from "./AuthorizationResponse.js";
|
|
15
16
|
import { evaluate, isAction, throwAuthorizationFailure } from "./evaluate.js";
|
|
16
17
|
import { PolicyAuthorizer } from "./PolicyAuthorizer.js";
|
|
17
18
|
import { emptyPermissions } from "./policyContext.js";
|
|
18
19
|
export class Bouncer {
|
|
20
|
+
#userOrResolver;
|
|
21
|
+
/** Lazily-resolved user cache (`undefined` until `#getUser` runs). */
|
|
19
22
|
#user;
|
|
20
23
|
#abilities;
|
|
21
24
|
#policies;
|
|
22
25
|
#scope;
|
|
23
26
|
#resolver;
|
|
27
|
+
#containerResolver;
|
|
28
|
+
#emitter;
|
|
24
29
|
/** Memoized resolution — a Bouncer is fixed per `(user, scope)`, so resolve once (D3). */
|
|
25
30
|
#resolved;
|
|
26
31
|
constructor(user, abilities, policies, context) {
|
|
27
|
-
this.#
|
|
32
|
+
this.#userOrResolver = user;
|
|
28
33
|
this.#abilities = abilities ?? {};
|
|
29
34
|
this.#policies = policies ?? {};
|
|
30
35
|
this.#scope = context?.scope ?? "global";
|
|
31
36
|
this.#resolver = context?.resolver;
|
|
37
|
+
this.#containerResolver = context?.containerResolver;
|
|
38
|
+
this.#emitter = context?.emitter;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the user, lazily invoking a resolver callback once and memoizing
|
|
42
|
+
* the result (Adonis `#getUser`). A plain `UserPayload | null` passes through.
|
|
43
|
+
*/
|
|
44
|
+
#getUser() {
|
|
45
|
+
if (this.#user === undefined) {
|
|
46
|
+
this.#user =
|
|
47
|
+
typeof this.#userOrResolver === "function"
|
|
48
|
+
? this.#userOrResolver()
|
|
49
|
+
: this.#userOrResolver;
|
|
50
|
+
}
|
|
51
|
+
return this.#user;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Define an ability and open a chainable {@link AbilitiesBuilder} (Adonis
|
|
55
|
+
* `Bouncer.define`). Read `.abilities` off the returned builder to pass into a
|
|
56
|
+
* `new Bouncer(user, abilities)`.
|
|
57
|
+
*/
|
|
58
|
+
static define(name, authorizer, options) {
|
|
59
|
+
return new AbilitiesBuilder().define(name, authorizer, options);
|
|
32
60
|
}
|
|
33
61
|
/** The active resolution scope (default `"global"`). */
|
|
34
62
|
get scope() {
|
|
@@ -42,9 +70,10 @@ export class Bouncer {
|
|
|
42
70
|
*/
|
|
43
71
|
#resolvePermissions() {
|
|
44
72
|
if (this.#resolved === undefined) {
|
|
73
|
+
const user = this.#getUser();
|
|
45
74
|
this.#resolved =
|
|
46
|
-
this.#resolver !== undefined &&
|
|
47
|
-
? this.#resolver.resolve(
|
|
75
|
+
this.#resolver !== undefined && user !== null
|
|
76
|
+
? this.#resolver.resolve(user, this.#scope)
|
|
48
77
|
: Promise.resolve(emptyPermissions(this.#scope));
|
|
49
78
|
}
|
|
50
79
|
return this.#resolved;
|
|
@@ -75,14 +104,31 @@ export class Bouncer {
|
|
|
75
104
|
deny(message, status) {
|
|
76
105
|
return AuthorizationResponse.deny(message, status);
|
|
77
106
|
}
|
|
78
|
-
/** Open a policy for checks (D8 — fresh
|
|
107
|
+
/** Open a policy for checks (D8 — fresh policy instance per check). */
|
|
79
108
|
with(policy) {
|
|
80
109
|
const factory = typeof policy === "string"
|
|
81
110
|
? this.#resolvePolicyClass(policy)
|
|
82
|
-
: () =>
|
|
111
|
+
: () => this.#construct(policy);
|
|
83
112
|
// The PolicyAuthorizer inherits the Bouncer's scope + the shared memoized
|
|
84
113
|
// resolve so every policy check sees the active `(user, scope)` (AC1/AC3).
|
|
85
|
-
return new PolicyAuthorizer(this.#
|
|
114
|
+
return new PolicyAuthorizer(this.#getUser(), factory, this.#scope, () => this.#resolvePermissions(), this.#emitter);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Construct a policy instance via the container resolver when present (Adonis
|
|
118
|
+
* DI parity), else a plain `new Policy()` (D8 — a fresh instance per check).
|
|
119
|
+
*/
|
|
120
|
+
#construct(ctor) {
|
|
121
|
+
return this.#containerResolver !== undefined
|
|
122
|
+
? this.#containerResolver.make(ctor)
|
|
123
|
+
: Promise.resolve(new ctor());
|
|
124
|
+
}
|
|
125
|
+
/** Emit `authorization:finished` when an emitter is wired (no-op otherwise). */
|
|
126
|
+
#emit(action, response) {
|
|
127
|
+
this.#emitter?.emit("authorization:finished", {
|
|
128
|
+
user: this.#getUser(),
|
|
129
|
+
action,
|
|
130
|
+
response,
|
|
131
|
+
});
|
|
86
132
|
}
|
|
87
133
|
execute(ability, ...args) {
|
|
88
134
|
return this.#evaluateAbility(ability, args);
|
|
@@ -101,13 +147,16 @@ export class Bouncer {
|
|
|
101
147
|
}
|
|
102
148
|
async #evaluateAbility(ability, args) {
|
|
103
149
|
const resolved = typeof ability === "string" ? this.#resolveAbility(ability) : ability;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
150
|
+
const action = typeof ability === "string" ? ability : "(ability)";
|
|
151
|
+
const response = await evaluate({
|
|
152
|
+
user: this.#getUser(),
|
|
153
|
+
action,
|
|
107
154
|
allowGuest: resolved.allowGuest,
|
|
108
155
|
run: (user) => resolved.execute(user, ...args),
|
|
109
156
|
args,
|
|
110
157
|
});
|
|
158
|
+
this.#emit(action, response);
|
|
159
|
+
return response;
|
|
111
160
|
}
|
|
112
161
|
#resolveAbility(name) {
|
|
113
162
|
const found = this.#abilities[name];
|
|
@@ -127,7 +176,7 @@ export class Bouncer {
|
|
|
127
176
|
hint: "Register it via new Bouncer(user, abilities, { [name]: Policy }).",
|
|
128
177
|
});
|
|
129
178
|
}
|
|
130
|
-
return
|
|
179
|
+
return this.#construct(ctor);
|
|
131
180
|
};
|
|
132
181
|
}
|
|
133
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Bouncer.js","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Bouncer.js","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,10 @@ import type { UserPayload } from "../AuthManager.js";
|
|
|
9
9
|
import type { EffectivePermissions, Scope } from "../rights/types.js";
|
|
10
10
|
import type { AuthorizationResponse } from "./AuthorizationResponse.js";
|
|
11
11
|
import { BasePolicy } from "./BasePolicy.js";
|
|
12
|
+
import type { BouncerEmitter } from "./types.js";
|
|
12
13
|
export declare class PolicyAuthorizer {
|
|
13
14
|
#private;
|
|
14
|
-
constructor(user: UserPayload | null, factory: () => BasePolicy
|
|
15
|
+
constructor(user: UserPayload | null, factory: () => Promise<BasePolicy>, scope?: Scope, resolvePermissions?: () => Promise<EffectivePermissions>, emitter?: BouncerEmitter);
|
|
15
16
|
/** Run a check and resolve to the full response (D8 — fresh policy per check). */
|
|
16
17
|
execute(action: string, ...args: unknown[]): Promise<AuthorizationResponse>;
|
|
17
18
|
/** True iff the action is authorized. Never throws on denial. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PolicyAuthorizer.d.ts","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"PolicyAuthorizer.d.ts","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAS7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA6CjD,qBAAa,gBAAgB;;gBAQ3B,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EAClC,KAAK,GAAE,KAAgB,EACvB,kBAAkB,GAAE,MAAM,OAAO,CAAC,oBAAoB,CACb,EACzC,OAAO,CAAC,EAAE,cAAc;IASzB,kFAAkF;IAC5E,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,qBAAqB,CAAC;IAyBjC,iEAAiE;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,kEAAkE;IAC5D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,6EAA6E;IACvE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAMlE"}
|
|
@@ -48,22 +48,24 @@ export class PolicyAuthorizer {
|
|
|
48
48
|
#factory;
|
|
49
49
|
#scope;
|
|
50
50
|
#resolvePermissions;
|
|
51
|
-
|
|
51
|
+
#emitter;
|
|
52
|
+
constructor(user, factory, scope = "global", resolvePermissions = () => Promise.resolve(emptyPermissions(scope)), emitter) {
|
|
52
53
|
this.#user = user;
|
|
53
54
|
this.#factory = factory;
|
|
54
55
|
this.#scope = scope;
|
|
55
56
|
this.#resolvePermissions = resolvePermissions;
|
|
57
|
+
this.#emitter = emitter;
|
|
56
58
|
}
|
|
57
59
|
/** Run a check and resolve to the full response (D8 — fresh policy per check). */
|
|
58
60
|
async execute(action, ...args) {
|
|
59
|
-
const policy = this.#factory();
|
|
61
|
+
const policy = await this.#factory();
|
|
60
62
|
// Attach the active scope + resolved permissions BEFORE dispatch so the
|
|
61
63
|
// before/method/after pipeline all read `this.scope` / `this.permissions`.
|
|
62
64
|
const permissions = await this.#resolvePermissions();
|
|
63
65
|
setPolicyContext(policy, { scope: this.#scope, permissions });
|
|
64
66
|
const method = resolveActionMethod(policy, action);
|
|
65
67
|
const options = getActionMetadata(policy, action);
|
|
66
|
-
|
|
68
|
+
const response = await evaluate({
|
|
67
69
|
user: this.#user,
|
|
68
70
|
action,
|
|
69
71
|
allowGuest: options.allowGuest ?? false,
|
|
@@ -72,6 +74,12 @@ export class PolicyAuthorizer {
|
|
|
72
74
|
before: policy.before?.bind(policy),
|
|
73
75
|
after: policy.after?.bind(policy),
|
|
74
76
|
});
|
|
77
|
+
this.#emitter?.emit("authorization:finished", {
|
|
78
|
+
user: this.#user,
|
|
79
|
+
action,
|
|
80
|
+
response,
|
|
81
|
+
});
|
|
82
|
+
return response;
|
|
75
83
|
}
|
|
76
84
|
/** True iff the action is authorized. Never throws on denial. */
|
|
77
85
|
async allows(action, ...args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PolicyAuthorizer.js","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAEN,QAAQ,EACR,QAAQ,EACR,yBAAyB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"PolicyAuthorizer.js","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,6 @@ export declare function evaluate(params: {
|
|
|
31
31
|
run: (user: UserPayload | null) => AuthorizerResponse;
|
|
32
32
|
args: unknown[];
|
|
33
33
|
before?: (user: UserPayload | null, action: string, ...args: unknown[]) => HookResponse;
|
|
34
|
-
after?: (user: UserPayload | null, action: string, result: AuthorizationResponse) => HookResponse;
|
|
34
|
+
after?: (user: UserPayload | null, action: string, result: AuthorizationResponse, ...args: unknown[]) => HookResponse;
|
|
35
35
|
}): Promise<AuthorizationResponse>;
|
|
36
36
|
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE,+DAA+D;AAC/D,MAAM,MAAM,MAAM,GAAG,CACpB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,kBAAkB,CAAC;AAExB,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GACpC,qBAAqB,CAKvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,4EAA4E;AAC5E,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,qBAAqB,GAC7B,KAAK,CASP;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,MAAM,EAAE;IACtC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,kBAAkB,CAAC;IACtD,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,CACR,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,YAAY,CAAC;IAClB,KAAK,CAAC,EAAE,CACP,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE,+DAA+D;AAC/D,MAAM,MAAM,MAAM,GAAG,CACpB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,kBAAkB,CAAC;AAExB,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GACpC,qBAAqB,CAKvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,4EAA4E;AAC5E,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,qBAAqB,GAC7B,KAAK,CASP;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,MAAM,EAAE;IACtC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,kBAAkB,CAAC;IACtD,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,CACR,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,YAAY,CAAC;IAClB,KAAK,CAAC,EAAE,CACP,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,EAC7B,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,YAAY,CAAC;CAClB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAgCjC"}
|
package/dist/bouncer/evaluate.js
CHANGED
|
@@ -52,9 +52,10 @@ export async function evaluate(params) {
|
|
|
52
52
|
response = normalizeResponse(await run(user));
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
// (4) after — non-undefined overrides.
|
|
55
|
+
// (4) after — non-undefined overrides. Receives the resource args (Adonis
|
|
56
|
+
// `policy.after(user, action, result, ...args)`).
|
|
56
57
|
if (after) {
|
|
57
|
-
const override = await after(user, action, response);
|
|
58
|
+
const override = await after(user, action, response, ...args);
|
|
58
59
|
if (override !== undefined) {
|
|
59
60
|
response = normalizeResponse(override);
|
|
60
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AASnE,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAChC,KAAsC;IAEtC,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACpC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,yBAAyB,CACxC,QAA+B;IAE/B,MAAM,IAAI,WAAW,CACpB,uBAAuB,EACvB,QAAQ,CAAC,OAAO,IAAI,sBAAsB,EAC1C;QACC,IAAI,EAAE,qDAAqD;QAC3D,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG;KAC9B,CACD,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AASnE,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAChC,KAAsC;IAEtC,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACpC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,yBAAyB,CACxC,QAA+B;IAE/B,MAAM,IAAI,WAAW,CACpB,uBAAuB,EACvB,QAAQ,CAAC,OAAO,IAAI,sBAAsB,EAC1C;QACC,IAAI,EAAE,qDAAqD;QAC3D,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG;KAC9B,CACD,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAiB9B;IACA,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEtE,IAAI,QAA2C,CAAC;IAEhD,wDAAwD;IACxD,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;IAED,sEAAsE;IACtE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC;aAAM,CAAC;YACP,QAAQ,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;IACF,CAAC;IAED,0EAA0E;IAC1E,kDAAkD;IAClD,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAC;QAC9D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC"}
|
package/dist/bouncer/types.d.ts
CHANGED
|
@@ -9,9 +9,26 @@ import type { UserPayload } from "../AuthManager.js";
|
|
|
9
9
|
import type { RightsResolver } from "../rights/RightsResolver.js";
|
|
10
10
|
import type { Scope } from "../rights/types.js";
|
|
11
11
|
import type { AuthorizationResponse } from "./AuthorizationResponse.js";
|
|
12
|
+
/**
|
|
13
|
+
* Agnostic IoC-container resolver used to construct policy instances (Adonis
|
|
14
|
+
* `PolicyAuthorizer`'s `#containerResolver`). Same shape as `ctx.containerResolver`
|
|
15
|
+
* so a Ream request context is passed through directly — warden never imports the
|
|
16
|
+
* container. Absent ⇒ policies are built with a plain `new Policy()`.
|
|
17
|
+
*/
|
|
18
|
+
export interface PolicyContainerResolver {
|
|
19
|
+
make<T>(ctor: new (...args: never[]) => T): Promise<T>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Agnostic event sink (Adonis `Bouncer.emitter`). When present, an
|
|
23
|
+
* `authorization:finished` event fires after every ability/policy evaluation with
|
|
24
|
+
* `{ user, action, response }`. No-op when absent.
|
|
25
|
+
*/
|
|
26
|
+
export interface BouncerEmitter {
|
|
27
|
+
emit(event: string, payload: unknown): void;
|
|
28
|
+
}
|
|
12
29
|
/**
|
|
13
30
|
* Optional 4th `Bouncer` ctor argument (56.3, D1) — the scope dimension + the
|
|
14
|
-
* Layer-1 resolver.
|
|
31
|
+
* Layer-1 resolver. All optional; omitting it ⇒ the implicit `global` scope
|
|
15
32
|
* with no resolver (single-tenant zero-config, D7). Additive: every 56.2 call
|
|
16
33
|
* site keeps compiling.
|
|
17
34
|
*/
|
|
@@ -20,6 +37,10 @@ export interface BouncerContext {
|
|
|
20
37
|
readonly scope?: Scope;
|
|
21
38
|
/** Layer-1 resolver consulted for this Bouncer's `(user, scope)`. */
|
|
22
39
|
readonly resolver?: RightsResolver;
|
|
40
|
+
/** IoC-container resolver used to construct policies (Adonis DI parity). */
|
|
41
|
+
readonly containerResolver?: PolicyContainerResolver;
|
|
42
|
+
/** Event sink for `authorization:finished` (Adonis `Bouncer.emitter`). */
|
|
43
|
+
readonly emitter?: BouncerEmitter;
|
|
23
44
|
}
|
|
24
45
|
/** A predicate's return — bool sugar or an explicit response, sync or async (D7). */
|
|
25
46
|
export type AuthorizerResponse = boolean | AuthorizationResponse | Promise<boolean | AuthorizationResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/bouncer/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/bouncer/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACvC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvD;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IACnC,4EAA4E;IAC5E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IACrD,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,qFAAqF;AACrF,MAAM,MAAM,kBAAkB,GAC3B,OAAO,GACP,qBAAqB,GACrB,OAAO,CAAC,OAAO,GAAG,qBAAqB,CAAC,CAAC;AAE5C,wGAAwG;AACxG,MAAM,MAAM,YAAY,GACrB,OAAO,GACP,qBAAqB,GACrB,SAAS,GACT,OAAO,CAAC,OAAO,GAAG,qBAAqB,GAAG,SAAS,CAAC,CAAC;AAExD,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IAC1D,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,CACjB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,kBAAkB,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC1C"}
|
package/dist/config.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* },
|
|
15
15
|
* })
|
|
16
16
|
*/
|
|
17
|
-
import type { UserPayload } from "./AuthManager.js";
|
|
17
|
+
import type { AuthStrategy, UserPayload } from "./AuthManager.js";
|
|
18
18
|
import type { BasePolicy } from "./bouncer/BasePolicy.js";
|
|
19
19
|
import type { Ability } from "./bouncer/types.js";
|
|
20
20
|
import type { MfaManager } from "./mfa/MfaManager.js";
|
|
@@ -47,10 +47,41 @@ export interface JwtConfig {
|
|
|
47
47
|
*/
|
|
48
48
|
blacklist?: TokenBlacklist;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* A guard entry in the AdonisJS-style config — an {@link AuthStrategy} instance,
|
|
52
|
+
* built via {@link jwtGuard}/{@link sessionGuard}/{@link apiKeyGuard}. Named a
|
|
53
|
+
* "factory" for AdonisJS symmetry (`sessionGuard({...})`), though Warden guards
|
|
54
|
+
* are shared per-app instances (the per-request state lives on the Authenticator).
|
|
55
|
+
*/
|
|
56
|
+
export type GuardFactory = AuthStrategy;
|
|
57
|
+
/** Build a JWT guard from its config (AdonisJS `jwtGuard()` shape). */
|
|
58
|
+
export declare function jwtGuard(config: JwtConfig): GuardFactory;
|
|
59
|
+
/** Build a session guard from its config (AdonisJS `sessionGuard()` shape). */
|
|
60
|
+
export declare function sessionGuard(config: SessionStrategyConfig): GuardFactory;
|
|
61
|
+
/** Build an API-key / access-tokens guard from its config. */
|
|
62
|
+
export declare function apiKeyGuard(config: ApiKeyConfig): GuardFactory;
|
|
50
63
|
export interface WardenConfig {
|
|
51
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* AdonisJS-style default guard NAME — the key in {@link WardenConfig.guards}
|
|
66
|
+
* used when a route/call names none. Preferred over {@link
|
|
67
|
+
* WardenConfig.defaultStrategy}.
|
|
68
|
+
*/
|
|
69
|
+
default?: string;
|
|
70
|
+
/**
|
|
71
|
+
* AdonisJS-style named guard map, e.g.
|
|
72
|
+
* `{ web: sessionGuard({...}), api: jwtGuard({...}) }`. Guards are named by
|
|
73
|
+
* YOU (multiple instances of the same driver are allowed). When supplied,
|
|
74
|
+
* this takes precedence over the driver-keyed `jwt`/`session`/`apiKey` fields.
|
|
75
|
+
*/
|
|
76
|
+
guards?: Record<string, GuardFactory>;
|
|
77
|
+
/**
|
|
78
|
+
* Login route an HTML client is redirected to when a session-guarded request
|
|
79
|
+
* is unauthenticated (AdonisJS session renderer parity). Absent ⇒ 401 JSON.
|
|
80
|
+
*/
|
|
81
|
+
loginRoute?: string;
|
|
82
|
+
/** Legacy default auth strategy name (default: 'jwt'). Prefer {@link WardenConfig.default}. */
|
|
52
83
|
defaultStrategy?: string;
|
|
53
|
-
/** JWT strategy configuration. */
|
|
84
|
+
/** JWT strategy configuration (legacy driver-keyed form). */
|
|
54
85
|
jwt?: JwtConfig;
|
|
55
86
|
/**
|
|
56
87
|
* Session strategy configuration. Supply `findUser` so `@Guard('session')`
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -14,6 +14,21 @@
|
|
|
14
14
|
* },
|
|
15
15
|
* })
|
|
16
16
|
*/
|
|
17
|
+
import { ApiKeyStrategy } from "./strategies/ApiKeyStrategy.js";
|
|
18
|
+
import { JwtStrategy } from "./strategies/JwtStrategy.js";
|
|
19
|
+
import { SessionStrategy } from "./strategies/SessionStrategy.js";
|
|
20
|
+
/** Build a JWT guard from its config (AdonisJS `jwtGuard()` shape). */
|
|
21
|
+
export function jwtGuard(config) {
|
|
22
|
+
return new JwtStrategy(config);
|
|
23
|
+
}
|
|
24
|
+
/** Build a session guard from its config (AdonisJS `sessionGuard()` shape). */
|
|
25
|
+
export function sessionGuard(config) {
|
|
26
|
+
return new SessionStrategy(config);
|
|
27
|
+
}
|
|
28
|
+
/** Build an API-key / access-tokens guard from its config. */
|
|
29
|
+
export function apiKeyGuard(config) {
|
|
30
|
+
return new ApiKeyStrategy(config);
|
|
31
|
+
}
|
|
17
32
|
/** Typed config helper — identity function for editor inference. */
|
|
18
33
|
export function defineConfig(config) {
|
|
19
34
|
return config;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAqClE,uEAAuE;AACvE,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACzC,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,MAA6B;IACzD,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC/C,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAuED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,MAAoB;IAChD,OAAO,MAAM,CAAC;AACf,CAAC"}
|
package/dist/configure.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAEA,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAEA,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDjE"}
|
package/dist/configure.js
CHANGED
|
@@ -6,21 +6,23 @@ export async function configure(codemods) {
|
|
|
6
6
|
JWT_SECRET: jwtSecret,
|
|
7
7
|
JWT_EXPIRY: "3600",
|
|
8
8
|
});
|
|
9
|
-
await codemods.writeFile("config/auth.ts", `import { defineConfig } from '@c9up/warden'
|
|
9
|
+
await codemods.writeFile("config/auth.ts", `import { defineConfig, jwtGuard } from '@c9up/warden'
|
|
10
10
|
|
|
11
11
|
export default defineConfig({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
default: 'jwt',
|
|
13
|
+
guards: {
|
|
14
|
+
jwt: jwtGuard({
|
|
15
|
+
secret: process.env.JWT_SECRET ?? '',
|
|
16
|
+
expiresInSeconds: Number(process.env.JWT_EXPIRY ?? '3600'),
|
|
17
|
+
// TODO: wire these to your user model (e.g. via your ORM).
|
|
18
|
+
// The JWT guard needs both to issue and verify tokens.
|
|
19
|
+
findUser: async (_id) => {
|
|
20
|
+
throw new Error('TODO: implement findUser(id) for the JWT guard in config/auth.ts')
|
|
21
|
+
},
|
|
22
|
+
verifyCredentials: async (_email, _password) => {
|
|
23
|
+
throw new Error('TODO: implement verifyCredentials(email, password) in config/auth.ts')
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
24
26
|
},
|
|
25
27
|
})
|
|
26
28
|
`);
|
package/dist/configure.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY1C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,MAAM,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,QAAQ,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IACpD,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,UAAU,EAAE,SAAS;QACrB,UAAU,EAAE,MAAM;KAClB,CAAC,CAAC;IACH,MAAM,QAAQ,CAAC,SAAS,CACvB,gBAAgB,EAChB
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY1C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,MAAM,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,QAAQ,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IACpD,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,UAAU,EAAE,SAAS;QACrB,UAAU,EAAE,MAAM;KAClB,CAAC,CAAC;IACH,MAAM,QAAQ,CAAC,SAAS,CACvB,gBAAgB,EAChB;;;;;;;;;;;;;;;;;;;CAmBD,CACC,CAAC;IACF,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,qEAAqE;IACrE,4DAA4D;IAC5D,iEAAiE;IACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB;QACC,EAAE;QACF,wDAAwD;QACxD,uDAAuD;QACvD,wEAAwE;QACxE,qEAAqE;QACrE,sDAAsD;QACtD,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;AACH,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -15,4 +15,31 @@ export declare class WardenError extends Error {
|
|
|
15
15
|
status?: number;
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* `E_UNAUTHORIZED_ACCESS` — raised when an incoming request cannot be
|
|
20
|
+
* authenticated (AdonisJS `@adonisjs/auth` parity). Carries `guardDriverName`
|
|
21
|
+
* (the guard that rejected) and, for session-guard flows, an optional
|
|
22
|
+
* `redirectTo` (the login route an HTML client is redirected to). Status 401.
|
|
23
|
+
*
|
|
24
|
+
* Content negotiation (redirect for `Accept: text/html` + session guard, else
|
|
25
|
+
* 401 JSON) is performed by Warden itself — see `renderAuthError` in
|
|
26
|
+
* `middleware.ts` — so the package stays agnostic of the host's exception
|
|
27
|
+
* handler.
|
|
28
|
+
*/
|
|
29
|
+
export declare class E_UNAUTHORIZED_ACCESS extends WardenError {
|
|
30
|
+
readonly redirectTo?: string;
|
|
31
|
+
readonly guardDriverName: string;
|
|
32
|
+
constructor(message: string, options: {
|
|
33
|
+
guardDriverName: string;
|
|
34
|
+
redirectTo?: string;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* `E_INVALID_CREDENTIALS` — raised when a credential check (email/password)
|
|
39
|
+
* fails (AdonisJS parity). Status 400. Distinct from `E_UNAUTHORIZED_ACCESS`
|
|
40
|
+
* (a missing/invalid session or token on a protected route → 401).
|
|
41
|
+
*/
|
|
42
|
+
export declare class E_INVALID_CREDENTIALS extends WardenError {
|
|
43
|
+
constructor(message?: string);
|
|
44
|
+
}
|
|
18
45
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAc7C;AAED;;;;;;;;;;GAUG;AACH,qBAAa,qBAAsB,SAAQ,WAAW;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAGhC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAM1D;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,WAAW;gBACzC,OAAO,SAA6B;CAGhD"}
|
package/dist/errors.js
CHANGED
|
@@ -13,9 +13,45 @@ export class WardenError extends Error {
|
|
|
13
13
|
constructor(code, message, options) {
|
|
14
14
|
super(message);
|
|
15
15
|
this.name = "WardenError";
|
|
16
|
-
|
|
16
|
+
// Warden's own codes carry the `WARDEN_` namespace. The AdonisJS auth
|
|
17
|
+
// identifiers (`E_UNAUTHORIZED_ACCESS`, `E_INVALID_CREDENTIALS`) are
|
|
18
|
+
// PRESERVED verbatim so the exposed `.code` matches Adonis exactly — a
|
|
19
|
+
// consumer branching on `error.code === 'E_UNAUTHORIZED_ACCESS'` (or a
|
|
20
|
+
// framework mapping the Adonis id) sees the same string it would under
|
|
21
|
+
// `@adonisjs/auth`. Documented deviation from the blanket prefix.
|
|
22
|
+
this.code = code.startsWith("E_") ? code : `WARDEN_${code}`;
|
|
17
23
|
this.hint = options?.hint;
|
|
18
24
|
this.status = options?.status;
|
|
19
25
|
}
|
|
20
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* `E_UNAUTHORIZED_ACCESS` — raised when an incoming request cannot be
|
|
29
|
+
* authenticated (AdonisJS `@adonisjs/auth` parity). Carries `guardDriverName`
|
|
30
|
+
* (the guard that rejected) and, for session-guard flows, an optional
|
|
31
|
+
* `redirectTo` (the login route an HTML client is redirected to). Status 401.
|
|
32
|
+
*
|
|
33
|
+
* Content negotiation (redirect for `Accept: text/html` + session guard, else
|
|
34
|
+
* 401 JSON) is performed by Warden itself — see `renderAuthError` in
|
|
35
|
+
* `middleware.ts` — so the package stays agnostic of the host's exception
|
|
36
|
+
* handler.
|
|
37
|
+
*/
|
|
38
|
+
export class E_UNAUTHORIZED_ACCESS extends WardenError {
|
|
39
|
+
redirectTo;
|
|
40
|
+
guardDriverName;
|
|
41
|
+
constructor(message, options) {
|
|
42
|
+
super("E_UNAUTHORIZED_ACCESS", message, { status: 401 });
|
|
43
|
+
this.guardDriverName = options.guardDriverName;
|
|
44
|
+
this.redirectTo = options.redirectTo;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `E_INVALID_CREDENTIALS` — raised when a credential check (email/password)
|
|
49
|
+
* fails (AdonisJS parity). Status 400. Distinct from `E_UNAUTHORIZED_ACCESS`
|
|
50
|
+
* (a missing/invalid session or token on a protected route → 401).
|
|
51
|
+
*/
|
|
52
|
+
export class E_INVALID_CREDENTIALS extends WardenError {
|
|
53
|
+
constructor(message = "Invalid user credentials") {
|
|
54
|
+
super("E_INVALID_CREDENTIALS", message, { status: 400 });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
21
57
|
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,IAAI,CAAU;IACvB;;;;OAIG;IACM,MAAM,CAAU;IAEzB,YACC,IAAY,EACZ,OAAe,EACf,OAA4C;QAE5C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,IAAI,CAAU;IACvB;;;;OAIG;IACM,MAAM,CAAU;IAEzB,YACC,IAAY,EACZ,OAAe,EACf,OAA4C;QAE5C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,sEAAsE;QACtE,qEAAqE;QACrE,uEAAuE;QACvE,uEAAuE;QACvE,uEAAuE;QACvE,kEAAkE;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAC/B,CAAC;CACD;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IAC5C,UAAU,CAAU;IACpB,eAAe,CAAS;IAEjC,YACC,OAAe,EACf,OAAyD;QAEzD,KAAK,CAAC,uBAAuB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACtC,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACrD,YAAY,OAAO,GAAG,0BAA0B;QAC/C,KAAK,CAAC,uBAAuB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC;CACD"}
|