@node-c/api-http 1.0.0-alpha9 → 1.0.0-beta0

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.
Files changed (62) hide show
  1. package/dist/common/definitions/common.constants.d.ts +1 -1
  2. package/dist/common/definitions/common.constants.js +1 -1
  3. package/dist/common/definitions/common.constants.js.map +1 -1
  4. package/dist/common/utils/index.d.ts +1 -0
  5. package/dist/{exceptionFilters → common/utils}/index.js +1 -1
  6. package/dist/common/utils/index.js.map +1 -0
  7. package/dist/common/utils/utils.checkRoutes.d.ts +1 -0
  8. package/dist/common/utils/utils.checkRoutes.js +27 -0
  9. package/dist/common/utils/utils.checkRoutes.js.map +1 -0
  10. package/dist/{exceptionFilters/http.exceptionFilters.httpException.js → filters/http.filtes.exception.js} +1 -1
  11. package/dist/filters/http.filtes.exception.js.map +1 -0
  12. package/dist/filters/index.d.ts +1 -0
  13. package/dist/filters/index.js +18 -0
  14. package/dist/filters/index.js.map +1 -0
  15. package/dist/guards/http.guards.accessControl.d.ts +2 -0
  16. package/dist/guards/http.guards.accessControl.js +18 -0
  17. package/dist/guards/http.guards.accessControl.js.map +1 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/interceptors/{http.interceptors.authorization.d.ts → http.interceptors.accessControl.d.ts} +2 -2
  22. package/dist/interceptors/{http.interceptors.authorization.js → http.interceptors.accessControl.js} +21 -28
  23. package/dist/interceptors/http.interceptors.accessControl.js.map +1 -0
  24. package/dist/interceptors/http.interceptors.error.js +2 -1
  25. package/dist/interceptors/http.interceptors.error.js.map +1 -1
  26. package/dist/interceptors/index.d.ts +1 -1
  27. package/dist/interceptors/index.js +1 -1
  28. package/dist/middlewares/http.middlewares.authorization.d.ts +14 -0
  29. package/dist/middlewares/{http.middlewares.authentication.js → http.middlewares.authorization.js} +71 -45
  30. package/dist/middlewares/http.middlewares.authorization.js.map +1 -0
  31. package/dist/middlewares/http.middlewares.cors.js +1 -1
  32. package/dist/middlewares/http.middlewares.cors.js.map +1 -1
  33. package/dist/middlewares/index.d.ts +1 -1
  34. package/dist/middlewares/index.js +1 -1
  35. package/dist/middlewares/index.js.map +1 -1
  36. package/dist/module/http.api.module.js +18 -7
  37. package/dist/module/http.api.module.js.map +1 -1
  38. package/package.json +11 -7
  39. package/src/common/definitions/common.constants.ts +1 -1
  40. package/src/common/utils/index.ts +1 -0
  41. package/src/common/utils/utils.checkRoutes.ts +31 -0
  42. package/src/filters/index.ts +1 -0
  43. package/src/guards/http.guards.accessControl.ts +13 -0
  44. package/src/index.ts +1 -1
  45. package/src/interceptors/http.interceptors.accessControl.ts +94 -0
  46. package/src/interceptors/http.interceptors.error.ts +1 -5
  47. package/src/interceptors/index.ts +1 -1
  48. package/src/middlewares/http.middlewares.authorization.ts +153 -0
  49. package/src/middlewares/http.middlewares.cors.ts +1 -1
  50. package/src/middlewares/index.ts +1 -1
  51. package/src/module/http.api.module.ts +20 -6
  52. package/dist/exceptionFilters/http.exceptionFilters.httpException.js.map +0 -1
  53. package/dist/exceptionFilters/index.d.ts +0 -1
  54. package/dist/exceptionFilters/index.js.map +0 -1
  55. package/dist/interceptors/http.interceptors.authorization.js.map +0 -1
  56. package/dist/middlewares/http.middlewares.authentication.d.ts +0 -13
  57. package/dist/middlewares/http.middlewares.authentication.js.map +0 -1
  58. package/src/exceptionFilters/index.ts +0 -1
  59. package/src/interceptors/http.interceptors.authorization.ts +0 -82
  60. package/src/middlewares/http.middlewares.authentication.ts +0 -111
  61. /package/dist/{exceptionFilters/http.exceptionFilters.httpException.d.ts → filters/http.filtes.exception.d.ts} +0 -0
  62. /package/src/{exceptionFilters/http.exceptionFilters.httpException.ts → filters/http.filtes.exception.ts} +0 -0
@@ -1,82 +0,0 @@
1
- import {
2
- CallHandler,
3
- ExecutionContext,
4
- HttpException,
5
- HttpStatus,
6
- Inject,
7
- Injectable,
8
- NestInterceptor
9
- } from '@nestjs/common';
10
-
11
- import { ConfigProviderService, EndpointSecurityMode } from '@node-c/core';
12
- import { AuthorizationPoint, IAMAuthorizationService, UserWithPermissionsData } from '@node-c/domain-iam';
13
-
14
- import { setNested } from '@ramster/general-tools';
15
- import { Observable } from 'rxjs';
16
-
17
- import { Constants, RequestWithLocals } from '../common/definitions';
18
-
19
- @Injectable()
20
- export class HTTPAuthorizationInterceptor<User extends UserWithPermissionsData<unknown, unknown>>
21
- implements NestInterceptor
22
- {
23
- constructor(
24
- @Inject(Constants.API_MODULE_AUTHORIZATION_SERVICE)
25
- // eslint-disable-next-line no-unused-vars
26
- protected authorizationService: IAMAuthorizationService<AuthorizationPoint<unknown>>,
27
- // eslint-disable-next-line no-unused-vars
28
- protected configProvider: ConfigProviderService,
29
- @Inject(Constants.API_MODULE_NAME)
30
- // eslint-disable-next-line no-unused-vars
31
- protected moduleName: string
32
- ) {}
33
-
34
- async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<unknown>> {
35
- const [req]: [RequestWithLocals<User>, unknown] = context.getArgs();
36
- const locals = req.locals!;
37
- if (!locals) {
38
- throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
39
- } else if (locals.isAnonymous) {
40
- return next.handle();
41
- }
42
- const { moduleName } = this;
43
- const controllerName = context.getClass().name;
44
- const handlerName = context.getHandler().name;
45
- // TODO: cache this in-memory
46
- const authorizationData = await this.authorizationService.mapAuthorizationPoints(moduleName);
47
- let controllerData = authorizationData![controllerName];
48
- if (!controllerData) {
49
- controllerData = authorizationData.__all;
50
- }
51
- const user = locals.user!; // we'll always have this, otherwise the system has not been configured properly
52
- let handlerData = controllerData[handlerName];
53
- if (!handlerData) {
54
- handlerData = controllerData.__all;
55
- if (!Object.keys(handlerData).length) {
56
- const { endpointSecurityMode } = this.configProvider.config.api[moduleName];
57
- if (!endpointSecurityMode || endpointSecurityMode === EndpointSecurityMode.Strict) {
58
- console.info(
59
- `[${moduleName}][HTTPAuthorizationInterceptor]: No authorization point data for handler ${controllerName}.${handlerName}.`
60
- );
61
- throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
62
- }
63
- return next.handle();
64
- }
65
- }
66
- const { hasAccess, inputDataToBeMutated } = IAMAuthorizationService.checkAccess(
67
- handlerData,
68
- { body: req.body, headers: req.headers, params: req.params, query: req.query },
69
- user
70
- );
71
- if (!hasAccess) {
72
- console.info(
73
- `[${moduleName}][HTTPAuthorizationInterceptor]: No user access to handler ${controllerName}.${handlerName}.`
74
- );
75
- throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
76
- }
77
- for (const key in inputDataToBeMutated) {
78
- setNested(req, key, inputDataToBeMutated[key]);
79
- }
80
- return next.handle();
81
- }
82
- }
@@ -1,111 +0,0 @@
1
- import { HttpException, HttpStatus, Inject, Injectable, NestMiddleware } from '@nestjs/common';
2
-
3
- import { AppConfigAPIHTTP, ConfigProviderService } from '@node-c/core';
4
- import { DecodedTokenContent, IAMTokenManagerService, IAMUsersService, UserTokenEnityFields } from '@node-c/domain-iam';
5
-
6
- import { checkRoutes } from '@ramster/general-tools';
7
-
8
- import { NextFunction, Response } from 'express';
9
-
10
- import { Constants, RequestWithLocals } from '../common/definitions';
11
-
12
- @Injectable()
13
- export class HTTPAuthenticationMiddleware<User extends object> implements NestMiddleware {
14
- constructor(
15
- // eslint-disable-next-line no-unused-vars
16
- protected configProvider: ConfigProviderService,
17
- @Inject(Constants.API_MODULE_NAME)
18
- // eslint-disable-next-line no-unused-vars
19
- protected moduleName: string,
20
- @Inject(Constants.AUTHENTICATION_MIDDLEWARE_TOKEN_MANAGER_SERVICE)
21
- // eslint-disable-next-line no-unused-vars
22
- protected tokenManager: IAMTokenManagerService<UserTokenEnityFields>,
23
- @Inject(Constants.AUTHENTICATION_MIDDLEWARE_USERS_SERVICE)
24
- // eslint-disable-next-line no-unused-vars
25
- protected usersService: IAMUsersService<User>
26
- ) {}
27
-
28
- use(req: RequestWithLocals<unknown>, res: Response, next: NextFunction): void {
29
- (async () => {
30
- const { anonymousAccessRoutes } = this.configProvider.config.api![this.moduleName] as AppConfigAPIHTTP;
31
- if (!req.locals) {
32
- req.locals = {};
33
- }
34
- if (anonymousAccessRoutes && Object.keys(anonymousAccessRoutes).length) {
35
- const originalUrl = req.originalUrl.split('?')[0];
36
- let isAnonymous = false;
37
- for (const route in anonymousAccessRoutes) {
38
- if (
39
- checkRoutes(originalUrl, [route]) &&
40
- anonymousAccessRoutes[route].find(method => method === req.method.toLowerCase())
41
- ) {
42
- isAnonymous = true;
43
- break;
44
- }
45
- }
46
- if (isAnonymous) {
47
- req.locals.isAnonymous = true;
48
- next();
49
- return;
50
- }
51
- }
52
- const { tokenManager, usersService } = this;
53
- let tokens: string[] = [];
54
- let authToken = req.headers.authorization;
55
- let authTokenIsNew = false;
56
- let refreshToken: string | undefined;
57
- let tokenContent: DecodedTokenContent<UserTokenEnityFields> | undefined;
58
- let useCookie = false;
59
- if (typeof authToken === 'string' && authToken.length && authToken.match(/^Bearer\s/)) {
60
- tokens = authToken.split(' ');
61
- if (tokens.length) {
62
- authToken = tokens[1];
63
- refreshToken = tokens[2];
64
- }
65
- } else {
66
- authToken = req.cookies['sid'];
67
- useCookie = true;
68
- }
69
- if (!authToken) {
70
- console.error('Missing auth token.');
71
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
72
- }
73
- try {
74
- const tokenRes = await tokenManager.verifyAccessToken(authToken, {
75
- deleteFromStoreIfExpired: true,
76
- identifierDataField: 'userId',
77
- persistNewToken: true,
78
- purgeStoreOnRenew: true,
79
- refreshToken,
80
- refreshTokenAccessTokenIdentifierDataField: 'accessToken'
81
- });
82
- tokenContent = tokenRes.content!;
83
- if (tokenRes.newToken) {
84
- authTokenIsNew = true;
85
- }
86
- } catch (e) {
87
- console.error('Failed to parse the access or refresh token:', e);
88
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
89
- }
90
- if (authTokenIsNew) {
91
- res.setHeader('Authorization', `Bearer ${authToken}${refreshToken ? ` ${refreshToken}` : ''}`);
92
- if (useCookie) {
93
- res.cookie('sid', authToken);
94
- }
95
- }
96
- const userId = tokenContent?.data?.userId;
97
- if (!userId) {
98
- console.error('Missing userId in the tokenContent data.');
99
- throw new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED);
100
- }
101
- req.locals!.user = await usersService.getUserWithPermissionsData({ filters: { id: userId } });
102
- next();
103
- })().then(
104
- () => true,
105
- err => {
106
- console.error(err);
107
- res.status((err && err.status) || HttpStatus.INTERNAL_SERVER_ERROR).end();
108
- }
109
- );
110
- }
111
- }