@spinajs/rbac-http-token 2.0.507
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 +152 -0
- package/lib/cjs/actions.d.ts +119 -0
- package/lib/cjs/actions.d.ts.map +1 -0
- package/lib/cjs/actions.js +257 -0
- package/lib/cjs/actions.js.map +1 -0
- package/lib/cjs/cli/CreateToken.d.ts +13 -0
- package/lib/cjs/cli/CreateToken.d.ts.map +1 -0
- package/lib/cjs/cli/CreateToken.js +56 -0
- package/lib/cjs/cli/CreateToken.js.map +1 -0
- package/lib/cjs/cli/DeleteExpiredTokens.d.ts +11 -0
- package/lib/cjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
- package/lib/cjs/cli/DeleteExpiredTokens.js +39 -0
- package/lib/cjs/cli/DeleteExpiredTokens.js.map +1 -0
- package/lib/cjs/cli/DeleteToken.d.ts +7 -0
- package/lib/cjs/cli/DeleteToken.d.ts.map +1 -0
- package/lib/cjs/cli/DeleteToken.js +36 -0
- package/lib/cjs/cli/DeleteToken.js.map +1 -0
- package/lib/cjs/cli/GrantTokenRole.d.ts +7 -0
- package/lib/cjs/cli/GrantTokenRole.d.ts.map +1 -0
- package/lib/cjs/cli/GrantTokenRole.js +37 -0
- package/lib/cjs/cli/GrantTokenRole.js.map +1 -0
- package/lib/cjs/cli/RevokeTokenRole.d.ts +12 -0
- package/lib/cjs/cli/RevokeTokenRole.d.ts.map +1 -0
- package/lib/cjs/cli/RevokeTokenRole.js +42 -0
- package/lib/cjs/cli/RevokeTokenRole.js.map +1 -0
- package/lib/cjs/config/rbac-http-token.d.ts +71 -0
- package/lib/cjs/config/rbac-http-token.d.ts.map +1 -0
- package/lib/cjs/config/rbac-http-token.js +98 -0
- package/lib/cjs/config/rbac-http-token.js.map +1 -0
- package/lib/cjs/controllers/AccessTokenController.d.ts +139 -0
- package/lib/cjs/controllers/AccessTokenController.d.ts.map +1 -0
- package/lib/cjs/controllers/AccessTokenController.js +264 -0
- package/lib/cjs/controllers/AccessTokenController.js.map +1 -0
- package/lib/cjs/dto/create-token-dto.d.ts +34 -0
- package/lib/cjs/dto/create-token-dto.d.ts.map +1 -0
- package/lib/cjs/dto/create-token-dto.js +35 -0
- package/lib/cjs/dto/create-token-dto.js.map +1 -0
- package/lib/cjs/events/AccessTokenCreated.d.ts +4 -0
- package/lib/cjs/events/AccessTokenCreated.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenCreated.js +18 -0
- package/lib/cjs/events/AccessTokenCreated.js.map +1 -0
- package/lib/cjs/events/AccessTokenDeleted.d.ts +4 -0
- package/lib/cjs/events/AccessTokenDeleted.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenDeleted.js +18 -0
- package/lib/cjs/events/AccessTokenDeleted.js.map +1 -0
- package/lib/cjs/events/AccessTokenEvent.d.ts +10 -0
- package/lib/cjs/events/AccessTokenEvent.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenEvent.js +26 -0
- package/lib/cjs/events/AccessTokenEvent.js.map +1 -0
- package/lib/cjs/events/AccessTokenRoleGranted.d.ts +7 -0
- package/lib/cjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenRoleGranted.js +27 -0
- package/lib/cjs/events/AccessTokenRoleGranted.js.map +1 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.d.ts +7 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.js +27 -0
- package/lib/cjs/events/AccessTokenRoleRevoked.js.map +1 -0
- package/lib/cjs/events/index.d.ts +6 -0
- package/lib/cjs/events/index.d.ts.map +1 -0
- package/lib/cjs/events/index.js +22 -0
- package/lib/cjs/events/index.js.map +1 -0
- package/lib/cjs/generator.d.ts +12 -0
- package/lib/cjs/generator.d.ts.map +1 -0
- package/lib/cjs/generator.js +42 -0
- package/lib/cjs/generator.js.map +1 -0
- package/lib/cjs/index.d.ts +20 -0
- package/lib/cjs/index.d.ts.map +1 -0
- package/lib/cjs/index.js +39 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/interfaces.d.ts +57 -0
- package/lib/cjs/interfaces.d.ts.map +1 -0
- package/lib/cjs/interfaces.js +11 -0
- package/lib/cjs/interfaces.js.map +1 -0
- package/lib/cjs/middlewares.d.ts +76 -0
- package/lib/cjs/middlewares.d.ts.map +1 -0
- package/lib/cjs/middlewares.js +181 -0
- package/lib/cjs/middlewares.js.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +38 -0
- package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
- package/lib/cjs/models/AccessToken.d.ts +55 -0
- package/lib/cjs/models/AccessToken.d.ts.map +1 -0
- package/lib/cjs/models/AccessToken.js +73 -0
- package/lib/cjs/models/AccessToken.js.map +1 -0
- package/lib/cjs/package.json +1 -0
- package/lib/cjs/policies/NoImpersonationPolicy.d.ts +28 -0
- package/lib/cjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/NoImpersonationPolicy.js +45 -0
- package/lib/cjs/policies/NoImpersonationPolicy.js.map +1 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.d.ts +12 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.js +24 -0
- package/lib/cjs/policies/NoTokenAuthPolicy.js.map +1 -0
- package/lib/cjs/policies/TokenPolicy.d.ts +49 -0
- package/lib/cjs/policies/TokenPolicy.d.ts.map +1 -0
- package/lib/cjs/policies/TokenPolicy.js +79 -0
- package/lib/cjs/policies/TokenPolicy.js.map +1 -0
- package/lib/mjs/actions.d.ts +119 -0
- package/lib/mjs/actions.d.ts.map +1 -0
- package/lib/mjs/actions.js +242 -0
- package/lib/mjs/actions.js.map +1 -0
- package/lib/mjs/cli/CreateToken.d.ts +13 -0
- package/lib/mjs/cli/CreateToken.d.ts.map +1 -0
- package/lib/mjs/cli/CreateToken.js +53 -0
- package/lib/mjs/cli/CreateToken.js.map +1 -0
- package/lib/mjs/cli/DeleteExpiredTokens.d.ts +11 -0
- package/lib/mjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
- package/lib/mjs/cli/DeleteExpiredTokens.js +36 -0
- package/lib/mjs/cli/DeleteExpiredTokens.js.map +1 -0
- package/lib/mjs/cli/DeleteToken.d.ts +7 -0
- package/lib/mjs/cli/DeleteToken.d.ts.map +1 -0
- package/lib/mjs/cli/DeleteToken.js +33 -0
- package/lib/mjs/cli/DeleteToken.js.map +1 -0
- package/lib/mjs/cli/GrantTokenRole.d.ts +7 -0
- package/lib/mjs/cli/GrantTokenRole.d.ts.map +1 -0
- package/lib/mjs/cli/GrantTokenRole.js +34 -0
- package/lib/mjs/cli/GrantTokenRole.js.map +1 -0
- package/lib/mjs/cli/RevokeTokenRole.d.ts +12 -0
- package/lib/mjs/cli/RevokeTokenRole.d.ts.map +1 -0
- package/lib/mjs/cli/RevokeTokenRole.js +39 -0
- package/lib/mjs/cli/RevokeTokenRole.js.map +1 -0
- package/lib/mjs/config/rbac-http-token.d.ts +71 -0
- package/lib/mjs/config/rbac-http-token.d.ts.map +1 -0
- package/lib/mjs/config/rbac-http-token.js +96 -0
- package/lib/mjs/config/rbac-http-token.js.map +1 -0
- package/lib/mjs/controllers/AccessTokenController.d.ts +139 -0
- package/lib/mjs/controllers/AccessTokenController.d.ts.map +1 -0
- package/lib/mjs/controllers/AccessTokenController.js +261 -0
- package/lib/mjs/controllers/AccessTokenController.js.map +1 -0
- package/lib/mjs/dto/create-token-dto.d.ts +34 -0
- package/lib/mjs/dto/create-token-dto.d.ts.map +1 -0
- package/lib/mjs/dto/create-token-dto.js +32 -0
- package/lib/mjs/dto/create-token-dto.js.map +1 -0
- package/lib/mjs/events/AccessTokenCreated.d.ts +4 -0
- package/lib/mjs/events/AccessTokenCreated.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenCreated.js +15 -0
- package/lib/mjs/events/AccessTokenCreated.js.map +1 -0
- package/lib/mjs/events/AccessTokenDeleted.d.ts +4 -0
- package/lib/mjs/events/AccessTokenDeleted.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenDeleted.js +15 -0
- package/lib/mjs/events/AccessTokenDeleted.js.map +1 -0
- package/lib/mjs/events/AccessTokenEvent.d.ts +10 -0
- package/lib/mjs/events/AccessTokenEvent.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenEvent.js +23 -0
- package/lib/mjs/events/AccessTokenEvent.js.map +1 -0
- package/lib/mjs/events/AccessTokenRoleGranted.d.ts +7 -0
- package/lib/mjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenRoleGranted.js +24 -0
- package/lib/mjs/events/AccessTokenRoleGranted.js.map +1 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.d.ts +7 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.js +24 -0
- package/lib/mjs/events/AccessTokenRoleRevoked.js.map +1 -0
- package/lib/mjs/events/index.d.ts +6 -0
- package/lib/mjs/events/index.d.ts.map +1 -0
- package/lib/mjs/events/index.js +6 -0
- package/lib/mjs/events/index.js.map +1 -0
- package/lib/mjs/generator.d.ts +12 -0
- package/lib/mjs/generator.d.ts.map +1 -0
- package/lib/mjs/generator.js +39 -0
- package/lib/mjs/generator.js.map +1 -0
- package/lib/mjs/index.d.ts +20 -0
- package/lib/mjs/index.d.ts.map +1 -0
- package/lib/mjs/index.js +23 -0
- package/lib/mjs/index.js.map +1 -0
- package/lib/mjs/interfaces.d.ts +57 -0
- package/lib/mjs/interfaces.d.ts.map +1 -0
- package/lib/mjs/interfaces.js +7 -0
- package/lib/mjs/interfaces.js.map +1 -0
- package/lib/mjs/middlewares.d.ts +76 -0
- package/lib/mjs/middlewares.d.ts.map +1 -0
- package/lib/mjs/middlewares.js +178 -0
- package/lib/mjs/middlewares.js.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +35 -0
- package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
- package/lib/mjs/models/AccessToken.d.ts +55 -0
- package/lib/mjs/models/AccessToken.d.ts.map +1 -0
- package/lib/mjs/models/AccessToken.js +70 -0
- package/lib/mjs/models/AccessToken.js.map +1 -0
- package/lib/mjs/package.json +1 -0
- package/lib/mjs/policies/NoImpersonationPolicy.d.ts +28 -0
- package/lib/mjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/NoImpersonationPolicy.js +41 -0
- package/lib/mjs/policies/NoImpersonationPolicy.js.map +1 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.d.ts +12 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.js +20 -0
- package/lib/mjs/policies/NoTokenAuthPolicy.js.map +1 -0
- package/lib/mjs/policies/TokenPolicy.d.ts +49 -0
- package/lib/mjs/policies/TokenPolicy.d.ts.map +1 -0
- package/lib/mjs/policies/TokenPolicy.js +75 -0
- package/lib/mjs/policies/TokenPolicy.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -0
- package/lib/tsconfig.mjs.tsbuildinfo +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AccessToken = void 0;
|
|
13
|
+
const orm_1 = require("@spinajs/orm");
|
|
14
|
+
const luxon_1 = require("luxon");
|
|
15
|
+
const uuid_1 = require("uuid");
|
|
16
|
+
const util_1 = require("@spinajs/util");
|
|
17
|
+
/**
|
|
18
|
+
* Personal access token. Only the SHA-256 hash of the token is stored;
|
|
19
|
+
* the plaintext is returned once at creation and cannot be recovered.
|
|
20
|
+
*/
|
|
21
|
+
let AccessToken = class AccessToken extends orm_1.ModelBase {
|
|
22
|
+
constructor(data) {
|
|
23
|
+
super(data);
|
|
24
|
+
this.Uuid = (0, util_1._check_arg)((0, util_1._default)((0, uuid_1.v4)()))(this.Uuid, 'uuid');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* True when the token carries an expiration in the past.
|
|
28
|
+
*/
|
|
29
|
+
get IsExpired() {
|
|
30
|
+
return !!this.ExpiresAt && this.ExpiresAt <= luxon_1.DateTime.now();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.AccessToken = AccessToken;
|
|
34
|
+
__decorate([
|
|
35
|
+
(0, orm_1.Primary)(),
|
|
36
|
+
(0, orm_1.Hidden)(),
|
|
37
|
+
__metadata("design:type", Number)
|
|
38
|
+
], AccessToken.prototype, "Id", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, orm_1.Hidden)(),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], AccessToken.prototype, "Token", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, orm_1.Set)(),
|
|
45
|
+
__metadata("design:type", Array)
|
|
46
|
+
], AccessToken.prototype, "Roles", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, orm_1.DateTime)(),
|
|
49
|
+
__metadata("design:type", luxon_1.DateTime)
|
|
50
|
+
], AccessToken.prototype, "ExpiresAt", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
(0, orm_1.CreatedAt)(),
|
|
53
|
+
__metadata("design:type", luxon_1.DateTime)
|
|
54
|
+
], AccessToken.prototype, "CreatedAt", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, orm_1.DateTime)(),
|
|
57
|
+
__metadata("design:type", luxon_1.DateTime)
|
|
58
|
+
], AccessToken.prototype, "LastUsedAt", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, orm_1.Hidden)(),
|
|
61
|
+
(0, orm_1.BelongsTo)('User'),
|
|
62
|
+
__metadata("design:type", orm_1.SingleRelation)
|
|
63
|
+
], AccessToken.prototype, "User", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
(0, orm_1.Hidden)(),
|
|
66
|
+
__metadata("design:type", Number)
|
|
67
|
+
], AccessToken.prototype, "user_id", void 0);
|
|
68
|
+
exports.AccessToken = AccessToken = __decorate([
|
|
69
|
+
(0, orm_1.Connection)('default'),
|
|
70
|
+
(0, orm_1.Model)('rbac_access_tokens'),
|
|
71
|
+
__metadata("design:paramtypes", [Object])
|
|
72
|
+
], AccessToken);
|
|
73
|
+
//# sourceMappingURL=AccessToken.js.map
|
|
@@ -0,0 +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;IA8DD;;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;;AA7DQ;IAFN,IAAA,aAAO,GAAE;IACT,IAAA,YAAM,GAAE;;uCACU;AAiBZ;IADN,IAAA,YAAM,GAAE;;0CACa;AAOf;IADN,IAAA,SAAG,GAAE;;0CACkB;AAWjB;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;sBAhEb,WAAW;IAFvB,IAAA,gBAAU,EAAC,SAAS,CAAC;IACrB,IAAA,WAAK,EAAC,oBAAoB,CAAC;;GACf,WAAW,CAwEvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
|
|
2
|
+
import '../interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* Rejects requests made from an impersonated session.
|
|
5
|
+
*
|
|
6
|
+
* Impersonation is a *supervised, revocable* act: an administrator borrows a
|
|
7
|
+
* user's view of the application and the borrowing ends when the impersonation
|
|
8
|
+
* does. An access token is the opposite - a bearer credential that outlives the
|
|
9
|
+
* session that minted it, carries the victim's roles, and is invisible in the
|
|
10
|
+
* impersonator's own audit trail. Letting a credential-issuing route run while
|
|
11
|
+
* impersonating therefore turns a temporary, reversible grant into a permanent
|
|
12
|
+
* one that the account owner never consented to and cannot see.
|
|
13
|
+
*
|
|
14
|
+
* `RbacMiddleware` puts the impersonation TARGET in `req.storage.User` and the
|
|
15
|
+
* original administrator in `req.storage.Impersonator`
|
|
16
|
+
* ( `rbac-http/src/middlewares.ts` ), so every ownership and permission check
|
|
17
|
+
* downstream already reads as the victim - this policy is the only thing that
|
|
18
|
+
* can tell the two situations apart.
|
|
19
|
+
*
|
|
20
|
+
* Same reasoning as a password change demanding the CURRENT password: an
|
|
21
|
+
* operation that hands out lasting credentials has to be performed by the
|
|
22
|
+
* account owner, not on their behalf.
|
|
23
|
+
*/
|
|
24
|
+
export declare class NoImpersonationPolicy extends BasePolicy {
|
|
25
|
+
isEnabled(_action: IRoute, _instance: IController): boolean;
|
|
26
|
+
execute(req: sRequest, _action: IRoute, _instance: IController): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=NoImpersonationPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoImpersonationPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/NoImpersonationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQrF,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;IAC5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoImpersonationPolicy = void 0;
|
|
4
|
+
const http_1 = require("@spinajs/http");
|
|
5
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
6
|
+
// Same side-effect import both siblings carry. `req.storage.Impersonator` comes
|
|
7
|
+
// from `@spinajs/rbac-http`'s augmentation of `IActionLocalStoregeContext`,
|
|
8
|
+
// which this package's `interfaces.ts` pulls into the program ( type-only ).
|
|
9
|
+
// Without it the field only type-checks when something ELSE in the compilation
|
|
10
|
+
// happened to drag that augmentation in - fine today, silently broken the day
|
|
11
|
+
// this file is compiled on its own.
|
|
12
|
+
require("../interfaces.js");
|
|
13
|
+
/**
|
|
14
|
+
* Rejects requests made from an impersonated session.
|
|
15
|
+
*
|
|
16
|
+
* Impersonation is a *supervised, revocable* act: an administrator borrows a
|
|
17
|
+
* user's view of the application and the borrowing ends when the impersonation
|
|
18
|
+
* does. An access token is the opposite - a bearer credential that outlives the
|
|
19
|
+
* session that minted it, carries the victim's roles, and is invisible in the
|
|
20
|
+
* impersonator's own audit trail. Letting a credential-issuing route run while
|
|
21
|
+
* impersonating therefore turns a temporary, reversible grant into a permanent
|
|
22
|
+
* one that the account owner never consented to and cannot see.
|
|
23
|
+
*
|
|
24
|
+
* `RbacMiddleware` puts the impersonation TARGET in `req.storage.User` and the
|
|
25
|
+
* original administrator in `req.storage.Impersonator`
|
|
26
|
+
* ( `rbac-http/src/middlewares.ts` ), so every ownership and permission check
|
|
27
|
+
* downstream already reads as the victim - this policy is the only thing that
|
|
28
|
+
* can tell the two situations apart.
|
|
29
|
+
*
|
|
30
|
+
* Same reasoning as a password change demanding the CURRENT password: an
|
|
31
|
+
* operation that hands out lasting credentials has to be performed by the
|
|
32
|
+
* account owner, not on their behalf.
|
|
33
|
+
*/
|
|
34
|
+
class NoImpersonationPolicy extends http_1.BasePolicy {
|
|
35
|
+
isEnabled(_action, _instance) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
async execute(req, _action, _instance) {
|
|
39
|
+
if (req.storage?.Impersonator) {
|
|
40
|
+
throw new exceptions_1.Forbidden('this route cannot be used while impersonating another user');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.NoImpersonationPolicy = NoImpersonationPolicy;
|
|
45
|
+
//# sourceMappingURL=NoImpersonationPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoImpersonationPolicy.js","sourceRoot":"","sources":["../../../src/policies/NoImpersonationPolicy.ts"],"names":[],"mappings":";;;AAAA,wCAAqF;AACrF,oDAAgD;AAChD,gFAAgF;AAChF,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,oCAAoC;AACpC,4BAA0B;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,2BAAmC,SAAQ,iBAAU;IAC5C,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,OAAe,EAAE,SAAsB;QACzE,IAAI,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;YAC9B,MAAM,IAAI,sBAAS,CAAC,4DAA4D,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
|
|
2
|
+
import '../interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* Rejects requests authenticated with an access token. Applied to the token
|
|
5
|
+
* management API so a token can never be used to mint or manage tokens
|
|
6
|
+
* ( no self-replication ). Session-authenticated requests pass through.
|
|
7
|
+
*/
|
|
8
|
+
export declare class NoTokenAuthPolicy extends BasePolicy {
|
|
9
|
+
isEnabled(_action: IRoute, _instance: IController): boolean;
|
|
10
|
+
execute(req: sRequest, _action: IRoute, _instance: IController): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=NoTokenAuthPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoTokenAuthPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/NoTokenAuthPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrF,OAAO,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IACxC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoTokenAuthPolicy = void 0;
|
|
4
|
+
const http_1 = require("@spinajs/http");
|
|
5
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
6
|
+
// Brings the `req.storage.TokenAuth` module augmentation into the program.
|
|
7
|
+
require("../interfaces.js");
|
|
8
|
+
/**
|
|
9
|
+
* Rejects requests authenticated with an access token. Applied to the token
|
|
10
|
+
* management API so a token can never be used to mint or manage tokens
|
|
11
|
+
* ( no self-replication ). Session-authenticated requests pass through.
|
|
12
|
+
*/
|
|
13
|
+
class NoTokenAuthPolicy extends http_1.BasePolicy {
|
|
14
|
+
isEnabled(_action, _instance) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
async execute(req, _action, _instance) {
|
|
18
|
+
if (req.storage?.TokenAuth) {
|
|
19
|
+
throw new exceptions_1.Forbidden('access tokens cannot be used on this route');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.NoTokenAuthPolicy = NoTokenAuthPolicy;
|
|
24
|
+
//# sourceMappingURL=NoTokenAuthPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoTokenAuthPolicy.js","sourceRoot":"","sources":["../../../src/policies/NoTokenAuthPolicy.ts"],"names":[],"mappings":";;;AAAA,wCAAqF;AACrF,oDAAgD;AAChD,2EAA2E;AAC3E,4BAA0B;AAE1B;;;;GAIG;AACH,uBAA+B,SAAQ,iBAAU;IACxC,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,OAAe,EAAE,SAAsB;QACzE,IAAI,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,sBAAS,CAAC,4CAA4C,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
|
|
2
|
+
import '../interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* Route requires authentication with an access token AND the token's
|
|
5
|
+
* effective roles must satisfy the route's @Resource/@Permission grants.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors RbacPolicy's grant enforcement, but for token-authenticated
|
|
8
|
+
* requests ( which carry no session ).
|
|
9
|
+
*
|
|
10
|
+
* WIRING - do NOT pass this policy to @Permission's `also` parameter:
|
|
11
|
+
*
|
|
12
|
+
* @Permission(['readOwn'], TokenPolicy) // BROKEN - always 401
|
|
13
|
+
*
|
|
14
|
+
* `@Permission` unconditionally bundles RbacPolicy together with every `also`
|
|
15
|
+
* policy into the SAME policy group ( rbac-http/src/decorators.ts ), and
|
|
16
|
+
* policies inside one group are combined with AND. RbacPolicy demands an
|
|
17
|
+
* authorized session, which a token-authenticated request never has, so the
|
|
18
|
+
* pair can never both pass and the route is permanently unreachable by token.
|
|
19
|
+
*
|
|
20
|
+
* Declare it as its OWN group at the ROUTE scope instead - groups of ONE scope
|
|
21
|
+
* are ORed, so a token request satisfies the TokenPolicy group while a session
|
|
22
|
+
* request satisfies the RbacPolicy group:
|
|
23
|
+
*
|
|
24
|
+
* @Get('data')
|
|
25
|
+
* @Permission(['readOwn']) // the permission metadata + RbacPolicy group
|
|
26
|
+
* @Policy(TokenPolicy) // METHOD level - a second route scope group
|
|
27
|
+
*
|
|
28
|
+
* The placement is not free-standing: a CLASS level `@Policy(TokenPolicy)` goes
|
|
29
|
+
* to the CONTROLLER scope, and the two scopes are ANDed - it would then have to
|
|
30
|
+
* hold TOGETHER with the route's RbacPolicy group, which is exactly the broken
|
|
31
|
+
* combination above. Only a method level declaration lands in the same scope as
|
|
32
|
+
* `@Permission` and gets ORed with it.
|
|
33
|
+
*
|
|
34
|
+
* Writing `@Policy(TokenPolicy)` BELOW `@Permission` is deliberate too.
|
|
35
|
+
* Decorators apply bottom up, so this one is pushed first, and when no group
|
|
36
|
+
* holds `createPolicyGate` reports the first rejection in declaration order: a
|
|
37
|
+
* token that authenticated but lacks the grant then gets this policy's 403
|
|
38
|
+
* instead of RbacPolicy's misleading "user not logged" 401.
|
|
39
|
+
*
|
|
40
|
+
* The `@Permission` line is still required even with `@Policy(TokenPolicy)`:
|
|
41
|
+
* this policy reads the same route permission metadata, and a route without it
|
|
42
|
+
* silently inherits the controller-level default `['readOwn']` rather than
|
|
43
|
+
* failing loudly.
|
|
44
|
+
*/
|
|
45
|
+
export declare class TokenPolicy extends BasePolicy {
|
|
46
|
+
isEnabled(_action: IRoute, _instance: IController): boolean;
|
|
47
|
+
execute(req: sRequest, action: IRoute, instance: IController): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=TokenPolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/TokenPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAe,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMlG,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,WAAY,SAAQ,UAAU;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBxF;CACF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TokenPolicy = void 0;
|
|
4
|
+
const http_1 = require("@spinajs/http");
|
|
5
|
+
const exceptions_1 = require("@spinajs/exceptions");
|
|
6
|
+
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
7
|
+
// Brings the `req.storage.TokenAuth` module augmentation into the program.
|
|
8
|
+
// Same side-effect import the middleware uses; without it this file compiles
|
|
9
|
+
// on its own against an un-augmented IActionLocalStoregeContext.
|
|
10
|
+
require("../interfaces.js");
|
|
11
|
+
/**
|
|
12
|
+
* Route requires authentication with an access token AND the token's
|
|
13
|
+
* effective roles must satisfy the route's @Resource/@Permission grants.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors RbacPolicy's grant enforcement, but for token-authenticated
|
|
16
|
+
* requests ( which carry no session ).
|
|
17
|
+
*
|
|
18
|
+
* WIRING - do NOT pass this policy to @Permission's `also` parameter:
|
|
19
|
+
*
|
|
20
|
+
* @Permission(['readOwn'], TokenPolicy) // BROKEN - always 401
|
|
21
|
+
*
|
|
22
|
+
* `@Permission` unconditionally bundles RbacPolicy together with every `also`
|
|
23
|
+
* policy into the SAME policy group ( rbac-http/src/decorators.ts ), and
|
|
24
|
+
* policies inside one group are combined with AND. RbacPolicy demands an
|
|
25
|
+
* authorized session, which a token-authenticated request never has, so the
|
|
26
|
+
* pair can never both pass and the route is permanently unreachable by token.
|
|
27
|
+
*
|
|
28
|
+
* Declare it as its OWN group at the ROUTE scope instead - groups of ONE scope
|
|
29
|
+
* are ORed, so a token request satisfies the TokenPolicy group while a session
|
|
30
|
+
* request satisfies the RbacPolicy group:
|
|
31
|
+
*
|
|
32
|
+
* @Get('data')
|
|
33
|
+
* @Permission(['readOwn']) // the permission metadata + RbacPolicy group
|
|
34
|
+
* @Policy(TokenPolicy) // METHOD level - a second route scope group
|
|
35
|
+
*
|
|
36
|
+
* The placement is not free-standing: a CLASS level `@Policy(TokenPolicy)` goes
|
|
37
|
+
* to the CONTROLLER scope, and the two scopes are ANDed - it would then have to
|
|
38
|
+
* hold TOGETHER with the route's RbacPolicy group, which is exactly the broken
|
|
39
|
+
* combination above. Only a method level declaration lands in the same scope as
|
|
40
|
+
* `@Permission` and gets ORed with it.
|
|
41
|
+
*
|
|
42
|
+
* Writing `@Policy(TokenPolicy)` BELOW `@Permission` is deliberate too.
|
|
43
|
+
* Decorators apply bottom up, so this one is pushed first, and when no group
|
|
44
|
+
* holds `createPolicyGate` reports the first rejection in declaration order: a
|
|
45
|
+
* token that authenticated but lacks the grant then gets this policy's 403
|
|
46
|
+
* instead of RbacPolicy's misleading "user not logged" 401.
|
|
47
|
+
*
|
|
48
|
+
* The `@Permission` line is still required even with `@Policy(TokenPolicy)`:
|
|
49
|
+
* this policy reads the same route permission metadata, and a route without it
|
|
50
|
+
* silently inherits the controller-level default `['readOwn']` rather than
|
|
51
|
+
* failing loudly.
|
|
52
|
+
*/
|
|
53
|
+
class TokenPolicy extends http_1.BasePolicy {
|
|
54
|
+
isEnabled(_action, _instance) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
async execute(req, action, instance) {
|
|
58
|
+
if (!req.storage || !req.storage.TokenAuth || !req.storage.User) {
|
|
59
|
+
throw new exceptions_1.AuthenticationFailed('access token required');
|
|
60
|
+
}
|
|
61
|
+
const descriptor = Reflect.getMetadata(rbac_http_1.ACL_CONTROLLER_DESCRIPTOR, instance);
|
|
62
|
+
// Guard BEFORE dereferencing `.Routes`: a route decorated with this policy
|
|
63
|
+
// but no @Resource/@Permission must produce the descriptive server error,
|
|
64
|
+
// not a raw TypeError 500.
|
|
65
|
+
if (!descriptor || !descriptor.Permission || descriptor.Permission.length === 0) {
|
|
66
|
+
throw new http_1.ServerError('no route permission or resources assigned');
|
|
67
|
+
}
|
|
68
|
+
let permission = descriptor.Permission ?? [];
|
|
69
|
+
if (descriptor.Routes.has(String(action.Method))) {
|
|
70
|
+
permission = descriptor.Routes.get(String(action.Method)).Permission ?? [];
|
|
71
|
+
}
|
|
72
|
+
if (!permission.some((p) => (0, rbac_http_1.checkRoutePermission)(req, descriptor.Resource, p)?.granted)) {
|
|
73
|
+
const effective = req.storage.ActiveRole ?? req.storage.User.Role;
|
|
74
|
+
throw new exceptions_1.Forbidden(`token role(s) ${effective} do not have permission ${permission} for resource ${descriptor.Resource}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.TokenPolicy = TokenPolicy;
|
|
79
|
+
//# sourceMappingURL=TokenPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenPolicy.js","sourceRoot":"","sources":["../../../src/policies/TokenPolicy.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAClG,oDAAsE;AACtE,kDAAsG;AACtG,2EAA2E;AAC3E,6EAA6E;AAC7E,iEAAiE;AACjE,4BAA0B;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,iBAAyB,SAAQ,iBAAU;IAClC,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,MAAc,EAAE,QAAqB;QACvE,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAChE,MAAM,IAAI,iCAAoB,CAAC,uBAAuB,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,UAAU,GAAoB,OAAO,CAAC,WAAW,CAAC,qCAAyB,EAAE,QAAQ,CAAC,CAAC;QAE7F,2EAA2E;QAC3E,0EAA0E;QAC1E,2BAA2B;QAC3B,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChF,MAAM,IAAI,kBAAW,CAAC,2CAA2C,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,UAAU,GAAG,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC;QAC7C,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACjD,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAE,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,gCAAoB,EAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;YACxF,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAClE,MAAM,IAAI,sBAAS,CAAC,iBAAiB,SAAS,2BAA2B,UAAU,iBAAiB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7H,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { User } from '@spinajs/rbac';
|
|
3
|
+
import { AccessToken } from './models/AccessToken.js';
|
|
4
|
+
/**
|
|
5
|
+
* Failure codes carried by every {@link ErrorCode} this module throws.
|
|
6
|
+
*
|
|
7
|
+
* Named `E_TOKEN_CODES` rather than the shorter `E_CODES` on purpose:
|
|
8
|
+
* `@spinajs/rbac` exports an enum called `E_CODES` too, and both are re-exported
|
|
9
|
+
* from their package index. A downstream barrel that does
|
|
10
|
+
* `export * from '@spinajs/rbac'; export * from '@spinajs/rbac-http-token';`
|
|
11
|
+
* would collide on the NAME while the members underneath carry different
|
|
12
|
+
* numeric values - the kind of clash that resolves silently in a barrel and
|
|
13
|
+
* makes an `err.code === E_CODES.X` comparison answer the wrong question.
|
|
14
|
+
*/
|
|
15
|
+
export declare enum E_TOKEN_CODES {
|
|
16
|
+
E_TOKEN_NOT_FOUND = 0,
|
|
17
|
+
E_TOKEN_EXPIRED = 1,
|
|
18
|
+
E_TOKEN_OWNER_INVALID = 2,
|
|
19
|
+
E_TOKEN_ROLE_NOT_ALLOWED = 3
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolves an AccessToken from an instance or its uuid.
|
|
23
|
+
*/
|
|
24
|
+
export declare function _token(token: AccessToken | string): () => Promise<AccessToken>;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the owning user by instance, numeric id or uuid, with metadata
|
|
27
|
+
* populated ( needed for IsBanned checks downstream ).
|
|
28
|
+
*/
|
|
29
|
+
export declare function _owner(user: User | number | string): () => Promise<User>;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new access token for a user.
|
|
32
|
+
*
|
|
33
|
+
* Roles must be a non-empty subset of the owner's current roles. `expiresAt`
|
|
34
|
+
* null means the token never expires. The plaintext is returned once and
|
|
35
|
+
* never persisted - only its hash is stored.
|
|
36
|
+
*
|
|
37
|
+
* @param user - owner: {@link User} instance, numeric id or uuid
|
|
38
|
+
* @param name - human readable label
|
|
39
|
+
* @param roles - roles carried by the token, subset of the owner's roles
|
|
40
|
+
* @param expiresAt - absolute expiration, or null for a token that never expires
|
|
41
|
+
*/
|
|
42
|
+
export declare function createToken(user: User | number | string, name: string, roles: string[], expiresAt: DateTime | null): Promise<{
|
|
43
|
+
Token: AccessToken;
|
|
44
|
+
Plaintext: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Permanently deletes ( revokes ) a token.
|
|
48
|
+
*
|
|
49
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
50
|
+
*/
|
|
51
|
+
export declare function deleteToken(token: AccessToken | string): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Adds a role to a token. The role must be held by the token owner.
|
|
54
|
+
*
|
|
55
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
56
|
+
* @param role - role name to grant
|
|
57
|
+
*/
|
|
58
|
+
export declare function grantTokenRole(token: AccessToken | string, role: string): Promise<AccessToken>;
|
|
59
|
+
/**
|
|
60
|
+
* Removes a role from a token.
|
|
61
|
+
*
|
|
62
|
+
* Not symmetric with {@link grantTokenRole}: revoking only ever narrows what a
|
|
63
|
+
* token may do, so it needs no owner check.
|
|
64
|
+
*
|
|
65
|
+
* A token must always keep at least one role - revoking the last one is
|
|
66
|
+
* refused, and full revocation means deleting the token. Beyond being
|
|
67
|
+
* meaningless ( a role-less token authorises nothing ), an empty list is
|
|
68
|
+
* actively corrupting: `@Set()` columns round-trip through `SqlSetConverter`,
|
|
69
|
+
* which stores `[]` as `''` and reads `''` back as `['']`. That phantom empty
|
|
70
|
+
* role then survives every later grant, permanently.
|
|
71
|
+
*
|
|
72
|
+
* @param token - {@link AccessToken} instance or its uuid
|
|
73
|
+
* @param role - role name to revoke
|
|
74
|
+
* @throws ErrorCode E_TOKEN_ROLE_NOT_ALLOWED when `role` is the token's last role
|
|
75
|
+
*/
|
|
76
|
+
export declare function revokeTokenRole(token: AccessToken | string, role: string): Promise<AccessToken>;
|
|
77
|
+
export interface ITokenValidationResult {
|
|
78
|
+
User: User;
|
|
79
|
+
Token: AccessToken;
|
|
80
|
+
/**
|
|
81
|
+
* Token roles that the owner still holds. Permission checks run with these.
|
|
82
|
+
*/
|
|
83
|
+
EffectiveRoles: string[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validates a presented plaintext token.
|
|
87
|
+
*
|
|
88
|
+
* Checks, in order: token exists ( by hash ), token not expired, owner active /
|
|
89
|
+
* not soft-deleted / not banned, effective role intersection non-empty.
|
|
90
|
+
* Throws ErrorCode with {@link E_TOKEN_CODES} on every failure path.
|
|
91
|
+
*
|
|
92
|
+
* The owner checks are spelled out instead of reusing the `isActiveUser` query
|
|
93
|
+
* scope on purpose - a single "no such active user" result cannot say WHY, and
|
|
94
|
+
* callers need to tell an expired token from a banned account.
|
|
95
|
+
*
|
|
96
|
+
* @param plaintext - token exactly as presented by the client
|
|
97
|
+
*/
|
|
98
|
+
export declare function validateToken(plaintext: string): Promise<ITokenValidationResult>;
|
|
99
|
+
/**
|
|
100
|
+
* Deletes every token whose expiration has passed. Returns the deleted count.
|
|
101
|
+
*
|
|
102
|
+
* Intended for cyclic execution from a worker ( see `rbac:token-delete-expired` ).
|
|
103
|
+
* Expired tokens are already refused by {@link validateToken}, so this is
|
|
104
|
+
* housekeeping, not enforcement.
|
|
105
|
+
*/
|
|
106
|
+
export declare function deleteExpiredTokens(): Promise<number>;
|
|
107
|
+
/**
|
|
108
|
+
* Updates `LastUsedAt`, throttled: writes only when the stamp is absent or
|
|
109
|
+
* older than `intervalSeconds`.
|
|
110
|
+
*
|
|
111
|
+
* Every authenticated request would otherwise write to the token row; the stamp
|
|
112
|
+
* only needs to be accurate enough to spot unused tokens. Callers may
|
|
113
|
+
* fire-and-forget.
|
|
114
|
+
*
|
|
115
|
+
* @param token - token to stamp
|
|
116
|
+
* @param intervalSeconds - minimum time between two writes
|
|
117
|
+
*/
|
|
118
|
+
export declare function touchToken(token: AccessToken, intervalSeconds: number): Promise<void>;
|
|
119
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAOrC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD;;;;;;;;;;GAUG;AACH,oBAAY,aAAa;IACvB,iBAAiB,IAAA;IACjB,eAAe,IAAA;IACf,qBAAqB,IAAA;IACrB,wBAAwB,IAAA;CACzB;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAM9E;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAUxE;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B7K;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5E;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAcpG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmBrG;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IAEnB;;OAEG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA4CtF;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAU3D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
|