@nmshd/typescript-rest 3.2.0 → 3.2.2

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/.ci/runChecks.sh CHANGED
@@ -4,4 +4,4 @@ npm ci
4
4
  npm run build
5
5
  npm run lint
6
6
  npx license-check
7
- npx better-npm-audit audit --exclude=1106509,1096727,1097682
7
+ npx better-npm-audit audit --exclude=1109540,1096727,1097682
@@ -8,8 +8,8 @@ jobs:
8
8
  run-checks:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
- - uses: actions/checkout@v4
12
- - uses: actions/setup-node@v4
11
+ - uses: actions/checkout@v5
12
+ - uses: actions/setup-node@v6
13
13
  with:
14
14
  node-version: current
15
15
  - run: bash .ci/runChecks.sh
@@ -28,6 +28,4 @@ jobs:
28
28
  - run: npm ci
29
29
  - run: npm run build
30
30
  - run: npx enhanced-publish --if-possible --use-preid-as-tag
31
- env:
32
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
33
31
  needs: ['run-checks']
@@ -13,8 +13,8 @@ jobs:
13
13
  run-checks:
14
14
  runs-on: ubuntu-latest
15
15
  steps:
16
- - uses: actions/checkout@v4
17
- - uses: actions/setup-node@v4
16
+ - uses: actions/checkout@v5
17
+ - uses: actions/setup-node@v6
18
18
  with:
19
19
  node-version: current
20
20
  - run: bash .ci/runChecks.sh
@@ -13,11 +13,11 @@ function routeRequiresAuthorization(authenticator, ...permittedRoles) {
13
13
  throw new Error(`Invalid permitted role(s) specified: ${nonMatchingRoles.join(', ')}. Roles must match the pattern: ${roleRegex}.`);
14
14
  }
15
15
  return (req, res, next) => {
16
- const requestRoles = authenticator.getRoles(req, res);
16
+ const rawUserRoles = authenticator.getRoles(req, res);
17
17
  if (debuggerInstance.enabled)
18
- debuggerInstance('Validating authentication roles: <%j>.', requestRoles);
19
- const transformedRoles = requestRoles.map(transformUserRole);
20
- const isAuthorized = permittedRoles.some((permittedRole) => isRoleMatched(permittedRole, transformedRoles));
18
+ debuggerInstance('Validating authentication roles: <%j>.', rawUserRoles);
19
+ const userRoles = rawUserRoles.map(Role.from);
20
+ const isAuthorized = permittedRoles.some((r) => isRoleMatched(r, userRoles));
21
21
  if (!isAuthorized) {
22
22
  next(new Errors.ForbiddenError('You are not allowed to access this endpoint.'));
23
23
  return;
@@ -26,19 +26,25 @@ function routeRequiresAuthorization(authenticator, ...permittedRoles) {
26
26
  };
27
27
  }
28
28
  function isRoleMatched(permittedRole, userRoles) {
29
- for (const userRole of userRoles) {
30
- const isMatch = userRole.test(permittedRole);
31
- if (isMatch)
32
- return true;
33
- }
34
- return false;
29
+ return userRoles.some((userRole) => userRole.matches(permittedRole));
35
30
  }
36
- function transformUserRole(userRole) {
37
- if (!userRole.includes('*'))
38
- return new RegExp(`^${userRole}$`);
39
- const regexString = userRole
40
- .replaceAll('**', '[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}')
41
- .replaceAll('*', '[a-zA-Z0-9_-]+');
42
- return new RegExp(`^${regexString}$`);
31
+ class Role {
32
+ constructor(role) {
33
+ this.roleRegex = this.transformUserRole(role);
34
+ }
35
+ static from(role) {
36
+ return new Role(role);
37
+ }
38
+ transformUserRole(userRole) {
39
+ if (!userRole.includes('*'))
40
+ return new RegExp(`^${userRole}$`);
41
+ const regexString = userRole
42
+ .replaceAll('**', '[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}')
43
+ .replaceAll('*', '[a-zA-Z0-9_-]+');
44
+ return new RegExp(`^${regexString}$`);
45
+ }
46
+ matches(permittedRole) {
47
+ return this.roleRegex.test(permittedRole);
48
+ }
43
49
  }
44
50
  //# sourceMappingURL=routeRequiresAuthorization.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routeRequiresAuthorization.js","sourceRoot":"","sources":["../../src/middlewares/routeRequiresAuthorization.ts"],"names":[],"mappings":";;AAMA,gEA2BC;AAjCD,+BAA+B;AAE/B,iDAAiD;AAEjD,MAAM,gBAAgB,GAAG,KAAK,CAAC,wDAAwD,CAAC,CAAC;AAEzF,SAAgB,0BAA0B,CACtC,aAA2E,EAC3E,GAAG,cAA0C;IAE7C,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAEnG,MAAM,SAAS,GAAG,uCAAuC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,wCAAwC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,SAAS,GAAG,CACrH,CAAC;IACN,CAAC;IAED,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACvD,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,gBAAgB,CAAC,OAAO;YAAE,gBAAgB,CAAC,wCAAwC,EAAE,YAAY,CAAC,CAAC;QAEvG,MAAM,gBAAgB,GAAG,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC5G,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,8CAA8C,CAAC,CAAC,CAAC;YAChF,OAAO;QACX,CAAC;QAED,IAAI,EAAE,CAAC;IACX,CAAC,CAAC;AACN,CAAC;AAED,SAAS,aAAa,CAAC,aAAqB,EAAE,SAAwB;IAClE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7C,IAAI,OAAO;YAAE,OAAO,IAAI,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,MAAM,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEhE,MAAM,WAAW,GAAG,QAAQ;SACvB,UAAU,CAAC,IAAI,EAAE,qCAAqC,CAAC;SACvD,UAAU,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IACvC,OAAO,IAAI,MAAM,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC;AAC1C,CAAC"}
1
+ {"version":3,"file":"routeRequiresAuthorization.js","sourceRoot":"","sources":["../../src/middlewares/routeRequiresAuthorization.ts"],"names":[],"mappings":";;AAMA,gEA2BC;AAjCD,+BAA+B;AAE/B,iDAAiD;AAEjD,MAAM,gBAAgB,GAAG,KAAK,CAAC,wDAAwD,CAAC,CAAC;AAEzF,SAAgB,0BAA0B,CACtC,aAA2E,EAC3E,GAAG,cAA0C;IAE7C,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAEnG,MAAM,SAAS,GAAG,uCAAuC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACX,wCAAwC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,SAAS,GAAG,CACrH,CAAC;IACN,CAAC;IAED,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACvD,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,gBAAgB,CAAC,OAAO;YAAE,gBAAgB,CAAC,wCAAwC,EAAE,YAAY,CAAC,CAAC;QAEvG,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,8CAA8C,CAAC,CAAC,CAAC;YAChF,OAAO;QACX,CAAC;QAED,IAAI,EAAE,CAAC;IACX,CAAC,CAAC;AACN,CAAC;AAED,SAAS,aAAa,CAAC,aAAqB,EAAE,SAAsB;IAChE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,IAAI;IAGN,YAAoB,IAAY;QAC5B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAEM,MAAM,CAAC,IAAI,CAAC,IAAY;QAC3B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAEO,iBAAiB,CAAC,QAAgB;QACtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,MAAM,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEhE,MAAM,WAAW,GAAG,QAAQ;aACvB,UAAU,CAAC,IAAI,EAAE,qCAAqC,CAAC;aACvD,UAAU,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACvC,OAAO,IAAI,MAAM,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC;IAC1C,CAAC;IAEM,OAAO,CAAC,aAAqB;QAChC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nmshd/typescript-rest",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "A Library to create RESTFul APIs with Typescript",
5
5
  "keywords": [
6
6
  "API",
@@ -60,44 +60,44 @@
60
60
  "sourceMap": true
61
61
  },
62
62
  "dependencies": {
63
- "@types/body-parser": "1.19.5",
64
- "@types/cookie-parser": "^1.4.8",
65
- "@types/express": "^5.0.2",
66
- "@types/multer": "^1.4.13",
67
- "body-parser": "^2.2.0",
63
+ "@types/body-parser": "1.19.6",
64
+ "@types/cookie-parser": "^1.4.9",
65
+ "@types/express": "^5.0.3",
66
+ "@types/multer": "^2.0.0",
67
+ "body-parser": "^2.2.1",
68
68
  "cookie-parser": "^1.4.7",
69
69
  "express": "^5.1.0",
70
- "fs-extra": "^11.3.0",
70
+ "fs-extra": "^11.3.2",
71
71
  "lodash": "^4.17.21",
72
- "multer": "^2.0.1",
72
+ "multer": "^2.0.2",
73
73
  "reflect-metadata": "^0.2.2",
74
74
  "require-glob": "^4.1.0",
75
75
  "swagger-ui-express": "^5.0.1",
76
76
  "yamljs": "^0.3.0"
77
77
  },
78
78
  "devDependencies": {
79
- "@js-soft/license-check": "^1.0.9",
80
- "@nmshd/typescript-ioc": "^3.2.4",
79
+ "@js-soft/license-check": "^1.0.10",
80
+ "@nmshd/typescript-ioc": "^3.2.5",
81
81
  "@types/debug": "^4.1.12",
82
82
  "@types/fs-extra": "^11.0.4",
83
- "@types/jest": "^29.5.14",
84
- "@types/lodash": "^4.17.16",
85
- "@types/node": "^22.15.19",
86
- "@types/request": "^2.48.12",
83
+ "@types/jest": "^30.0.0",
84
+ "@types/lodash": "^4.17.20",
85
+ "@types/node": "^24.7.2",
86
+ "@types/request": "^2.48.13",
87
87
  "@types/yamljs": "^0.2.34",
88
88
  "@typescript-eslint/eslint-plugin": "^6.20.0",
89
89
  "@typescript-eslint/parser": "^6.20.0",
90
- "cross-env": "^7.0.3",
90
+ "cross-env": "^10.1.0",
91
91
  "eslint": "^8.56.0",
92
92
  "eslint-config-prettier": "^9.1.0",
93
93
  "eslint-plugin-jsdoc": "^48.0.4",
94
94
  "eslint-plugin-prefer-arrow": "^1.2.3",
95
- "jest": "^29.7.0",
96
- "prettier": "^3.5.3",
95
+ "jest": "^30.2.0",
96
+ "prettier": "^3.6.2",
97
97
  "request": "^2.88.2",
98
98
  "rimraf": "^6.0.1",
99
- "ts-jest": "^29.3.4",
100
- "typescript": "^5.8.3"
99
+ "ts-jest": "^29.4.5",
100
+ "typescript": "^5.9.3"
101
101
  },
102
102
  "engines": {
103
103
  "node": ">=6.0.0"
@@ -19,11 +19,11 @@ export function routeRequiresAuthorization(
19
19
  }
20
20
 
21
21
  return (req: Request, res: Response, next: NextFunction) => {
22
- const requestRoles = authenticator.getRoles(req, res);
23
- if (debuggerInstance.enabled) debuggerInstance('Validating authentication roles: <%j>.', requestRoles);
22
+ const rawUserRoles = authenticator.getRoles(req, res);
23
+ if (debuggerInstance.enabled) debuggerInstance('Validating authentication roles: <%j>.', rawUserRoles);
24
24
 
25
- const transformedRoles = requestRoles.map(transformUserRole);
26
- const isAuthorized = permittedRoles.some((permittedRole) => isRoleMatched(permittedRole, transformedRoles));
25
+ const userRoles = rawUserRoles.map(Role.from);
26
+ const isAuthorized = permittedRoles.some((r) => isRoleMatched(r, userRoles));
27
27
  if (!isAuthorized) {
28
28
  next(new Errors.ForbiddenError('You are not allowed to access this endpoint.'));
29
29
  return;
@@ -33,20 +33,31 @@ export function routeRequiresAuthorization(
33
33
  };
34
34
  }
35
35
 
36
- function isRoleMatched(permittedRole: string, userRoles: Array<RegExp>): boolean {
37
- for (const userRole of userRoles) {
38
- const isMatch = userRole.test(permittedRole);
39
- if (isMatch) return true;
36
+ function isRoleMatched(permittedRole: string, userRoles: Array<Role>): boolean {
37
+ return userRoles.some((userRole) => userRole.matches(permittedRole));
38
+ }
39
+
40
+ class Role {
41
+ private roleRegex: RegExp;
42
+
43
+ private constructor(role: string) {
44
+ this.roleRegex = this.transformUserRole(role);
40
45
  }
41
46
 
42
- return false;
43
- }
47
+ public static from(role: string): Role {
48
+ return new Role(role);
49
+ }
50
+
51
+ private transformUserRole(userRole: string): RegExp {
52
+ if (!userRole.includes('*')) return new RegExp(`^${userRole}$`);
44
53
 
45
- function transformUserRole(userRole: string): RegExp {
46
- if (!userRole.includes('*')) return new RegExp(`^${userRole}$`);
54
+ const regexString = userRole
55
+ .replaceAll('**', '[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}')
56
+ .replaceAll('*', '[a-zA-Z0-9_-]+');
57
+ return new RegExp(`^${regexString}$`);
58
+ }
47
59
 
48
- const regexString = userRole
49
- .replaceAll('**', '[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+){0,}')
50
- .replaceAll('*', '[a-zA-Z0-9_-]+');
51
- return new RegExp(`^${regexString}$`);
60
+ public matches(permittedRole: string): unknown {
61
+ return this.roleRegex.test(permittedRole);
62
+ }
52
63
  }