permissions-contractx 1.0.2 → 1.2.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 (87) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +53 -1346
  3. package/dist/constants/contractx-permissions.constants.d.ts +84 -92
  4. package/dist/constants/contractx-permissions.constants.d.ts.map +1 -1
  5. package/dist/constants/contractx-permissions.constants.js +2 -2
  6. package/dist/constants/contractx-roles.constants.d.ts +150 -254
  7. package/dist/constants/contractx-roles.constants.d.ts.map +1 -1
  8. package/dist/constants/contractx-roles.constants.js +2 -2
  9. package/dist/constants/index.d.ts +1 -0
  10. package/dist/constants/index.d.ts.map +1 -1
  11. package/dist/constants/index.js +1 -0
  12. package/dist/constants/permission-names.constants.d.ts +432 -0
  13. package/dist/constants/permission-names.constants.d.ts.map +1 -0
  14. package/dist/constants/permission-names.constants.js +304 -0
  15. package/dist/constants/security.constants.d.ts +49 -49
  16. package/dist/constants/security.constants.d.ts.map +1 -1
  17. package/dist/constants/security.constants.js +2 -2
  18. package/dist/decorators/current-user.decorator.d.ts +5 -53
  19. package/dist/decorators/current-user.decorator.d.ts.map +1 -1
  20. package/dist/decorators/current-user.decorator.js +4 -51
  21. package/dist/decorators/index.d.ts +1 -0
  22. package/dist/decorators/index.d.ts.map +1 -1
  23. package/dist/decorators/index.js +1 -0
  24. package/dist/decorators/permission-writes.decorator.d.ts +14 -0
  25. package/dist/decorators/permission-writes.decorator.d.ts.map +1 -0
  26. package/dist/decorators/permission-writes.decorator.js +18 -0
  27. package/dist/decorators/permissions.decorator.d.ts +0 -58
  28. package/dist/decorators/permissions.decorator.d.ts.map +1 -1
  29. package/dist/decorators/permissions.decorator.js +0 -58
  30. package/dist/decorators/public.decorator.d.ts +0 -0
  31. package/dist/decorators/public.decorator.d.ts.map +0 -0
  32. package/dist/decorators/public.decorator.js +0 -0
  33. package/dist/decorators/roles.decorator.d.ts +4 -57
  34. package/dist/decorators/roles.decorator.d.ts.map +1 -1
  35. package/dist/decorators/roles.decorator.js +6 -57
  36. package/dist/guards/authorization.guard.d.ts +37 -0
  37. package/dist/guards/authorization.guard.d.ts.map +1 -0
  38. package/dist/guards/authorization.guard.js +150 -0
  39. package/dist/guards/index.d.ts +1 -0
  40. package/dist/guards/index.d.ts.map +1 -1
  41. package/dist/guards/index.js +1 -0
  42. package/dist/guards/jwt-auth.guard.d.ts +0 -0
  43. package/dist/guards/jwt-auth.guard.d.ts.map +1 -1
  44. package/dist/guards/jwt-auth.guard.js +0 -0
  45. package/dist/guards/permissions.guard.d.ts +0 -0
  46. package/dist/guards/permissions.guard.d.ts.map +1 -1
  47. package/dist/guards/permissions.guard.js +8 -2
  48. package/dist/guards/roles.guard.d.ts +0 -0
  49. package/dist/guards/roles.guard.d.ts.map +1 -1
  50. package/dist/guards/roles.guard.js +1 -1
  51. package/dist/index.d.ts +0 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +0 -6
  54. package/dist/interfaces/index.d.ts +1 -0
  55. package/dist/interfaces/index.d.ts.map +1 -1
  56. package/dist/interfaces/index.js +1 -0
  57. package/dist/interfaces/jwt-payload.interface.d.ts +46 -9
  58. package/dist/interfaces/jwt-payload.interface.d.ts.map +1 -1
  59. package/dist/interfaces/jwt-payload.interface.js +19 -0
  60. package/dist/interfaces/permission-mode.enum.d.ts +22 -0
  61. package/dist/interfaces/permission-mode.enum.d.ts.map +1 -0
  62. package/dist/interfaces/permission-mode.enum.js +25 -0
  63. package/dist/modules/index.d.ts +0 -0
  64. package/dist/modules/index.d.ts.map +0 -0
  65. package/dist/modules/index.js +0 -0
  66. package/dist/modules/permissions-contractx.module.d.ts +0 -0
  67. package/dist/modules/permissions-contractx.module.d.ts.map +1 -1
  68. package/dist/modules/permissions-contractx.module.js +4 -2
  69. package/dist/services/contractx-authorization.service.d.ts +198 -27
  70. package/dist/services/contractx-authorization.service.d.ts.map +1 -1
  71. package/dist/services/contractx-authorization.service.js +2 -0
  72. package/dist/services/contractx-validation.service.d.ts +93 -12
  73. package/dist/services/contractx-validation.service.d.ts.map +1 -1
  74. package/dist/services/contractx-validation.service.js +1 -0
  75. package/dist/services/index.d.ts +0 -2
  76. package/dist/services/index.d.ts.map +1 -1
  77. package/dist/services/index.js +2 -0
  78. package/dist/services/user-context.service.d.ts +29 -34
  79. package/dist/services/user-context.service.d.ts.map +1 -1
  80. package/dist/services/user-context.service.js +65 -44
  81. package/package.json +5 -24
  82. package/dist/services/contractx-document-compliance.service.d.ts +0 -85
  83. package/dist/services/contractx-document-compliance.service.d.ts.map +0 -1
  84. package/dist/services/contractx-document-compliance.service.js +0 -536
  85. package/dist/test-document-compliance.d.ts +0 -7
  86. package/dist/test-document-compliance.d.ts.map +0 -1
  87. package/dist/test-document-compliance.js +0 -118
@@ -0,0 +1,14 @@
1
+ /**
2
+ * [ADR-004 Fase 2 / Bloque 1] Override del eje lectura/escritura (D3) que usa el
3
+ * AuthorizationGuard para clasificar la petición, cuando el método HTTP no basta:
4
+ * - @PermissionWrites(true) → tratar como ESCRITURA (p.ej. un GET que muta).
5
+ * - @PermissionWrites(false) → tratar como LECTURA (p.ej. búsqueda por POST).
6
+ * Sin el decorador, la clasificación cae por método HTTP (GET/HEAD/OPTIONS = lectura).
7
+ *
8
+ * Nota: `RequirePermissions` NO se define aquí — ya existe en
9
+ * permissions.decorator.ts (mismo metadata key 'permissions' que lee el guard).
10
+ * Este archivo solo añade lo que faltaba en el paquete.
11
+ */
12
+ export declare const PERMISSION_WRITES_KEY = "permission_writes";
13
+ export declare const PermissionWrites: (writes: boolean) => import("@nestjs/common").CustomDecorator<string>;
14
+ //# sourceMappingURL=permission-writes.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-writes.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/permission-writes.decorator.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAEzD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,qDAA+C,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionWrites = exports.PERMISSION_WRITES_KEY = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ /**
6
+ * [ADR-004 Fase 2 / Bloque 1] Override del eje lectura/escritura (D3) que usa el
7
+ * AuthorizationGuard para clasificar la petición, cuando el método HTTP no basta:
8
+ * - @PermissionWrites(true) → tratar como ESCRITURA (p.ej. un GET que muta).
9
+ * - @PermissionWrites(false) → tratar como LECTURA (p.ej. búsqueda por POST).
10
+ * Sin el decorador, la clasificación cae por método HTTP (GET/HEAD/OPTIONS = lectura).
11
+ *
12
+ * Nota: `RequirePermissions` NO se define aquí — ya existe en
13
+ * permissions.decorator.ts (mismo metadata key 'permissions' que lee el guard).
14
+ * Este archivo solo añade lo que faltaba en el paquete.
15
+ */
16
+ exports.PERMISSION_WRITES_KEY = 'permission_writes';
17
+ const PermissionWrites = (writes) => (0, common_1.SetMetadata)(exports.PERMISSION_WRITES_KEY, writes);
18
+ exports.PermissionWrites = PermissionWrites;
@@ -8,90 +8,32 @@ export declare const PERMISSIONS_KEY = "permissions";
8
8
  * User must have all specified permissions (AND logic).
9
9
  *
10
10
  * @param permissions - Array of permission codes required to access the route
11
- *
12
- * @example
13
- * ```typescript
14
- * @RequirePermissions('users.create', 'users.update')
15
- * @Post('users')
16
- * createUser() {
17
- * // User must have both users.create AND users.update permissions
18
- * }
19
- * ```
20
11
  */
21
12
  export declare const RequirePermissions: (...permissions: string[]) => import("@nestjs/common").CustomDecorator<string>;
22
13
  /**
23
14
  * Decorator requiring any of the specified permissions (OR logic)
24
15
  *
25
16
  * @param permissions - Array of permission codes, user needs at least one
26
- *
27
- * @example
28
- * ```typescript
29
- * @RequireAnyPermission('users.read', 'users.show')
30
- * @Get('users/:id')
31
- * getUser() {
32
- * // User needs either users.read OR users.show permission
33
- * }
34
- * ```
35
17
  */
36
18
  export declare const RequireAnyPermission: (...permissions: string[]) => import("@nestjs/common").CustomDecorator<string>;
37
19
  /**
38
20
  * Decorator for read access (show, read, filter)
39
- *
40
21
  * @param module - Module name (e.g., 'users', 'contracts')
41
- *
42
- * @example
43
- * ```typescript
44
- * @ReadAccess('users')
45
- * @Get('users')
46
- * getUsers() {
47
- * // User needs users.read, users.show, or users.filter permission
48
- * }
49
- * ```
50
22
  */
51
23
  export declare const ReadAccess: (module: string) => import("@nestjs/common").CustomDecorator<string>;
52
24
  /**
53
25
  * Decorator for write access (create, update)
54
- *
55
26
  * @param module - Module name (e.g., 'users', 'contracts')
56
- *
57
- * @example
58
- * ```typescript
59
- * @WriteAccess('users')
60
- * @Put('users/:id')
61
- * updateUser() {
62
- * // User needs users.create or users.update permission
63
- * }
64
- * ```
65
27
  */
66
28
  export declare const WriteAccess: (module: string) => import("@nestjs/common").CustomDecorator<string>;
67
29
  /**
68
30
  * Decorator for delete access
69
- *
70
31
  * @param module - Module name (e.g., 'users', 'contracts')
71
- *
72
- * @example
73
- * ```typescript
74
- * @DeleteAccess('users')
75
- * @Delete('users/:id')
76
- * deleteUser() {
77
- * // User needs users.delete permission
78
- * }
79
- * ```
80
32
  */
81
33
  export declare const DeleteAccess: (module: string) => import("@nestjs/common").CustomDecorator<string>;
82
34
  /**
83
35
  * Decorator for full CRUD access to a module
84
- *
85
36
  * @param module - Module name (e.g., 'users', 'contracts')
86
- *
87
- * @example
88
- * ```typescript
89
- * @FullAccess('users')
90
- * @Controller('users')
91
- * export class UsersController {
92
- * // All methods require full user module access
93
- * }
94
- * ```
95
37
  */
96
38
  export declare const FullAccess: (module: string) => import("@nestjs/common").CustomDecorator<string>;
97
39
  //# sourceMappingURL=permissions.decorator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/permissions.decorator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,aAAa,MAAM,EAAE,qDAChB,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,GAAI,GAAG,aAAa,MAAM,EAAE,qDACjB,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,qDAKtC,CAAC;AAEJ;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,qDAIvC,CAAC;AAEJ;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,qDACH,CAAC;AAEzC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,qDAQtC,CAAC"}
1
+ {"version":3,"file":"permissions.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/permissions.decorator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,aAAa,MAAM,EAAE,qDAA8C,CAAC;AAE1G;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAI,GAAG,aAAa,MAAM,EAAE,qDAA+C,CAAC;AAE7G;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,qDACqC,CAAC;AAE/E;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,qDAAiE,CAAC;AAE5G;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,qDAA2C,CAAC;AAEvF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,qDAQtC,CAAC"}
@@ -12,15 +12,6 @@ exports.PERMISSIONS_KEY = 'permissions';
12
12
  * User must have all specified permissions (AND logic).
13
13
  *
14
14
  * @param permissions - Array of permission codes required to access the route
15
- *
16
- * @example
17
- * ```typescript
18
- * @RequirePermissions('users.create', 'users.update')
19
- * @Post('users')
20
- * createUser() {
21
- * // User must have both users.create AND users.update permissions
22
- * }
23
- * ```
24
15
  */
25
16
  const RequirePermissions = (...permissions) => (0, common_1.SetMetadata)(exports.PERMISSIONS_KEY, permissions);
26
17
  exports.RequirePermissions = RequirePermissions;
@@ -28,79 +19,30 @@ exports.RequirePermissions = RequirePermissions;
28
19
  * Decorator requiring any of the specified permissions (OR logic)
29
20
  *
30
21
  * @param permissions - Array of permission codes, user needs at least one
31
- *
32
- * @example
33
- * ```typescript
34
- * @RequireAnyPermission('users.read', 'users.show')
35
- * @Get('users/:id')
36
- * getUser() {
37
- * // User needs either users.read OR users.show permission
38
- * }
39
- * ```
40
22
  */
41
23
  const RequireAnyPermission = (...permissions) => (0, common_1.SetMetadata)('anyPermissions', permissions);
42
24
  exports.RequireAnyPermission = RequireAnyPermission;
43
25
  /**
44
26
  * Decorator for read access (show, read, filter)
45
- *
46
27
  * @param module - Module name (e.g., 'users', 'contracts')
47
- *
48
- * @example
49
- * ```typescript
50
- * @ReadAccess('users')
51
- * @Get('users')
52
- * getUsers() {
53
- * // User needs users.read, users.show, or users.filter permission
54
- * }
55
- * ```
56
28
  */
57
29
  const ReadAccess = (module) => (0, exports.RequireAnyPermission)(`${module}.read`, `${module}.show`, `${module}.filter`);
58
30
  exports.ReadAccess = ReadAccess;
59
31
  /**
60
32
  * Decorator for write access (create, update)
61
- *
62
33
  * @param module - Module name (e.g., 'users', 'contracts')
63
- *
64
- * @example
65
- * ```typescript
66
- * @WriteAccess('users')
67
- * @Put('users/:id')
68
- * updateUser() {
69
- * // User needs users.create or users.update permission
70
- * }
71
- * ```
72
34
  */
73
35
  const WriteAccess = (module) => (0, exports.RequireAnyPermission)(`${module}.create`, `${module}.update`);
74
36
  exports.WriteAccess = WriteAccess;
75
37
  /**
76
38
  * Decorator for delete access
77
- *
78
39
  * @param module - Module name (e.g., 'users', 'contracts')
79
- *
80
- * @example
81
- * ```typescript
82
- * @DeleteAccess('users')
83
- * @Delete('users/:id')
84
- * deleteUser() {
85
- * // User needs users.delete permission
86
- * }
87
- * ```
88
40
  */
89
41
  const DeleteAccess = (module) => (0, exports.RequirePermissions)(`${module}.delete`);
90
42
  exports.DeleteAccess = DeleteAccess;
91
43
  /**
92
44
  * Decorator for full CRUD access to a module
93
- *
94
45
  * @param module - Module name (e.g., 'users', 'contracts')
95
- *
96
- * @example
97
- * ```typescript
98
- * @FullAccess('users')
99
- * @Controller('users')
100
- * export class UsersController {
101
- * // All methods require full user module access
102
- * }
103
- * ```
104
46
  */
105
47
  const FullAccess = (module) => (0, exports.RequireAnyPermission)(`${module}.create`, `${module}.read`, `${module}.update`, `${module}.delete`, `${module}.show`, `${module}.filter`);
106
48
  exports.FullAccess = FullAccess;
File without changes
File without changes
File without changes
@@ -8,68 +8,15 @@ export declare const ROLES_KEY = "roles";
8
8
  * User must have at least one of the specified roles (OR logic).
9
9
  *
10
10
  * @param roles - Array of role names required to access the route
11
- *
12
- * @example
13
- * ```typescript
14
- * @Roles('superadmin', 'client_contract_admin')
15
- * @Get('admin-data')
16
- * getAdminData() {
17
- * // Only users with superadmin OR client_contract_admin role
18
- * }
19
- * ```
20
11
  */
21
12
  export declare const Roles: (...roles: string[]) => import("@nestjs/common").CustomDecorator<string>;
22
- /**
23
- * Decorator for ContractX specific admin roles
24
- *
25
- * @example
26
- * ```typescript
27
- * @AdminOnly()
28
- * @Delete(':id')
29
- * deleteResource() {
30
- * // Only admin roles can access
31
- * }
32
- * ```
33
- */
13
+ /** Decorator for ContractX specific admin roles */
34
14
  export declare const AdminOnly: () => import("@nestjs/common").CustomDecorator<string>;
35
- /**
36
- * Decorator for client-side roles only
37
- *
38
- * @example
39
- * ```typescript
40
- * @ClientOnly()
41
- * @Get('client-data')
42
- * getClientData() {
43
- * // Only client-side roles can access
44
- * }
45
- * ```
46
- */
15
+ /** Decorator for client-side roles only */
47
16
  export declare const ClientOnly: () => import("@nestjs/common").CustomDecorator<string>;
48
- /**
49
- * Decorator for provider-side roles only
50
- *
51
- * @example
52
- * ```typescript
53
- * @ProviderOnly()
54
- * @Get('provider-data')
55
- * getProviderData() {
56
- * // Only provider-side roles can access
57
- * }
58
- * ```
59
- */
17
+ /** Decorator for provider-side roles only */
60
18
  export declare const ProviderOnly: () => import("@nestjs/common").CustomDecorator<string>;
61
- /**
62
- * Decorator for superadmin access only
63
- *
64
- * @example
65
- * ```typescript
66
- * @SuperAdminOnly()
67
- * @Post('system/configure')
68
- * configureSystem() {
69
- * // Only superadmin can access
70
- * }
71
- * ```
72
- */
19
+ /** Decorator for superadmin access only */
73
20
  export declare const SuperAdminOnly: () => import("@nestjs/common").CustomDecorator<string>;
74
21
  /**
75
22
  * Alias for Roles decorator for backward compatibility
@@ -1 +1 @@
1
- {"version":3,"file":"roles.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/roles.decorator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,MAAM,EAAE,qDAAkC,CAAC;AAE3E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,wDAIrB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,wDAOtB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,wDAOxB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,wDAA4B,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,YAAY,aAhFO,MAAM,EAAE,qDAgFP,CAAC"}
1
+ {"version":3,"file":"roles.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/roles.decorator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,MAAM,EAAE,qDAAkC,CAAC;AAK3E,mDAAmD;AACnD,eAAO,MAAM,SAAS,wDAAgF,CAAC;AAEvG,2CAA2C;AAC3C,eAAO,MAAM,UAAU,wDAQpB,CAAC;AAEJ,6CAA6C;AAC7C,eAAO,MAAM,YAAY,wDAQtB,CAAC;AAEJ,2CAA2C;AAC3C,eAAO,MAAM,cAAc,wDAA4B,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,YAAY,aArCO,MAAM,EAAE,qDAqCP,CAAC"}
@@ -12,72 +12,21 @@ exports.ROLES_KEY = 'roles';
12
12
  * User must have at least one of the specified roles (OR logic).
13
13
  *
14
14
  * @param roles - Array of role names required to access the route
15
- *
16
- * @example
17
- * ```typescript
18
- * @Roles('superadmin', 'client_contract_admin')
19
- * @Get('admin-data')
20
- * getAdminData() {
21
- * // Only users with superadmin OR client_contract_admin role
22
- * }
23
- * ```
24
15
  */
25
16
  const Roles = (...roles) => (0, common_1.SetMetadata)(exports.ROLES_KEY, roles);
26
17
  exports.Roles = Roles;
27
- /**
28
- * Decorator for ContractX specific admin roles
29
- *
30
- * @example
31
- * ```typescript
32
- * @AdminOnly()
33
- * @Delete(':id')
34
- * deleteResource() {
35
- * // Only admin roles can access
36
- * }
37
- * ```
38
- */
18
+ // NOTA[reconstrucción]: los helpers de abajo hardcodean nombres de rol del vocabulario VIEJO
19
+ // (superadmin, client_performance_manager, ...) "se reemplaza" al portar al modelo nuevo.
20
+ /** Decorator for ContractX specific admin roles */
39
21
  const AdminOnly = () => (0, exports.Roles)('superadmin', 'client_contract_admin', 'provider_contract_admin');
40
22
  exports.AdminOnly = AdminOnly;
41
- /**
42
- * Decorator for client-side roles only
43
- *
44
- * @example
45
- * ```typescript
46
- * @ClientOnly()
47
- * @Get('client-data')
48
- * getClientData() {
49
- * // Only client-side roles can access
50
- * }
51
- * ```
52
- */
23
+ /** Decorator for client-side roles only */
53
24
  const ClientOnly = () => (0, exports.Roles)('client_contract_admin', 'client_performance_manager', 'client_finance_manager', 'client_reports_manager', 'client_relationship_manager', 'client_risk_manager');
54
25
  exports.ClientOnly = ClientOnly;
55
- /**
56
- * Decorator for provider-side roles only
57
- *
58
- * @example
59
- * ```typescript
60
- * @ProviderOnly()
61
- * @Get('provider-data')
62
- * getProviderData() {
63
- * // Only provider-side roles can access
64
- * }
65
- * ```
66
- */
26
+ /** Decorator for provider-side roles only */
67
27
  const ProviderOnly = () => (0, exports.Roles)('provider_contract_admin', 'provider_performance_manager', 'provider_finance_manager', 'provider_reports_manager', 'provider_relationship_manager', 'provider_risk_manager');
68
28
  exports.ProviderOnly = ProviderOnly;
69
- /**
70
- * Decorator for superadmin access only
71
- *
72
- * @example
73
- * ```typescript
74
- * @SuperAdminOnly()
75
- * @Post('system/configure')
76
- * configureSystem() {
77
- * // Only superadmin can access
78
- * }
79
- * ```
80
- */
29
+ /** Decorator for superadmin access only */
81
30
  const SuperAdminOnly = () => (0, exports.Roles)('superadmin');
82
31
  exports.SuperAdminOnly = SuperAdminOnly;
83
32
  /**
@@ -0,0 +1,37 @@
1
+ import { CanActivate, ExecutionContext } from '@nestjs/common';
2
+ import { Reflector } from '@nestjs/core';
3
+ /**
4
+ * [ADR-004] AuthorizationGuard — guard de 4 estados portado desde Auth.
5
+ *
6
+ * Lee dos conjuntos ya resueltos del JWT (la resolución deny-wins ocurre en Auth,
7
+ * vía resolvePermissionEntitlements, NO aquí):
8
+ * - user.permissions = acceso pleno (write/full)
9
+ * - user.permissionsView = modo-ver (👁, solo lectura)
10
+ *
11
+ * Eje lectura/escritura (D3): por método HTTP (GET/HEAD/OPTIONS = lectura), salvo
12
+ * override @PermissionWrites. En lectura vale acceso pleno O modo-ver; en escritura
13
+ * SOLO acceso pleno (modo-ver bloquea).
14
+ *
15
+ * Doble gateo rol+permiso (D4) vía env AUTHZ_ENFORCEMENT:
16
+ * - legacy (default): rol O permiso (comportamiento previo, sin cambio).
17
+ * - observe: el rol decide; se loguea la discrepancia con el permiso (recolección).
18
+ * - strict: el permiso decide.
19
+ */
20
+ export declare class AuthorizationGuard implements CanActivate {
21
+ private reflector;
22
+ private readonly logger;
23
+ constructor(reflector: Reflector);
24
+ canActivate(context: ExecutionContext): boolean;
25
+ /**
26
+ * [D4] Modo de enforcement del doble gateo, vía env `AUTHZ_ENFORCEMENT`.
27
+ * Default 'legacy' ⇒ comportamiento previo (rol O permiso) sin cambio hasta optar in.
28
+ */
29
+ private resolveEnforcementMode;
30
+ /**
31
+ * Clasifica la petición como escritura o lectura para el eje modo-ver (D3).
32
+ * Override explícito @PermissionWrites(boolean) gana; si no, cae por método HTTP
33
+ * (GET/HEAD/OPTIONS = lectura; el resto = escritura).
34
+ */
35
+ private isWriteRequest;
36
+ }
37
+ //# sourceMappingURL=authorization.guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.guard.d.ts","sourceRoot":"","sources":["../../src/guards/authorization.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAWzC;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,kBAAmB,YAAW,WAAW;IAGxC,OAAO,CAAC,SAAS;IAF7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAE1C,SAAS,EAAE,SAAS;IAExC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;IA+G/C;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAUvB"}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || 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") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var AuthorizationGuard_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AuthorizationGuard = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const core_1 = require("@nestjs/core");
16
+ const permission_writes_decorator_1 = require("../decorators/permission-writes.decorator");
17
+ const READ_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
18
+ /**
19
+ * [ADR-004] AuthorizationGuard — guard de 4 estados portado desde Auth.
20
+ *
21
+ * Lee dos conjuntos ya resueltos del JWT (la resolución deny-wins ocurre en Auth,
22
+ * vía resolvePermissionEntitlements, NO aquí):
23
+ * - user.permissions = acceso pleno (write/full)
24
+ * - user.permissionsView = modo-ver (👁, solo lectura)
25
+ *
26
+ * Eje lectura/escritura (D3): por método HTTP (GET/HEAD/OPTIONS = lectura), salvo
27
+ * override @PermissionWrites. En lectura vale acceso pleno O modo-ver; en escritura
28
+ * SOLO acceso pleno (modo-ver bloquea).
29
+ *
30
+ * Doble gateo rol+permiso (D4) vía env AUTHZ_ENFORCEMENT:
31
+ * - legacy (default): rol O permiso (comportamiento previo, sin cambio).
32
+ * - observe: el rol decide; se loguea la discrepancia con el permiso (recolección).
33
+ * - strict: el permiso decide.
34
+ */
35
+ let AuthorizationGuard = AuthorizationGuard_1 = class AuthorizationGuard {
36
+ constructor(reflector) {
37
+ this.reflector = reflector;
38
+ this.logger = new common_1.Logger(AuthorizationGuard_1.name);
39
+ }
40
+ canActivate(context) {
41
+ const requiredRoles = this.reflector.getAllAndOverride('roles', [
42
+ context.getHandler(),
43
+ context.getClass(),
44
+ ]);
45
+ const requiredPermissions = this.reflector.getAllAndOverride('permissions', [
46
+ context.getHandler(),
47
+ context.getClass(),
48
+ ]);
49
+ if ((!requiredRoles || requiredRoles.length === 0) &&
50
+ (!requiredPermissions || requiredPermissions.length === 0)) {
51
+ return true;
52
+ }
53
+ const request = context.switchToHttp().getRequest();
54
+ const user = request.user;
55
+ if (!user) {
56
+ this.logger.warn('No user found in request context for authorization');
57
+ throw new common_1.ForbiddenException('Authentication required for access');
58
+ }
59
+ const userId = user.sub;
60
+ const userRoles = user.role || [];
61
+ // Dos conjuntos resueltos en la carga del JWT: permissions = acceso pleno;
62
+ // permissionsView = modo-ver (solo lectura). Las filas `deny` ya fueron retiradas
63
+ // en origen (resolvePermissionEntitlements), así que el guard no necesita conocer
64
+ // grant_type — la decisión es pertenencia a estos arrays.
65
+ const userPermissions = user.permissions || [];
66
+ const userPermissionsView = user.permissionsView || [];
67
+ let hasRole = true;
68
+ if (requiredRoles && requiredRoles.length > 0) {
69
+ hasRole = requiredRoles.some((role) => userRoles.includes(role));
70
+ if (!hasRole) {
71
+ this.logger.warn(`Role access denied: User ${userId} with roles [${userRoles.join(', ')}] attempted to access resource requiring [${requiredRoles.join(', ')}]`);
72
+ }
73
+ }
74
+ let hasPermissions = true;
75
+ if (requiredPermissions && requiredPermissions.length > 0) {
76
+ // Eje lectura/escritura (D3): por método HTTP, salvo override @PermissionWrites.
77
+ const isWrite = this.isWriteRequest(context, request.method);
78
+ // Lectura: vale acceso pleno O modo-ver. Escritura: SOLO acceso pleno (modo-ver bloquea).
79
+ const allowsCode = (permission) => isWrite
80
+ ? userPermissions.includes(permission)
81
+ : userPermissions.includes(permission) || userPermissionsView.includes(permission);
82
+ hasPermissions = requiredPermissions.every(allowsCode);
83
+ if (!hasPermissions) {
84
+ const missingPermissions = requiredPermissions.filter((permission) => !allowsCode(permission));
85
+ const viewOnlyBlocked = requiredPermissions.filter((permission) => isWrite && userPermissionsView.includes(permission) && !userPermissions.includes(permission));
86
+ this.logger.warn(`Permission access denied: User ${userId} (${isWrite ? 'write' : 'read'}) missing [${missingPermissions.join(', ')}]` +
87
+ (viewOnlyBlocked.length ? ` — view-only on [${viewOnlyBlocked.join(', ')}] cannot write` : ''));
88
+ }
89
+ }
90
+ const bothPresent = requiredRoles && requiredRoles.length > 0 && requiredPermissions && requiredPermissions.length > 0;
91
+ let hasAccess;
92
+ if (bothPresent) {
93
+ const mode = this.resolveEnforcementMode();
94
+ if (mode === 'observe') {
95
+ if (hasRole !== hasPermissions) {
96
+ this.logger.warn(`AUTHZ_DISCREPANCY user=${userId} ${request.method ?? '?'} ${request.url ?? '?'} ` +
97
+ `role_decides=${hasRole} permission_would=${hasPermissions} ` +
98
+ `roles=[${(requiredRoles ?? []).join(', ')}] perms=[${(requiredPermissions ?? []).join(', ')}]`);
99
+ }
100
+ hasAccess = hasRole;
101
+ }
102
+ else if (mode === 'strict') {
103
+ hasAccess = hasPermissions;
104
+ }
105
+ else {
106
+ hasAccess = hasRole || hasPermissions;
107
+ }
108
+ }
109
+ else {
110
+ // Solo uno presente → ése decide (el ausente quedó en true por defecto).
111
+ hasAccess = hasRole && hasPermissions;
112
+ }
113
+ if (!hasAccess) {
114
+ const roleMsg = requiredRoles?.length > 0 ? `roles: [${requiredRoles.join(', ')}]` : '';
115
+ const permMsg = requiredPermissions?.length > 0 ? `permissions: [${requiredPermissions.join(', ')}]` : '';
116
+ const requirements = [roleMsg, permMsg].filter(Boolean).join(' or ');
117
+ throw new common_1.ForbiddenException(`Access denied. Required ${requirements}`);
118
+ }
119
+ this.logger.debug(`Authorization granted: User ${userId} accessing resource with roles [${userRoles.join(', ')}] and permissions [${userPermissions.join(', ')}]`);
120
+ return true;
121
+ }
122
+ /**
123
+ * [D4] Modo de enforcement del doble gateo, vía env `AUTHZ_ENFORCEMENT`.
124
+ * Default 'legacy' ⇒ comportamiento previo (rol O permiso) sin cambio hasta optar in.
125
+ */
126
+ resolveEnforcementMode() {
127
+ const v = (process.env.AUTHZ_ENFORCEMENT ?? 'legacy').toLowerCase();
128
+ return v === 'observe' || v === 'strict' ? v : 'legacy';
129
+ }
130
+ /**
131
+ * Clasifica la petición como escritura o lectura para el eje modo-ver (D3).
132
+ * Override explícito @PermissionWrites(boolean) gana; si no, cae por método HTTP
133
+ * (GET/HEAD/OPTIONS = lectura; el resto = escritura).
134
+ */
135
+ isWriteRequest(context, method) {
136
+ const override = this.reflector.getAllAndOverride(permission_writes_decorator_1.PERMISSION_WRITES_KEY, [
137
+ context.getHandler(),
138
+ context.getClass(),
139
+ ]);
140
+ if (typeof override === 'boolean') {
141
+ return override;
142
+ }
143
+ return !READ_METHODS.has((method ?? '').toUpperCase());
144
+ }
145
+ };
146
+ exports.AuthorizationGuard = AuthorizationGuard;
147
+ exports.AuthorizationGuard = AuthorizationGuard = AuthorizationGuard_1 = __decorate([
148
+ (0, common_1.Injectable)(),
149
+ __metadata("design:paramtypes", [core_1.Reflector])
150
+ ], AuthorizationGuard);
@@ -1,4 +1,5 @@
1
1
  export * from './jwt-auth.guard';
2
2
  export * from './roles.guard';
3
3
  export * from './permissions.guard';
4
+ export * from './authorization.guard';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guards/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./jwt-auth.guard"), exports);
18
18
  __exportStar(require("./roles.guard"), exports);
19
19
  __exportStar(require("./permissions.guard"), exports);
20
+ __exportStar(require("./authorization.guard"), exports);
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-auth.guard.d.ts","sourceRoot":"","sources":["../../src/guards/jwt-auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAIjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAc,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAIrE;;;GAGG;AACH,qBACa,YAAa,YAAW,WAAW;IAI5C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;gBAGrC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EAEpB,OAAO,EAAE,wBAAwB;IAG9C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IA2E9D;;OAEG;IACH,OAAO,CAAC,sBAAsB;CAe/B"}
1
+ {"version":3,"file":"jwt-auth.guard.d.ts","sourceRoot":"","sources":["../../src/guards/jwt-auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAqD,MAAM,gBAAgB,CAAC;AAClH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD;;;GAGG;AACH,qBACa,YAAa,YAAW,WAAW;IAI5C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;gBAGrC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EAEpB,OAAO,EAAE,wBAAwB;IAG9C,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IA2D9D;;OAEG;IACH,OAAO,CAAC,sBAAsB;CAY/B"}
File without changes
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.guard.d.ts","sourceRoot":"","sources":["../../src/guards/permissions.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC;;;;GAIG;AACH,qBACa,gBAAiB,YAAW,WAAW;IAGtC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAE/B,SAAS,EAAE,SAAS;IAEjD,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;CAwFhD"}
1
+ {"version":3,"file":"permissions.guard.d.ts","sourceRoot":"","sources":["../../src/guards/permissions.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAA0C,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC;;;;GAIG;AACH,qBACa,gBAAiB,YAAW,WAAW;IAGtC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAE/B,SAAS,EAAE,SAAS;IAEjD,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;CA6DhD"}
@@ -26,9 +26,15 @@ let PermissionsGuard = PermissionsGuard_1 = class PermissionsGuard {
26
26
  }
27
27
  canActivate(context) {
28
28
  // Check for required permissions (AND logic)
29
- const requiredPermissions = this.reflector.getAllAndOverride(decorators_1.PERMISSIONS_KEY, [context.getHandler(), context.getClass()]);
29
+ const requiredPermissions = this.reflector.getAllAndOverride(decorators_1.PERMISSIONS_KEY, [
30
+ context.getHandler(),
31
+ context.getClass(),
32
+ ]);
30
33
  // Check for any permissions (OR logic)
31
- const anyPermissions = this.reflector.getAllAndOverride('anyPermissions', [context.getHandler(), context.getClass()]);
34
+ const anyPermissions = this.reflector.getAllAndOverride('anyPermissions', [
35
+ context.getHandler(),
36
+ context.getClass(),
37
+ ]);
32
38
  // If no permissions are specified, allow access
33
39
  if ((!requiredPermissions || requiredPermissions.length === 0) &&
34
40
  (!anyPermissions || anyPermissions.length === 0)) {
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"roles.guard.d.ts","sourceRoot":"","sources":["../../src/guards/roles.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC;;;GAGG;AACH,qBACa,UAAW,YAAW,WAAW;IAGhC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAEzB,SAAS,EAAE,SAAS;IAEjD,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;CA2ChD"}
1
+ {"version":3,"file":"roles.guard.d.ts","sourceRoot":"","sources":["../../src/guards/roles.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAA0C,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC;;;GAGG;AACH,qBACa,UAAW,YAAW,WAAW;IAGhC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAEzB,SAAS,EAAE,SAAS;IAEjD,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;CA8BhD"}