@privateaim/server-http-kit 0.7.0
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/CHANGELOG.md +68 -0
- package/LICENSE +202 -0
- package/README.md +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/basic.d.ts +3 -0
- package/dist/middlewares/basic.d.ts.map +1 -0
- package/dist/middlewares/basic.js +14 -0
- package/dist/middlewares/basic.js.map +1 -0
- package/dist/middlewares/cors.d.ts +3 -0
- package/dist/middlewares/cors.d.ts.map +1 -0
- package/dist/middlewares/cors.js +23 -0
- package/dist/middlewares/cors.js.map +1 -0
- package/dist/middlewares/decorators.d.ts +4 -0
- package/dist/middlewares/decorators.d.ts.map +1 -0
- package/dist/middlewares/decorators.js +39 -0
- package/dist/middlewares/decorators.js.map +1 -0
- package/dist/middlewares/error.d.ts +3 -0
- package/dist/middlewares/error.d.ts.map +1 -0
- package/dist/middlewares/error.js +50 -0
- package/dist/middlewares/error.js.map +1 -0
- package/dist/middlewares/force-logged-in.d.ts +6 -0
- package/dist/middlewares/force-logged-in.d.ts.map +1 -0
- package/dist/middlewares/force-logged-in.js +22 -0
- package/dist/middlewares/force-logged-in.js.map +1 -0
- package/dist/middlewares/index.d.ts +9 -0
- package/dist/middlewares/index.d.ts.map +1 -0
- package/dist/middlewares/index.js +31 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/middlewares/module.d.ts +4 -0
- package/dist/middlewares/module.d.ts.map +1 -0
- package/dist/middlewares/module.js +46 -0
- package/dist/middlewares/module.js.map +1 -0
- package/dist/middlewares/prometheus.d.ts +3 -0
- package/dist/middlewares/prometheus.d.ts.map +1 -0
- package/dist/middlewares/prometheus.js +14 -0
- package/dist/middlewares/prometheus.js.map +1 -0
- package/dist/middlewares/rate-limit.d.ts +3 -0
- package/dist/middlewares/rate-limit.d.ts.map +1 -0
- package/dist/middlewares/rate-limit.js +40 -0
- package/dist/middlewares/rate-limit.js.map +1 -0
- package/dist/middlewares/swagger.d.ts +4 -0
- package/dist/middlewares/swagger.d.ts.map +1 -0
- package/dist/middlewares/swagger.js +29 -0
- package/dist/middlewares/swagger.js.map +1 -0
- package/dist/middlewares/types.d.ts +20 -0
- package/dist/middlewares/types.d.ts.map +1 -0
- package/dist/middlewares/types.js +9 -0
- package/dist/middlewares/types.js.map +1 -0
- package/dist/request/env.d.ts +6 -0
- package/dist/request/env.d.ts.map +1 -0
- package/dist/request/env.js +21 -0
- package/dist/request/env.js.map +1 -0
- package/dist/request/index.d.ts +3 -0
- package/dist/request/index.d.ts.map +1 -0
- package/dist/request/index.js +25 -0
- package/dist/request/index.js.map +1 -0
- package/dist/request/types.d.ts +15 -0
- package/dist/request/types.d.ts.map +1 -0
- package/dist/request/types.js +9 -0
- package/dist/request/types.js.map +1 -0
- package/dist/services/authup/index.d.ts +3 -0
- package/dist/services/authup/index.d.ts.map +1 -0
- package/dist/services/authup/index.js +25 -0
- package/dist/services/authup/index.js.map +1 -0
- package/dist/services/authup/middleware.d.ts +4 -0
- package/dist/services/authup/middleware.d.ts.map +1 -0
- package/dist/services/authup/middleware.js +86 -0
- package/dist/services/authup/middleware.js.map +1 -0
- package/dist/services/authup/types.d.ts +10 -0
- package/dist/services/authup/types.d.ts.map +1 -0
- package/dist/services/authup/types.js +9 -0
- package/dist/services/authup/types.js.map +1 -0
- package/dist/services/authup/utils.d.ts +7 -0
- package/dist/services/authup/utils.d.ts.map +1 -0
- package/dist/services/authup/utils.js +59 -0
- package/dist/services/authup/utils.js.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +24 -0
- package/dist/services/index.js.map +1 -0
- package/dist/swagger/index.d.ts +2 -0
- package/dist/swagger/index.d.ts.map +1 -0
- package/dist/swagger/index.js +24 -0
- package/dist/swagger/index.js.map +1 -0
- package/dist/swagger/module.d.ts +3 -0
- package/dist/swagger/module.d.ts.map +1 -0
- package/dist/swagger/module.js +66 -0
- package/dist/swagger/module.js.map +1 -0
- package/dist/swagger/types.d.ts +7 -0
- package/dist/swagger/types.d.ts.map +1 -0
- package/dist/swagger/types.js +9 -0
- package/dist/swagger/types.js.map +1 -0
- package/dist/utils/boolable-to-object.d.ts +2 -0
- package/dist/utils/boolable-to-object.d.ts.map +1 -0
- package/dist/utils/boolable-to-object.js +16 -0
- package/dist/utils/boolable-to-object.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +24 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/validation/index.d.ts +5 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +27 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/message.d.ts +2 -0
- package/dist/validation/message.d.ts.map +1 -0
- package/dist/validation/message.js +17 -0
- package/dist/validation/message.js.map +1 -0
- package/dist/validation/module.d.ts +6 -0
- package/dist/validation/module.d.ts.map +1 -0
- package/dist/validation/module.js +45 -0
- package/dist/validation/module.js.map +1 -0
- package/dist/validation/result.d.ts +7 -0
- package/dist/validation/result.d.ts.map +1 -0
- package/dist/validation/result.js +43 -0
- package/dist/validation/result.js.map +1 -0
- package/dist/validation/type.d.ts +15 -0
- package/dist/validation/type.d.ts.map +1 -0
- package/dist/validation/type.js +9 -0
- package/dist/validation/type.js.map +1 -0
- package/package.json +49 -0
- package/src/index.ts +12 -0
- package/src/middlewares/basic.ts +13 -0
- package/src/middlewares/cors.ts +19 -0
- package/src/middlewares/decorators.ts +42 -0
- package/src/middlewares/error.ts +55 -0
- package/src/middlewares/force-logged-in.ts +26 -0
- package/src/middlewares/index.ts +15 -0
- package/src/middlewares/module.ts +53 -0
- package/src/middlewares/prometheus.ts +13 -0
- package/src/middlewares/rate-limit.ts +47 -0
- package/src/middlewares/swagger.ts +26 -0
- package/src/middlewares/types.ts +30 -0
- package/src/request/env.ts +28 -0
- package/src/request/index.ts +9 -0
- package/src/request/types.ts +22 -0
- package/src/services/authup/index.ts +9 -0
- package/src/services/authup/middleware.ts +110 -0
- package/src/services/authup/types.ts +17 -0
- package/src/services/authup/utils.ts +79 -0
- package/src/services/index.ts +8 -0
- package/src/swagger/index.ts +8 -0
- package/src/swagger/module.ts +67 -0
- package/src/swagger/types.ts +13 -0
- package/src/utils/boolable-to-object.ts +14 -0
- package/src/utils/index.ts +8 -0
- package/src/validation/index.ts +11 -0
- package/src/validation/message.ts +17 -0
- package/src/validation/module.ts +49 -0
- package/src/validation/result.ts +58 -0
- package/src/validation/type.ts +28 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +9 -0
- package/writable/.gitkeep +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { UnauthorizedError } from '@ebec/http';
|
|
9
|
+
import type { HandlerInterface } from '@routup/decorators';
|
|
10
|
+
import type {
|
|
11
|
+
Next, Request, Response,
|
|
12
|
+
} from 'routup';
|
|
13
|
+
import { useRequestEnv } from '../request';
|
|
14
|
+
|
|
15
|
+
export class ForceLoggedInMiddleware implements HandlerInterface {
|
|
16
|
+
public run(request: Request, response: Response, next: Next) {
|
|
17
|
+
if (
|
|
18
|
+
typeof useRequestEnv(request, 'userId') === 'undefined' &&
|
|
19
|
+
typeof useRequestEnv(request, 'robotId') === 'undefined'
|
|
20
|
+
) {
|
|
21
|
+
throw new UnauthorizedError();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
next();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2022-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export * from './cors';
|
|
9
|
+
export * from './error';
|
|
10
|
+
export * from './force-logged-in';
|
|
11
|
+
export * from './module';
|
|
12
|
+
export * from './prometheus';
|
|
13
|
+
export * from './rate-limit';
|
|
14
|
+
export * from './swagger';
|
|
15
|
+
export * from './types';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Router } from 'routup';
|
|
9
|
+
import { mountAuthupMiddleware } from '../services';
|
|
10
|
+
import { boolableToObject } from '../utils';
|
|
11
|
+
import { mountBasicMiddleware } from './basic';
|
|
12
|
+
import { mountCorsMiddleware } from './cors';
|
|
13
|
+
import { mountDecoratorsMiddleware } from './decorators';
|
|
14
|
+
import { mountPrometheusMiddleware } from './prometheus';
|
|
15
|
+
import { mountRateLimiterMiddleware } from './rate-limit';
|
|
16
|
+
import { mountSwaggerMiddleware } from './swagger';
|
|
17
|
+
import type { MiddlewareRegistrationContext } from './types';
|
|
18
|
+
|
|
19
|
+
export function mountMiddlewares(router: Router, ctx: MiddlewareRegistrationContext) {
|
|
20
|
+
ctx.basic ??= true;
|
|
21
|
+
ctx.cors ??= true;
|
|
22
|
+
ctx.prometheus ??= true;
|
|
23
|
+
ctx.rateLimit ??= true;
|
|
24
|
+
ctx.swagger ??= true;
|
|
25
|
+
|
|
26
|
+
if (ctx.cors) {
|
|
27
|
+
mountCorsMiddleware(router);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (ctx.basic) {
|
|
31
|
+
mountBasicMiddleware(router);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (ctx.authup) {
|
|
35
|
+
mountAuthupMiddleware(router, ctx.authup);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (ctx.prometheus) {
|
|
39
|
+
mountPrometheusMiddleware(router);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (ctx.rateLimit) {
|
|
43
|
+
mountRateLimiterMiddleware(router);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (ctx.swagger) {
|
|
47
|
+
mountSwaggerMiddleware(router, boolableToObject(ctx.swagger));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (ctx.decorators) {
|
|
51
|
+
mountDecoratorsMiddleware(router, ctx.decorators);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { prometheus } from '@routup/prometheus';
|
|
9
|
+
import type { Router } from 'routup';
|
|
10
|
+
|
|
11
|
+
export function mountPrometheusMiddleware(router: Router) {
|
|
12
|
+
router.use(prometheus());
|
|
13
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { REALM_MASTER_NAME } from '@authup/core-kit';
|
|
9
|
+
import type { OptionsInput } from '@routup/rate-limit';
|
|
10
|
+
import { rateLimit } from '@routup/rate-limit';
|
|
11
|
+
import type { Request, Router } from 'routup';
|
|
12
|
+
import { useRequestEnv } from '../request';
|
|
13
|
+
|
|
14
|
+
export function mountRateLimiterMiddleware(router: Router) {
|
|
15
|
+
const options : OptionsInput = {
|
|
16
|
+
skip(req: Request) {
|
|
17
|
+
const robot = useRequestEnv(req, 'robotId');
|
|
18
|
+
if (robot) {
|
|
19
|
+
const { name } = useRequestEnv(req, 'realm');
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
name === REALM_MASTER_NAME &&
|
|
23
|
+
useRequestEnv(req, 'robotName') === 'system'
|
|
24
|
+
) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return false;
|
|
30
|
+
},
|
|
31
|
+
max(req: Request) {
|
|
32
|
+
if (useRequestEnv(req, 'userId')) {
|
|
33
|
+
return 60 * 100; // 100 req p. sec
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const robot = useRequestEnv(req, 'robotId');
|
|
37
|
+
if (robot) {
|
|
38
|
+
return 60 * 1000; // 1000 req p. sec
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return 60 * 20; // 20 req p. sec
|
|
42
|
+
},
|
|
43
|
+
windowMs: 60 * 1000, // 60 sec
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
router.use(rateLimit(options));
|
|
47
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { swaggerUI } from '@routup/swagger';
|
|
10
|
+
import { loadSync } from 'locter';
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
import type { Router } from 'routup';
|
|
13
|
+
import type { MiddlewareSwaggerOptions } from './types';
|
|
14
|
+
|
|
15
|
+
export function mountSwaggerMiddleware(router: Router, options: MiddlewareSwaggerOptions) {
|
|
16
|
+
let document : any;
|
|
17
|
+
if (options.cwd) {
|
|
18
|
+
document = loadSync(path.join(options.cwd, 'swagger.json'));
|
|
19
|
+
} else {
|
|
20
|
+
document = loadSync(path.join(process.cwd(), 'writable', 'swagger.json'));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
router.use('/docs', swaggerUI(document, {
|
|
24
|
+
baseURL: options.baseURL,
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ClassType } from '@routup/decorators';
|
|
9
|
+
import type { AuthupMiddlewareRegistrationOptions } from '../services';
|
|
10
|
+
|
|
11
|
+
export type MiddlewareSwaggerOptions = {
|
|
12
|
+
cwd?: string,
|
|
13
|
+
baseURL?: string
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type MiddlewareDecoratorsOptions = {
|
|
17
|
+
controllers: (ClassType | Record<string, any>)[]
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type MiddlewareRegistrationContext = {
|
|
21
|
+
options?: MiddlewareSwaggerOptions,
|
|
22
|
+
|
|
23
|
+
authup?: AuthupMiddlewareRegistrationOptions,
|
|
24
|
+
basic?: boolean,
|
|
25
|
+
cors?: boolean,
|
|
26
|
+
decorators?: MiddlewareDecoratorsOptions,
|
|
27
|
+
prometheus?: boolean,
|
|
28
|
+
rateLimit?: boolean,
|
|
29
|
+
swagger?: MiddlewareSwaggerOptions | boolean,
|
|
30
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { setRequestEnv as setEnv, useRequestEnv as useEnv } from 'routup';
|
|
9
|
+
import type { Request } from 'routup';
|
|
10
|
+
import type { RequestEnv } from './types';
|
|
11
|
+
|
|
12
|
+
export function useRequestEnv(req: Request) : RequestEnv;
|
|
13
|
+
export function useRequestEnv<T extends keyof RequestEnv>(req: Request, key: T) : RequestEnv[T];
|
|
14
|
+
export function useRequestEnv<T extends keyof RequestEnv>(req: Request, key?: T) {
|
|
15
|
+
if (typeof key === 'string') {
|
|
16
|
+
return useEnv(req, key) as RequestEnv[T];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return useEnv(req);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function setRequestEnv<T extends keyof RequestEnv>(
|
|
23
|
+
req: Request,
|
|
24
|
+
key: T,
|
|
25
|
+
value: RequestEnv[T],
|
|
26
|
+
) {
|
|
27
|
+
return setEnv(req, key, value);
|
|
28
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Abilities } from '@authup/kit';
|
|
9
|
+
|
|
10
|
+
export type RequestEnv = {
|
|
11
|
+
abilities?: Abilities,
|
|
12
|
+
|
|
13
|
+
realmId?: string,
|
|
14
|
+
realmName?: string,
|
|
15
|
+
realm?: { id?: string, name?: string },
|
|
16
|
+
|
|
17
|
+
userId?: string,
|
|
18
|
+
userName?: string,
|
|
19
|
+
|
|
20
|
+
robotId?: string,
|
|
21
|
+
robotName?: string
|
|
22
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TokenCreatorOptions } from '@authup/core-http-kit';
|
|
9
|
+
import type { TokenVerifierRedisCacheOptions } from '@authup/server-core-plugin-kit';
|
|
10
|
+
import { createMiddleware } from '@authup/server-core-plugin-http';
|
|
11
|
+
import { useRequestCookie } from '@routup/basic/cookie';
|
|
12
|
+
import { parseAuthorizationHeader } from 'hapic';
|
|
13
|
+
import type { Router } from 'routup';
|
|
14
|
+
import { coreHandler, getRequestHeader } from 'routup';
|
|
15
|
+
import type { AuthupMiddlewareRegistrationOptions } from './types';
|
|
16
|
+
import { applyTokenVerificationData, createFakeTokenVerificationData } from './utils';
|
|
17
|
+
|
|
18
|
+
export function mountAuthupMiddleware(
|
|
19
|
+
router: Router,
|
|
20
|
+
options: AuthupMiddlewareRegistrationOptions,
|
|
21
|
+
) {
|
|
22
|
+
if (!options.client) {
|
|
23
|
+
const data = createFakeTokenVerificationData();
|
|
24
|
+
|
|
25
|
+
router.use(coreHandler((req, res, next) => {
|
|
26
|
+
applyTokenVerificationData(req, data, options.fakeAbilities);
|
|
27
|
+
next();
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
router.use(coreHandler(async (req, res, next) => {
|
|
34
|
+
const headerRaw = getRequestHeader(req, 'authorization');
|
|
35
|
+
if (typeof headerRaw !== 'string') {
|
|
36
|
+
next();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const cacheKey = `authorization-header:${headerRaw}`;
|
|
40
|
+
|
|
41
|
+
if (options.redisClient) {
|
|
42
|
+
const data = await options.redisClient.get(cacheKey);
|
|
43
|
+
if (data) {
|
|
44
|
+
req.headers.authorization = `Bearer ${data}`;
|
|
45
|
+
next();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const header = parseAuthorizationHeader(headerRaw);
|
|
51
|
+
|
|
52
|
+
if (header.type === 'Basic') {
|
|
53
|
+
const token = await options.client.token.createWithPasswordGrant({
|
|
54
|
+
username: header.username,
|
|
55
|
+
password: header.password,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
req.headers.authorization = `Bearer ${token.access_token}`;
|
|
59
|
+
if (options.redisClient) {
|
|
60
|
+
await options.redisClient.setex(cacheKey, token.expires_in, token.access_token);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
next();
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
let tokenCreator : TokenCreatorOptions;
|
|
68
|
+
if (options.vaultClient) {
|
|
69
|
+
tokenCreator = {
|
|
70
|
+
type: 'robotInVault',
|
|
71
|
+
name: 'system',
|
|
72
|
+
vault: options.vaultClient,
|
|
73
|
+
baseURL: options.client.getBaseURL(),
|
|
74
|
+
};
|
|
75
|
+
} else {
|
|
76
|
+
tokenCreator = {
|
|
77
|
+
type: 'user',
|
|
78
|
+
name: 'admin',
|
|
79
|
+
password: 'start123',
|
|
80
|
+
baseURL: options.client.getBaseURL(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let tokenCache : TokenVerifierRedisCacheOptions | undefined;
|
|
85
|
+
if (options.redisClient) {
|
|
86
|
+
tokenCache = {
|
|
87
|
+
type: 'redis',
|
|
88
|
+
client: options.redisClient,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const middleware = createMiddleware({
|
|
93
|
+
tokenByCookie: (req, cookieName) => useRequestCookie(req, cookieName),
|
|
94
|
+
tokenVerifier: {
|
|
95
|
+
baseURL: options.client.getBaseURL(),
|
|
96
|
+
creator: tokenCreator,
|
|
97
|
+
cache: tokenCache,
|
|
98
|
+
},
|
|
99
|
+
tokenVerifierHandler: (
|
|
100
|
+
req,
|
|
101
|
+
data,
|
|
102
|
+
) => applyTokenVerificationData(req, data, options.fakeAbilities),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
router.use(coreHandler((
|
|
106
|
+
req,
|
|
107
|
+
res,
|
|
108
|
+
next,
|
|
109
|
+
) => middleware(req, res, next)));
|
|
110
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { VaultClient } from '@hapic/vault';
|
|
9
|
+
import type { Client as RedisClient } from 'redis-extension';
|
|
10
|
+
import type { Client as AuthupClient } from '@authup/core-http-kit';
|
|
11
|
+
|
|
12
|
+
export type AuthupMiddlewareRegistrationOptions = {
|
|
13
|
+
client?: AuthupClient,
|
|
14
|
+
vaultClient?: VaultClient,
|
|
15
|
+
redisClient?: RedisClient,
|
|
16
|
+
fakeAbilities?: boolean
|
|
17
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Ability } from '@authup/kit';
|
|
9
|
+
import { Abilities } from '@authup/kit';
|
|
10
|
+
import { REALM_MASTER_NAME } from '@authup/core-kit';
|
|
11
|
+
import type { TokenVerificationData } from '@authup/server-core-plugin-kit';
|
|
12
|
+
import { PermissionID } from '@privateaim/kit';
|
|
13
|
+
import type { Request } from 'routup';
|
|
14
|
+
import { setRequestEnv } from '../../request';
|
|
15
|
+
|
|
16
|
+
type TokenVerificationDataMinimal = Pick<
|
|
17
|
+
TokenVerificationData,
|
|
18
|
+
'permissions' |
|
|
19
|
+
'realm_id' |
|
|
20
|
+
'realm_name' |
|
|
21
|
+
'sub' |
|
|
22
|
+
'sub_kind' |
|
|
23
|
+
'sub_name'
|
|
24
|
+
>;
|
|
25
|
+
|
|
26
|
+
function generateAbilities(): Ability[] {
|
|
27
|
+
return Object.values(PermissionID).map((name) => ({
|
|
28
|
+
name,
|
|
29
|
+
} satisfies Ability));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createFakeTokenVerificationData(): TokenVerificationDataMinimal {
|
|
33
|
+
return {
|
|
34
|
+
realm_id: 'd94b2f28-29e3-4ced-b8f1-6923a01dc1ee',
|
|
35
|
+
realm_name: REALM_MASTER_NAME,
|
|
36
|
+
|
|
37
|
+
sub_kind: 'user',
|
|
38
|
+
sub: 'd94b2f28-29e3-4ced-b8f1-6923a01dc1ee',
|
|
39
|
+
sub_name: 'admin',
|
|
40
|
+
|
|
41
|
+
permissions: generateAbilities(),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function applyTokenVerificationData(
|
|
46
|
+
req: Request,
|
|
47
|
+
data: TokenVerificationDataMinimal,
|
|
48
|
+
fakeAbilities?: boolean,
|
|
49
|
+
) {
|
|
50
|
+
let abilities: Ability[];
|
|
51
|
+
if (fakeAbilities) {
|
|
52
|
+
abilities = generateAbilities();
|
|
53
|
+
} else {
|
|
54
|
+
abilities = data.permissions;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const ability = new Abilities(abilities);
|
|
58
|
+
setRequestEnv(req, 'abilities', ability);
|
|
59
|
+
|
|
60
|
+
setRequestEnv(req, 'realmId', data.realm_id);
|
|
61
|
+
setRequestEnv(req, 'realmName', data.realm_name);
|
|
62
|
+
setRequestEnv(req, 'realm', {
|
|
63
|
+
id: data.realm_id,
|
|
64
|
+
name: data.realm_name,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
switch (data.sub_kind) {
|
|
68
|
+
case 'user': {
|
|
69
|
+
setRequestEnv(req, 'userId', data.sub);
|
|
70
|
+
setRequestEnv(req, 'userName', data.sub_name);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'robot': {
|
|
74
|
+
setRequestEnv(req, 'robotId', data.sub);
|
|
75
|
+
setRequestEnv(req, 'robotName', data.sub_name);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import type { GeneratorOptionsInput } from '@routup/swagger';
|
|
10
|
+
import { Version, generate } from '@routup/swagger';
|
|
11
|
+
import { load } from 'locter';
|
|
12
|
+
import process from 'node:process';
|
|
13
|
+
import type { SwaggerGenerateOptions } from './types';
|
|
14
|
+
|
|
15
|
+
export async function generateSwagger(options: SwaggerGenerateOptions) {
|
|
16
|
+
const cwd = options.cwd || process.cwd();
|
|
17
|
+
const packageJson = await load(path.join(cwd, 'package.json')) as Record<string, any>;
|
|
18
|
+
|
|
19
|
+
const securityDefinitions : GeneratorOptionsInput['securityDefinitions'] = {
|
|
20
|
+
bearer: {
|
|
21
|
+
name: 'Bearer',
|
|
22
|
+
type: 'apiKey',
|
|
23
|
+
in: 'header',
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
basicAuth: {
|
|
27
|
+
type: 'http',
|
|
28
|
+
schema: 'basic',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (options.authupURL) {
|
|
33
|
+
securityDefinitions.oauth2 = {
|
|
34
|
+
type: 'oauth2',
|
|
35
|
+
flows: {
|
|
36
|
+
password: {
|
|
37
|
+
tokenUrl: new URL('token', options.authupURL).href,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return generate({
|
|
44
|
+
version: Version.V2,
|
|
45
|
+
options: {
|
|
46
|
+
metadata: {
|
|
47
|
+
cache: false,
|
|
48
|
+
entryPoint: [
|
|
49
|
+
{ pattern: '**/*.ts', cwd: options.controllerBasePath },
|
|
50
|
+
],
|
|
51
|
+
ignore: ['**/node_modules/**'],
|
|
52
|
+
allow: ['**/@authup/**'],
|
|
53
|
+
},
|
|
54
|
+
yaml: false,
|
|
55
|
+
servers: [
|
|
56
|
+
options.baseURL,
|
|
57
|
+
],
|
|
58
|
+
name: 'API Documentation',
|
|
59
|
+
description: 'Explore the REST Endpoints.',
|
|
60
|
+
version: packageJson.version,
|
|
61
|
+
outputDirectory: path.join(cwd, 'writable'),
|
|
62
|
+
securityDefinitions,
|
|
63
|
+
consumes: ['application/json'],
|
|
64
|
+
produces: ['application/json'],
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type SwaggerGenerateOptions = {
|
|
9
|
+
baseURL: string,
|
|
10
|
+
authupURL?: string,
|
|
11
|
+
cwd?: string,
|
|
12
|
+
controllerBasePath: string,
|
|
13
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function boolableToObject<T extends Record<string, any>>(input: T | boolean) : T {
|
|
9
|
+
if (typeof input === 'boolean') {
|
|
10
|
+
return {} as T;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return input;
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export * from './message';
|
|
9
|
+
export * from './module';
|
|
10
|
+
export * from './type';
|
|
11
|
+
export * from './result';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function buildHTTPValidationErrorMessage<
|
|
9
|
+
T extends Record<string, any> = Record<string, any>,
|
|
10
|
+
>(name: keyof T | (keyof T)[]) {
|
|
11
|
+
const names = Array.isArray(name) ? name : [name];
|
|
12
|
+
|
|
13
|
+
if (names.length > 1) {
|
|
14
|
+
return `The parameters ${names.join(', ')} is invalid.`;
|
|
15
|
+
}
|
|
16
|
+
return `The parameter ${String(names[0])} is invalid.`;
|
|
17
|
+
}
|