@dangao/bun-server 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/controller.d.ts +35 -0
- package/dist/auth/controller.d.ts.map +1 -0
- package/dist/auth/decorators.d.ts +38 -0
- package/dist/auth/decorators.d.ts.map +1 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/jwt.d.ts +43 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/oauth2.d.ts +45 -0
- package/dist/auth/oauth2.d.ts.map +1 -0
- package/dist/auth/types.d.ts +238 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/controller/controller.d.ts +5 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/core/application.d.ts.map +1 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/di/module-registry.d.ts +14 -2
- package/dist/di/module-registry.d.ts.map +1 -1
- package/dist/di/module.d.ts +12 -1
- package/dist/di/module.d.ts.map +1 -1
- package/dist/extensions/index.d.ts +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/logger-module.d.ts +30 -0
- package/dist/extensions/logger-module.d.ts.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1154 -12
- package/dist/router/registry.d.ts +4 -1
- package/dist/router/registry.d.ts.map +1 -1
- package/dist/router/route.d.ts +9 -1
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/router.d.ts +8 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/security/access-decision-manager.d.ts +14 -0
- package/dist/security/access-decision-manager.d.ts.map +1 -0
- package/dist/security/authentication-manager.d.ts +22 -0
- package/dist/security/authentication-manager.d.ts.map +1 -0
- package/dist/security/context.d.ts +46 -0
- package/dist/security/context.d.ts.map +1 -0
- package/dist/security/filter.d.ts +27 -0
- package/dist/security/filter.d.ts.map +1 -0
- package/dist/security/index.d.ts +8 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/providers/index.d.ts +3 -0
- package/dist/security/providers/index.d.ts.map +1 -0
- package/dist/security/providers/jwt-provider.d.ts +19 -0
- package/dist/security/providers/jwt-provider.d.ts.map +1 -0
- package/dist/security/providers/oauth2-provider.d.ts +19 -0
- package/dist/security/providers/oauth2-provider.d.ts.map +1 -0
- package/dist/security/security-module.d.ts +50 -0
- package/dist/security/security-module.d.ts.map +1 -0
- package/dist/security/types.d.ts +152 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/swagger/decorators.d.ts +56 -0
- package/dist/swagger/decorators.d.ts.map +1 -0
- package/dist/swagger/generator.d.ts +17 -0
- package/dist/swagger/generator.d.ts.map +1 -0
- package/dist/swagger/index.d.ts +7 -0
- package/dist/swagger/index.d.ts.map +1 -0
- package/dist/swagger/swagger-extension.d.ts +25 -0
- package/dist/swagger/swagger-extension.d.ts.map +1 -0
- package/dist/swagger/swagger-module.d.ts +37 -0
- package/dist/swagger/swagger-module.d.ts.map +1 -0
- package/dist/swagger/types.d.ts +176 -0
- package/dist/swagger/types.d.ts.map +1 -0
- package/dist/swagger/ui.d.ts +13 -0
- package/dist/swagger/ui.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
var __legacyDecorateClassTS = 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")
|
|
5
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
6
|
+
else
|
|
7
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
8
|
+
if (d = decorators[i])
|
|
9
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
10
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
11
|
+
};
|
|
12
|
+
var __legacyDecorateParamTS = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
13
|
+
var __legacyMetadataTS = (k, v) => {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
|
15
|
+
return Reflect.metadata(k, v);
|
|
16
|
+
};
|
|
17
|
+
|
|
2
18
|
// src/request/body-parser.ts
|
|
3
19
|
class BodyParser {
|
|
4
20
|
static async parse(request) {
|
|
@@ -141,9 +157,12 @@ class Context {
|
|
|
141
157
|
this.statusCode = code;
|
|
142
158
|
}
|
|
143
159
|
createResponse(body, init) {
|
|
160
|
+
if (body instanceof Response) {
|
|
161
|
+
return body;
|
|
162
|
+
}
|
|
144
163
|
const headers = new Headers(this.responseHeaders);
|
|
145
164
|
if (body !== undefined && body !== null) {
|
|
146
|
-
if (typeof body === "object" && !(body instanceof
|
|
165
|
+
if (typeof body === "object" && !(body instanceof ArrayBuffer) && !(body instanceof Blob)) {
|
|
147
166
|
headers.set("Content-Type", "application/json");
|
|
148
167
|
const jsonString = JSON.stringify(body);
|
|
149
168
|
return new Response(jsonString, {
|
|
@@ -271,15 +290,19 @@ class Route {
|
|
|
271
290
|
method;
|
|
272
291
|
path;
|
|
273
292
|
handler;
|
|
293
|
+
controllerClass;
|
|
294
|
+
methodName;
|
|
274
295
|
pattern;
|
|
275
296
|
paramNames;
|
|
276
297
|
middlewarePipeline;
|
|
277
298
|
staticKey;
|
|
278
299
|
isStatic;
|
|
279
|
-
constructor(method, path, handler, middlewares = []) {
|
|
300
|
+
constructor(method, path, handler, middlewares = [], controllerClass, methodName) {
|
|
280
301
|
this.method = method;
|
|
281
302
|
this.path = path;
|
|
282
303
|
this.handler = handler;
|
|
304
|
+
this.controllerClass = controllerClass;
|
|
305
|
+
this.methodName = methodName;
|
|
283
306
|
const { pattern, paramNames } = this.parsePath(path);
|
|
284
307
|
this.pattern = pattern;
|
|
285
308
|
this.paramNames = paramNames;
|
|
@@ -328,8 +351,15 @@ class Router {
|
|
|
328
351
|
routes = [];
|
|
329
352
|
staticRoutes = new Map;
|
|
330
353
|
dynamicRoutes = [];
|
|
331
|
-
|
|
332
|
-
|
|
354
|
+
normalizePath(path) {
|
|
355
|
+
if (path.length > 1 && path.endsWith("/")) {
|
|
356
|
+
return path.slice(0, -1);
|
|
357
|
+
}
|
|
358
|
+
return path;
|
|
359
|
+
}
|
|
360
|
+
register(method, path, handler, middlewares = [], controllerClass, methodName) {
|
|
361
|
+
const normalizedPath = this.normalizePath(path);
|
|
362
|
+
const route = new Route(method, normalizedPath, handler, middlewares, controllerClass, methodName);
|
|
333
363
|
this.routes.push(route);
|
|
334
364
|
const staticKey = route.getStaticKey();
|
|
335
365
|
if (staticKey) {
|
|
@@ -368,14 +398,21 @@ class Router {
|
|
|
368
398
|
}
|
|
369
399
|
async handle(context) {
|
|
370
400
|
const method = context.method;
|
|
371
|
-
const
|
|
401
|
+
const path = this.normalizePath(context.path);
|
|
402
|
+
const route = this.findRoute(method, path);
|
|
372
403
|
if (!route) {
|
|
373
404
|
return;
|
|
374
405
|
}
|
|
375
|
-
const match = route.match(method,
|
|
406
|
+
const match = route.match(method, path);
|
|
376
407
|
if (match.matched) {
|
|
377
408
|
context.params = match.params;
|
|
378
409
|
}
|
|
410
|
+
if (route.controllerClass && route.methodName) {
|
|
411
|
+
context.routeHandler = {
|
|
412
|
+
controller: route.controllerClass,
|
|
413
|
+
method: route.methodName
|
|
414
|
+
};
|
|
415
|
+
}
|
|
379
416
|
return await route.execute(context);
|
|
380
417
|
}
|
|
381
418
|
getRoutes() {
|
|
@@ -401,8 +438,8 @@ class RouteRegistry {
|
|
|
401
438
|
}
|
|
402
439
|
return RouteRegistry.instance;
|
|
403
440
|
}
|
|
404
|
-
register(method, path, handler, middlewares = []) {
|
|
405
|
-
this.router.register(method, path, handler, middlewares);
|
|
441
|
+
register(method, path, handler, middlewares = [], controllerClass, methodName) {
|
|
442
|
+
this.router.register(method, path, handler, middlewares, controllerClass, methodName);
|
|
406
443
|
}
|
|
407
444
|
get(path, handler, middlewares = []) {
|
|
408
445
|
this.router.get(path, handler, middlewares);
|
|
@@ -1487,6 +1524,9 @@ class ControllerRegistry {
|
|
|
1487
1524
|
}
|
|
1488
1525
|
const result = method.apply(controllerInstance, params);
|
|
1489
1526
|
const responseData = await Promise.resolve(result);
|
|
1527
|
+
if (responseData instanceof Response) {
|
|
1528
|
+
return responseData;
|
|
1529
|
+
}
|
|
1490
1530
|
return context.createResponse(responseData);
|
|
1491
1531
|
} catch (error) {
|
|
1492
1532
|
if (error instanceof ValidationError) {
|
|
@@ -1512,7 +1552,7 @@ class ControllerRegistry {
|
|
|
1512
1552
|
if (propertyKey) {
|
|
1513
1553
|
middlewares.push(...getMethodMiddlewares(prototype, propertyKey));
|
|
1514
1554
|
}
|
|
1515
|
-
registry.register(route.method, fullPath, handler, middlewares);
|
|
1555
|
+
registry.register(route.method, fullPath, handler, middlewares, controllerClass, propertyKey);
|
|
1516
1556
|
}
|
|
1517
1557
|
}
|
|
1518
1558
|
combinePaths(basePath, methodPath) {
|
|
@@ -1526,6 +1566,9 @@ class ControllerRegistry {
|
|
|
1526
1566
|
getContainer() {
|
|
1527
1567
|
return this.container;
|
|
1528
1568
|
}
|
|
1569
|
+
getRegisteredControllers() {
|
|
1570
|
+
return Array.from(this.controllerContainers.keys());
|
|
1571
|
+
}
|
|
1529
1572
|
clear() {
|
|
1530
1573
|
this.controllers.clear();
|
|
1531
1574
|
this.container.clear();
|
|
@@ -1685,7 +1728,9 @@ function getModuleMetadata(moduleClass) {
|
|
|
1685
1728
|
imports: metadata.imports ?? [],
|
|
1686
1729
|
controllers: metadata.controllers ?? [],
|
|
1687
1730
|
providers: metadata.providers ?? [],
|
|
1688
|
-
exports: metadata.exports ?? []
|
|
1731
|
+
exports: metadata.exports ?? [],
|
|
1732
|
+
extensions: metadata.extensions ?? [],
|
|
1733
|
+
middlewares: metadata.middlewares ?? []
|
|
1689
1734
|
};
|
|
1690
1735
|
}
|
|
1691
1736
|
|
|
@@ -1744,7 +1789,9 @@ class ModuleRegistry {
|
|
|
1744
1789
|
metadata,
|
|
1745
1790
|
container,
|
|
1746
1791
|
controllersRegistered: false,
|
|
1747
|
-
attachedParents: new Set
|
|
1792
|
+
attachedParents: new Set,
|
|
1793
|
+
extensions: metadata.extensions ?? [],
|
|
1794
|
+
middlewares: metadata.middlewares ?? []
|
|
1748
1795
|
};
|
|
1749
1796
|
this.registerControllers(ref);
|
|
1750
1797
|
this.moduleRefs.set(moduleClass, ref);
|
|
@@ -1796,6 +1843,27 @@ class ModuleRegistry {
|
|
|
1796
1843
|
for (const exportedToken of moduleRef.metadata.exports) {
|
|
1797
1844
|
this.registerExport(parentContainer, moduleRef, exportedToken);
|
|
1798
1845
|
}
|
|
1846
|
+
for (const imported of moduleRef.metadata.imports) {
|
|
1847
|
+
const importedRef = this.moduleRefs.get(imported);
|
|
1848
|
+
if (importedRef) {
|
|
1849
|
+
moduleRef.extensions.push(...importedRef.extensions);
|
|
1850
|
+
moduleRef.middlewares.push(...importedRef.middlewares);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
getModuleExtensions(moduleClass) {
|
|
1855
|
+
const moduleRef = this.moduleRefs.get(moduleClass);
|
|
1856
|
+
if (!moduleRef) {
|
|
1857
|
+
return [];
|
|
1858
|
+
}
|
|
1859
|
+
return moduleRef.extensions;
|
|
1860
|
+
}
|
|
1861
|
+
getModuleMiddlewares(moduleClass) {
|
|
1862
|
+
const moduleRef = this.moduleRefs.get(moduleClass);
|
|
1863
|
+
if (!moduleRef) {
|
|
1864
|
+
return [];
|
|
1865
|
+
}
|
|
1866
|
+
return moduleRef.middlewares;
|
|
1799
1867
|
}
|
|
1800
1868
|
registerExport(parentContainer, moduleRef, token) {
|
|
1801
1869
|
if (!moduleRef.container.isRegistered(token)) {
|
|
@@ -1868,6 +1936,14 @@ class Application {
|
|
|
1868
1936
|
registerModule(moduleClass) {
|
|
1869
1937
|
const registry = ModuleRegistry.getInstance();
|
|
1870
1938
|
registry.register(moduleClass, this.getContainer());
|
|
1939
|
+
const extensions = registry.getModuleExtensions(moduleClass);
|
|
1940
|
+
for (const extension of extensions) {
|
|
1941
|
+
this.registerExtension(extension);
|
|
1942
|
+
}
|
|
1943
|
+
const middlewares = registry.getModuleMiddlewares(moduleClass);
|
|
1944
|
+
for (const middleware of middlewares) {
|
|
1945
|
+
this.use(middleware);
|
|
1946
|
+
}
|
|
1871
1947
|
}
|
|
1872
1948
|
registerWebSocketGateway(gatewayClass) {
|
|
1873
1949
|
this.websocketRegistry.register(gatewayClass);
|
|
@@ -1993,8 +2069,1048 @@ class ResponseBuilder {
|
|
|
1993
2069
|
});
|
|
1994
2070
|
}
|
|
1995
2071
|
}
|
|
2072
|
+
// src/extensions/logger-module.ts
|
|
2073
|
+
class LoggerModule {
|
|
2074
|
+
static forRoot(options = {}) {
|
|
2075
|
+
const extensions = [];
|
|
2076
|
+
const middlewares = [];
|
|
2077
|
+
const loggerExtension = new LoggerExtension(options.logger);
|
|
2078
|
+
extensions.push(loggerExtension);
|
|
2079
|
+
if (options.enableRequestLogging !== false) {
|
|
2080
|
+
const requestLoggingMiddleware = createLoggerMiddleware({
|
|
2081
|
+
prefix: options.requestLoggingPrefix
|
|
2082
|
+
});
|
|
2083
|
+
middlewares.push(requestLoggingMiddleware);
|
|
2084
|
+
}
|
|
2085
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, LoggerModule) || {};
|
|
2086
|
+
const metadata = {
|
|
2087
|
+
...existingMetadata,
|
|
2088
|
+
extensions,
|
|
2089
|
+
middlewares
|
|
2090
|
+
};
|
|
2091
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, LoggerModule);
|
|
2092
|
+
return LoggerModule;
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
LoggerModule = __legacyDecorateClassTS([
|
|
2096
|
+
Module({
|
|
2097
|
+
extensions: [],
|
|
2098
|
+
middlewares: []
|
|
2099
|
+
})
|
|
2100
|
+
], LoggerModule);
|
|
2101
|
+
|
|
1996
2102
|
// src/extensions/index.ts
|
|
1997
2103
|
import { LoggerManager as LoggerManager7, LogLevel as LogLevel2, SimpleLogger as SimpleLogger2 } from "@dangao/logsmith";
|
|
2104
|
+
// src/swagger/decorators.ts
|
|
2105
|
+
import"reflect-metadata";
|
|
2106
|
+
var API_TAG_METADATA_KEY = Symbol("swagger:api-tag");
|
|
2107
|
+
var API_OPERATION_METADATA_KEY = Symbol("swagger:api-operation");
|
|
2108
|
+
var API_PARAM_METADATA_KEY = Symbol("swagger:api-param");
|
|
2109
|
+
var API_BODY_METADATA_KEY = Symbol("swagger:api-body");
|
|
2110
|
+
var API_RESPONSE_METADATA_KEY = Symbol("swagger:api-response");
|
|
2111
|
+
function ApiTags(...tags) {
|
|
2112
|
+
return function(target, propertyKey) {
|
|
2113
|
+
if (propertyKey === undefined) {
|
|
2114
|
+
Reflect.defineMetadata(API_TAG_METADATA_KEY, tags, target);
|
|
2115
|
+
} else {
|
|
2116
|
+
const existingTags = Reflect.getMetadata(API_TAG_METADATA_KEY, target, propertyKey) || [];
|
|
2117
|
+
Reflect.defineMetadata(API_TAG_METADATA_KEY, [...existingTags, ...tags], target, propertyKey);
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
function ApiOperation(metadata) {
|
|
2122
|
+
return function(target, propertyKey) {
|
|
2123
|
+
Reflect.defineMetadata(API_OPERATION_METADATA_KEY, metadata, target, propertyKey);
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
function ApiParam(metadata) {
|
|
2127
|
+
return function(target, propertyKey, parameterIndex) {
|
|
2128
|
+
const existingParams = Reflect.getMetadata(API_PARAM_METADATA_KEY, target, propertyKey) || [];
|
|
2129
|
+
existingParams.push({ index: parameterIndex, metadata });
|
|
2130
|
+
Reflect.defineMetadata(API_PARAM_METADATA_KEY, existingParams, target, propertyKey);
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
function ApiBody(metadata) {
|
|
2134
|
+
return function(target, propertyKey) {
|
|
2135
|
+
Reflect.defineMetadata(API_BODY_METADATA_KEY, metadata, target, propertyKey);
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
function ApiResponse(metadata) {
|
|
2139
|
+
return function(target, propertyKey) {
|
|
2140
|
+
const existingResponses = Reflect.getMetadata(API_RESPONSE_METADATA_KEY, target, propertyKey) || [];
|
|
2141
|
+
existingResponses.push(metadata);
|
|
2142
|
+
Reflect.defineMetadata(API_RESPONSE_METADATA_KEY, existingResponses, target, propertyKey);
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
function getApiTags(target, propertyKey) {
|
|
2146
|
+
if (propertyKey === undefined) {
|
|
2147
|
+
return Reflect.getMetadata(API_TAG_METADATA_KEY, target) || [];
|
|
2148
|
+
}
|
|
2149
|
+
return Reflect.getMetadata(API_TAG_METADATA_KEY, target, propertyKey) || [];
|
|
2150
|
+
}
|
|
2151
|
+
function getApiOperation(target, propertyKey) {
|
|
2152
|
+
return Reflect.getMetadata(API_OPERATION_METADATA_KEY, target, propertyKey);
|
|
2153
|
+
}
|
|
2154
|
+
function getApiParams(target, propertyKey) {
|
|
2155
|
+
return Reflect.getMetadata(API_PARAM_METADATA_KEY, target, propertyKey) || [];
|
|
2156
|
+
}
|
|
2157
|
+
function getApiBody(target, propertyKey) {
|
|
2158
|
+
return Reflect.getMetadata(API_BODY_METADATA_KEY, target, propertyKey);
|
|
2159
|
+
}
|
|
2160
|
+
function getApiResponses(target, propertyKey) {
|
|
2161
|
+
return Reflect.getMetadata(API_RESPONSE_METADATA_KEY, target, propertyKey) || [];
|
|
2162
|
+
}
|
|
2163
|
+
// src/swagger/generator.ts
|
|
2164
|
+
class SwaggerGenerator {
|
|
2165
|
+
options;
|
|
2166
|
+
constructor(options) {
|
|
2167
|
+
this.options = options;
|
|
2168
|
+
}
|
|
2169
|
+
generate() {
|
|
2170
|
+
const document = {
|
|
2171
|
+
openapi: "3.0.0",
|
|
2172
|
+
info: {
|
|
2173
|
+
title: this.options.info.title,
|
|
2174
|
+
version: this.options.info.version,
|
|
2175
|
+
description: this.options.info.description,
|
|
2176
|
+
contact: this.options.info.contact,
|
|
2177
|
+
license: this.options.info.license
|
|
2178
|
+
},
|
|
2179
|
+
servers: this.options.servers,
|
|
2180
|
+
tags: this.options.tags,
|
|
2181
|
+
paths: {}
|
|
2182
|
+
};
|
|
2183
|
+
const controllerRegistry = ControllerRegistry.getInstance();
|
|
2184
|
+
const controllers = controllerRegistry.getRegisteredControllers();
|
|
2185
|
+
if (controllers.length === 0) {
|
|
2186
|
+
return document;
|
|
2187
|
+
}
|
|
2188
|
+
for (const controllerClass of controllers) {
|
|
2189
|
+
const controllerMetadata = getControllerMetadata(controllerClass);
|
|
2190
|
+
if (!controllerMetadata) {
|
|
2191
|
+
console.log(`[SwaggerGenerator] No metadata for controller: ${controllerClass.name}`);
|
|
2192
|
+
continue;
|
|
2193
|
+
}
|
|
2194
|
+
const basePath = controllerMetadata.path;
|
|
2195
|
+
const prototype = controllerClass.prototype;
|
|
2196
|
+
const routes = getRouteMetadata(prototype);
|
|
2197
|
+
if (!routes || routes.length === 0) {
|
|
2198
|
+
continue;
|
|
2199
|
+
}
|
|
2200
|
+
const controllerTags = getApiTags(controllerClass);
|
|
2201
|
+
for (const route of routes) {
|
|
2202
|
+
let propertyKey = route.propertyKey;
|
|
2203
|
+
if (!propertyKey && route.handler) {
|
|
2204
|
+
propertyKey = route.handler.name;
|
|
2205
|
+
if (!propertyKey || propertyKey === "") {
|
|
2206
|
+
const propertyNames = Object.getOwnPropertyNames(prototype);
|
|
2207
|
+
for (const key of propertyNames) {
|
|
2208
|
+
if (key === "constructor")
|
|
2209
|
+
continue;
|
|
2210
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, key);
|
|
2211
|
+
if (descriptor && descriptor.value === route.handler) {
|
|
2212
|
+
propertyKey = key;
|
|
2213
|
+
break;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
if (!propertyKey) {
|
|
2219
|
+
continue;
|
|
2220
|
+
}
|
|
2221
|
+
const method = route.method.toLowerCase();
|
|
2222
|
+
let methodPath = route.path;
|
|
2223
|
+
if (methodPath && !methodPath.startsWith("/")) {
|
|
2224
|
+
methodPath = "/" + methodPath;
|
|
2225
|
+
}
|
|
2226
|
+
const swaggerPath = (basePath + methodPath).replace(/:([^/]+)/g, "{$1}");
|
|
2227
|
+
const fullPath = this.normalizePath(swaggerPath);
|
|
2228
|
+
const operationMetadata = getApiOperation(prototype, propertyKey);
|
|
2229
|
+
const methodTags = getApiTags(prototype, propertyKey);
|
|
2230
|
+
const params = getApiParams(prototype, propertyKey);
|
|
2231
|
+
const body = getApiBody(prototype, propertyKey);
|
|
2232
|
+
const responses = getApiResponses(prototype, propertyKey);
|
|
2233
|
+
const tags = [...new Set([...controllerTags, ...methodTags])];
|
|
2234
|
+
const pathItem = {
|
|
2235
|
+
summary: operationMetadata?.summary,
|
|
2236
|
+
description: operationMetadata?.description,
|
|
2237
|
+
operationId: operationMetadata?.operationId || propertyKey,
|
|
2238
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
2239
|
+
deprecated: operationMetadata?.deprecated
|
|
2240
|
+
};
|
|
2241
|
+
const pathParams = [];
|
|
2242
|
+
const pathParamMatches = fullPath.matchAll(/\{([^}]+)\}/g);
|
|
2243
|
+
for (const match of pathParamMatches) {
|
|
2244
|
+
const paramName = match[1];
|
|
2245
|
+
const existingParam = params.find((p) => p.metadata.name === paramName && p.metadata.in === "path");
|
|
2246
|
+
if (!existingParam) {
|
|
2247
|
+
pathParams.push({
|
|
2248
|
+
name: paramName,
|
|
2249
|
+
in: "path",
|
|
2250
|
+
required: true,
|
|
2251
|
+
schema: { type: "string" }
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
for (const param of params) {
|
|
2256
|
+
pathParams.push({
|
|
2257
|
+
name: param.metadata.name,
|
|
2258
|
+
in: param.metadata.in,
|
|
2259
|
+
description: param.metadata.description,
|
|
2260
|
+
required: param.metadata.required,
|
|
2261
|
+
schema: param.metadata.schema
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
2264
|
+
if (pathParams.length > 0) {
|
|
2265
|
+
pathItem.parameters = pathParams;
|
|
2266
|
+
}
|
|
2267
|
+
if (body) {
|
|
2268
|
+
pathItem.requestBody = {
|
|
2269
|
+
description: body.description,
|
|
2270
|
+
required: body.required,
|
|
2271
|
+
content: {
|
|
2272
|
+
"application/json": {
|
|
2273
|
+
schema: body.schema,
|
|
2274
|
+
examples: body.examples
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
};
|
|
2278
|
+
}
|
|
2279
|
+
if (responses.length > 0) {
|
|
2280
|
+
pathItem.responses = {};
|
|
2281
|
+
for (const response of responses) {
|
|
2282
|
+
pathItem.responses[String(response.status)] = {
|
|
2283
|
+
description: response.description,
|
|
2284
|
+
content: {
|
|
2285
|
+
"application/json": {
|
|
2286
|
+
schema: response.schema,
|
|
2287
|
+
examples: response.examples
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2292
|
+
} else {
|
|
2293
|
+
pathItem.responses = {
|
|
2294
|
+
"200": {
|
|
2295
|
+
description: "Success"
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
if (!document.paths[fullPath]) {
|
|
2300
|
+
document.paths[fullPath] = {};
|
|
2301
|
+
}
|
|
2302
|
+
document.paths[fullPath][method] = pathItem;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
return document;
|
|
2306
|
+
}
|
|
2307
|
+
normalizePath(path) {
|
|
2308
|
+
path = path.replace(/\/+/g, "/");
|
|
2309
|
+
if (!path.startsWith("/")) {
|
|
2310
|
+
path = "/" + path;
|
|
2311
|
+
}
|
|
2312
|
+
if (path.length > 1 && path.endsWith("/")) {
|
|
2313
|
+
path = path.slice(0, -1);
|
|
2314
|
+
}
|
|
2315
|
+
return path;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
// src/swagger/swagger-extension.ts
|
|
2319
|
+
class SwaggerExtension {
|
|
2320
|
+
options;
|
|
2321
|
+
generator;
|
|
2322
|
+
constructor(options) {
|
|
2323
|
+
this.options = options;
|
|
2324
|
+
}
|
|
2325
|
+
register(_container) {
|
|
2326
|
+
this.generator = new SwaggerGenerator(this.options);
|
|
2327
|
+
}
|
|
2328
|
+
getGenerator() {
|
|
2329
|
+
if (!this.generator) {
|
|
2330
|
+
this.generator = new SwaggerGenerator(this.options);
|
|
2331
|
+
}
|
|
2332
|
+
return this.generator;
|
|
2333
|
+
}
|
|
2334
|
+
generateJSON() {
|
|
2335
|
+
return JSON.stringify(this.getGenerator().generate(), null, 2);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
// src/swagger/ui.ts
|
|
2339
|
+
var SWAGGER_UI_HTML = (jsonUrl, title) => `<!DOCTYPE html>
|
|
2340
|
+
<html lang="en">
|
|
2341
|
+
<head>
|
|
2342
|
+
<meta charset="UTF-8">
|
|
2343
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2344
|
+
<title>${title} - Swagger UI</title>
|
|
2345
|
+
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css" />
|
|
2346
|
+
<style>
|
|
2347
|
+
html {
|
|
2348
|
+
box-sizing: border-box;
|
|
2349
|
+
overflow: -moz-scrollbars-vertical;
|
|
2350
|
+
overflow-y: scroll;
|
|
2351
|
+
}
|
|
2352
|
+
*, *:before, *:after {
|
|
2353
|
+
box-sizing: inherit;
|
|
2354
|
+
}
|
|
2355
|
+
body {
|
|
2356
|
+
margin:0;
|
|
2357
|
+
background: #fafafa;
|
|
2358
|
+
}
|
|
2359
|
+
</style>
|
|
2360
|
+
</head>
|
|
2361
|
+
<body>
|
|
2362
|
+
<div id="swagger-ui"></div>
|
|
2363
|
+
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js"></script>
|
|
2364
|
+
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-standalone-preset.js"></script>
|
|
2365
|
+
<script>
|
|
2366
|
+
window.onload = function() {
|
|
2367
|
+
const ui = SwaggerUIBundle({
|
|
2368
|
+
url: "${jsonUrl}",
|
|
2369
|
+
dom_id: '#swagger-ui',
|
|
2370
|
+
deepLinking: true,
|
|
2371
|
+
presets: [
|
|
2372
|
+
SwaggerUIBundle.presets.apis,
|
|
2373
|
+
SwaggerUIStandalonePreset
|
|
2374
|
+
],
|
|
2375
|
+
plugins: [
|
|
2376
|
+
SwaggerUIBundle.plugins.DownloadUrl
|
|
2377
|
+
],
|
|
2378
|
+
layout: "StandaloneLayout"
|
|
2379
|
+
});
|
|
2380
|
+
};
|
|
2381
|
+
</script>
|
|
2382
|
+
</body>
|
|
2383
|
+
</html>`;
|
|
2384
|
+
function createSwaggerUIMiddleware(extension, options = {}) {
|
|
2385
|
+
const uiPath = options.uiPath || "/swagger";
|
|
2386
|
+
const jsonPath = options.jsonPath || "/swagger.json";
|
|
2387
|
+
const title = options.title || "API Documentation";
|
|
2388
|
+
return async (ctx, next) => {
|
|
2389
|
+
const url = new URL(ctx.request.url);
|
|
2390
|
+
const pathname = url.pathname;
|
|
2391
|
+
if (pathname === uiPath || pathname === `${uiPath}/`) {
|
|
2392
|
+
const html = SWAGGER_UI_HTML(jsonPath, title);
|
|
2393
|
+
return new Response(html, {
|
|
2394
|
+
headers: {
|
|
2395
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
2396
|
+
}
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
if (pathname === jsonPath) {
|
|
2400
|
+
const json = extension.generateJSON();
|
|
2401
|
+
return new Response(json, {
|
|
2402
|
+
headers: {
|
|
2403
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
2404
|
+
}
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
2407
|
+
return await next();
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// src/swagger/swagger-module.ts
|
|
2412
|
+
class SwaggerModule {
|
|
2413
|
+
static forRoot(options) {
|
|
2414
|
+
const extensions = [];
|
|
2415
|
+
const middlewares = [];
|
|
2416
|
+
const swaggerExtension = new SwaggerExtension({
|
|
2417
|
+
info: options.info,
|
|
2418
|
+
servers: options.servers,
|
|
2419
|
+
basePath: options.basePath,
|
|
2420
|
+
tags: options.tags
|
|
2421
|
+
});
|
|
2422
|
+
extensions.push(swaggerExtension);
|
|
2423
|
+
if (options.enableUI !== false) {
|
|
2424
|
+
const uiMiddleware = createSwaggerUIMiddleware(swaggerExtension, {
|
|
2425
|
+
uiPath: options.uiPath || "/swagger",
|
|
2426
|
+
jsonPath: options.jsonPath || "/swagger.json",
|
|
2427
|
+
title: options.uiTitle || options.info.title || "API Documentation"
|
|
2428
|
+
});
|
|
2429
|
+
middlewares.push(uiMiddleware);
|
|
2430
|
+
}
|
|
2431
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SwaggerModule) || {};
|
|
2432
|
+
const metadata = {
|
|
2433
|
+
...existingMetadata,
|
|
2434
|
+
extensions,
|
|
2435
|
+
middlewares
|
|
2436
|
+
};
|
|
2437
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SwaggerModule);
|
|
2438
|
+
return SwaggerModule;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
SwaggerModule = __legacyDecorateClassTS([
|
|
2442
|
+
Module({
|
|
2443
|
+
extensions: [],
|
|
2444
|
+
middlewares: []
|
|
2445
|
+
})
|
|
2446
|
+
], SwaggerModule);
|
|
2447
|
+
// src/security/context.ts
|
|
2448
|
+
class SecurityContextImpl {
|
|
2449
|
+
_authentication = null;
|
|
2450
|
+
get authentication() {
|
|
2451
|
+
return this._authentication;
|
|
2452
|
+
}
|
|
2453
|
+
setAuthentication(authentication) {
|
|
2454
|
+
this._authentication = authentication;
|
|
2455
|
+
}
|
|
2456
|
+
isAuthenticated() {
|
|
2457
|
+
return this._authentication?.authenticated ?? false;
|
|
2458
|
+
}
|
|
2459
|
+
getPrincipal() {
|
|
2460
|
+
return this._authentication?.principal ?? null;
|
|
2461
|
+
}
|
|
2462
|
+
getAuthorities() {
|
|
2463
|
+
return this._authentication?.authorities ?? [];
|
|
2464
|
+
}
|
|
2465
|
+
clear() {
|
|
2466
|
+
this._authentication = null;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
class SecurityContextHolder {
|
|
2471
|
+
static contexts = new Map;
|
|
2472
|
+
static getContext() {
|
|
2473
|
+
const threadId = Bun.main ? 0 : Date.now();
|
|
2474
|
+
if (!this.contexts.has(threadId)) {
|
|
2475
|
+
this.contexts.set(threadId, new SecurityContextImpl);
|
|
2476
|
+
}
|
|
2477
|
+
return this.contexts.get(threadId);
|
|
2478
|
+
}
|
|
2479
|
+
static clearContext() {
|
|
2480
|
+
const threadId = Bun.main ? 0 : Date.now();
|
|
2481
|
+
this.contexts.delete(threadId);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
// src/security/authentication-manager.ts
|
|
2485
|
+
class AuthenticationManager {
|
|
2486
|
+
providers = [];
|
|
2487
|
+
registerProvider(provider) {
|
|
2488
|
+
this.providers.push(provider);
|
|
2489
|
+
}
|
|
2490
|
+
async authenticate(request) {
|
|
2491
|
+
const type = request.type || "default";
|
|
2492
|
+
const provider = this.providers.find((p) => p.supports(type));
|
|
2493
|
+
if (!provider) {
|
|
2494
|
+
throw new Error(`No authentication provider found for type: ${type}`);
|
|
2495
|
+
}
|
|
2496
|
+
return await provider.authenticate(request);
|
|
2497
|
+
}
|
|
2498
|
+
getProviders() {
|
|
2499
|
+
return [...this.providers];
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
// src/security/access-decision-manager.ts
|
|
2503
|
+
class RoleBasedAccessDecisionManager {
|
|
2504
|
+
decide(authentication, requiredAuthorities) {
|
|
2505
|
+
if (requiredAuthorities.length === 0) {
|
|
2506
|
+
return true;
|
|
2507
|
+
}
|
|
2508
|
+
if (!authentication.authenticated) {
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
const userAuthorities = authentication.authorities || [];
|
|
2512
|
+
return requiredAuthorities.some((required) => userAuthorities.includes(required));
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
// src/auth/decorators.ts
|
|
2516
|
+
import"reflect-metadata";
|
|
2517
|
+
var AUTH_METADATA_KEY = Symbol("@dangao/bun-server:auth");
|
|
2518
|
+
function Auth(config = {}) {
|
|
2519
|
+
return (target, propertyKey) => {
|
|
2520
|
+
const metadata = Reflect.getMetadata(AUTH_METADATA_KEY, target) || {};
|
|
2521
|
+
metadata[propertyKey] = {
|
|
2522
|
+
required: config.required !== false,
|
|
2523
|
+
roles: config.roles || [],
|
|
2524
|
+
allowAnonymous: config.allowAnonymous || false
|
|
2525
|
+
};
|
|
2526
|
+
Reflect.defineMetadata(AUTH_METADATA_KEY, metadata, target);
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
function getAuthMetadata(target, propertyKey) {
|
|
2530
|
+
const metadata = Reflect.getMetadata(AUTH_METADATA_KEY, target);
|
|
2531
|
+
return metadata?.[propertyKey];
|
|
2532
|
+
}
|
|
2533
|
+
function requiresAuth(target, propertyKey) {
|
|
2534
|
+
const config = getAuthMetadata(target, propertyKey);
|
|
2535
|
+
return config?.required !== false;
|
|
2536
|
+
}
|
|
2537
|
+
function checkRoles(target, propertyKey, userRoles = []) {
|
|
2538
|
+
const config = getAuthMetadata(target, propertyKey);
|
|
2539
|
+
if (!config?.roles || config.roles.length === 0) {
|
|
2540
|
+
return true;
|
|
2541
|
+
}
|
|
2542
|
+
return config.roles.some((role) => userRoles.includes(role));
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
// src/security/filter.ts
|
|
2546
|
+
function createSecurityFilter(config) {
|
|
2547
|
+
const {
|
|
2548
|
+
authenticationManager,
|
|
2549
|
+
accessDecisionManager = new RoleBasedAccessDecisionManager,
|
|
2550
|
+
excludePaths = [],
|
|
2551
|
+
defaultAuthRequired = true,
|
|
2552
|
+
extractToken
|
|
2553
|
+
} = config;
|
|
2554
|
+
return async (ctx, next) => {
|
|
2555
|
+
const path = ctx.request.url.split("?")[0];
|
|
2556
|
+
if (excludePaths.some((exclude) => path.startsWith(exclude))) {
|
|
2557
|
+
return await next();
|
|
2558
|
+
}
|
|
2559
|
+
const securityContext = SecurityContextHolder.getContext();
|
|
2560
|
+
try {
|
|
2561
|
+
const token = extractToken ? extractToken(ctx) : extractTokenFromHeader(ctx);
|
|
2562
|
+
if (token) {
|
|
2563
|
+
const request = {
|
|
2564
|
+
principal: "",
|
|
2565
|
+
credentials: token,
|
|
2566
|
+
type: "jwt"
|
|
2567
|
+
};
|
|
2568
|
+
const authentication = await authenticationManager.authenticate(request);
|
|
2569
|
+
if (authentication) {
|
|
2570
|
+
securityContext.setAuthentication(authentication);
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
const handler = ctx.routeHandler;
|
|
2574
|
+
if (handler) {
|
|
2575
|
+
const controller = handler.controller;
|
|
2576
|
+
const method = handler.method;
|
|
2577
|
+
if (requiresAuth(controller, method)) {
|
|
2578
|
+
const authentication = securityContext.authentication;
|
|
2579
|
+
if (!authentication || !authentication.authenticated) {
|
|
2580
|
+
throw new UnauthorizedException("Authentication required");
|
|
2581
|
+
}
|
|
2582
|
+
const requiredRoles = getRequiredRoles(controller, method);
|
|
2583
|
+
if (requiredRoles.length > 0) {
|
|
2584
|
+
const hasAccess = accessDecisionManager.decide(authentication, requiredRoles);
|
|
2585
|
+
if (!hasAccess) {
|
|
2586
|
+
const userRoles = authentication.authorities || [];
|
|
2587
|
+
throw new ForbiddenException(`Insufficient permissions. Required roles: ${requiredRoles.join(", ")}, User roles: ${userRoles.join(", ")}`);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
} else if (defaultAuthRequired && !securityContext.isAuthenticated()) {
|
|
2592
|
+
throw new UnauthorizedException("Authentication required");
|
|
2593
|
+
}
|
|
2594
|
+
ctx.security = securityContext;
|
|
2595
|
+
ctx.auth = {
|
|
2596
|
+
isAuthenticated: securityContext.isAuthenticated(),
|
|
2597
|
+
user: securityContext.getPrincipal(),
|
|
2598
|
+
payload: securityContext.authentication?.details
|
|
2599
|
+
};
|
|
2600
|
+
return await next();
|
|
2601
|
+
} finally {}
|
|
2602
|
+
};
|
|
2603
|
+
}
|
|
2604
|
+
function extractTokenFromHeader(ctx) {
|
|
2605
|
+
const authHeader = ctx.getHeader("authorization");
|
|
2606
|
+
if (!authHeader) {
|
|
2607
|
+
return null;
|
|
2608
|
+
}
|
|
2609
|
+
const parts = authHeader.split(" ");
|
|
2610
|
+
if (parts.length !== 2 || parts[0] !== "Bearer") {
|
|
2611
|
+
return null;
|
|
2612
|
+
}
|
|
2613
|
+
return parts[1];
|
|
2614
|
+
}
|
|
2615
|
+
function getRequiredRoles(target, propertyKey) {
|
|
2616
|
+
const metadata = getAuthMetadata(target, propertyKey);
|
|
2617
|
+
return metadata?.roles || [];
|
|
2618
|
+
}
|
|
2619
|
+
// src/security/providers/jwt-provider.ts
|
|
2620
|
+
class JwtAuthenticationProvider {
|
|
2621
|
+
jwtUtil;
|
|
2622
|
+
supportedTypes = ["jwt", "bearer"];
|
|
2623
|
+
constructor(jwtUtil) {
|
|
2624
|
+
this.jwtUtil = jwtUtil;
|
|
2625
|
+
}
|
|
2626
|
+
supports(type) {
|
|
2627
|
+
return this.supportedTypes.includes(type.toLowerCase());
|
|
2628
|
+
}
|
|
2629
|
+
async authenticate(request) {
|
|
2630
|
+
const token = request.credentials;
|
|
2631
|
+
if (!token) {
|
|
2632
|
+
return null;
|
|
2633
|
+
}
|
|
2634
|
+
const payload = this.jwtUtil.verify(token);
|
|
2635
|
+
if (!payload) {
|
|
2636
|
+
return null;
|
|
2637
|
+
}
|
|
2638
|
+
const principal = {
|
|
2639
|
+
id: payload.sub,
|
|
2640
|
+
username: payload.username || payload.sub,
|
|
2641
|
+
roles: payload.roles || []
|
|
2642
|
+
};
|
|
2643
|
+
const authorities = principal.roles || [];
|
|
2644
|
+
return {
|
|
2645
|
+
authenticated: true,
|
|
2646
|
+
principal,
|
|
2647
|
+
credentials: { type: "jwt", data: token },
|
|
2648
|
+
authorities,
|
|
2649
|
+
details: payload
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
// src/security/providers/oauth2-provider.ts
|
|
2654
|
+
class OAuth2AuthenticationProvider {
|
|
2655
|
+
oauth2Service;
|
|
2656
|
+
supportedTypes = ["oauth2", "authorization_code"];
|
|
2657
|
+
constructor(oauth2Service) {
|
|
2658
|
+
this.oauth2Service = oauth2Service;
|
|
2659
|
+
}
|
|
2660
|
+
supports(type) {
|
|
2661
|
+
return this.supportedTypes.includes(type.toLowerCase());
|
|
2662
|
+
}
|
|
2663
|
+
async authenticate(request) {
|
|
2664
|
+
const credentials = request.credentials;
|
|
2665
|
+
if (!credentials || credentials.grantType !== "authorization_code") {
|
|
2666
|
+
return null;
|
|
2667
|
+
}
|
|
2668
|
+
const tokenResponse = await this.oauth2Service.exchangeCodeForToken(credentials);
|
|
2669
|
+
if (!tokenResponse) {
|
|
2670
|
+
return null;
|
|
2671
|
+
}
|
|
2672
|
+
const userInfo = {
|
|
2673
|
+
id: "user-1",
|
|
2674
|
+
username: "user",
|
|
2675
|
+
roles: ["user"]
|
|
2676
|
+
};
|
|
2677
|
+
const principal = {
|
|
2678
|
+
id: userInfo.id,
|
|
2679
|
+
username: userInfo.username,
|
|
2680
|
+
roles: userInfo.roles
|
|
2681
|
+
};
|
|
2682
|
+
return {
|
|
2683
|
+
authenticated: true,
|
|
2684
|
+
principal,
|
|
2685
|
+
credentials: {
|
|
2686
|
+
type: "oauth2",
|
|
2687
|
+
data: tokenResponse
|
|
2688
|
+
},
|
|
2689
|
+
authorities: principal.roles || [],
|
|
2690
|
+
details: tokenResponse
|
|
2691
|
+
};
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
// src/auth/jwt.ts
|
|
2695
|
+
class JWTUtil {
|
|
2696
|
+
config;
|
|
2697
|
+
constructor(config) {
|
|
2698
|
+
this.config = {
|
|
2699
|
+
secret: config.secret,
|
|
2700
|
+
accessTokenExpiresIn: config.accessTokenExpiresIn ?? 3600,
|
|
2701
|
+
refreshTokenExpiresIn: config.refreshTokenExpiresIn ?? 86400 * 7,
|
|
2702
|
+
algorithm: config.algorithm ?? "HS256"
|
|
2703
|
+
};
|
|
2704
|
+
}
|
|
2705
|
+
generateAccessToken(payload) {
|
|
2706
|
+
const now = Math.floor(Date.now() / 1000);
|
|
2707
|
+
const tokenPayload = {
|
|
2708
|
+
...payload,
|
|
2709
|
+
sub: payload.sub,
|
|
2710
|
+
iat: now,
|
|
2711
|
+
exp: now + this.config.accessTokenExpiresIn
|
|
2712
|
+
};
|
|
2713
|
+
return this.sign(tokenPayload);
|
|
2714
|
+
}
|
|
2715
|
+
generateRefreshToken(payload) {
|
|
2716
|
+
const now = Math.floor(Date.now() / 1000);
|
|
2717
|
+
const tokenPayload = {
|
|
2718
|
+
...payload,
|
|
2719
|
+
sub: payload.sub,
|
|
2720
|
+
iat: now,
|
|
2721
|
+
exp: now + this.config.refreshTokenExpiresIn
|
|
2722
|
+
};
|
|
2723
|
+
return this.sign(tokenPayload);
|
|
2724
|
+
}
|
|
2725
|
+
verify(token) {
|
|
2726
|
+
try {
|
|
2727
|
+
const parts = token.split(".");
|
|
2728
|
+
if (parts.length !== 3) {
|
|
2729
|
+
return null;
|
|
2730
|
+
}
|
|
2731
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
2732
|
+
const signature = this.signature(parts[0] + "." + parts[1]);
|
|
2733
|
+
if (signature !== parts[2]) {
|
|
2734
|
+
return null;
|
|
2735
|
+
}
|
|
2736
|
+
if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
|
|
2737
|
+
return null;
|
|
2738
|
+
}
|
|
2739
|
+
return payload;
|
|
2740
|
+
} catch {
|
|
2741
|
+
return null;
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
sign(payload) {
|
|
2745
|
+
const header = {
|
|
2746
|
+
alg: this.config.algorithm,
|
|
2747
|
+
typ: "JWT"
|
|
2748
|
+
};
|
|
2749
|
+
const encodedHeader = this.base64UrlEncode(JSON.stringify(header));
|
|
2750
|
+
const encodedPayload = this.base64UrlEncode(JSON.stringify(payload));
|
|
2751
|
+
const signature = this.signature(encodedHeader + "." + encodedPayload);
|
|
2752
|
+
return `${encodedHeader}.${encodedPayload}.${signature}`;
|
|
2753
|
+
}
|
|
2754
|
+
signature(data) {
|
|
2755
|
+
const encoder = new TextEncoder;
|
|
2756
|
+
const keyData = encoder.encode(this.config.secret);
|
|
2757
|
+
const messageData = encoder.encode(data);
|
|
2758
|
+
const hash = this.hmacSha256(keyData, messageData);
|
|
2759
|
+
return this.base64UrlEncode(Buffer.from(hash).toString("base64"));
|
|
2760
|
+
}
|
|
2761
|
+
hmacSha256(key, data) {
|
|
2762
|
+
const blockSize = 64;
|
|
2763
|
+
let keyBuffer;
|
|
2764
|
+
if (key.length > blockSize) {
|
|
2765
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
2766
|
+
hasher.update(key);
|
|
2767
|
+
keyBuffer = new Uint8Array(hasher.digest());
|
|
2768
|
+
} else {
|
|
2769
|
+
keyBuffer = new Uint8Array(blockSize);
|
|
2770
|
+
keyBuffer.set(key);
|
|
2771
|
+
}
|
|
2772
|
+
const oKeyPad = new Uint8Array(blockSize);
|
|
2773
|
+
const iKeyPad = new Uint8Array(blockSize);
|
|
2774
|
+
for (let i = 0;i < blockSize; i++) {
|
|
2775
|
+
oKeyPad[i] = keyBuffer[i] ^ 92;
|
|
2776
|
+
iKeyPad[i] = keyBuffer[i] ^ 54;
|
|
2777
|
+
}
|
|
2778
|
+
const innerData = new Uint8Array(iKeyPad.length + data.length);
|
|
2779
|
+
innerData.set(iKeyPad);
|
|
2780
|
+
innerData.set(data, iKeyPad.length);
|
|
2781
|
+
const innerHasher = new Bun.CryptoHasher("sha256");
|
|
2782
|
+
innerHasher.update(innerData);
|
|
2783
|
+
const innerHash = new Uint8Array(innerHasher.digest());
|
|
2784
|
+
const outerData = new Uint8Array(oKeyPad.length + innerHash.length);
|
|
2785
|
+
outerData.set(oKeyPad);
|
|
2786
|
+
outerData.set(innerHash, oKeyPad.length);
|
|
2787
|
+
const outerHasher = new Bun.CryptoHasher("sha256");
|
|
2788
|
+
outerHasher.update(outerData);
|
|
2789
|
+
return new Uint8Array(outerHasher.digest());
|
|
2790
|
+
}
|
|
2791
|
+
base64UrlEncode(str) {
|
|
2792
|
+
return Buffer.from(str).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
// src/auth/oauth2.ts
|
|
2797
|
+
class OAuth2Service {
|
|
2798
|
+
jwtUtil;
|
|
2799
|
+
clients;
|
|
2800
|
+
codes;
|
|
2801
|
+
codeConfig;
|
|
2802
|
+
userProvider;
|
|
2803
|
+
constructor(jwtUtil, clients = [], codeConfig = {}, userProvider) {
|
|
2804
|
+
this.jwtUtil = jwtUtil;
|
|
2805
|
+
this.clients = new Map;
|
|
2806
|
+
this.codes = new Map;
|
|
2807
|
+
this.codeConfig = {
|
|
2808
|
+
expiresIn: codeConfig.expiresIn ?? 600,
|
|
2809
|
+
length: codeConfig.length ?? 32
|
|
2810
|
+
};
|
|
2811
|
+
for (const client of clients) {
|
|
2812
|
+
this.clients.set(client.clientId, client);
|
|
2813
|
+
}
|
|
2814
|
+
this.userProvider = userProvider;
|
|
2815
|
+
setInterval(() => this.cleanupExpiredCodes(), 60000);
|
|
2816
|
+
}
|
|
2817
|
+
registerClient(client) {
|
|
2818
|
+
this.clients.set(client.clientId, client);
|
|
2819
|
+
}
|
|
2820
|
+
validateAuthorizationRequest(request) {
|
|
2821
|
+
const client = this.clients.get(request.clientId);
|
|
2822
|
+
if (!client) {
|
|
2823
|
+
return { valid: false, error: "invalid_client" };
|
|
2824
|
+
}
|
|
2825
|
+
if (request.responseType !== "code") {
|
|
2826
|
+
return { valid: false, error: "unsupported_response_type" };
|
|
2827
|
+
}
|
|
2828
|
+
if (!client.redirectUris.includes(request.redirectUri)) {
|
|
2829
|
+
return { valid: false, error: "invalid_redirect_uri" };
|
|
2830
|
+
}
|
|
2831
|
+
return { valid: true };
|
|
2832
|
+
}
|
|
2833
|
+
generateAuthorizationCode(clientId, redirectUri, userId, scope) {
|
|
2834
|
+
const code = this.generateRandomString(this.codeConfig.length);
|
|
2835
|
+
const expiresAt = Date.now() + this.codeConfig.expiresIn * 1000;
|
|
2836
|
+
this.codes.set(code, {
|
|
2837
|
+
code,
|
|
2838
|
+
clientId,
|
|
2839
|
+
redirectUri,
|
|
2840
|
+
userId,
|
|
2841
|
+
scope,
|
|
2842
|
+
expiresAt
|
|
2843
|
+
});
|
|
2844
|
+
return code;
|
|
2845
|
+
}
|
|
2846
|
+
async exchangeCodeForToken(request) {
|
|
2847
|
+
if (request.grantType !== "authorization_code") {
|
|
2848
|
+
return null;
|
|
2849
|
+
}
|
|
2850
|
+
const codeData = this.codes.get(request.code);
|
|
2851
|
+
if (!codeData) {
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2854
|
+
if (codeData.expiresAt < Date.now()) {
|
|
2855
|
+
this.codes.delete(request.code);
|
|
2856
|
+
return null;
|
|
2857
|
+
}
|
|
2858
|
+
const client = this.clients.get(request.clientId);
|
|
2859
|
+
if (!client || client.clientSecret !== request.clientSecret) {
|
|
2860
|
+
return null;
|
|
2861
|
+
}
|
|
2862
|
+
if (codeData.redirectUri !== request.redirectUri) {
|
|
2863
|
+
return null;
|
|
2864
|
+
}
|
|
2865
|
+
this.codes.delete(request.code);
|
|
2866
|
+
let userInfo = null;
|
|
2867
|
+
if (this.userProvider) {
|
|
2868
|
+
userInfo = await this.userProvider(codeData.userId);
|
|
2869
|
+
}
|
|
2870
|
+
if (!userInfo) {
|
|
2871
|
+
userInfo = {
|
|
2872
|
+
id: codeData.userId,
|
|
2873
|
+
username: codeData.userId
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
const payload = {
|
|
2877
|
+
sub: userInfo.id,
|
|
2878
|
+
username: userInfo.username,
|
|
2879
|
+
roles: userInfo.roles
|
|
2880
|
+
};
|
|
2881
|
+
const accessToken = this.jwtUtil.generateAccessToken(payload);
|
|
2882
|
+
const refreshToken = this.jwtUtil.generateRefreshToken(payload);
|
|
2883
|
+
return {
|
|
2884
|
+
accessToken,
|
|
2885
|
+
tokenType: "Bearer",
|
|
2886
|
+
expiresIn: this.jwtUtil["config"].accessTokenExpiresIn,
|
|
2887
|
+
refreshToken,
|
|
2888
|
+
scope: codeData.scope
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
async refreshToken(refreshToken) {
|
|
2892
|
+
const payload = this.jwtUtil.verify(refreshToken);
|
|
2893
|
+
if (!payload || !payload.sub) {
|
|
2894
|
+
return null;
|
|
2895
|
+
}
|
|
2896
|
+
let userInfo = null;
|
|
2897
|
+
if (this.userProvider) {
|
|
2898
|
+
userInfo = await this.userProvider(payload.sub);
|
|
2899
|
+
}
|
|
2900
|
+
if (!userInfo) {
|
|
2901
|
+
userInfo = {
|
|
2902
|
+
id: payload.sub,
|
|
2903
|
+
username: payload.username || payload.sub,
|
|
2904
|
+
roles: payload.roles
|
|
2905
|
+
};
|
|
2906
|
+
}
|
|
2907
|
+
const newPayload = {
|
|
2908
|
+
sub: userInfo.id,
|
|
2909
|
+
username: userInfo.username,
|
|
2910
|
+
roles: userInfo.roles
|
|
2911
|
+
};
|
|
2912
|
+
const accessToken = this.jwtUtil.generateAccessToken(newPayload);
|
|
2913
|
+
const newRefreshToken = this.jwtUtil.generateRefreshToken(newPayload);
|
|
2914
|
+
return {
|
|
2915
|
+
accessToken,
|
|
2916
|
+
tokenType: "Bearer",
|
|
2917
|
+
expiresIn: this.jwtUtil["config"].accessTokenExpiresIn,
|
|
2918
|
+
refreshToken: newRefreshToken
|
|
2919
|
+
};
|
|
2920
|
+
}
|
|
2921
|
+
generateRandomString(length) {
|
|
2922
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
2923
|
+
let result = "";
|
|
2924
|
+
for (let i = 0;i < length; i++) {
|
|
2925
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
2926
|
+
}
|
|
2927
|
+
return result;
|
|
2928
|
+
}
|
|
2929
|
+
cleanupExpiredCodes() {
|
|
2930
|
+
const now = Date.now();
|
|
2931
|
+
for (const [code, data] of this.codes.entries()) {
|
|
2932
|
+
if (data.expiresAt < now) {
|
|
2933
|
+
this.codes.delete(code);
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
// src/auth/controller.ts
|
|
2939
|
+
var OAUTH2_SERVICE_TOKEN = Symbol("OAUTH2_SERVICE");
|
|
2940
|
+
var JWT_UTIL_TOKEN = Symbol("JWT_UTIL");
|
|
2941
|
+
|
|
2942
|
+
class OAuth2Controller {
|
|
2943
|
+
oauth2Service;
|
|
2944
|
+
constructor(oauth2Service) {
|
|
2945
|
+
this.oauth2Service = oauth2Service;
|
|
2946
|
+
}
|
|
2947
|
+
authorize(clientId, redirectUri, state, scope) {
|
|
2948
|
+
const query = {
|
|
2949
|
+
client_id: clientId,
|
|
2950
|
+
redirect_uri: redirectUri,
|
|
2951
|
+
...state && { state },
|
|
2952
|
+
...scope && { scope }
|
|
2953
|
+
};
|
|
2954
|
+
const request = {
|
|
2955
|
+
clientId: query.client_id || "",
|
|
2956
|
+
redirectUri: query.redirect_uri || "",
|
|
2957
|
+
responseType: "code",
|
|
2958
|
+
scope: query.scope,
|
|
2959
|
+
state: query.state
|
|
2960
|
+
};
|
|
2961
|
+
const validation = this.oauth2Service.validateAuthorizationRequest(request);
|
|
2962
|
+
if (!validation.valid) {
|
|
2963
|
+
throw new Error(`Invalid authorization request: ${validation.error}`);
|
|
2964
|
+
}
|
|
2965
|
+
const userId = "user-1";
|
|
2966
|
+
const code = this.oauth2Service.generateAuthorizationCode(request.clientId, request.redirectUri, userId, request.scope);
|
|
2967
|
+
const redirectUrl = new URL(request.redirectUri);
|
|
2968
|
+
redirectUrl.searchParams.set("code", code);
|
|
2969
|
+
if (request.state) {
|
|
2970
|
+
redirectUrl.searchParams.set("state", request.state);
|
|
2971
|
+
}
|
|
2972
|
+
return ResponseBuilder.redirect(redirectUrl.toString());
|
|
2973
|
+
}
|
|
2974
|
+
async token(body) {
|
|
2975
|
+
const request = {
|
|
2976
|
+
code: body.code || "",
|
|
2977
|
+
clientId: body.client_id || "",
|
|
2978
|
+
clientSecret: body.client_secret || "",
|
|
2979
|
+
redirectUri: body.redirect_uri || "",
|
|
2980
|
+
grantType: body.grant_type || "authorization_code",
|
|
2981
|
+
refreshToken: body.refresh_token
|
|
2982
|
+
};
|
|
2983
|
+
if (request.grantType === "authorization_code") {
|
|
2984
|
+
const tokenResponse = await this.oauth2Service.exchangeCodeForToken(request);
|
|
2985
|
+
if (!tokenResponse) {
|
|
2986
|
+
return {
|
|
2987
|
+
error: "invalid_grant",
|
|
2988
|
+
error_description: "Invalid authorization code"
|
|
2989
|
+
};
|
|
2990
|
+
}
|
|
2991
|
+
return tokenResponse;
|
|
2992
|
+
}
|
|
2993
|
+
if (request.grantType === "refresh_token" && request.refreshToken) {
|
|
2994
|
+
const tokenResponse = await this.oauth2Service.refreshToken(request.refreshToken);
|
|
2995
|
+
if (!tokenResponse) {
|
|
2996
|
+
return {
|
|
2997
|
+
error: "invalid_grant",
|
|
2998
|
+
error_description: "Invalid refresh token"
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
return tokenResponse;
|
|
3002
|
+
}
|
|
3003
|
+
return {
|
|
3004
|
+
error: "unsupported_grant_type",
|
|
3005
|
+
error_description: "Unsupported grant type"
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
userinfo() {
|
|
3009
|
+
return {
|
|
3010
|
+
sub: "user-1",
|
|
3011
|
+
username: "alice",
|
|
3012
|
+
roles: ["user"]
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
__legacyDecorateClassTS([
|
|
3017
|
+
GET("/authorize"),
|
|
3018
|
+
__legacyDecorateParamTS(0, Query("client_id")),
|
|
3019
|
+
__legacyDecorateParamTS(1, Query("redirect_uri")),
|
|
3020
|
+
__legacyDecorateParamTS(2, Query("state")),
|
|
3021
|
+
__legacyDecorateParamTS(3, Query("scope")),
|
|
3022
|
+
__legacyMetadataTS("design:type", Function),
|
|
3023
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
3024
|
+
String,
|
|
3025
|
+
String,
|
|
3026
|
+
String,
|
|
3027
|
+
String
|
|
3028
|
+
]),
|
|
3029
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
3030
|
+
], OAuth2Controller.prototype, "authorize", null);
|
|
3031
|
+
__legacyDecorateClassTS([
|
|
3032
|
+
POST("/token"),
|
|
3033
|
+
__legacyDecorateParamTS(0, Body()),
|
|
3034
|
+
__legacyMetadataTS("design:type", Function),
|
|
3035
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
3036
|
+
typeof Record === "undefined" ? Object : Record
|
|
3037
|
+
]),
|
|
3038
|
+
__legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
3039
|
+
], OAuth2Controller.prototype, "token", null);
|
|
3040
|
+
__legacyDecorateClassTS([
|
|
3041
|
+
GET("/userinfo"),
|
|
3042
|
+
Auth(),
|
|
3043
|
+
__legacyMetadataTS("design:type", Function),
|
|
3044
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3045
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
3046
|
+
], OAuth2Controller.prototype, "userinfo", null);
|
|
3047
|
+
OAuth2Controller = __legacyDecorateClassTS([
|
|
3048
|
+
Controller("/oauth2"),
|
|
3049
|
+
Injectable(),
|
|
3050
|
+
__legacyDecorateParamTS(0, Inject(OAUTH2_SERVICE_TOKEN)),
|
|
3051
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
3052
|
+
typeof OAuth2Service === "undefined" ? Object : OAuth2Service
|
|
3053
|
+
])
|
|
3054
|
+
], OAuth2Controller);
|
|
3055
|
+
|
|
3056
|
+
// src/security/security-module.ts
|
|
3057
|
+
class SecurityModule {
|
|
3058
|
+
static forRoot(config) {
|
|
3059
|
+
const jwtUtil = new JWTUtil(config.jwt);
|
|
3060
|
+
const userProvider = config.userProvider ? async (userId) => config.userProvider.findById(userId) : undefined;
|
|
3061
|
+
const oauth2Service = new OAuth2Service(jwtUtil, config.oauth2Clients || [], {}, userProvider);
|
|
3062
|
+
const authenticationManager = new AuthenticationManager;
|
|
3063
|
+
authenticationManager.registerProvider(new JwtAuthenticationProvider(jwtUtil));
|
|
3064
|
+
authenticationManager.registerProvider(new OAuth2AuthenticationProvider(oauth2Service));
|
|
3065
|
+
const securityFilter = createSecurityFilter({
|
|
3066
|
+
authenticationManager,
|
|
3067
|
+
excludePaths: [
|
|
3068
|
+
...config.excludePaths || [],
|
|
3069
|
+
...config.enableOAuth2Endpoints !== false ? [config.oauth2Prefix || "/oauth2"] : []
|
|
3070
|
+
],
|
|
3071
|
+
defaultAuthRequired: config.defaultAuthRequired ?? false
|
|
3072
|
+
});
|
|
3073
|
+
const controllers = [];
|
|
3074
|
+
const providers = [];
|
|
3075
|
+
const middlewares = [];
|
|
3076
|
+
if (config.enableOAuth2Endpoints !== false) {
|
|
3077
|
+
controllers.push(OAuth2Controller);
|
|
3078
|
+
}
|
|
3079
|
+
providers.push({
|
|
3080
|
+
provide: JWT_UTIL_TOKEN,
|
|
3081
|
+
useValue: jwtUtil
|
|
3082
|
+
}, {
|
|
3083
|
+
provide: OAUTH2_SERVICE_TOKEN,
|
|
3084
|
+
useValue: oauth2Service
|
|
3085
|
+
}, {
|
|
3086
|
+
provide: AuthenticationManager,
|
|
3087
|
+
useValue: authenticationManager
|
|
3088
|
+
});
|
|
3089
|
+
middlewares.push(securityFilter);
|
|
3090
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SecurityModule) || {};
|
|
3091
|
+
const metadata = {
|
|
3092
|
+
...existingMetadata,
|
|
3093
|
+
controllers: [...existingMetadata.controllers || [], ...controllers],
|
|
3094
|
+
providers: [...existingMetadata.providers || [], ...providers],
|
|
3095
|
+
middlewares: [...existingMetadata.middlewares || [], ...middlewares],
|
|
3096
|
+
exports: [
|
|
3097
|
+
...existingMetadata.exports || [],
|
|
3098
|
+
JWT_UTIL_TOKEN,
|
|
3099
|
+
OAUTH2_SERVICE_TOKEN,
|
|
3100
|
+
AuthenticationManager
|
|
3101
|
+
]
|
|
3102
|
+
};
|
|
3103
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SecurityModule);
|
|
3104
|
+
return SecurityModule;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
SecurityModule = __legacyDecorateClassTS([
|
|
3108
|
+
Module({
|
|
3109
|
+
controllers: [],
|
|
3110
|
+
providers: [],
|
|
3111
|
+
middlewares: []
|
|
3112
|
+
})
|
|
3113
|
+
], SecurityModule);
|
|
1998
3114
|
// src/testing/harness.ts
|
|
1999
3115
|
import { performance as performance2 } from "perf_hooks";
|
|
2000
3116
|
|
|
@@ -2056,22 +3172,33 @@ class StressTester {
|
|
|
2056
3172
|
}
|
|
2057
3173
|
}
|
|
2058
3174
|
export {
|
|
3175
|
+
requiresAuth,
|
|
3176
|
+
getAuthMetadata,
|
|
3177
|
+
createSwaggerUIMiddleware,
|
|
2059
3178
|
createStaticFileMiddleware,
|
|
3179
|
+
createSecurityFilter,
|
|
2060
3180
|
createRequestLoggingMiddleware,
|
|
2061
3181
|
createLoggerMiddleware,
|
|
2062
3182
|
createFileUploadMiddleware,
|
|
2063
3183
|
createErrorHandlingMiddleware,
|
|
2064
3184
|
createCorsMiddleware,
|
|
3185
|
+
checkRoles,
|
|
2065
3186
|
WebSocketGatewayRegistry,
|
|
2066
3187
|
WebSocketGateway,
|
|
2067
3188
|
ValidationError,
|
|
2068
3189
|
Validate,
|
|
2069
3190
|
UseMiddleware,
|
|
2070
3191
|
UnauthorizedException,
|
|
3192
|
+
SwaggerModule,
|
|
3193
|
+
SwaggerGenerator,
|
|
3194
|
+
SwaggerExtension,
|
|
2071
3195
|
StressTester,
|
|
3196
|
+
SecurityModule,
|
|
3197
|
+
SecurityContextHolder,
|
|
2072
3198
|
Router,
|
|
2073
3199
|
RouteRegistry,
|
|
2074
3200
|
Route,
|
|
3201
|
+
RoleBasedAccessDecisionManager,
|
|
2075
3202
|
ResponseBuilder,
|
|
2076
3203
|
RequestWrapper,
|
|
2077
3204
|
Query,
|
|
@@ -2084,15 +3211,23 @@ export {
|
|
|
2084
3211
|
OnOpen,
|
|
2085
3212
|
OnMessage,
|
|
2086
3213
|
OnClose,
|
|
3214
|
+
OAuth2Service,
|
|
3215
|
+
OAuth2Controller,
|
|
3216
|
+
OAuth2AuthenticationProvider,
|
|
3217
|
+
OAUTH2_SERVICE_TOKEN,
|
|
2087
3218
|
NotFoundException,
|
|
2088
3219
|
ModuleRegistry,
|
|
2089
3220
|
Module,
|
|
2090
3221
|
MinLength,
|
|
2091
3222
|
MiddlewarePipeline,
|
|
3223
|
+
LoggerModule,
|
|
2092
3224
|
LoggerExtension,
|
|
2093
3225
|
LogLevel2 as LogLevel,
|
|
2094
3226
|
Lifecycle,
|
|
2095
3227
|
LOGGER_TOKEN,
|
|
3228
|
+
JwtAuthenticationProvider,
|
|
3229
|
+
JWT_UTIL_TOKEN,
|
|
3230
|
+
JWTUtil,
|
|
2096
3231
|
IsString,
|
|
2097
3232
|
IsOptional,
|
|
2098
3233
|
IsNumber,
|
|
@@ -2114,5 +3249,12 @@ export {
|
|
|
2114
3249
|
BodyParser,
|
|
2115
3250
|
Body,
|
|
2116
3251
|
BadRequestException,
|
|
2117
|
-
|
|
3252
|
+
AuthenticationManager,
|
|
3253
|
+
Auth,
|
|
3254
|
+
Application,
|
|
3255
|
+
ApiTags,
|
|
3256
|
+
ApiResponse,
|
|
3257
|
+
ApiParam,
|
|
3258
|
+
ApiOperation,
|
|
3259
|
+
ApiBody
|
|
2118
3260
|
};
|