@spinajs/rbac-http-token 2.0.513 → 2.0.515
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/README.md +62 -6
- package/lib/cjs/actions.d.ts +43 -7
- package/lib/cjs/actions.d.ts.map +1 -1
- package/lib/cjs/actions.js +95 -16
- package/lib/cjs/actions.js.map +1 -1
- package/lib/cjs/cli/CreateToken.js +1 -1
- package/lib/cjs/cli/CreateToken.js.map +1 -1
- package/lib/cjs/cli/GrantTokenRole.js +1 -1
- package/lib/cjs/cli/GrantTokenRole.js.map +1 -1
- package/lib/cjs/config/rbac-http-token.d.ts +17 -0
- package/lib/cjs/config/rbac-http-token.d.ts.map +1 -1
- package/lib/cjs/config/rbac-http-token.js +17 -0
- package/lib/cjs/config/rbac-http-token.js.map +1 -1
- package/lib/cjs/controllers/AccessTokenController.d.ts +38 -5
- package/lib/cjs/controllers/AccessTokenController.d.ts.map +1 -1
- package/lib/cjs/controllers/AccessTokenController.js +60 -6
- package/lib/cjs/controllers/AccessTokenController.js.map +1 -1
- package/lib/cjs/dto/create-token-dto.d.ts +7 -0
- package/lib/cjs/dto/create-token-dto.d.ts.map +1 -1
- package/lib/cjs/dto/create-token-dto.js +7 -1
- package/lib/cjs/dto/create-token-dto.js.map +1 -1
- package/lib/cjs/index.d.ts +3 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +3 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +58 -0
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js +41 -1
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/middlewares.d.ts +5 -0
- package/lib/cjs/middlewares.d.ts.map +1 -1
- package/lib/cjs/middlewares.js +11 -1
- package/lib/cjs/middlewares.js.map +1 -1
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts +6 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js +24 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js.map +1 -0
- package/lib/cjs/models/AccessToken.d.ts +6 -0
- package/lib/cjs/models/AccessToken.d.ts.map +1 -1
- package/lib/cjs/models/AccessToken.js.map +1 -1
- package/lib/cjs/role-policy.d.ts +28 -0
- package/lib/cjs/role-policy.d.ts.map +1 -0
- package/lib/cjs/role-policy.js +52 -0
- package/lib/cjs/role-policy.js.map +1 -0
- package/lib/mjs/actions.d.ts +43 -7
- package/lib/mjs/actions.d.ts.map +1 -1
- package/lib/mjs/actions.js +94 -17
- package/lib/mjs/actions.js.map +1 -1
- package/lib/mjs/cli/CreateToken.js +1 -1
- package/lib/mjs/cli/CreateToken.js.map +1 -1
- package/lib/mjs/cli/GrantTokenRole.js +1 -1
- package/lib/mjs/cli/GrantTokenRole.js.map +1 -1
- package/lib/mjs/config/rbac-http-token.d.ts +17 -0
- package/lib/mjs/config/rbac-http-token.d.ts.map +1 -1
- package/lib/mjs/config/rbac-http-token.js +17 -0
- package/lib/mjs/config/rbac-http-token.js.map +1 -1
- package/lib/mjs/controllers/AccessTokenController.d.ts +38 -5
- package/lib/mjs/controllers/AccessTokenController.d.ts.map +1 -1
- package/lib/mjs/controllers/AccessTokenController.js +62 -8
- package/lib/mjs/controllers/AccessTokenController.js.map +1 -1
- package/lib/mjs/dto/create-token-dto.d.ts +7 -0
- package/lib/mjs/dto/create-token-dto.d.ts.map +1 -1
- package/lib/mjs/dto/create-token-dto.js +7 -1
- package/lib/mjs/dto/create-token-dto.js.map +1 -1
- package/lib/mjs/index.d.ts +3 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +3 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +58 -0
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js +39 -0
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/middlewares.d.ts +5 -0
- package/lib/mjs/middlewares.d.ts.map +1 -1
- package/lib/mjs/middlewares.js +11 -1
- package/lib/mjs/middlewares.js.map +1 -1
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts +6 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js +21 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js.map +1 -0
- package/lib/mjs/models/AccessToken.d.ts +6 -0
- package/lib/mjs/models/AccessToken.d.ts.map +1 -1
- package/lib/mjs/models/AccessToken.js.map +1 -1
- package/lib/mjs/role-policy.d.ts +28 -0
- package/lib/mjs/role-policy.d.ts.map +1 -0
- package/lib/mjs/role-policy.js +48 -0
- package/lib/mjs/role-policy.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +15 -15
|
@@ -60,6 +60,38 @@ const NoImpersonationPolicy_js_1 = require("../policies/NoImpersonationPolicy.js
|
|
|
60
60
|
* @tags AccessTokens
|
|
61
61
|
*/
|
|
62
62
|
let AccessTokenController = class AccessTokenController extends http_1.BaseController {
|
|
63
|
+
/**
|
|
64
|
+
* Roles that may be put on a new token
|
|
65
|
+
* Answers from the configured AccessTokenRolePolicy - the same source
|
|
66
|
+
* `POST user/tokens` validates against, so a client can never be offered a
|
|
67
|
+
* role the create call would then refuse.
|
|
68
|
+
*
|
|
69
|
+
* With `profile` given the answer is relative to that profile, which a policy
|
|
70
|
+
* may narrow below the owner-wide union - the picker must ask with the profile
|
|
71
|
+
* the user has selected, or it will keep offering roles the pinned create call
|
|
72
|
+
* then refuses. Without the param the answer is what this route always gave.
|
|
73
|
+
* @security cookieAuth
|
|
74
|
+
* @param profile Optional profile ( root role ) the roles are asked for
|
|
75
|
+
* @response 200 Roles the caller may put on a token
|
|
76
|
+
* @response 401 Unauthorized - valid session required
|
|
77
|
+
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
78
|
+
*/
|
|
79
|
+
async roles(user, profile) {
|
|
80
|
+
return new http_1.Ok({ Roles: await (0, actions_js_1._allowed_roles)(user, profile) });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Profiles the caller may pin a new token to
|
|
84
|
+
* Answers from the configured AccessTokenRolePolicy - the same source
|
|
85
|
+
* `POST user/tokens` validates `Profile` against. Empty for applications that
|
|
86
|
+
* did not opt into profile tokens: the shipped default policy offers none.
|
|
87
|
+
* @security cookieAuth
|
|
88
|
+
* @response 200 Profiles the caller may pin a token to
|
|
89
|
+
* @response 401 Unauthorized - valid session required
|
|
90
|
+
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
91
|
+
*/
|
|
92
|
+
async profiles(user) {
|
|
93
|
+
return new http_1.Ok({ Profiles: await (0, actions_js_1._allowed_profiles)(user) });
|
|
94
|
+
}
|
|
63
95
|
/**
|
|
64
96
|
* List own access tokens
|
|
65
97
|
* Hashes are never returned - `Token` is `@Hidden()` on the model, so the
|
|
@@ -76,17 +108,21 @@ let AccessTokenController = class AccessTokenController extends http_1.BaseContr
|
|
|
76
108
|
/**
|
|
77
109
|
* Create an access token
|
|
78
110
|
* The plaintext appears in this response only and cannot be retrieved again.
|
|
79
|
-
* Roles must be a subset of the
|
|
111
|
+
* Roles must be a subset of what the configured AccessTokenRolePolicy allows
|
|
112
|
+
* the caller - the same set `GET user/tokens/roles` reports. An optional
|
|
113
|
+
* `Profile` pins the token to one of the profiles `GET user/tokens/profiles`
|
|
114
|
+
* reports, and narrows the role check to that profile; omitted, the token is
|
|
115
|
+
* scoped by the union of its roles as before.
|
|
80
116
|
* @security cookieAuth
|
|
81
117
|
* @response 200 Token created, `Plaintext` returned once
|
|
82
|
-
* @response 400 Requested roles are not
|
|
118
|
+
* @response 400 Requested roles or profile are not allowed for the caller by the configured role policy
|
|
83
119
|
* @response 401 Unauthorized - valid session required
|
|
84
120
|
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
85
121
|
*/
|
|
86
122
|
async create(user, dto) {
|
|
87
123
|
const expiresAt = dto.ExpiresAt ? luxon_1.DateTime.fromISO(dto.ExpiresAt) : null;
|
|
88
124
|
try {
|
|
89
|
-
const { Token, Plaintext } = await (0, actions_js_1.createToken)(user, dto.Name, dto.Roles, expiresAt);
|
|
125
|
+
const { Token, Plaintext } = await (0, actions_js_1.createToken)(user, dto.Name, dto.Roles, expiresAt, dto.Profile);
|
|
90
126
|
return new http_1.Ok({ Token: this.toWire(Token), Plaintext }, { Headers: [{ Name: 'Cache-Control', Value: 'no-store' }] });
|
|
91
127
|
}
|
|
92
128
|
catch (err) {
|
|
@@ -112,13 +148,14 @@ let AccessTokenController = class AccessTokenController extends http_1.BaseContr
|
|
|
112
148
|
}
|
|
113
149
|
/**
|
|
114
150
|
* Grant a role to an own token
|
|
115
|
-
* The role must be
|
|
116
|
-
*
|
|
151
|
+
* The role must be allowed for the caller by the configured
|
|
152
|
+
* AccessTokenRolePolicy - a token can never carry more than the policy
|
|
153
|
+
* permits its owner.
|
|
117
154
|
* @security cookieAuth
|
|
118
155
|
* @param uuid Public identifier of the token
|
|
119
156
|
* @param role Role name to grant
|
|
120
157
|
* @response 200 Updated token
|
|
121
|
-
* @response 400 Role is not
|
|
158
|
+
* @response 400 Role is not allowed for the caller by the configured role policy
|
|
122
159
|
* @response 401 Unauthorized - valid session required
|
|
123
160
|
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
124
161
|
* @response 404 No such token for this user
|
|
@@ -210,6 +247,23 @@ let AccessTokenController = class AccessTokenController extends http_1.BaseContr
|
|
|
210
247
|
}
|
|
211
248
|
};
|
|
212
249
|
exports.AccessTokenController = AccessTokenController;
|
|
250
|
+
__decorate([
|
|
251
|
+
(0, http_1.Get)('tokens/roles'),
|
|
252
|
+
(0, rbac_http_1.Permission)(['readOwn']),
|
|
253
|
+
__param(0, (0, rbac_http_1.User)()),
|
|
254
|
+
__param(1, (0, http_1.Query)()),
|
|
255
|
+
__metadata("design:type", Function),
|
|
256
|
+
__metadata("design:paramtypes", [rbac_1.User, String]),
|
|
257
|
+
__metadata("design:returntype", Promise)
|
|
258
|
+
], AccessTokenController.prototype, "roles", null);
|
|
259
|
+
__decorate([
|
|
260
|
+
(0, http_1.Get)('tokens/profiles'),
|
|
261
|
+
(0, rbac_http_1.Permission)(['readOwn']),
|
|
262
|
+
__param(0, (0, rbac_http_1.User)()),
|
|
263
|
+
__metadata("design:type", Function),
|
|
264
|
+
__metadata("design:paramtypes", [rbac_1.User]),
|
|
265
|
+
__metadata("design:returntype", Promise)
|
|
266
|
+
], AccessTokenController.prototype, "profiles", null);
|
|
213
267
|
__decorate([
|
|
214
268
|
(0, http_1.Get)('tokens'),
|
|
215
269
|
(0, rbac_http_1.Permission)(['readOwn']),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessTokenController.js","sourceRoot":"","sources":["../../../src/controllers/AccessTokenController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"AccessTokenController.js","sourceRoot":"","sources":["../../../src/controllers/AccessTokenController.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,12 @@ export declare const CreateTokenDtoSchema: {
|
|
|
17
17
|
minItems: number;
|
|
18
18
|
description: string;
|
|
19
19
|
};
|
|
20
|
+
Profile: {
|
|
21
|
+
type: string;
|
|
22
|
+
minLength: number;
|
|
23
|
+
maxLength: number;
|
|
24
|
+
description: string;
|
|
25
|
+
};
|
|
20
26
|
ExpiresAt: {
|
|
21
27
|
type: string[];
|
|
22
28
|
format: string;
|
|
@@ -28,6 +34,7 @@ export declare const CreateTokenDtoSchema: {
|
|
|
28
34
|
export declare class CreateTokenDto {
|
|
29
35
|
Name: string;
|
|
30
36
|
Roles: string[];
|
|
37
|
+
Profile?: string;
|
|
31
38
|
ExpiresAt?: string | null;
|
|
32
39
|
constructor(data: any);
|
|
33
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-token-dto.d.ts","sourceRoot":"","sources":["../../../src/dto/create-token-dto.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB;IAC/B,OAAO;IACP,KAAK;IACL,IAAI;IACJ,UAAU;QACR,IAAI;YAAI,IAAI;YAAY,SAAS;YAAK,SAAS;YAAO,WAAW;;QACjE,KAAK;YAAI,IAAI;YAAW,KAAK;gBAAI,IAAI;;YAAc,QAAQ;YAAK,WAAW;;
|
|
1
|
+
{"version":3,"file":"create-token-dto.d.ts","sourceRoot":"","sources":["../../../src/dto/create-token-dto.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB;IAC/B,OAAO;IACP,KAAK;IACL,IAAI;IACJ,UAAU;QACR,IAAI;YAAI,IAAI;YAAY,SAAS;YAAK,SAAS;YAAO,WAAW;;QACjE,KAAK;YAAI,IAAI;YAAW,KAAK;gBAAI,IAAI;;YAAc,QAAQ;YAAK,WAAW;;QAM3E,OAAO;YAAI,IAAI;YAAY,SAAS;YAAK,SAAS;YAAO,WAAW;;QACpE,SAAS;YAAI,IAAI;YAAsB,MAAM;YAAe,WAAW;;;IAEzE,QAAQ;CACT,CAAC;AAEF,qBACa,cAAc;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC,YAAY,IAAI,EAAE,GAAG,EAEpB;CACF"}
|
|
@@ -17,7 +17,13 @@ exports.CreateTokenDtoSchema = {
|
|
|
17
17
|
type: 'object',
|
|
18
18
|
properties: {
|
|
19
19
|
Name: { type: 'string', minLength: 1, maxLength: 128, description: 'Human readable token label' },
|
|
20
|
-
Roles: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Roles allowed on the token, must be subset of
|
|
20
|
+
Roles: { type: 'array', items: { type: 'string' }, minItems: 1, description: 'Roles allowed on the token, must be subset of what the role policy allows' },
|
|
21
|
+
// `minLength: 1` is load bearing, not cosmetic: an empty string is falsy all
|
|
22
|
+
// the way down the actions layer, so `Profile: ''` would mint an UNPINNED
|
|
23
|
+
// token instead of a refused one - a silent widening of what the token may
|
|
24
|
+
// reach. Rejecting it here is what keeps "asked for a profile" and "pinned
|
|
25
|
+
// to a profile" the same statement.
|
|
26
|
+
Profile: { type: 'string', minLength: 1, maxLength: 128, description: 'Profile (root role) to pin the token to; omitted = legacy union-scoped token' },
|
|
21
27
|
ExpiresAt: { type: ['string', 'null'], format: 'date-time', description: 'ISO expiration instant; null or omitted = never expires' },
|
|
22
28
|
},
|
|
23
29
|
required: ['Name', 'Roles'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-token-dto.js","sourceRoot":"","sources":["../../../src/dto/create-token-dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA6C;AAEhC,QAAA,oBAAoB,GAAG;IAClC,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,yBAAyB;IAChC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,4BAA4B,EAAE;QACjG,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"create-token-dto.js","sourceRoot":"","sources":["../../../src/dto/create-token-dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA6C;AAEhC,QAAA,oBAAoB,GAAG;IAClC,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,yBAAyB;IAChC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,4BAA4B,EAAE;QACjG,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,2EAA2E,EAAE;QAC1J,6EAA6E;QAC7E,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,oCAAoC;QACpC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,8EAA8E,EAAE;QACtJ,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,yDAAyD,EAAE;KACrI;IACD,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;CAC5B,CAAC;AAGK,IAAM,cAAc,GAApB,MAAM,cAAc;IAMzB,YAAY,IAAS;QACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF,CAAA;;yBATY,cAAc;IAD1B,IAAA,mBAAM,EAAC,QAAA,oBAAoB,CAAC;;GAChB,cAAc,CAS1B"}
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import './generator.js';
|
|
2
|
+
import './role-policy.js';
|
|
2
3
|
import './middlewares.js';
|
|
3
4
|
export * from './interfaces.js';
|
|
4
5
|
export * from './models/AccessToken.js';
|
|
5
6
|
export * from './migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js';
|
|
7
|
+
export * from './migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js';
|
|
6
8
|
export * from './generator.js';
|
|
9
|
+
export * from './role-policy.js';
|
|
7
10
|
export * from './events/index.js';
|
|
8
11
|
export * from './actions.js';
|
|
9
12
|
export * from './middlewares.js';
|
package/lib/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,gBAAgB,CAAC;AACxB,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0DAA0D,CAAC;AACzE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,gBAAgB,CAAC;AACxB,OAAO,kBAAkB,CAAC;AAC1B,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0DAA0D,CAAC;AACzE,cAAc,0DAA0D,CAAC;AACzE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC"}
|
package/lib/cjs/index.js
CHANGED
|
@@ -18,11 +18,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
// generator and the token authorization middleware ) the moment they are
|
|
19
19
|
// loaded, so they must run even if a consumer imports nothing from them.
|
|
20
20
|
require("./generator.js");
|
|
21
|
+
require("./role-policy.js");
|
|
21
22
|
require("./middlewares.js");
|
|
22
23
|
__exportStar(require("./interfaces.js"), exports);
|
|
23
24
|
__exportStar(require("./models/AccessToken.js"), exports);
|
|
24
25
|
__exportStar(require("./migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js"), exports);
|
|
26
|
+
__exportStar(require("./migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js"), exports);
|
|
25
27
|
__exportStar(require("./generator.js"), exports);
|
|
28
|
+
__exportStar(require("./role-policy.js"), exports);
|
|
26
29
|
__exportStar(require("./events/index.js"), exports);
|
|
27
30
|
__exportStar(require("./actions.js"), exports);
|
|
28
31
|
__exportStar(require("./middlewares.js"), exports);
|
package/lib/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,0BAAwB;AACxB,4BAA0B;AAE1B,kDAAgC;AAChC,0DAAwC;AACxC,2FAAyE;AACzE,iDAA+B;AAC/B,oDAAkC;AAClC,+CAA6B;AAC7B,mDAAiC;AACjC,4DAA0C;AAC1C,kEAAgD;AAChD,sEAAoD;AACpD,yEAAuD;AACvD,4DAA0C;AAC1C,uDAAqC;AACrC,uDAAqC;AACrC,0DAAwC;AACxC,2DAAyC;AACzC,+DAA6C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,0BAAwB;AACxB,4BAA0B;AAC1B,4BAA0B;AAE1B,kDAAgC;AAChC,0DAAwC;AACxC,2FAAyE;AACzE,2FAAyE;AACzE,iDAA+B;AAC/B,mDAAiC;AACjC,oDAAkC;AAClC,+CAA6B;AAC7B,mDAAiC;AACjC,4DAA0C;AAC1C,kEAAgD;AAChD,sEAAoD;AACpD,yEAAuD;AACvD,4DAA0C;AAC1C,uDAAqC;AACrC,uDAAqC;AACrC,0DAAwC;AACxC,2DAAyC;AACzC,+DAA6C"}
|
package/lib/cjs/interfaces.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { User } from '@spinajs/rbac';
|
|
1
2
|
export interface IGeneratedToken {
|
|
2
3
|
/**
|
|
3
4
|
* Full token as handed to the user, e.g. `spt_<base64url>`. Shown exactly once.
|
|
@@ -31,6 +32,63 @@ export interface ITokenAuthInfo {
|
|
|
31
32
|
* Uuid of the AccessToken row - safe to log; never the token itself.
|
|
32
33
|
*/
|
|
33
34
|
Uuid: string;
|
|
35
|
+
/**
|
|
36
|
+
* The profile (a role name) this token is pinned to, when it carries one.
|
|
37
|
+
* Consumed by application row-scoping the way a session's ActiveRole is;
|
|
38
|
+
* permission checks do NOT read it - they stay on the narrowed User.Role.
|
|
39
|
+
*/
|
|
40
|
+
Profile?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Decides which roles a given owner may put on an access token.
|
|
44
|
+
*
|
|
45
|
+
* ONE method, FOUR call sites - `createToken`, `grantTokenRole`,
|
|
46
|
+
* `validateToken`, and the `GET user/tokens/roles` controller route (all
|
|
47
|
+
* through the shared `_allowed_roles` helper in `src/actions.ts`). That is
|
|
48
|
+
* deliberate: creation time and request time have to answer the same
|
|
49
|
+
* question, otherwise a role a user was allowed to pick could be one their
|
|
50
|
+
* token silently loses on the next request.
|
|
51
|
+
*
|
|
52
|
+
* `owner` is NOT hydrated the same way by every call site: `GET
|
|
53
|
+
* user/tokens/roles` and `createToken` (from `POST user/tokens`) are handed
|
|
54
|
+
* `req.storage.User` - the application's `User` subclass, with whatever
|
|
55
|
+
* request-pipeline hydration already ran - while `grantTokenRole` and
|
|
56
|
+
* `validateToken` are handed a base `User` with only `Metadata` populated
|
|
57
|
+
* ( `_owner()` / a direct `User.where(...)` lookup, deliberately unscoped by
|
|
58
|
+
* any application model override - see `_owner()`'s comments in
|
|
59
|
+
* `src/actions.ts` ). A correct implementation MUST NOT rely on anything
|
|
60
|
+
* beyond the base `User` model plus `Metadata` being present on `owner` -
|
|
61
|
+
* that is the only shape all four call sites agree on. Any
|
|
62
|
+
* application-specific field a policy reads may be populated on a
|
|
63
|
+
* session-authenticated call and absent on a token-authenticated one,
|
|
64
|
+
* answering the identical question two different ways.
|
|
65
|
+
*
|
|
66
|
+
* Replaceable via config `rbac.token.rolePolicy.service`, the same pattern
|
|
67
|
+
* `rbac.token.generation.service` uses for the token generator. The shipped
|
|
68
|
+
* default ( `OwnRolesTokenRolePolicy` ) answers with the owner's own roles,
|
|
69
|
+
* which is the behaviour this package had before the seam existed.
|
|
70
|
+
*/
|
|
71
|
+
export declare abstract class AccessTokenRolePolicy {
|
|
72
|
+
/**
|
|
73
|
+
* Roles `owner` may carry on a token. Also the set every one of their
|
|
74
|
+
* existing tokens is re-intersected with on each authenticated request, so a
|
|
75
|
+
* role dropped from this answer stops authorising immediately.
|
|
76
|
+
*
|
|
77
|
+
* With `profile` set the answer is relative to that profile - an application
|
|
78
|
+
* policy may (and should) narrow it to roles the profile's own grants cover.
|
|
79
|
+
* The shipped default ignores the argument.
|
|
80
|
+
*
|
|
81
|
+
* @param owner - at minimum a base `User` with `Metadata` populated; see the
|
|
82
|
+
* class docblock above for why nothing more may be assumed.
|
|
83
|
+
* @param profile - the profile the token is (or will be) pinned to
|
|
84
|
+
*/
|
|
85
|
+
abstract allowedRoles(owner: User, profile?: string): Promise<string[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Profiles `owner` may pin a token to. A profile plays the row-scoping part
|
|
88
|
+
* a session's ActiveRole plays - see `ITokenAuthInfo.Profile`. Default: none;
|
|
89
|
+
* an application that wants profile tokens overrides this in its policy.
|
|
90
|
+
*/
|
|
91
|
+
allowedProfiles(_owner: User): Promise<string[]>;
|
|
34
92
|
}
|
|
35
93
|
declare module '@spinajs/rbac' {
|
|
36
94
|
interface IRbacAsyncStorage {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAO1C,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,8BAAsB,6BAA6B;IACjD;;OAEG;IACH,SAAgB,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAErD;;OAEG;IACH,SAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,8BAAsB,qBAAqB;IACzC;;;;;;;;;;;;OAYG;IACH,SAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE/E;;;;OAIG;IACU,eAAe,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE5D;CACF;AAED,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,iBAAiB;QACzB;;WAEG;QACH,SAAS,CAAC,EAAE,cAAc,CAAC;KAC5B;CACF;AAED;;;;;GAKG;AACH,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,0BAA0B;QAClC;;WAEG;QACH,SAAS,CAAC,EAAE,cAAc,CAAC;KAC5B;CACF"}
|
package/lib/cjs/interfaces.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AccessTokenGenerationProvider = void 0;
|
|
3
|
+
exports.AccessTokenRolePolicy = exports.AccessTokenGenerationProvider = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Token generation algorithm. Replaceable via config
|
|
6
6
|
* `rbac.token.generation.service` - same pattern as `rbac.password.service`.
|
|
@@ -8,4 +8,44 @@ exports.AccessTokenGenerationProvider = void 0;
|
|
|
8
8
|
class AccessTokenGenerationProvider {
|
|
9
9
|
}
|
|
10
10
|
exports.AccessTokenGenerationProvider = AccessTokenGenerationProvider;
|
|
11
|
+
/**
|
|
12
|
+
* Decides which roles a given owner may put on an access token.
|
|
13
|
+
*
|
|
14
|
+
* ONE method, FOUR call sites - `createToken`, `grantTokenRole`,
|
|
15
|
+
* `validateToken`, and the `GET user/tokens/roles` controller route (all
|
|
16
|
+
* through the shared `_allowed_roles` helper in `src/actions.ts`). That is
|
|
17
|
+
* deliberate: creation time and request time have to answer the same
|
|
18
|
+
* question, otherwise a role a user was allowed to pick could be one their
|
|
19
|
+
* token silently loses on the next request.
|
|
20
|
+
*
|
|
21
|
+
* `owner` is NOT hydrated the same way by every call site: `GET
|
|
22
|
+
* user/tokens/roles` and `createToken` (from `POST user/tokens`) are handed
|
|
23
|
+
* `req.storage.User` - the application's `User` subclass, with whatever
|
|
24
|
+
* request-pipeline hydration already ran - while `grantTokenRole` and
|
|
25
|
+
* `validateToken` are handed a base `User` with only `Metadata` populated
|
|
26
|
+
* ( `_owner()` / a direct `User.where(...)` lookup, deliberately unscoped by
|
|
27
|
+
* any application model override - see `_owner()`'s comments in
|
|
28
|
+
* `src/actions.ts` ). A correct implementation MUST NOT rely on anything
|
|
29
|
+
* beyond the base `User` model plus `Metadata` being present on `owner` -
|
|
30
|
+
* that is the only shape all four call sites agree on. Any
|
|
31
|
+
* application-specific field a policy reads may be populated on a
|
|
32
|
+
* session-authenticated call and absent on a token-authenticated one,
|
|
33
|
+
* answering the identical question two different ways.
|
|
34
|
+
*
|
|
35
|
+
* Replaceable via config `rbac.token.rolePolicy.service`, the same pattern
|
|
36
|
+
* `rbac.token.generation.service` uses for the token generator. The shipped
|
|
37
|
+
* default ( `OwnRolesTokenRolePolicy` ) answers with the owner's own roles,
|
|
38
|
+
* which is the behaviour this package had before the seam existed.
|
|
39
|
+
*/
|
|
40
|
+
class AccessTokenRolePolicy {
|
|
41
|
+
/**
|
|
42
|
+
* Profiles `owner` may pin a token to. A profile plays the row-scoping part
|
|
43
|
+
* a session's ActiveRole plays - see `ITokenAuthInfo.Profile`. Default: none;
|
|
44
|
+
* an application that wants profile tokens overrides this in its policy.
|
|
45
|
+
*/
|
|
46
|
+
async allowedProfiles(_owner) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.AccessTokenRolePolicy = AccessTokenRolePolicy;
|
|
11
51
|
//# sourceMappingURL=interfaces.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":";;;AAsBA;;;GAGG;AACH;CAUC"}
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":";;;AAsBA;;;GAGG;AACH;CAUC;;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;IAgBE;;;;OAIG;IACI,KAAK,CAAC,eAAe,CAAC,MAAY;QACvC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}
|
package/lib/cjs/middlewares.d.ts
CHANGED
|
@@ -35,6 +35,11 @@ import './interfaces.js';
|
|
|
35
35
|
* runs first and, on a session-less request, stamps the GUEST account's first
|
|
36
36
|
* role into it, which would otherwise survive into the token's own request.
|
|
37
37
|
*
|
|
38
|
+
* A token's profile is therefore published on `req.storage.TokenAuth.Profile`
|
|
39
|
+
* instead, for the application's row-scoping layer to read; it is deliberately
|
|
40
|
+
* NOT written to `ActiveRole`, so it scopes rows without narrowing what the
|
|
41
|
+
* token is authorized for.
|
|
42
|
+
*
|
|
38
43
|
* Never throws: an invalid token leaves the request as guest and lets the
|
|
39
44
|
* route's policy produce the rejection.
|
|
40
45
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC,OAAO,iBAAiB,CAAC;AAQzB
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC,OAAO,iBAAiB,CAAC;AAQzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBACa,mBAAoB,SAAQ,gBAAgB;IAEvD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAG7B,SAAS,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAEzC,cAIC;IAEM,MAAM,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI,CAuD1F;IAEM,KAAK,IAAI,IAAI,CAEnB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CASvD;IAED;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAgB9C;CACF"}
|
package/lib/cjs/middlewares.js
CHANGED
|
@@ -54,6 +54,11 @@ const BEARER_SCHEME = /^bearer\s+/i;
|
|
|
54
54
|
* runs first and, on a session-less request, stamps the GUEST account's first
|
|
55
55
|
* role into it, which would otherwise survive into the token's own request.
|
|
56
56
|
*
|
|
57
|
+
* A token's profile is therefore published on `req.storage.TokenAuth.Profile`
|
|
58
|
+
* instead, for the application's row-scoping layer to read; it is deliberately
|
|
59
|
+
* NOT written to `ActiveRole`, so it scopes rows without narrowing what the
|
|
60
|
+
* token is authorized for.
|
|
61
|
+
*
|
|
57
62
|
* Never throws: an invalid token leaves the request as guest and lets the
|
|
58
63
|
* route's policy produce the rejection.
|
|
59
64
|
*/
|
|
@@ -89,7 +94,12 @@ let TokenAuthMiddleware = class TokenAuthMiddleware extends http_1.ServerMiddlew
|
|
|
89
94
|
return next();
|
|
90
95
|
}
|
|
91
96
|
req.storage.User = this.narrowRoles(result.User, result.EffectiveRoles);
|
|
92
|
-
|
|
97
|
+
// `?? undefined` is not cosmetic: an unpinned token stores NULL and the
|
|
98
|
+
// orm reads it back as `null`, while `ITokenAuthInfo.Profile` is
|
|
99
|
+
// `string | undefined`. Passing the `null` through would make every
|
|
100
|
+
// `Profile === undefined` check downstream answer false on exactly the
|
|
101
|
+
// legacy tokens it is meant to recognise.
|
|
102
|
+
req.storage.TokenAuth = { Uuid: result.Token.Uuid, Profile: result.Token.Profile ?? undefined };
|
|
93
103
|
// CLEARED, not merely left alone - see the class docblock for why a
|
|
94
104
|
// token must carry no active role at all. `RbacMiddleware` has already
|
|
95
105
|
// run by now and, finding no session, wrote the GUEST user's first role
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,oCAAyC;AACzC,0DAAgD;AAChD,sCAA2C;AAC3C,wCAAsE;AACtE,oDAAgD;AAGhD,6CAAyD;AACzD,2BAAyB;AAEzB;;;GAGG;AACH,MAAM,aAAa,GAAG,aAAa,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { OrmMigration, OrmDriver } from '@spinajs/orm';
|
|
2
|
+
export declare class RbacHttpTokenProfile_2026_08_21_00_00_00 extends OrmMigration {
|
|
3
|
+
up(connection: OrmDriver): Promise<void>;
|
|
4
|
+
down(connection: OrmDriver): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts","sourceRoot":"","sources":["../../../src/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAuB,MAAM,cAAc,CAAC;AAE5E,qBACa,wCAAyC,SAAQ,YAAY;IAC3D,EAAE,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpD;IAEY,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtD;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RbacHttpTokenProfile_2026_08_21_00_00_00 = void 0;
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
11
|
+
const orm_1 = require("@spinajs/orm");
|
|
12
|
+
let RbacHttpTokenProfile_2026_08_21_00_00_00 = class RbacHttpTokenProfile_2026_08_21_00_00_00 extends orm_1.OrmMigration {
|
|
13
|
+
async up(connection) {
|
|
14
|
+
await connection.schema().raw(new orm_1.RawQuery('ALTER TABLE rbac_access_tokens ADD COLUMN Profile VARCHAR(128) NULL'));
|
|
15
|
+
}
|
|
16
|
+
async down(connection) {
|
|
17
|
+
await connection.schema().raw(new orm_1.RawQuery('ALTER TABLE rbac_access_tokens DROP COLUMN Profile'));
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
exports.RbacHttpTokenProfile_2026_08_21_00_00_00 = RbacHttpTokenProfile_2026_08_21_00_00_00;
|
|
21
|
+
exports.RbacHttpTokenProfile_2026_08_21_00_00_00 = RbacHttpTokenProfile_2026_08_21_00_00_00 = __decorate([
|
|
22
|
+
(0, orm_1.Migration)('default')
|
|
23
|
+
], RbacHttpTokenProfile_2026_08_21_00_00_00);
|
|
24
|
+
//# sourceMappingURL=RbacHttpTokenProfile_2026_08_21_00_00_00.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RbacHttpTokenProfile_2026_08_21_00_00_00.js","sourceRoot":"","sources":["../../../src/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.ts"],"names":[],"mappings":";;;;;;;;;AAAA,sDAAsD;AACtD,sCAA4E;AAGrE,IAAM,wCAAwC,GAA9C,MAAM,wCAAyC,SAAQ,kBAAY;IACjE,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,cAAQ,CAAC,qEAAqE,CAAC,CAAC,CAAC;IACrH,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,UAAqB;QACrC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,cAAQ,CAAC,oDAAoD,CAAC,CAAC,CAAC;IACpG,CAAC;CACF,CAAA;;mDARY,wCAAwC;IADpD,IAAA,eAAS,EAAC,SAAS,CAAC;GACR,wCAAwC,CAQpD"}
|
|
@@ -29,6 +29,12 @@ export declare class AccessToken extends ModelBase<AccessToken> {
|
|
|
29
29
|
* intersection of this list with the owner's current roles.
|
|
30
30
|
*/
|
|
31
31
|
Roles: string[];
|
|
32
|
+
/**
|
|
33
|
+
* The profile (a role name) this token is pinned to; null/undefined = legacy
|
|
34
|
+
* token, scoped by the union of its roles. Validated against
|
|
35
|
+
* `AccessTokenRolePolicy.allowedProfiles` at creation and on every request.
|
|
36
|
+
*/
|
|
37
|
+
Profile?: string;
|
|
32
38
|
/**
|
|
33
39
|
* Absolute expiration. Null/absent = never expires.
|
|
34
40
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessToken.d.ts","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,SAAS,EAAgB,cAAc,EAAE,MAAM,cAAc,CAAC;AACxI,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjC;;;GAGG;AACH,qBAEa,WAAY,SAAQ,SAAS,CAAC,WAAW,CAAC;IACrD,YAAmB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAG7C;IAED;;OAEG;IAGI,EAAE,EAAG,MAAM,CAAC;IAEnB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;;OAGG;IAEI,KAAK,EAAG,MAAM,CAAC;IAEtB;;;OAGG;IAEI,KAAK,EAAG,MAAM,EAAE,CAAC;IAExB;;;;;;;OAOG;IAEI,SAAS,CAAC,EAAE,QAAQ,CAAC;IAGrB,SAAS,EAAG,QAAQ,CAAC;IAE5B;;;;OAIG;IAEI,UAAU,CAAC,EAAE,QAAQ,CAAC;IAItB,IAAI,EAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAG5B,OAAO,EAAG,MAAM,CAAC;IAExB;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;CACF"}
|
|
1
|
+
{"version":3,"file":"AccessToken.d.ts","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,SAAS,EAAgB,cAAc,EAAE,MAAM,cAAc,CAAC;AACxI,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjC;;;GAGG;AACH,qBAEa,WAAY,SAAQ,SAAS,CAAC,WAAW,CAAC;IACrD,YAAmB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAG7C;IAED;;OAEG;IAGI,EAAE,EAAG,MAAM,CAAC;IAEnB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;;OAGG;IAEI,KAAK,EAAG,MAAM,CAAC;IAEtB;;;OAGG;IAEI,KAAK,EAAG,MAAM,EAAE,CAAC;IAExB;;;;OAIG;IACI,OAAO,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;OAOG;IAEI,SAAS,CAAC,EAAE,QAAQ,CAAC;IAGrB,SAAS,EAAG,QAAQ,CAAC;IAE5B;;;;OAIG;IAEI,UAAU,CAAC,EAAE,QAAQ,CAAC;IAItB,IAAI,EAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAG5B,OAAO,EAAG,MAAM,CAAC;IAExB;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessToken.js","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAAwI;AAExI,iCAAiC;AACjC,+BAAoC;AACpC,wCAAqD;AAErD;;;GAGG;AAGI,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,eAAsB;IACrD,YAAmB,IAA2B;QAC5C,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,IAAA,iBAAU,EAAC,IAAA,eAAQ,EAAC,IAAA,SAAM,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChE,CAAC;
|
|
1
|
+
{"version":3,"file":"AccessToken.js","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAAwI;AAExI,iCAAiC;AACjC,+BAAoC;AACpC,wCAAqD;AAErD;;;GAGG;AAGI,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,eAAsB;IACrD,YAAmB,IAA2B;QAC5C,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,IAAA,iBAAU,EAAC,IAAA,eAAQ,EAAC,IAAA,SAAM,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChE,CAAC;IAqED;;OAEG;IACH,IAAW,SAAS;QAClB,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAI,gBAAQ,CAAC,GAAG,EAAE,CAAC;IAC9D,CAAC;CACF,CAAA;;AApEQ;IAFN,IAAA,aAAO,GAAE;IACT,IAAA,YAAM,GAAE;;uCACU;AAiBZ;IADN,IAAA,YAAM,GAAE;;0CACa;AAOf;IADN,IAAA,SAAG,GAAE;;0CACkB;AAkBjB;IADN,IAAA,cAAE,GAAE;8BACc,gBAAQ;8CAAC;AAGrB;IADN,IAAA,eAAS,GAAE;8BACO,gBAAQ;8CAAC;AAQrB;IADN,IAAA,cAAE,GAAE;8BACe,gBAAQ;+CAAC;AAItB;IAFN,IAAA,YAAM,GAAE;IACR,IAAA,eAAS,EAAC,MAAM,CAAC;8BACJ,oBAAc;yCAAO;AAG5B;IADN,IAAA,YAAM,GAAE;;4CACe;sBAvEb,WAAW;IAFvB,IAAA,gBAAU,EAAC,SAAS,CAAC;IACrB,IAAA,WAAK,EAAC,oBAAoB,CAAC;;GACf,WAAW,CA+EvB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { User } from '@spinajs/rbac';
|
|
2
|
+
import { AccessTokenRolePolicy } from './interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* The behaviour this package shipped before the policy seam: a token may carry
|
|
5
|
+
* only roles its owner literally holds in `users.Role`.
|
|
6
|
+
*
|
|
7
|
+
* Safe by construction and needs no access-control lookup, which is why it
|
|
8
|
+
* stays the default - an application that wants finer scopes opts in by
|
|
9
|
+
* registering its own implementation under `rbac.token.rolePolicy.service`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class OwnRolesTokenRolePolicy extends AccessTokenRolePolicy {
|
|
12
|
+
allowedRoles(owner: User, _profile?: string): Promise<string[]>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Whether `role` matches any entry of `patterns`.
|
|
16
|
+
*
|
|
17
|
+
* A pattern is either an exact role name, or a name ending in `.*` which
|
|
18
|
+
* matches that prefix and everything beneath it - `route.*` covers `route.home`
|
|
19
|
+
* and `route.admin.users`, but not `routes.read`: the dot is part of the
|
|
20
|
+
* boundary, so a pattern can never swallow an unrelated role that merely starts
|
|
21
|
+
* with the same letters. No other wildcard syntax, on purpose - a full glob in
|
|
22
|
+
* a security list invites patterns nobody can reason about.
|
|
23
|
+
*
|
|
24
|
+
* @param role - role name to test
|
|
25
|
+
* @param patterns - exclusion patterns, typically from `rbac.token.excludedRoles`
|
|
26
|
+
*/
|
|
27
|
+
export declare function _role_excluded(role: string, patterns: string[]): boolean;
|
|
28
|
+
//# sourceMappingURL=role-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-policy.d.ts","sourceRoot":"","sources":["../../src/role-policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD;;;;;;;GAOG;AACH,qBACa,uBAAwB,SAAQ,qBAAqB;IACnD,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE3E;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CASxE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.OwnRolesTokenRolePolicy = void 0;
|
|
10
|
+
exports._role_excluded = _role_excluded;
|
|
11
|
+
const di_1 = require("@spinajs/di");
|
|
12
|
+
const interfaces_js_1 = require("./interfaces.js");
|
|
13
|
+
/**
|
|
14
|
+
* The behaviour this package shipped before the policy seam: a token may carry
|
|
15
|
+
* only roles its owner literally holds in `users.Role`.
|
|
16
|
+
*
|
|
17
|
+
* Safe by construction and needs no access-control lookup, which is why it
|
|
18
|
+
* stays the default - an application that wants finer scopes opts in by
|
|
19
|
+
* registering its own implementation under `rbac.token.rolePolicy.service`.
|
|
20
|
+
*/
|
|
21
|
+
let OwnRolesTokenRolePolicy = class OwnRolesTokenRolePolicy extends interfaces_js_1.AccessTokenRolePolicy {
|
|
22
|
+
async allowedRoles(owner, _profile) {
|
|
23
|
+
return [...owner.Role];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.OwnRolesTokenRolePolicy = OwnRolesTokenRolePolicy;
|
|
27
|
+
exports.OwnRolesTokenRolePolicy = OwnRolesTokenRolePolicy = __decorate([
|
|
28
|
+
(0, di_1.Injectable)(interfaces_js_1.AccessTokenRolePolicy)
|
|
29
|
+
], OwnRolesTokenRolePolicy);
|
|
30
|
+
/**
|
|
31
|
+
* Whether `role` matches any entry of `patterns`.
|
|
32
|
+
*
|
|
33
|
+
* A pattern is either an exact role name, or a name ending in `.*` which
|
|
34
|
+
* matches that prefix and everything beneath it - `route.*` covers `route.home`
|
|
35
|
+
* and `route.admin.users`, but not `routes.read`: the dot is part of the
|
|
36
|
+
* boundary, so a pattern can never swallow an unrelated role that merely starts
|
|
37
|
+
* with the same letters. No other wildcard syntax, on purpose - a full glob in
|
|
38
|
+
* a security list invites patterns nobody can reason about.
|
|
39
|
+
*
|
|
40
|
+
* @param role - role name to test
|
|
41
|
+
* @param patterns - exclusion patterns, typically from `rbac.token.excludedRoles`
|
|
42
|
+
*/
|
|
43
|
+
function _role_excluded(role, patterns) {
|
|
44
|
+
return patterns.some((pattern) => {
|
|
45
|
+
if (pattern.endsWith('.*')) {
|
|
46
|
+
const prefix = pattern.slice(0, -1); // keeps the trailing dot
|
|
47
|
+
return role.startsWith(prefix);
|
|
48
|
+
}
|
|
49
|
+
return role === pattern;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=role-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-policy.js","sourceRoot":"","sources":["../../src/role-policy.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,oCAAyC;AAGzC,mDAAwD;AAExD;;;;;;;GAOG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,qCAAqB;IACzD,KAAK,CAAC,YAAY,CAAC,KAAW,EAAE,QAAiB;QACtD,OAAO,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;CACF,CAAA;;kCAJY,uBAAuB;IADnC,IAAA,eAAU,EAAC,qCAAqB,CAAC;GACrB,uBAAuB,CAInC;AAED;;;;;;;;;;;;GAYG;AACH,wBAA+B,IAAY,EAAE,QAAkB;IAC7D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAC/B,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB;YAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,IAAI,KAAK,OAAO,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
|