@decohere/http 0.0.1-dev.130 → 0.0.1-dev.20261105.103
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/es6/src/routing/services/route-registry.js +5 -0
- package/package.json +9 -14
- package/commonjs/src/app/app.js +0 -166
- package/commonjs/src/app/index.js +0 -19
- package/commonjs/src/app/module.js +0 -17
- package/commonjs/src/auth/ability.js +0 -54
- package/commonjs/src/auth/auth.config.js +0 -23
- package/commonjs/src/auth/auth.extensions.js +0 -106
- package/commonjs/src/auth/auth.types.js +0 -65
- package/commonjs/src/auth/casl-authorization.service.js +0 -36
- package/commonjs/src/auth/index.js +0 -23
- package/commonjs/src/auth/principal-provider.js +0 -19
- package/commonjs/src/auth/safe-outbound-url.js +0 -102
- package/commonjs/src/auth/token-service.js +0 -151
- package/commonjs/src/builder/builder.js +0 -95
- package/commonjs/src/builder/index.js +0 -18
- package/commonjs/src/const.js +0 -86
- package/commonjs/src/health/health.controller.js +0 -75
- package/commonjs/src/health/health.extensions.js +0 -50
- package/commonjs/src/health/index.js +0 -21
- package/commonjs/src/health/readiness.service.js +0 -67
- package/commonjs/src/health/readiness.types.js +0 -7
- package/commonjs/src/hosting/hosted-service-host.js +0 -88
- package/commonjs/src/hosting/hosted-service.js +0 -11
- package/commonjs/src/hosting/index.js +0 -19
- package/commonjs/src/http/http.compression.js +0 -27
- package/commonjs/src/http/http.extensions.js +0 -269
- package/commonjs/src/http/http.options.js +0 -26
- package/commonjs/src/http/http.options.store.js +0 -20
- package/commonjs/src/http/http.security.js +0 -27
- package/commonjs/src/http/http.static.js +0 -248
- package/commonjs/src/http/index.js +0 -22
- package/commonjs/src/index.js +0 -27
- package/commonjs/src/openapi/index.js +0 -45
- package/commonjs/src/openapi/openapi.generator.js +0 -103
- package/commonjs/src/openapi/openapi.types.js +0 -4
- package/commonjs/src/openapi/request-schema.js +0 -187
- package/commonjs/src/openapi/request-validator.js +0 -85
- package/commonjs/src/providers/fastify.provider.js +0 -391
- package/commonjs/src/providers/index.js +0 -18
- package/commonjs/src/routing/decorators/argument.decorator.js +0 -49
- package/commonjs/src/routing/decorators/auth.decorator.js +0 -70
- package/commonjs/src/routing/decorators/controller.decorator.js +0 -16
- package/commonjs/src/routing/decorators/field.decorator.js +0 -25
- package/commonjs/src/routing/decorators/index.js +0 -24
- package/commonjs/src/routing/decorators/request.decorator.js +0 -30
- package/commonjs/src/routing/decorators/response.decorator.js +0 -34
- package/commonjs/src/routing/decorators/route.decorator.js +0 -67
- package/commonjs/src/routing/filters/exception-filter-host.js +0 -145
- package/commonjs/src/routing/filters/exception-filter.js +0 -28
- package/commonjs/src/routing/http.types.js +0 -99
- package/commonjs/src/routing/index.js +0 -25
- package/commonjs/src/routing/middleware/http-access-log.middleware.js +0 -47
- package/commonjs/src/routing/middleware/middleware.js +0 -20
- package/commonjs/src/routing/middleware/request-id.js +0 -30
- package/commonjs/src/routing/path.util.js +0 -51
- package/commonjs/src/routing/pipes/index.js +0 -18
- package/commonjs/src/routing/pipes/pipes.js +0 -145
- package/commonjs/src/routing/services/index.js +0 -18
- package/commonjs/src/routing/services/route-argument-resolver.js +0 -77
- package/commonjs/src/routing/services/route-registry.js +0 -194
- package/commonjs/src/routing/services/router.js +0 -158
- package/commonjs/src/sse/index.js +0 -26
- package/commonjs/src/sse/sse.decorator.js +0 -42
- package/commonjs/src/sse/sse.encoder.js +0 -73
- package/commonjs/src/sse/sse.types.js +0 -36
- package/commonjs/src/sse/sse.wire.js +0 -40
- package/commonjs/src/testing/boot-module.js +0 -38
- package/commonjs/src/testing/index.js +0 -20
- package/commonjs/src/testing/sse-reader.js +0 -98
|
@@ -95,6 +95,11 @@ export class RouteRegistry {
|
|
|
95
95
|
}
|
|
96
96
|
getRouteArgument(argumentType, argumentIndex, handler) {
|
|
97
97
|
const argMeta = getArgumentMeta(MetadataKeys.parameter, handler, argumentIndex);
|
|
98
|
+
// A named value typed as a union or interface reaches here as Object, which would build an
|
|
99
|
+
// empty object. Pass the value through as it arrived.
|
|
100
|
+
if (argumentType === Object && argMeta?.mappingKey != null && !isInjectedPart(argMeta.argumentLocation)) {
|
|
101
|
+
return this.getRouteArgument(String, argumentIndex, handler);
|
|
102
|
+
}
|
|
98
103
|
// @CurrentUser() / interface params are Object (or other non-DTO types) — no field map.
|
|
99
104
|
if (isInjectedPart(argMeta?.argumentLocation) || !isConstructable(argumentType)) {
|
|
100
105
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decohere/http",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.20261105.103",
|
|
4
4
|
"description": "Web API and microservice platform built on Fastify with decorator-based routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -27,28 +27,23 @@
|
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
29
|
"types": "./types/src/index.d.ts",
|
|
30
|
-
"import": "./es6/src/index.js"
|
|
31
|
-
"require": "./commonjs/src/index.js"
|
|
30
|
+
"import": "./es6/src/index.js"
|
|
32
31
|
},
|
|
33
32
|
"./providers": {
|
|
34
33
|
"types": "./types/src/providers/index.d.ts",
|
|
35
|
-
"import": "./es6/src/providers/index.js"
|
|
36
|
-
"require": "./commonjs/src/providers/index.js"
|
|
34
|
+
"import": "./es6/src/providers/index.js"
|
|
37
35
|
},
|
|
38
36
|
"./auth": {
|
|
39
37
|
"types": "./types/src/auth/auth.extensions.d.ts",
|
|
40
|
-
"import": "./es6/src/auth/auth.extensions.js"
|
|
41
|
-
"require": "./commonjs/src/auth/auth.extensions.js"
|
|
38
|
+
"import": "./es6/src/auth/auth.extensions.js"
|
|
42
39
|
},
|
|
43
40
|
"./testing": {
|
|
44
41
|
"types": "./types/src/testing/index.d.ts",
|
|
45
|
-
"import": "./es6/src/testing/index.js"
|
|
46
|
-
"require": "./commonjs/src/testing/index.js"
|
|
42
|
+
"import": "./es6/src/testing/index.js"
|
|
47
43
|
},
|
|
48
44
|
"./http": {
|
|
49
45
|
"types": "./types/src/http/index.d.ts",
|
|
50
|
-
"import": "./es6/src/http/index.js"
|
|
51
|
-
"require": "./commonjs/src/http/index.js"
|
|
46
|
+
"import": "./es6/src/http/index.js"
|
|
52
47
|
}
|
|
53
48
|
},
|
|
54
49
|
"scripts": {
|
|
@@ -56,9 +51,9 @@
|
|
|
56
51
|
},
|
|
57
52
|
"dependencies": {
|
|
58
53
|
"@casl/ability": "^6.8.1",
|
|
59
|
-
"@decohere/core": "0.0.1-dev.
|
|
60
|
-
"@decohere/crucible": "0.0.1-dev.
|
|
61
|
-
"@decohere/scribe": "0.0.1-dev.
|
|
54
|
+
"@decohere/core": "0.0.1-dev.20261105.103",
|
|
55
|
+
"@decohere/crucible": "0.0.1-dev.20261105.103",
|
|
56
|
+
"@decohere/scribe": "0.0.1-dev.20261105.103",
|
|
62
57
|
"@fastify/compress": "^9.2.1",
|
|
63
58
|
"@fastify/cors": "^11.3.0",
|
|
64
59
|
"@fastify/helmet": "^13.1.0",
|
package/commonjs/src/app/app.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get ApiConfiguration () {
|
|
13
|
-
return ApiConfiguration;
|
|
14
|
-
},
|
|
15
|
-
get App () {
|
|
16
|
-
return App;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const _crucible = require("@decohere/crucible");
|
|
20
|
-
const _decorators = require("@decohere/crucible/decorators");
|
|
21
|
-
const _configuration = require("@decohere/core/configuration");
|
|
22
|
-
const _scribe = require("@decohere/scribe");
|
|
23
|
-
const _const = require("../const.js");
|
|
24
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
25
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
26
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
27
|
-
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;
|
|
28
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
29
|
-
}
|
|
30
|
-
function _ts_metadata(k, v) {
|
|
31
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
32
|
-
}
|
|
33
|
-
function _ts_param(paramIndex, decorator) {
|
|
34
|
-
return function(target, key) {
|
|
35
|
-
decorator(target, key, paramIndex);
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const DEFAULT_PORT = 3000;
|
|
39
|
-
const DEFAULT_SHUTDOWN_SIGNALS = [
|
|
40
|
-
"SIGTERM",
|
|
41
|
-
"SIGINT"
|
|
42
|
-
];
|
|
43
|
-
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 10_000;
|
|
44
|
-
class ApiConfiguration {
|
|
45
|
-
port;
|
|
46
|
-
}
|
|
47
|
-
class App {
|
|
48
|
-
container;
|
|
49
|
-
configurationService;
|
|
50
|
-
httpProvider;
|
|
51
|
-
hostedServices;
|
|
52
|
-
_addresses = Array.of();
|
|
53
|
-
logger = _scribe.scribe.logger(App.name);
|
|
54
|
-
disposing;
|
|
55
|
-
disposingContainer = false;
|
|
56
|
-
signalHandler;
|
|
57
|
-
shutdownSignals = [];
|
|
58
|
-
constructor(container, configurationService, httpProvider, hostedServices){
|
|
59
|
-
this.container = container;
|
|
60
|
-
this.configurationService = configurationService;
|
|
61
|
-
this.httpProvider = httpProvider;
|
|
62
|
-
this.hostedServices = hostedServices;
|
|
63
|
-
}
|
|
64
|
-
get addresses() {
|
|
65
|
-
return this._addresses;
|
|
66
|
-
}
|
|
67
|
-
async start(options) {
|
|
68
|
-
this.logger.info("Starting app");
|
|
69
|
-
// Before HTTP, so a request never reaches a service that has not started.
|
|
70
|
-
await this.hostedServices?.start(this.container);
|
|
71
|
-
// The app was stopped while a hosted service was still starting.
|
|
72
|
-
if (this.disposing != null) return;
|
|
73
|
-
const hasHostedServices = this.hostedServices != null && !this.hostedServices.isEmpty;
|
|
74
|
-
if (!this.httpProvider) {
|
|
75
|
-
if (hasHostedServices) this.stopOnSignals(options);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const port = await this.getPort(options);
|
|
79
|
-
this.logger.info(`Starting http on port ${port}`);
|
|
80
|
-
const startResponse = await this.httpProvider?.start({
|
|
81
|
-
port,
|
|
82
|
-
...options?.host != null ? {
|
|
83
|
-
host: options.host
|
|
84
|
-
} : {}
|
|
85
|
-
});
|
|
86
|
-
this._addresses = [
|
|
87
|
-
...startResponse.addresses
|
|
88
|
-
];
|
|
89
|
-
this.logger.info("Listening on:", this._addresses);
|
|
90
|
-
this.stopOnSignals(options);
|
|
91
|
-
return startResponse;
|
|
92
|
-
}
|
|
93
|
-
[Symbol.asyncDispose]() {
|
|
94
|
-
// The container holds this App too; when stop() disposes the container it lands
|
|
95
|
-
// here, and awaiting our own shutdown would deadlock.
|
|
96
|
-
if (this.disposingContainer) return Promise.resolve();
|
|
97
|
-
return this.dispose();
|
|
98
|
-
}
|
|
99
|
-
/** Stop the app. Calling it again (or from a signal) returns the same shutdown. */ dispose() {
|
|
100
|
-
this.disposing ??= this.stop();
|
|
101
|
-
return this.disposing;
|
|
102
|
-
}
|
|
103
|
-
async stop() {
|
|
104
|
-
// Removed first, so a second Ctrl+C / SIGTERM gets Node's default: exit now.
|
|
105
|
-
this.removeSignalHandlers();
|
|
106
|
-
this.logger.info("Stopping");
|
|
107
|
-
// Hosted services hear the signal at once, so background work winds down while HTTP drains.
|
|
108
|
-
this.hostedServices?.abort();
|
|
109
|
-
try {
|
|
110
|
-
// HTTP first: in-flight requests still need the services (DB pools etc.) that
|
|
111
|
-
// disposing the container would close.
|
|
112
|
-
await this.httpProvider?.stop();
|
|
113
|
-
// Hosted services next, while what they use is still open.
|
|
114
|
-
await this.hostedServices?.stop();
|
|
115
|
-
} finally{
|
|
116
|
-
this.disposingContainer = true;
|
|
117
|
-
await this.container[Symbol.asyncDispose]();
|
|
118
|
-
await _scribe.scribe.stop();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
stopOnSignals(options) {
|
|
122
|
-
const signals = options?.shutdownSignals ?? DEFAULT_SHUTDOWN_SIGNALS;
|
|
123
|
-
const timeoutMs = options?.shutdownTimeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
|
124
|
-
if (signals === false || signals.length === 0) return;
|
|
125
|
-
this.signalHandler = (signal)=>{
|
|
126
|
-
this.logger.info(`Received ${signal}; finishing in-flight requests`);
|
|
127
|
-
// console.error, not the logger: scribe may be the thing that's stuck.
|
|
128
|
-
const timer = setTimeout(()=>{
|
|
129
|
-
console.error(`Shutdown did not finish within ${timeoutMs}ms; exiting.`);
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}, timeoutMs);
|
|
132
|
-
timer.unref();
|
|
133
|
-
this.dispose().then(()=>clearTimeout(timer), (error)=>{
|
|
134
|
-
clearTimeout(timer);
|
|
135
|
-
console.error("Shutdown failed:", error);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
this.shutdownSignals = signals;
|
|
140
|
-
for (const signal of signals)process.on(signal, this.signalHandler);
|
|
141
|
-
}
|
|
142
|
-
removeSignalHandlers() {
|
|
143
|
-
if (!this.signalHandler) return;
|
|
144
|
-
for (const signal of this.shutdownSignals)process.off(signal, this.signalHandler);
|
|
145
|
-
}
|
|
146
|
-
async getPort(options) {
|
|
147
|
-
const port = options?.port ?? (await this.configurationService?.get(ApiConfiguration))?.port ?? DEFAULT_PORT;
|
|
148
|
-
return port;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
App = _ts_decorate([
|
|
152
|
-
_ts_param(0, (0, _decorators.inject)(_crucible.LifetimeScopeToken)),
|
|
153
|
-
_ts_param(1, (0, _decorators.inject)(_configuration.ConfigurationServiceToken)),
|
|
154
|
-
_ts_param(1, (0, _decorators.optional)()),
|
|
155
|
-
_ts_param(2, (0, _decorators.inject)(_const.HttpProviderToken)),
|
|
156
|
-
_ts_param(2, (0, _decorators.optional)()),
|
|
157
|
-
_ts_param(3, (0, _decorators.inject)(_const.HostedServiceHostToken)),
|
|
158
|
-
_ts_param(3, (0, _decorators.optional)()),
|
|
159
|
-
_ts_metadata("design:type", Function),
|
|
160
|
-
_ts_metadata("design:paramtypes", [
|
|
161
|
-
typeof LifetimeScope === "undefined" ? Object : LifetimeScope,
|
|
162
|
-
typeof IConfigurationService === "undefined" ? Object : IConfigurationService,
|
|
163
|
-
typeof HttpProvider === "undefined" ? Object : HttpProvider,
|
|
164
|
-
typeof HostedServiceHost === "undefined" ? Object : HostedServiceHost
|
|
165
|
-
])
|
|
166
|
-
], App);
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
_export_star(require("./app.js"), exports);
|
|
6
|
-
_export_star(require("./module.js"), exports);
|
|
7
|
-
function _export_star(from, to) {
|
|
8
|
-
Object.keys(from).forEach(function(k) {
|
|
9
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
10
|
-
Object.defineProperty(to, k, {
|
|
11
|
-
enumerable: true,
|
|
12
|
-
get: function() {
|
|
13
|
-
return from[k];
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
return from;
|
|
19
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "Module", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return Module;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
class Module {
|
|
12
|
-
constructor(data){
|
|
13
|
-
Object.assign(this, data);
|
|
14
|
-
}
|
|
15
|
-
entities;
|
|
16
|
-
repositories;
|
|
17
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get ADMIN_ROLE () {
|
|
13
|
-
return ADMIN_ROLE;
|
|
14
|
-
},
|
|
15
|
-
get createPrincipalFromPayload () {
|
|
16
|
-
return createPrincipalFromPayload;
|
|
17
|
-
},
|
|
18
|
-
get defineAbilitiesFor () {
|
|
19
|
-
return defineAbilitiesFor;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
const _ability = require("@casl/ability");
|
|
23
|
-
const ADMIN_ROLE = "admin";
|
|
24
|
-
function defineAbilitiesFor(principal) {
|
|
25
|
-
const { can, build } = new _ability.AbilityBuilder(_ability.createMongoAbility);
|
|
26
|
-
if (principal.roles?.includes(ADMIN_ROLE)) {
|
|
27
|
-
can("manage", "all");
|
|
28
|
-
return build();
|
|
29
|
-
}
|
|
30
|
-
for (const scope of principal.scopes ?? []){
|
|
31
|
-
const [action, subject] = scope.split(":");
|
|
32
|
-
if (action && subject) can(action, subject);
|
|
33
|
-
}
|
|
34
|
-
return build();
|
|
35
|
-
}
|
|
36
|
-
function createPrincipalFromPayload(payload) {
|
|
37
|
-
const sub = typeof payload.sub === "string" ? payload.sub : "";
|
|
38
|
-
const fromScopeClaim = typeof payload.scope === "string" ? payload.scope.split(" ").filter(Boolean) : Array.isArray(payload.scopes) ? payload.scopes.filter((s)=>typeof s === "string") : [];
|
|
39
|
-
const fromPermissions = Array.isArray(payload.permissions) ? payload.permissions.filter((s)=>typeof s === "string") : [];
|
|
40
|
-
const merged = [
|
|
41
|
-
...new Set([
|
|
42
|
-
...fromScopeClaim,
|
|
43
|
-
...fromPermissions
|
|
44
|
-
])
|
|
45
|
-
];
|
|
46
|
-
const scopes = merged.length > 0 ? merged : undefined;
|
|
47
|
-
const roles = Array.isArray(payload.roles) ? payload.roles.filter((r)=>typeof r === "string") : undefined;
|
|
48
|
-
return {
|
|
49
|
-
...payload,
|
|
50
|
-
sub,
|
|
51
|
-
roles: roles && roles.length > 0 ? roles : undefined,
|
|
52
|
-
scopes
|
|
53
|
-
};
|
|
54
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "AuthConfig", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return AuthConfig;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
class AuthConfig {
|
|
12
|
-
/** OIDC discovery URL — the issuer base URL, e.g. https://accounts.google.com.
|
|
13
|
-
* The framework appends `/.well-known/openid-configuration` automatically.
|
|
14
|
-
* Use this instead of `jwksUrl` for any standard OIDC-compliant IdP.
|
|
15
|
-
*/ discoveryUrl;
|
|
16
|
-
/** JWKS endpoint URL (RS256 / ES256 via remote key set). */ jwksUrl;
|
|
17
|
-
/** PEM-encoded public key or JWK JSON string (RS256 / ES256 static key). */ publicKey;
|
|
18
|
-
algorithms;
|
|
19
|
-
/** Shared secret for HS256. */ secret;
|
|
20
|
-
/** Issuer claim to validate (all non-devStatic variants). */ issuer;
|
|
21
|
-
/** Audience claim to validate (all non-devStatic variants). */ audience;
|
|
22
|
-
/** Static principal injected for every request (development only). */ devStatic;
|
|
23
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get ADMIN_ROLE () {
|
|
13
|
-
return _ability.ADMIN_ROLE;
|
|
14
|
-
},
|
|
15
|
-
get BuilderExtensions () {
|
|
16
|
-
return BuilderExtensions;
|
|
17
|
-
},
|
|
18
|
-
get createPrincipalFromPayload () {
|
|
19
|
-
return _ability.createPrincipalFromPayload;
|
|
20
|
-
},
|
|
21
|
-
get defineAbilitiesFor () {
|
|
22
|
-
return _ability.defineAbilitiesFor;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
const _extensibility = require("@decohere/core/extensibility");
|
|
26
|
-
const _builder = require("../builder/builder.js");
|
|
27
|
-
const _const = require("../const.js");
|
|
28
|
-
const _ability = require("./ability.js");
|
|
29
|
-
const _authconfig = require("./auth.config.js");
|
|
30
|
-
const _authtypes = require("./auth.types.js");
|
|
31
|
-
const _caslauthorizationservice = require("./casl-authorization.service.js");
|
|
32
|
-
const _tokenservice = require("./token-service.js");
|
|
33
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
34
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
35
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
36
|
-
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;
|
|
37
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
38
|
-
}
|
|
39
|
-
function _ts_metadata(k, v) {
|
|
40
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
41
|
-
}
|
|
42
|
-
class BuilderExtensions {
|
|
43
|
-
static withAuth(builder, abilityFactory = _ability.defineAbilitiesFor, options) {
|
|
44
|
-
builder.registerPreBuildStep(async (configService, containerBuilder)=>{
|
|
45
|
-
const authConfig = await configService.get(_authconfig.AuthConfig);
|
|
46
|
-
const tokenConfig = toTokenServiceConfig(authConfig);
|
|
47
|
-
const tokenService = new _tokenservice.TokenService(tokenConfig, options?.principalMapper);
|
|
48
|
-
containerBuilder.registerSingleton(_const.TokenServiceToken, tokenService);
|
|
49
|
-
containerBuilder.registerSingleton(_const.AuthorizationServiceToken, new _caslauthorizationservice.CaslAuthorizationService(abilityFactory, tokenService));
|
|
50
|
-
});
|
|
51
|
-
return builder;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
_ts_decorate([
|
|
55
|
-
(0, _extensibility.extension)(_builder.Builder),
|
|
56
|
-
_ts_metadata("design:type", Function),
|
|
57
|
-
_ts_metadata("design:paramtypes", [
|
|
58
|
-
typeof _builder.Builder === "undefined" ? Object : _builder.Builder,
|
|
59
|
-
typeof AbilityFactory === "undefined" ? Object : AbilityFactory,
|
|
60
|
-
typeof WithAuthOptions === "undefined" ? Object : WithAuthOptions
|
|
61
|
-
]),
|
|
62
|
-
_ts_metadata("design:returntype", void 0)
|
|
63
|
-
], BuilderExtensions, "withAuth", null);
|
|
64
|
-
function toTokenServiceConfig(config) {
|
|
65
|
-
// Prefer real verification strategies over devStatic so a leftover
|
|
66
|
-
// development block cannot disable OIDC/JWKS in any environment.
|
|
67
|
-
if (config.discoveryUrl != null) {
|
|
68
|
-
(0, _authtypes.assertNonEmptyAudience)(config.audience);
|
|
69
|
-
return {
|
|
70
|
-
discoveryUrl: config.discoveryUrl,
|
|
71
|
-
audience: config.audience
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
if (config.jwksUrl != null) {
|
|
75
|
-
(0, _authtypes.assertNonEmptyAudience)(config.audience);
|
|
76
|
-
return {
|
|
77
|
-
jwksUrl: config.jwksUrl,
|
|
78
|
-
issuer: config.issuer,
|
|
79
|
-
audience: config.audience
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
if (config.publicKey != null) {
|
|
83
|
-
(0, _authtypes.assertNonEmptyAudience)(config.audience);
|
|
84
|
-
return {
|
|
85
|
-
publicKey: config.publicKey,
|
|
86
|
-
algorithms: config.algorithms,
|
|
87
|
-
issuer: config.issuer,
|
|
88
|
-
audience: config.audience
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
if (config.secret != null) {
|
|
92
|
-
(0, _authtypes.assertNonEmptyAudience)(config.audience);
|
|
93
|
-
return {
|
|
94
|
-
secret: config.secret,
|
|
95
|
-
issuer: config.issuer,
|
|
96
|
-
audience: config.audience
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
if (config.devStatic != null) {
|
|
100
|
-
(0, _authtypes.assertDevStaticAllowed)();
|
|
101
|
-
return {
|
|
102
|
-
devStatic: config.devStatic
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
throw new Error("AuthConfig must specify one of: discoveryUrl, jwksUrl, publicKey, secret, or devStatic");
|
|
106
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get assertDevStaticAllowed () {
|
|
13
|
-
return assertDevStaticAllowed;
|
|
14
|
-
},
|
|
15
|
-
get assertNonEmptyAudience () {
|
|
16
|
-
return assertNonEmptyAudience;
|
|
17
|
-
},
|
|
18
|
-
get isDevStaticConfig () {
|
|
19
|
-
return isDevStaticConfig;
|
|
20
|
-
},
|
|
21
|
-
get isDevelopmentNodeEnv () {
|
|
22
|
-
return isDevelopmentNodeEnv;
|
|
23
|
-
},
|
|
24
|
-
get isDiscoveryConfig () {
|
|
25
|
-
return isDiscoveryConfig;
|
|
26
|
-
},
|
|
27
|
-
get isJwksConfig () {
|
|
28
|
-
return isJwksConfig;
|
|
29
|
-
},
|
|
30
|
-
get isPublicKeyConfig () {
|
|
31
|
-
return isPublicKeyConfig;
|
|
32
|
-
},
|
|
33
|
-
get isSecretConfig () {
|
|
34
|
-
return isSecretConfig;
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
function isDiscoveryConfig(config) {
|
|
38
|
-
return "discoveryUrl" in config;
|
|
39
|
-
}
|
|
40
|
-
function isDevStaticConfig(config) {
|
|
41
|
-
return "devStatic" in config;
|
|
42
|
-
}
|
|
43
|
-
function isJwksConfig(config) {
|
|
44
|
-
return "jwksUrl" in config;
|
|
45
|
-
}
|
|
46
|
-
function isPublicKeyConfig(config) {
|
|
47
|
-
return "publicKey" in config;
|
|
48
|
-
}
|
|
49
|
-
function isSecretConfig(config) {
|
|
50
|
-
return "secret" in config;
|
|
51
|
-
}
|
|
52
|
-
function isDevelopmentNodeEnv(nodeEnv = process.env.NODE_ENV) {
|
|
53
|
-
const env = nodeEnv?.toLowerCase();
|
|
54
|
-
return env === "development" || env === "dev";
|
|
55
|
-
}
|
|
56
|
-
function assertDevStaticAllowed(nodeEnv = process.env.NODE_ENV) {
|
|
57
|
-
if (!isDevelopmentNodeEnv(nodeEnv)) {
|
|
58
|
-
throw new Error(`AuthConfig.devStatic is only allowed when NODE_ENV is "development" or "dev" (got ${JSON.stringify(nodeEnv ?? "")}).`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function assertNonEmptyAudience(audience) {
|
|
62
|
-
if (typeof audience !== "string" || audience.trim().length === 0) {
|
|
63
|
-
throw new Error(`JWT audience must be a non-empty string (got ${JSON.stringify(audience)}). ` + "Empty audience disables aud validation and accepts tokens minted for other APIs.");
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "CaslAuthorizationService", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return CaslAuthorizationService;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _httptypes = require("../routing/http.types.js");
|
|
12
|
-
class CaslAuthorizationService {
|
|
13
|
-
factory;
|
|
14
|
-
tokenService;
|
|
15
|
-
constructor(factory, tokenService){
|
|
16
|
-
this.factory = factory;
|
|
17
|
-
this.tokenService = tokenService;
|
|
18
|
-
}
|
|
19
|
-
async authorizeRequest(request, action, subject) {
|
|
20
|
-
const principal = await this.authenticateRequest(request);
|
|
21
|
-
await this.authorize(principal, action, subject);
|
|
22
|
-
return principal;
|
|
23
|
-
}
|
|
24
|
-
async authenticateRequest(request) {
|
|
25
|
-
if (!this.tokenService) {
|
|
26
|
-
throw new Error("CaslAuthorizationService requires a TokenService to authenticate requests. Register it via .withAuth().");
|
|
27
|
-
}
|
|
28
|
-
return this.tokenService.verifyRequest(request);
|
|
29
|
-
}
|
|
30
|
-
async authorize(principal, action, subject) {
|
|
31
|
-
const ability = this.factory(principal);
|
|
32
|
-
if (ability.cannot(action, subject)) {
|
|
33
|
-
throw new _httptypes.ForbiddenError(`Cannot perform "${action}" on "${subject}"`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
_export_star(require("./ability.js"), exports);
|
|
6
|
-
_export_star(require("./auth.config.js"), exports);
|
|
7
|
-
_export_star(require("./auth.types.js"), exports);
|
|
8
|
-
_export_star(require("./casl-authorization.service.js"), exports);
|
|
9
|
-
_export_star(require("./principal-provider.js"), exports);
|
|
10
|
-
_export_star(require("./token-service.js"), exports);
|
|
11
|
-
function _export_star(from, to) {
|
|
12
|
-
Object.keys(from).forEach(function(k) {
|
|
13
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
14
|
-
Object.defineProperty(to, k, {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function() {
|
|
17
|
-
return from[k];
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
return from;
|
|
23
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "PrincipalProvider", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return PrincipalProvider;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
class PrincipalProvider {
|
|
12
|
-
_principal;
|
|
13
|
-
get currentPrincipal() {
|
|
14
|
-
return this._principal;
|
|
15
|
-
}
|
|
16
|
-
setPrincipal(principal) {
|
|
17
|
-
this._principal = principal;
|
|
18
|
-
}
|
|
19
|
-
}
|