@globaltracking/auth-middleware 2.0.1 → 3.0.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.
Files changed (50) hide show
  1. package/README.md +421 -372
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +7 -1
  4. package/dist/config.js.map +1 -1
  5. package/dist/extract-user.d.ts +6 -1
  6. package/dist/extract-user.d.ts.map +1 -1
  7. package/dist/extract-user.js +39 -2
  8. package/dist/extract-user.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/middlewares/require-permission.d.ts +2 -2
  14. package/dist/middlewares/require-permission.d.ts.map +1 -1
  15. package/dist/middlewares/require-permission.js +23 -8
  16. package/dist/middlewares/require-permission.js.map +1 -1
  17. package/dist/middlewares/require-role.d.ts +4 -2
  18. package/dist/middlewares/require-role.d.ts.map +1 -1
  19. package/dist/middlewares/require-role.js +12 -4
  20. package/dist/middlewares/require-role.js.map +1 -1
  21. package/dist/middlewares/require-self.d.ts +1 -1
  22. package/dist/middlewares/require-self.d.ts.map +1 -1
  23. package/dist/middlewares/require-self.js +4 -3
  24. package/dist/middlewares/require-self.js.map +1 -1
  25. package/dist/nestjs/gt-auth.module.d.ts +22 -0
  26. package/dist/nestjs/gt-auth.module.d.ts.map +1 -1
  27. package/dist/nestjs/gt-auth.module.js +39 -28
  28. package/dist/nestjs/gt-auth.module.js.map +1 -1
  29. package/dist/nestjs/guards/permissions.guard.d.ts +5 -1
  30. package/dist/nestjs/guards/permissions.guard.d.ts.map +1 -1
  31. package/dist/nestjs/guards/permissions.guard.js +12 -3
  32. package/dist/nestjs/guards/permissions.guard.js.map +1 -1
  33. package/dist/strategies/gateway-header.strategy.d.ts.map +1 -1
  34. package/dist/strategies/gateway-header.strategy.js +8 -1
  35. package/dist/strategies/gateway-header.strategy.js.map +1 -1
  36. package/dist/strategies/jwt.strategy.d.ts.map +1 -1
  37. package/dist/strategies/jwt.strategy.js +8 -1
  38. package/dist/strategies/jwt.strategy.js.map +1 -1
  39. package/dist/strategies/trusted-headers.strategy.d.ts.map +1 -1
  40. package/dist/strategies/trusted-headers.strategy.js +16 -1
  41. package/dist/strategies/trusted-headers.strategy.js.map +1 -1
  42. package/dist/types.d.ts +45 -2
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/utils/helpers.d.ts +14 -1
  45. package/dist/utils/helpers.d.ts.map +1 -1
  46. package/dist/utils/helpers.js +22 -2
  47. package/dist/utils/helpers.js.map +1 -1
  48. package/dist/utils/jwt.js +8 -1
  49. package/dist/utils/jwt.js.map +1 -1
  50. package/package.json +82 -82
@@ -35,10 +35,17 @@ class GatewayHeaderStrategy {
35
35
  if (!payload.sub) {
36
36
  throw new errors_1.UnauthorizedError('Token missing required claim: sub');
37
37
  }
38
+ const roles = Array.isArray(payload.roles)
39
+ ? payload.roles.filter((r) => typeof r === 'string')
40
+ : payload.role
41
+ ? [payload.role]
42
+ : [];
38
43
  return {
39
44
  userId: payload.sub,
40
45
  email: payload.email || '',
41
- role: payload.role || '',
46
+ role: roles[0] ?? payload.role ?? '',
47
+ roles,
48
+ isSystemAdmin: payload.is_system_admin === true,
42
49
  orgId: payload.org_id || '',
43
50
  tenantId: payload.tenant_id || payload.org_id || '',
44
51
  permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-header.strategy.js","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,qBAAqB;IAAlC;QACW,SAAI,GAAG,gBAAgB,CAAC;IAwCnC,CAAC;IAtCC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAW,CAAC;QAEpE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,iCAAiC,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,6BAA6B,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;QACnE,CAAC;QAED,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,GAAG;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;YACxB,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC3B,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;YACnD,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YAC1E,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAY,IAAI,EAAE;YACxD,UAAU,EAAE,gBAAgB;SAC7B,CAAC;IACJ,CAAC;CACF;AAzCD,sDAyCC"}
1
+ {"version":3,"file":"gateway-header.strategy.js","sourceRoot":"","sources":["../../src/strategies/gateway-header.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,qBAAqB;IAAlC;QACW,SAAI,GAAG,gBAAgB,CAAC;IAgDnC,CAAC;IA9CC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAW,CAAC;QAEpE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,iCAAiC,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,0BAAiB,CAAC,6BAA6B,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;YACjE,CAAC,CAAC,OAAO,CAAC,IAAI;gBACZ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;gBAChB,CAAC,CAAC,EAAE,CAAC;QAET,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,GAAG;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE;YACpC,KAAK;YACL,aAAa,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI;YAC/C,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC3B,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;YACnD,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YAC1E,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAY,IAAI,EAAE;YACxD,UAAU,EAAE,gBAAgB;SAC7B,CAAC;IACJ,CAAC;CACF;AAjDD,sDAiDC"}
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,WAAY,YAAW,sBAAsB;IACxD,QAAQ,CAAC,IAAI,SAAS;IAEtB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAIhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CA8ChC"}
1
+ {"version":3,"file":"jwt.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,qBAAa,WAAY,YAAW,sBAAsB;IACxD,QAAQ,CAAC,IAAI,SAAS;IAEtB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAIhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CAsDhC"}
@@ -78,10 +78,17 @@ class JwtStrategy {
78
78
  if (!decoded.sub) {
79
79
  throw new errors_1.UnauthorizedError('Token missing required claim: sub');
80
80
  }
81
+ const roles = Array.isArray(decoded.roles)
82
+ ? decoded.roles.filter((r) => typeof r === 'string')
83
+ : decoded.role
84
+ ? [decoded.role]
85
+ : [];
81
86
  return {
82
87
  userId: decoded.sub,
83
88
  email: decoded.email || '',
84
- role: decoded.role || '',
89
+ role: roles[0] ?? decoded.role ?? '',
90
+ roles,
91
+ isSystemAdmin: decoded.is_system_admin === true,
85
92
  orgId: decoded.org_id || '',
86
93
  tenantId: decoded.tenant_id || decoded.org_id || '',
87
94
  permissions: Array.isArray(decoded.permissions) ? decoded.permissions : [],
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAoC;AAEpC,sCAAsC;AAEtC,sCAA8C;AAG9C;;;GAGG;AACH,MAAa,WAAW;IAAxB;QACW,SAAI,GAAG,KAAK,CAAC;IAoDxB,CAAC;IAlDC,SAAS,CAAC,GAAY;QACpB,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAc,CAAC;QAE9C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAChD,MAAM,IAAI,0BAAiB,CAAC,iEAAiE,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,0BAAiB,CAAC,2DAA2D,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;gBAC5C,UAAU,EAAE,CAAC,OAAO,CAAC;gBACrB,MAAM,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS;aACtC,CAAe,CAAC;QACnB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBACzC,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;gBACzC,MAAM,IAAI,0BAAiB,CAAC,kBAAkB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,IAAI,0BAAiB,CAAC,2BAA2B,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;QACnE,CAAC;QAED,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,GAAG;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;YACxB,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;YAC3B,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;YACnD,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YAC1E,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAY,IAAI,EAAE;YACxD,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;CACF;AArDD,kCAqDC"}
1
+ {"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/strategies/jwt.strategy.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"trusted-headers.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAMhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CA8BhC"}
1
+ {"version":3,"file":"trusted-headers.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;GAMG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAMhC,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ;CA+ChC"}
@@ -34,10 +34,25 @@ class TrustedHeadersStrategy {
34
34
  }
35
35
  }
36
36
  const orgId = req.headers[headerNames.orgId] || '';
37
+ // Prefer `x-user-roles` (comma-separated) over the legacy single-role header.
38
+ const rawRolesHeader = req.headers[headerNames.roles];
39
+ const legacyRole = req.headers[headerNames.userRole] || '';
40
+ const roles = rawRolesHeader
41
+ ? rawRolesHeader
42
+ .split(',')
43
+ .map((r) => r.trim())
44
+ .filter((r) => r.length > 0)
45
+ : legacyRole
46
+ ? [legacyRole]
47
+ : [];
48
+ const isAdminHeader = req.headers[headerNames.isSystemAdmin] ?? '';
49
+ const isSystemAdmin = ['true', '1', 'yes'].includes(isAdminHeader.trim().toLowerCase());
37
50
  return {
38
51
  userId,
39
52
  email: '',
40
- role: req.headers[headerNames.userRole] || '',
53
+ role: roles[0] ?? legacyRole,
54
+ roles,
55
+ isSystemAdmin,
41
56
  orgId,
42
57
  tenantId: orgId,
43
58
  permissions: [],
@@ -1 +1 @@
1
- {"version":3,"file":"trusted-headers.strategy.js","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;;;;GAMG;AACH,MAAa,sBAAsB;IAAnC;QACW,SAAI,GAAG,iBAAiB,CAAC;IAsCpC,CAAC;IApCC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAC9C,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAuB,CAAC;QACrE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,0BAAiB,CAAC,0CAA0C,CAAC,CAAC;QAC1E,CAAC;QAED,uCAAuC;QACvC,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAuB,CAAC;YACjF,IAAI,YAAY,KAAK,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBACjD,MAAM,IAAI,0BAAiB,CAAC,kCAAkC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAY,IAAI,EAAE,CAAC;QAE/D,OAAO;YACL,MAAM;YACN,KAAK,EAAE,EAAE;YACT,IAAI,EAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAY,IAAI,EAAE;YACzD,KAAK;YACL,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,EAAE;YACf,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAY,IAAI,EAAE;YAC/D,UAAU,EAAE,iBAAiB;SAC9B,CAAC;IACJ,CAAC;CACF;AAvCD,wDAuCC"}
1
+ {"version":3,"file":"trusted-headers.strategy.js","sourceRoot":"","sources":["../../src/strategies/trusted-headers.strategy.ts"],"names":[],"mappings":";;;AACA,sCAAsC;AAEtC,sCAA8C;AAG9C;;;;;;GAMG;AACH,MAAa,sBAAsB;IAAnC;QACW,SAAI,GAAG,iBAAiB,CAAC;IAuDpC,CAAC;IArDC,SAAS,CAAC,GAAY;QACpB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAC9C,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,GAAY;QAClB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC;QAE9C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAuB,CAAC;QACrE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,0BAAiB,CAAC,0CAA0C,CAAC,CAAC;QAC1E,CAAC;QAED,uCAAuC;QACvC,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAuB,CAAC;YACjF,IAAI,YAAY,KAAK,MAAM,CAAC,oBAAoB,EAAE,CAAC;gBACjD,MAAM,IAAI,0BAAiB,CAAC,kCAAkC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAY,IAAI,EAAE,CAAC;QAE/D,8EAA8E;QAC9E,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAuB,CAAC;QAC5E,MAAM,UAAU,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAY,IAAI,EAAE,CAAC;QACvE,MAAM,KAAK,GAAa,cAAc;YACpC,CAAC,CAAC,cAAc;iBACX,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAChC,CAAC,CAAC,UAAU;gBACV,CAAC,CAAC,CAAC,UAAU,CAAC;gBACd,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,aAAa,GAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAwB,IAAI,EAAE,CAAC;QAC3F,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAExF,OAAO;YACL,MAAM;YACN,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU;YAC5B,KAAK;YACL,aAAa;YACb,KAAK;YACL,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,EAAE;YACf,SAAS,EAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAY,IAAI,EAAE;YAC/D,UAAU,EAAE,iBAAiB;SAC9B,CAAC;IACJ,CAAC;CACF;AAxDD,wDAwDC"}
package/dist/types.d.ts CHANGED
@@ -3,9 +3,34 @@ export type UserRole = 'system_admin' | 'org_admin' | 'user' | (string & {});
3
3
  export interface AuthUser {
4
4
  userId: string;
5
5
  email: string;
6
+ /**
7
+ * @deprecated Use `roles` (array) instead. This is `roles[0] ?? ''` for
8
+ * backwards compatibility with callers that haven't migrated yet.
9
+ */
6
10
  role: UserRole;
11
+ /** All roles assigned to this user in their current org. */
12
+ roles: string[];
13
+ /**
14
+ * True when this user is a cross-tenant Global Tracking platform staff
15
+ * member. Sourced from `users.is_system_admin` via the JWT. Grants a
16
+ * middleware-level bypass on permission checks AND allows cross-tenant
17
+ * action via `X-Acting-On-Org`.
18
+ */
19
+ isSystemAdmin: boolean;
7
20
  orgId: string;
8
21
  tenantId: string;
22
+ /**
23
+ * When a system admin used `X-Acting-On-Org` to target a different tenant,
24
+ * this records their HOME org (the org they logged in as). Downstream
25
+ * audit logging should include this so staff actions on customer tenants
26
+ * are traceable.
27
+ */
28
+ actingOnOrg?: {
29
+ /** The system admin's original home org (from their JWT). */
30
+ homeOrgId: string;
31
+ /** The org they are currently acting on (= `orgId`). */
32
+ targetOrgId: string;
33
+ };
9
34
  permissions: string[];
10
35
  requestId: string;
11
36
  authSource: AuthStrategy;
@@ -16,6 +41,9 @@ export interface TrustedHeaderNames {
16
41
  userId?: string;
17
42
  orgId?: string;
18
43
  userRole?: string;
44
+ roles?: string;
45
+ isSystemAdmin?: string;
46
+ actingOnOrg?: string;
19
47
  requestId?: string;
20
48
  gatewayToken?: string;
21
49
  }
@@ -32,7 +60,14 @@ export interface AuthConfig {
32
60
  superAdminRole?: string;
33
61
  /** Ordered list of strategies to try. Default: ['gateway-header', 'jwt'] */
34
62
  strategies?: AuthStrategy[];
35
- /** Roles that bypass all permission checks. Default: ['system_admin', 'org_admin'] */
63
+ /**
64
+ * RBAC role names that receive a permission-check bypass within their own
65
+ * tenant. Default: ['org_admin'].
66
+ *
67
+ * Note: `system_admin` is NOT on this list — system-admin bypass is
68
+ * sourced from the `is_system_admin` claim, and (unlike org_admin) comes
69
+ * with cross-tenant authority via `X-Acting-On-Org`.
70
+ */
36
71
  adminRoles?: string[];
37
72
  /** Shared secret for InternalOnlyGuard. Also reads from env INTERNAL_GATEWAY_TOKEN */
38
73
  internalGatewayToken?: string;
@@ -46,7 +81,15 @@ export interface AuthConfig {
46
81
  export interface JwtPayload {
47
82
  sub: string;
48
83
  email: string;
49
- role: string;
84
+ /** @deprecated Prefer `roles` (array). Kept as `roles[0]` for older consumers. */
85
+ role?: string;
86
+ /** All RBAC role names assigned to this user in their current org. */
87
+ roles?: string[];
88
+ /**
89
+ * Whether this user is a Global Tracking platform-staff member
90
+ * (`users.is_system_admin = TRUE`). Grants cross-tenant privilege.
91
+ */
92
+ is_system_admin?: boolean;
50
93
  tenant_id: string;
51
94
  org_id: string;
52
95
  permissions: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,21 @@
1
1
  import { AuthUser } from '../types';
2
2
  /**
3
- * Check if a user has one of the specified roles.
3
+ * Check if a user has ANY of the specified roles. Checks the full `roles`
4
+ * array, not just the legacy `role` single-value field.
4
5
  */
5
6
  export declare function hasRole(user: AuthUser, ...roles: string[]): boolean;
7
+ /**
8
+ * True when this user is a Global Tracking platform-staff member (from
9
+ * the `is_system_admin` JWT claim). System admins get cross-tenant scope
10
+ * via the `X-Acting-On-Org` header and bypass permission checks
11
+ * unconditionally.
12
+ */
13
+ export declare function isSystemAdmin(user: AuthUser): boolean;
14
+ /**
15
+ * True when this user has the `org_admin` RBAC role in their tenant.
16
+ * org_admin does NOT cross tenants; their bypass is scoped to `user.orgId`.
17
+ */
18
+ export declare function isOrgAdmin(user: AuthUser): boolean;
6
19
  /**
7
20
  * Check if a user has ALL of the specified permissions.
8
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAEnE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAG/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAGlF"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAErD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAG/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAGlF"}
@@ -1,13 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasRole = hasRole;
4
+ exports.isSystemAdmin = isSystemAdmin;
5
+ exports.isOrgAdmin = isOrgAdmin;
4
6
  exports.hasPermission = hasPermission;
5
7
  exports.hasAnyPermission = hasAnyPermission;
6
8
  /**
7
- * Check if a user has one of the specified roles.
9
+ * Check if a user has ANY of the specified roles. Checks the full `roles`
10
+ * array, not just the legacy `role` single-value field.
8
11
  */
9
12
  function hasRole(user, ...roles) {
10
- return roles.includes(user.role);
13
+ const userRoles = new Set(user.roles);
14
+ return roles.some((r) => userRoles.has(r));
15
+ }
16
+ /**
17
+ * True when this user is a Global Tracking platform-staff member (from
18
+ * the `is_system_admin` JWT claim). System admins get cross-tenant scope
19
+ * via the `X-Acting-On-Org` header and bypass permission checks
20
+ * unconditionally.
21
+ */
22
+ function isSystemAdmin(user) {
23
+ return user.isSystemAdmin === true;
24
+ }
25
+ /**
26
+ * True when this user has the `org_admin` RBAC role in their tenant.
27
+ * org_admin does NOT cross tenants; their bypass is scoped to `user.orgId`.
28
+ */
29
+ function isOrgAdmin(user) {
30
+ return user.roles.includes('org_admin');
11
31
  }
12
32
  /**
13
33
  * Check if a user has ALL of the specified permissions.
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":";;AAKA,0BAEC;AAKD,sCAGC;AAKD,4CAGC;AArBD;;GAEG;AACH,SAAgB,OAAO,CAAC,IAAc,EAAE,GAAG,KAAe;IACxD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,IAAc,EAAE,GAAG,WAAqB;IACpE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,IAAc,EAAE,GAAG,WAAqB;IACvE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":";;AAMA,0BAGC;AAQD,sCAEC;AAMD,gCAEC;AAKD,sCAGC;AAKD,4CAGC;AAzCD;;;GAGG;AACH,SAAgB,OAAO,CAAC,IAAc,EAAE,GAAG,KAAe;IACxD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,IAAc;IAC1C,OAAO,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,IAAc;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,IAAc,EAAE,GAAG,WAAqB;IACpE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,IAAc,EAAE,GAAG,WAAqB;IACvE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
package/dist/utils/jwt.js CHANGED
@@ -90,10 +90,17 @@ function mapPayloadToUser(payload, authSource) {
90
90
  if (!payload.sub) {
91
91
  throw new errors_1.UnauthorizedError('Token missing required claim: sub');
92
92
  }
93
+ const roles = Array.isArray(payload.roles)
94
+ ? payload.roles.filter((r) => typeof r === 'string')
95
+ : payload.role
96
+ ? [payload.role]
97
+ : [];
93
98
  return {
94
99
  userId: payload.sub,
95
100
  email: payload.email || '',
96
- role: payload.role || '',
101
+ role: roles[0] ?? payload.role ?? '',
102
+ roles,
103
+ isSystemAdmin: payload.is_system_admin === true,
97
104
  tenantId: payload.tenant_id || payload.org_id || '',
98
105
  orgId: payload.org_id || '',
99
106
  permissions: Array.isArray(payload.permissions) ? payload.permissions : [],
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,kCA2BC;AAMD,kDAkBC;AA5DD,kDAAoC;AACpC,sCAAsC;AAEtC,sCAA8C;AAE9C;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,0BAAiB,CACzB,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,IAAI,OAAmB,CAAC;IAExB,IAAI,CAAC;QACH,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE;YAC5C,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE,MAAM,CAAC,SAAS,IAAI,SAAS;SACtC,CAAe,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACzC,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,GAAG,YAAY,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACzC,MAAM,IAAI,0BAAiB,CAAC,kBAAkB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,0BAAiB,CAAC,2BAA2B,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,IAAI,OAAe,CAAC;IAEpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAAiB,CAAC,iCAAiC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,OAAmB,CAAC;IAExB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,0BAAiB,CAAC,6BAA6B,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAmB,EAAE,UAAoC;IACjF,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,0BAAiB,CAAC,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,GAAG;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;QACxB,QAAQ,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;QACnD,KAAK,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC3B,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;QAC1E,SAAS,EAAE,EAAE;QACb,UAAU;KACX,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,82 +1,82 @@
1
- {
2
- "name": "@globaltracking/auth-middleware",
3
- "version": "2.0.1",
4
- "description": "Unified authentication and authorization middleware for the Global Tracking platform (Express + NestJS)",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "default": "./dist/index.js"
11
- },
12
- "./nestjs": {
13
- "types": "./dist/nestjs.d.ts",
14
- "default": "./dist/nestjs.js"
15
- }
16
- },
17
- "files": [
18
- "dist"
19
- ],
20
- "scripts": {
21
- "build": "tsc -p tsconfig.build.json",
22
- "clean": "rm -rf dist",
23
- "prebuild": "npm run clean",
24
- "test": "jest --coverage",
25
- "test:watch": "jest --watch",
26
- "prepublishOnly": "npm run build"
27
- },
28
- "keywords": [
29
- "globaltracking",
30
- "auth",
31
- "middleware",
32
- "express",
33
- "nestjs",
34
- "rbac",
35
- "multi-tenant",
36
- "jwt",
37
- "rls"
38
- ],
39
- "author": "GeoSentry",
40
- "license": "UNLICENSED",
41
- "repository": {
42
- "type": "git",
43
- "url": "https://github.com/TrackCongoInfra/gt-auth-middleware.git"
44
- },
45
- "publishConfig": {
46
- "registry": "https://registry.npmjs.org",
47
- "access": "public"
48
- },
49
- "peerDependencies": {
50
- "express": "^4.18.0",
51
- "@nestjs/common": "^11.0.0",
52
- "@nestjs/core": "^11.0.0",
53
- "typeorm": "^0.3.0",
54
- "rxjs": "^7.0.0"
55
- },
56
- "peerDependenciesMeta": {
57
- "@nestjs/common": { "optional": true },
58
- "@nestjs/core": { "optional": true },
59
- "typeorm": { "optional": true },
60
- "rxjs": { "optional": true }
61
- },
62
- "dependencies": {
63
- "jsonwebtoken": "^9.0.2"
64
- },
65
- "devDependencies": {
66
- "@nestjs/common": "^11.1.18",
67
- "@nestjs/core": "^11.1.18",
68
- "@nestjs/testing": "^11.1.18",
69
- "@types/express": "^4.17.21",
70
- "@types/jest": "^29.5.14",
71
- "@types/jsonwebtoken": "^9.0.9",
72
- "@types/node": "^22.0.0",
73
- "express": "^4.21.0",
74
- "jest": "^29.7.0",
75
- "reflect-metadata": "^0.2.2",
76
- "rxjs": "^7.8.2",
77
- "ts-jest": "^29.2.5",
78
- "ts-node": "^10.9.2",
79
- "typeorm": "^0.3.28",
80
- "typescript": "^5.7.3"
81
- }
82
- }
1
+ {
2
+ "name": "@globaltracking/auth-middleware",
3
+ "version": "3.0.0",
4
+ "description": "Unified authentication and authorization middleware for the Global Tracking platform (Express + NestJS)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./nestjs": {
13
+ "types": "./dist/nestjs.d.ts",
14
+ "default": "./dist/nestjs.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.build.json",
22
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
23
+ "prebuild": "npm run clean",
24
+ "test": "jest --coverage",
25
+ "test:watch": "jest --watch",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "keywords": [
29
+ "globaltracking",
30
+ "auth",
31
+ "middleware",
32
+ "express",
33
+ "nestjs",
34
+ "rbac",
35
+ "multi-tenant",
36
+ "jwt",
37
+ "rls"
38
+ ],
39
+ "author": "GeoSentry",
40
+ "license": "UNLICENSED",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/TrackCongoInfra/gt-auth-middleware.git"
44
+ },
45
+ "publishConfig": {
46
+ "registry": "https://registry.npmjs.org",
47
+ "access": "public"
48
+ },
49
+ "peerDependencies": {
50
+ "express": "^4.18.0",
51
+ "@nestjs/common": "^11.0.0",
52
+ "@nestjs/core": "^11.0.0",
53
+ "typeorm": "^0.3.0",
54
+ "rxjs": "^7.0.0"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "@nestjs/common": { "optional": true },
58
+ "@nestjs/core": { "optional": true },
59
+ "typeorm": { "optional": true },
60
+ "rxjs": { "optional": true }
61
+ },
62
+ "dependencies": {
63
+ "jsonwebtoken": "^9.0.2"
64
+ },
65
+ "devDependencies": {
66
+ "@nestjs/common": "^11.1.18",
67
+ "@nestjs/core": "^11.1.18",
68
+ "@nestjs/testing": "^11.1.18",
69
+ "@types/express": "^4.17.21",
70
+ "@types/jest": "^29.5.14",
71
+ "@types/jsonwebtoken": "^9.0.9",
72
+ "@types/node": "^22.0.0",
73
+ "express": "^4.21.0",
74
+ "jest": "^29.7.0",
75
+ "reflect-metadata": "^0.2.2",
76
+ "rxjs": "^7.8.2",
77
+ "ts-jest": "^29.2.5",
78
+ "ts-node": "^10.9.2",
79
+ "typeorm": "^0.3.28",
80
+ "typescript": "^5.7.3"
81
+ }
82
+ }