@klerick/acl-json-api-nestjs 0.1.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 (135) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +3556 -0
  3. package/package.json +41 -0
  4. package/src/index.d.ts +8 -0
  5. package/src/index.js +15 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/constants/index.d.ts +14 -0
  8. package/src/lib/constants/index.js +18 -0
  9. package/src/lib/constants/index.js.map +1 -0
  10. package/src/lib/decorators/acl-controller.decorator.d.ts +4 -0
  11. package/src/lib/decorators/acl-controller.decorator.js +19 -0
  12. package/src/lib/decorators/acl-controller.decorator.js.map +1 -0
  13. package/src/lib/decorators/index.d.ts +1 -0
  14. package/src/lib/decorators/index.js +6 -0
  15. package/src/lib/decorators/index.js.map +1 -0
  16. package/src/lib/factories/ability-proxy.factory.d.ts +17 -0
  17. package/src/lib/factories/ability-proxy.factory.js +100 -0
  18. package/src/lib/factories/ability-proxy.factory.js.map +1 -0
  19. package/src/lib/factories/ability.factory.d.ts +49 -0
  20. package/src/lib/factories/ability.factory.js +235 -0
  21. package/src/lib/factories/ability.factory.js.map +1 -0
  22. package/src/lib/factories/index.d.ts +2 -0
  23. package/src/lib/factories/index.js +6 -0
  24. package/src/lib/factories/index.js.map +1 -0
  25. package/src/lib/guards/acl.guard.d.ts +21 -0
  26. package/src/lib/guards/acl.guard.js +68 -0
  27. package/src/lib/guards/acl.guard.js.map +1 -0
  28. package/src/lib/guards/index.d.ts +1 -0
  29. package/src/lib/guards/index.js +5 -0
  30. package/src/lib/guards/index.js.map +1 -0
  31. package/src/lib/nestjs-acl-permissions.module.d.ts +9 -0
  32. package/src/lib/nestjs-acl-permissions.module.js +56 -0
  33. package/src/lib/nestjs-acl-permissions.module.js.map +1 -0
  34. package/src/lib/services/acl-authorization.service.d.ts +10 -0
  35. package/src/lib/services/acl-authorization.service.js +100 -0
  36. package/src/lib/services/acl-authorization.service.js.map +1 -0
  37. package/src/lib/services/index.d.ts +2 -0
  38. package/src/lib/services/index.js +6 -0
  39. package/src/lib/services/index.js.map +1 -0
  40. package/src/lib/services/rule-materializer.service.d.ts +73 -0
  41. package/src/lib/services/rule-materializer.service.js +251 -0
  42. package/src/lib/services/rule-materializer.service.js.map +1 -0
  43. package/src/lib/types/acl-context.types.d.ts +14 -0
  44. package/src/lib/types/acl-context.types.js +3 -0
  45. package/src/lib/types/acl-context.types.js.map +1 -0
  46. package/src/lib/types/acl-options.types.d.ts +97 -0
  47. package/src/lib/types/acl-options.types.js +3 -0
  48. package/src/lib/types/acl-options.types.js.map +1 -0
  49. package/src/lib/types/acl-rules.types.d.ts +201 -0
  50. package/src/lib/types/acl-rules.types.js +27 -0
  51. package/src/lib/types/acl-rules.types.js.map +1 -0
  52. package/src/lib/types/decorator-options.types.d.ts +64 -0
  53. package/src/lib/types/decorator-options.types.js +3 -0
  54. package/src/lib/types/decorator-options.types.js.map +1 -0
  55. package/src/lib/types/index.d.ts +4 -0
  56. package/src/lib/types/index.js +8 -0
  57. package/src/lib/types/index.js.map +1 -0
  58. package/src/lib/utils/index.d.ts +10 -0
  59. package/src/lib/utils/index.js +53 -0
  60. package/src/lib/utils/index.js.map +1 -0
  61. package/src/lib/utils/orm-proxy/extract-field-paths.d.ts +73 -0
  62. package/src/lib/utils/orm-proxy/extract-field-paths.js +155 -0
  63. package/src/lib/utils/orm-proxy/extract-field-paths.js.map +1 -0
  64. package/src/lib/utils/orm-proxy/handle-acl-query-error.d.ts +19 -0
  65. package/src/lib/utils/orm-proxy/handle-acl-query-error.js +53 -0
  66. package/src/lib/utils/orm-proxy/handle-acl-query-error.js.map +1 -0
  67. package/src/lib/utils/orm-proxy/index.d.ts +9 -0
  68. package/src/lib/utils/orm-proxy/index.js +24 -0
  69. package/src/lib/utils/orm-proxy/index.js.map +1 -0
  70. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.d.ts +27 -0
  71. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js +78 -0
  72. package/src/lib/utils/orm-proxy/merge-query-with-acl-data.js.map +1 -0
  73. package/src/lib/utils/orm-proxy/prepare-acl-query.d.ts +11 -0
  74. package/src/lib/utils/orm-proxy/prepare-acl-query.js +35 -0
  75. package/src/lib/utils/orm-proxy/prepare-acl-query.js.map +1 -0
  76. package/src/lib/utils/orm-proxy/process-item-field-restrictions.d.ts +24 -0
  77. package/src/lib/utils/orm-proxy/process-item-field-restrictions.js +42 -0
  78. package/src/lib/utils/orm-proxy/process-item-field-restrictions.js.map +1 -0
  79. package/src/lib/utils/orm-proxy/remove-acl-added-fields.d.ts +31 -0
  80. package/src/lib/utils/orm-proxy/remove-acl-added-fields.js +104 -0
  81. package/src/lib/utils/orm-proxy/remove-acl-added-fields.js.map +1 -0
  82. package/src/lib/utils/orm-proxy/unset-deep.d.ts +13 -0
  83. package/src/lib/utils/orm-proxy/unset-deep.js +41 -0
  84. package/src/lib/utils/orm-proxy/unset-deep.js.map +1 -0
  85. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.d.ts +19 -0
  86. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js +33 -0
  87. package/src/lib/utils/orm-proxy/validate-no-current-in-rules.js.map +1 -0
  88. package/src/lib/utils/orm-proxy/validate-rules-for-orm.d.ts +16 -0
  89. package/src/lib/utils/orm-proxy/validate-rules-for-orm.js +35 -0
  90. package/src/lib/utils/orm-proxy/validate-rules-for-orm.js.map +1 -0
  91. package/src/lib/wrappers/index.d.ts +9 -0
  92. package/src/lib/wrappers/index.js +32 -0
  93. package/src/lib/wrappers/index.js.map +1 -0
  94. package/src/lib/wrappers/logger-init.d.ts +2 -0
  95. package/src/lib/wrappers/logger-init.js +9 -0
  96. package/src/lib/wrappers/logger-init.js.map +1 -0
  97. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.d.ts +4 -0
  98. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js +47 -0
  99. package/src/lib/wrappers/wrapper-json-method-controller/get-proxy-orm.js.map +1 -0
  100. package/src/lib/wrappers/wrapper-json-method-controller/index.d.ts +3 -0
  101. package/src/lib/wrappers/wrapper-json-method-controller/index.js +21 -0
  102. package/src/lib/wrappers/wrapper-json-method-controller/index.js.map +1 -0
  103. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.d.ts +3 -0
  104. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js +51 -0
  105. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-one-proxy.js.map +1 -0
  106. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.d.ts +4 -0
  107. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js +59 -0
  108. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/delete-relationship-proxy.js.map +1 -0
  109. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.d.ts +13 -0
  110. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js +67 -0
  111. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-all-proxy.js.map +1 -0
  112. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.d.ts +12 -0
  113. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js +50 -0
  114. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-one-proxy.js.map +1 -0
  115. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.d.ts +4 -0
  116. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js +50 -0
  117. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/get-relationship-proxy.js.map +1 -0
  118. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.d.ts +9 -0
  119. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js +13 -0
  120. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/index.js.map +1 -0
  121. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.d.ts +3 -0
  122. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js +132 -0
  123. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-one-proxy.js.map +1 -0
  124. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.d.ts +4 -0
  125. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js +68 -0
  126. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/patch-relationship-proxy.js.map +1 -0
  127. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.d.ts +3 -0
  128. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js +73 -0
  129. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-one-proxy.js.map +1 -0
  130. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.d.ts +4 -0
  131. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js +66 -0
  132. package/src/lib/wrappers/wrapper-json-method-controller/method-proxy/post-relationship-proxy.js.map +1 -0
  133. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.d.ts +2 -0
  134. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js +16 -0
  135. package/src/lib/wrappers/wrapper-json-method-controller/on-module-init.js.map +1 -0
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExtractFieldPaths = void 0;
4
+ exports.getCurrentEntityAndParamMap = getCurrentEntityAndParamMap;
5
+ exports.extractFieldsForCheck = extractFieldsForCheck;
6
+ const json_api_nestjs_1 = require("@klerick/json-api-nestjs");
7
+ const remove_acl_added_fields_1 = require("./remove-acl-added-fields");
8
+ const handle_acl_query_error_1 = require("./handle-acl-query-error");
9
+ /**
10
+ * Singleton class for extracting field paths from entity objects
11
+ *
12
+ * Features:
13
+ * - Skips primary keys (they are always accessible, no ACL check needed)
14
+ * - Recursively processes relationships
15
+ * - Returns flat array of dot-notation paths
16
+ * - Handles one-to-many (arrays) and one-to-one (objects) relationships
17
+ *
18
+ * @example
19
+ * const extractor = ExtractFieldPaths.getInstance(entityParamMap);
20
+ * const obj = {
21
+ * id: 1, // primary key - will be skipped
22
+ * login: 'user',
23
+ * profile: { id: 10, phone: '123' } // profile.id also skipped
24
+ * };
25
+ *
26
+ * const paths = extractor.fields(obj, User);
27
+ * // Returns: ['login', 'profile.phone']
28
+ */
29
+ class ExtractFieldPaths {
30
+ entityParamMap;
31
+ constructor(entityParamMap) {
32
+ this.entityParamMap = entityParamMap;
33
+ }
34
+ extractField(obj, nameEntity, prefix = '') {
35
+ const fields = [];
36
+ const entityParam = this.entityParamMap.get(nameEntity);
37
+ if (!entityParam) {
38
+ throw new Error(`Entity ${nameEntity.name} not found in EntityParamMap`);
39
+ }
40
+ // Add all properties (fields)
41
+ for (const prop of entityParam.props) {
42
+ if (!(prop in obj) || entityParam.primaryColumnName === prop) {
43
+ continue;
44
+ }
45
+ const path = (prefix ? `${prefix}.${prop.toString()}` : prop).toString();
46
+ fields.push(path);
47
+ }
48
+ for (const relation of entityParam.relations) {
49
+ const value = obj[relation];
50
+ const path = (prefix ? `${prefix}.${relation.toString()}` : relation).toString();
51
+ if (value === null || value === undefined) {
52
+ continue;
53
+ }
54
+ // Get relation metadata
55
+ const relationMeta = entityParam.relationProperty[relation];
56
+ if (!relationMeta || !('entityClass' in relationMeta)) {
57
+ continue;
58
+ }
59
+ // Handle arrays (one-to-many)
60
+ if (Array.isArray(value)) {
61
+ if (value.length > 0 &&
62
+ typeof value[0] === 'object' &&
63
+ value[0] !== null) {
64
+ const relObject = value[0];
65
+ fields.push(...this.extractField(relObject, relationMeta.entityClass, path));
66
+ }
67
+ continue;
68
+ }
69
+ // Handle single object (one-to-one, many-to-one)
70
+ if (typeof value === 'object') {
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ fields.push(...this.extractField(value, relationMeta.entityClass, path));
73
+ }
74
+ }
75
+ return fields;
76
+ }
77
+ fields(obj, entityClass) {
78
+ return this.extractField(obj, entityClass);
79
+ }
80
+ /**
81
+ * Extracts only props (entity fields) from object, excluding relationships and primary key
82
+ * Skips primary key (same as fields() method)
83
+ *
84
+ * Use case: Create merged entity with only base fields for ACL checks
85
+ *
86
+ * @param obj - Source entity object (may contain loaded relationships)
87
+ * @param entityClass - Entity class
88
+ * @returns New object with only entity props (no relationships, no primary key)
89
+ *
90
+ * @example
91
+ * const entity = { id: 1, login: 'user', role: 'admin', profile: { phone: '123' } };
92
+ * const propsOnly = extractor.props(entity, User);
93
+ * // Returns: { login: 'user', role: 'admin' }
94
+ * // Note: id (primary key) and profile (relationship) excluded
95
+ */
96
+ props(obj, entityClass) {
97
+ const entityParam = this.entityParamMap.get(entityClass);
98
+ if (!entityParam) {
99
+ throw new Error(`Entity ${entityClass.name} not found in EntityParamMap`);
100
+ }
101
+ const propsOnly = {};
102
+ // Copy all props (excluding primary key)
103
+ for (const prop of entityParam.props) {
104
+ // Skip if prop not in object OR prop is primary key
105
+ if (!(prop in obj) || entityParam.primaryColumnName === prop) {
106
+ continue;
107
+ }
108
+ propsOnly[prop] = obj[prop];
109
+ }
110
+ return propsOnly;
111
+ }
112
+ static instance;
113
+ static getInstance(entityParamMap) {
114
+ if (!ExtractFieldPaths.instance) {
115
+ ExtractFieldPaths.instance = new ExtractFieldPaths(entityParamMap);
116
+ }
117
+ return ExtractFieldPaths.instance;
118
+ }
119
+ }
120
+ exports.ExtractFieldPaths = ExtractFieldPaths;
121
+ function getCurrentEntityAndParamMap(moduleRef) {
122
+ const currentEntity = moduleRef.get(json_api_nestjs_1.CURRENT_ENTITY);
123
+ const entityParamMapService = moduleRef.get(json_api_nestjs_1.ENTITY_PARAM_MAP, {
124
+ strict: false,
125
+ });
126
+ const entityParamMap = entityParamMapService.get(currentEntity);
127
+ if (!entityParamMap) {
128
+ throw (0, handle_acl_query_error_1.handleAclQueryError)(new Error(`EntityParamMap not found for ${currentEntity.name}`), currentEntity.name, 'extractFieldsForCheck');
129
+ }
130
+ return { currentEntity, entityParamMap, entityParamMapService };
131
+ }
132
+ /**
133
+ * Extracts field paths for ACL checking
134
+ *
135
+ * This function:
136
+ * 1. Gets entity metadata from moduleRef
137
+ * 2. Clones the sample item
138
+ * 3. Removes ACL-added fields that weren't requested by user
139
+ * 4. Extracts field paths for checking
140
+ *
141
+ * @param moduleRef - NestJS module reference
142
+ * @param sampleItem - Sample entity item (first item for getAll, result for getOne)
143
+ * @param userQuery - Original user query
144
+ * @param aclQueryData - ACL query data (fields and include that were added by ACL)
145
+ * @returns Array of field paths to check
146
+ */
147
+ function extractFieldsForCheck(moduleRef, sampleItem, userQuery, aclQueryData) {
148
+ const { currentEntity, entityParamMapService } = getCurrentEntityAndParamMap(moduleRef);
149
+ const copyItemForGetFieldCheck = structuredClone(sampleItem);
150
+ if (aclQueryData) {
151
+ (0, remove_acl_added_fields_1.removeAclAddedFields)(copyItemForGetFieldCheck, userQuery['fields'], aclQueryData.fields, userQuery['include'], aclQueryData.include);
152
+ }
153
+ return ExtractFieldPaths.getInstance(entityParamMapService).fields(copyItemForGetFieldCheck, currentEntity);
154
+ }
155
+ //# sourceMappingURL=extract-field-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-field-paths.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/extract-field-paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { HttpException } from '@nestjs/common/exceptions/http.exception';
2
+ /**
3
+ * Handles errors that occur during ACL query execution
4
+ *
5
+ * In development mode:
6
+ * - Logs detailed error information
7
+ * - Throws InternalServerErrorException with error details
8
+ *
9
+ * In production mode:
10
+ * - Logs error without details
11
+ * - Throws ForbiddenException without revealing ACL logic
12
+ *
13
+ * @param error - The error that occurred
14
+ * @param subject - The subject (entity name) being queried
15
+ * @param methodName - The proxy method name (for logging context)
16
+ * @return {InternalServerErrorException} In development mode
17
+ * @return {ForbiddenException} In production mode
18
+ */
19
+ export declare function handleAclQueryError(error: unknown, subject: string, methodName: string): HttpException;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleAclQueryError = handleAclQueryError;
4
+ const common_1 = require("@nestjs/common");
5
+ const http_exception_1 = require("@nestjs/common/exceptions/http.exception");
6
+ /**
7
+ * Handles errors that occur during ACL query execution
8
+ *
9
+ * In development mode:
10
+ * - Logs detailed error information
11
+ * - Throws InternalServerErrorException with error details
12
+ *
13
+ * In production mode:
14
+ * - Logs error without details
15
+ * - Throws ForbiddenException without revealing ACL logic
16
+ *
17
+ * @param error - The error that occurred
18
+ * @param subject - The subject (entity name) being queried
19
+ * @param methodName - The proxy method name (for logging context)
20
+ * @return {InternalServerErrorException} In development mode
21
+ * @return {ForbiddenException} In production mode
22
+ */
23
+ function handleAclQueryError(error, subject, methodName) {
24
+ const isDevelopment = process.env['NODE_ENV'] === 'development';
25
+ // Log error for debugging
26
+ common_1.Logger.error(`ACL query execution failed for subject "${subject}": ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error.stack : undefined, methodName);
27
+ if (error instanceof http_exception_1.HttpException) {
28
+ throw error;
29
+ }
30
+ if (isDevelopment) {
31
+ // Development: 500 with error details for debugging
32
+ return new common_1.InternalServerErrorException([
33
+ {
34
+ code: 'internal_server_error',
35
+ message: `ACL query failed: ${error instanceof Error ? error.message : 'unknown error'}`,
36
+ path: [],
37
+ },
38
+ ], {
39
+ description: `Failed to execute ACL query for subject "${subject}"`,
40
+ });
41
+ }
42
+ // Production: 403 without details to avoid leaking ACL logic
43
+ return new common_1.ForbiddenException([
44
+ {
45
+ code: 'forbidden',
46
+ message: 'not allow access',
47
+ path: [],
48
+ },
49
+ ], {
50
+ description: `Access denied for subject "${subject}"`,
51
+ });
52
+ }
53
+ //# sourceMappingURL=handle-acl-query-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-acl-query-error.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/handle-acl-query-error.ts"],"names":[],"mappings":";;AAwBA,kDAmDC;AA3ED,2CAIwB;AACxB,6EAAyE;AAEzE;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,mBAAmB,CACjC,KAAc,EACd,OAAe,EACf,UAAkB;IAElB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,aAAa,CAAC;IAEhE,0BAA0B;IAC1B,eAAM,CAAC,KAAK,CACV,2CAA2C,OAAO,MAChD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAChD,UAAU,CACX,CAAC;IAEF,IAAI,KAAK,YAAY,8BAAa,EAAE,CAAC;QACnC,MAAM,KAAK,CAAA;IACb,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,oDAAoD;QACpD,OAAO,IAAI,qCAA4B,CACrC;YACE;gBACE,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,qBACP,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAC3C,EAAE;gBACF,IAAI,EAAE,EAAE;aACT;SACF,EACD;YACE,WAAW,EAAE,4CAA4C,OAAO,GAAG;SACpE,CACF,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,OAAO,IAAI,2BAAkB,CAC3B;QACE;YACE,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,kBAAkB;YAC3B,IAAI,EAAE,EAAE;SACT;KACF,EACD;QACE,WAAW,EAAE,8BAA8B,OAAO,GAAG;KACtD,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { unsetDeep } from './unset-deep';
2
+ export { mergeQueryWithAclData } from './merge-query-with-acl-data';
3
+ export { removeAclAddedFields } from './remove-acl-added-fields';
4
+ export { ExtractFieldPaths, extractFieldsForCheck, getCurrentEntityAndParamMap } from './extract-field-paths';
5
+ export { handleAclQueryError } from './handle-acl-query-error';
6
+ export { prepareAclQuery } from './prepare-acl-query';
7
+ export { processItemFieldRestrictions } from './process-item-field-restrictions';
8
+ export { validateRulesForORM } from './validate-rules-for-orm';
9
+ export { validateNoCurrentInRules } from './validate-no-current-in-rules';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateNoCurrentInRules = exports.validateRulesForORM = exports.processItemFieldRestrictions = exports.prepareAclQuery = exports.handleAclQueryError = exports.getCurrentEntityAndParamMap = exports.extractFieldsForCheck = exports.ExtractFieldPaths = exports.removeAclAddedFields = exports.mergeQueryWithAclData = exports.unsetDeep = void 0;
4
+ var unset_deep_1 = require("./unset-deep");
5
+ Object.defineProperty(exports, "unsetDeep", { enumerable: true, get: function () { return unset_deep_1.unsetDeep; } });
6
+ var merge_query_with_acl_data_1 = require("./merge-query-with-acl-data");
7
+ Object.defineProperty(exports, "mergeQueryWithAclData", { enumerable: true, get: function () { return merge_query_with_acl_data_1.mergeQueryWithAclData; } });
8
+ var remove_acl_added_fields_1 = require("./remove-acl-added-fields");
9
+ Object.defineProperty(exports, "removeAclAddedFields", { enumerable: true, get: function () { return remove_acl_added_fields_1.removeAclAddedFields; } });
10
+ var extract_field_paths_1 = require("./extract-field-paths");
11
+ Object.defineProperty(exports, "ExtractFieldPaths", { enumerable: true, get: function () { return extract_field_paths_1.ExtractFieldPaths; } });
12
+ Object.defineProperty(exports, "extractFieldsForCheck", { enumerable: true, get: function () { return extract_field_paths_1.extractFieldsForCheck; } });
13
+ Object.defineProperty(exports, "getCurrentEntityAndParamMap", { enumerable: true, get: function () { return extract_field_paths_1.getCurrentEntityAndParamMap; } });
14
+ var handle_acl_query_error_1 = require("./handle-acl-query-error");
15
+ Object.defineProperty(exports, "handleAclQueryError", { enumerable: true, get: function () { return handle_acl_query_error_1.handleAclQueryError; } });
16
+ var prepare_acl_query_1 = require("./prepare-acl-query");
17
+ Object.defineProperty(exports, "prepareAclQuery", { enumerable: true, get: function () { return prepare_acl_query_1.prepareAclQuery; } });
18
+ var process_item_field_restrictions_1 = require("./process-item-field-restrictions");
19
+ Object.defineProperty(exports, "processItemFieldRestrictions", { enumerable: true, get: function () { return process_item_field_restrictions_1.processItemFieldRestrictions; } });
20
+ var validate_rules_for_orm_1 = require("./validate-rules-for-orm");
21
+ Object.defineProperty(exports, "validateRulesForORM", { enumerable: true, get: function () { return validate_rules_for_orm_1.validateRulesForORM; } });
22
+ var validate_no_current_in_rules_1 = require("./validate-no-current-in-rules");
23
+ Object.defineProperty(exports, "validateNoCurrentInRules", { enumerable: true, get: function () { return validate_no_current_in_rules_1.validateNoCurrentInRules; } });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/index.ts"],"names":[],"mappings":";;;AAAA,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAClB,yEAAoE;AAA3D,kIAAA,qBAAqB,OAAA;AAC9B,qEAAiE;AAAxD,+HAAA,oBAAoB,OAAA;AAC7B,6DAA8G;AAArG,wHAAA,iBAAiB,OAAA;AAAE,4HAAA,qBAAqB,OAAA;AAAE,kIAAA,2BAA2B,OAAA;AAC9E,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAC5B,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AACxB,qFAAiF;AAAxE,+IAAA,4BAA4B,OAAA;AACrC,mEAA+D;AAAtD,6HAAA,mBAAmB,OAAA;AAC5B,+EAA0E;AAAjE,wIAAA,wBAAwB,OAAA"}
@@ -0,0 +1,27 @@
1
+ import { Query, QueryOne } from '@klerick/json-api-nestjs';
2
+ import { QueryField } from '@klerick/json-api-nestjs-shared';
3
+ /**
4
+ * Merges user query with ACL fields and includes
5
+ *
6
+ * IMPORTANT: fields: null or missing relation key means "select ALL fields"
7
+ * We should NOT add ACL fields in such cases to avoid turning "all fields" into "specific fields"
8
+ *
9
+ * @param query - Original user query
10
+ * @param aclFields - ACL fields to add (fields structure with target and relations)
11
+ * @param aclInclude - ACL includes to add
12
+ * @returns Merged query
13
+ *
14
+ * @example
15
+ * // Case 1: fields: null → select all, don't add ACL fields
16
+ * mergeQueryWithAclData({ fields: null }, { target: ['role'] })
17
+ * // → { fields: null } (unchanged)
18
+ *
19
+ * // Case 2: fields: { target: ['id'] } → add ACL fields to target
20
+ * mergeQueryWithAclData({ fields: { target: ['id'] } }, { target: ['role'] })
21
+ * // → { fields: { target: ['id', 'role'] } }
22
+ *
23
+ * // Case 3: fields: { target: ['id'] } + ACL needs profile → don't add profile fields
24
+ * mergeQueryWithAclData({ fields: { target: ['id'] } }, { profile: ['isPublic'] })
25
+ * // → { fields: { target: ['id'] } } (profile missing = all fields)
26
+ */
27
+ export declare function mergeQueryWithAclData<E extends object, IdKey extends string, Q extends QueryOne<E, IdKey> | Query<E, IdKey>>(query: Q, aclFields?: Q[QueryField.fields], aclInclude?: Q[QueryField.include]): Q;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeQueryWithAclData = mergeQueryWithAclData;
4
+ /**
5
+ * Merges user query with ACL fields and includes
6
+ *
7
+ * IMPORTANT: fields: null or missing relation key means "select ALL fields"
8
+ * We should NOT add ACL fields in such cases to avoid turning "all fields" into "specific fields"
9
+ *
10
+ * @param query - Original user query
11
+ * @param aclFields - ACL fields to add (fields structure with target and relations)
12
+ * @param aclInclude - ACL includes to add
13
+ * @returns Merged query
14
+ *
15
+ * @example
16
+ * // Case 1: fields: null → select all, don't add ACL fields
17
+ * mergeQueryWithAclData({ fields: null }, { target: ['role'] })
18
+ * // → { fields: null } (unchanged)
19
+ *
20
+ * // Case 2: fields: { target: ['id'] } → add ACL fields to target
21
+ * mergeQueryWithAclData({ fields: { target: ['id'] } }, { target: ['role'] })
22
+ * // → { fields: { target: ['id', 'role'] } }
23
+ *
24
+ * // Case 3: fields: { target: ['id'] } + ACL needs profile → don't add profile fields
25
+ * mergeQueryWithAclData({ fields: { target: ['id'] } }, { profile: ['isPublic'] })
26
+ * // → { fields: { target: ['id'] } } (profile missing = all fields)
27
+ */
28
+ function mergeQueryWithAclData(query, aclFields, aclInclude) {
29
+ // Start with merged query
30
+ const mergedQuery = { ...query };
31
+ // 1. Always merge includes (add ACL includes to user includes)
32
+ if (aclInclude &&
33
+ 'length' in aclInclude &&
34
+ parseInt(`${aclInclude.length}`) > 0) {
35
+ const userInclude = Array.isArray(query.include) ? query.include : [];
36
+ const aclIncludeArray = Array.isArray(aclInclude) ? aclInclude : [];
37
+ mergedQuery.include = Array.from(new Set([...userInclude, ...aclIncludeArray]));
38
+ }
39
+ // 2. Merge fields (complex logic for null/undefined handling)
40
+ if (!aclFields) {
41
+ return mergedQuery; // No ACL fields to merge
42
+ }
43
+ // CASE 1: fields === null → "select ALL fields everywhere"
44
+ if (query.fields === null) {
45
+ return mergedQuery; // Don't modify, null already includes all ACL fields
46
+ }
47
+ // CASE 2: fields === undefined → "select ALL fields everywhere"
48
+ if (query.fields === undefined) {
49
+ return mergedQuery; // Don't modify
50
+ }
51
+ // CASE 3: fields === {} (empty object) → "select ALL fields everywhere"
52
+ if (Object.keys(query.fields).length === 0) {
53
+ return mergedQuery; // Don't modify
54
+ }
55
+ // CASE 4: fields is object with keys → merge selectively
56
+ mergedQuery.fields = { ...query.fields };
57
+ for (const [relation, aclFieldsList] of Object.entries(aclFields)) {
58
+ if (!Array.isArray(aclFieldsList)) {
59
+ continue; // Skip invalid ACL fields
60
+ }
61
+ const userFieldsList = query.fields[relation];
62
+ // Sub-case 1: relation key missing in user fields → "all fields for this relation"
63
+ if (userFieldsList === undefined) {
64
+ continue; // Don't add ACL fields, user wants all fields for this relation
65
+ }
66
+ // Sub-case 2: relation: null → "all fields for this relation"
67
+ if (userFieldsList === null) {
68
+ continue; // Don't add ACL fields
69
+ }
70
+ // Sub-case 3: relation is array → merge with ACL fields
71
+ if (Array.isArray(userFieldsList)) {
72
+ const merged = [...new Set([...userFieldsList, ...aclFieldsList])];
73
+ mergedQuery.fields[relation] = merged;
74
+ }
75
+ }
76
+ return mergedQuery;
77
+ }
78
+ //# sourceMappingURL=merge-query-with-acl-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-query-with-acl-data.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/merge-query-with-acl-data.ts"],"names":[],"mappings":";;AA0BA,sDAyEC;AAjGD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,qBAAqB,CAKnC,KAAQ,EACR,SAAgC,EAChC,UAAkC;IAElC,0BAA0B;IAC1B,MAAM,WAAW,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAEjC,+DAA+D;IAC/D,IACE,UAAU;QACV,QAAQ,IAAI,UAAU;QACtB,QAAQ,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EACpC,CAAC;QACD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAC9B,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,eAAe,CAAC,CAAC,CACvC,CAAC;IACX,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,WAAW,CAAC,CAAC,yBAAyB;IAC/C,CAAC;IAED,2DAA2D;IAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1B,OAAO,WAAW,CAAC,CAAC,qDAAqD;IAC3E,CAAC;IAED,gEAAgE;IAChE,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,CAAC,eAAe;IACrC,CAAC;IAED,wEAAwE;IACxE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,WAAW,CAAC,CAAC,eAAe;IACrC,CAAC;IAED,yDAAyD;IACzD,WAAW,CAAC,MAAM,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;IAEzC,KAAK,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,SAAS,CAAC,0BAA0B;QACtC,CAAC;QAED,MAAM,cAAc,GAAI,KAAK,CAAC,MAAc,CAAC,QAAQ,CAAC,CAAC;QAEvD,mFAAmF;QACnF,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,SAAS,CAAC,gEAAgE;QAC5E,CAAC;QAED,8DAA8D;QAC9D,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;YAC5B,SAAS,CAAC,uBAAuB;QACnC,CAAC;QAED,wDAAwD;QACxD,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YAClE,WAAW,CAAC,MAAc,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { ExtendAbility } from '../../factories';
2
+ import { Query, QueryOne } from '@klerick/json-api-nestjs';
3
+ export declare function prepareAclQuery<E extends object, IdKey extends string, Q extends QueryOne<E, IdKey> | Query<E, IdKey>>(extendAbility: ExtendAbility, query: Q, needValidateRules?: boolean): {
4
+ transformToJsonApi: boolean;
5
+ aclQueryData: {
6
+ fields?: Q[import("dist/libs/json-api/json-api-nestjs-shared/cjs/src").QueryField.fields] | undefined;
7
+ include?: Q[import("dist/libs/json-api/json-api-nestjs-shared/cjs/src").QueryField.include] | undefined;
8
+ rulesForQuery?: Record<string, unknown>;
9
+ } | undefined;
10
+ mergedQuery: Q;
11
+ } | null;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareAclQuery = prepareAclQuery;
4
+ const merge_query_with_acl_data_1 = require("./merge-query-with-acl-data");
5
+ const validate_rules_for_orm_1 = require("./validate-rules-for-orm");
6
+ function prepareAclQuery(extendAbility, query, needValidateRules = true) {
7
+ // Fast path: no rules or no restrictions
8
+ if (!extendAbility ||
9
+ extendAbility.rules.length === 0 ||
10
+ (!extendAbility.hasConditions && !extendAbility.hasFields)) {
11
+ return null;
12
+ }
13
+ // Determine strategy
14
+ const hasConditions = extendAbility.hasConditions;
15
+ const hasFields = extendAbility.hasFields;
16
+ const transformToJsonApi = hasConditions && !hasFields;
17
+ // Validate rules for ORM compatibility if there are conditions
18
+ if (needValidateRules && hasConditions) {
19
+ (0, validate_rules_for_orm_1.validateRulesForORM)(extendAbility);
20
+ }
21
+ // Fetch with ACL query
22
+ const aclQueryData = hasConditions
23
+ ? extendAbility.getQueryObject()
24
+ : undefined;
25
+ // Merge ACL query with user query
26
+ const mergedQuery = aclQueryData
27
+ ? (0, merge_query_with_acl_data_1.mergeQueryWithAclData)(query, aclQueryData.fields, aclQueryData.include)
28
+ : query;
29
+ return {
30
+ transformToJsonApi,
31
+ aclQueryData,
32
+ mergedQuery,
33
+ };
34
+ }
35
+ //# sourceMappingURL=prepare-acl-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-acl-query.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/prepare-acl-query.ts"],"names":[],"mappings":";;AAKA,0CA2CC;AA/CD,2EAAoE;AACpE,qEAA+D;AAG/D,SAAgB,eAAe,CAC7B,aAA4B,EAC5B,KAAQ,EACR,iBAAiB,GAAG,IAAI;IAExB,yCAAyC;IACzC,IACE,CAAC,aAAa;QACd,aAAa,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAChC,CAAC,CAAC,aAAa,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAC1D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qBAAqB;IACrB,MAAM,aAAa,GAAG,aAAa,CAAC,aAAa,CAAC;IAClD,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;IAC1C,MAAM,kBAAkB,GAAG,aAAa,IAAI,CAAC,SAAS,CAAC;IAEvD,+DAA+D;IAC/D,IAAI,iBAAiB,IAAI,aAAa,EAAE,CAAC;QACvC,IAAA,4CAAmB,EAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,uBAAuB;IACvB,MAAM,YAAY,GAAG,aAAa;QAChC,CAAC,CAAC,aAAa,CAAC,cAAc,EAAe;QAC7C,CAAC,CAAC,SAAS,CAAC;IAEd,kCAAkC;IAClC,MAAM,WAAW,GAAG,YAAY;QAC9B,CAAC,CAAC,IAAA,iDAAqB,EACnB,KAAK,EACL,YAAY,CAAC,MAAM,EACnB,YAAY,CAAC,OAAO,CACrB;QACH,CAAC,CAAC,KAAK,CAAC;IAEV,OAAO;QACL,kBAAkB;QAClB,YAAY;QACZ,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { ExtendAbility } from '../../factories';
2
+ import { QueryField } from '@klerick/json-api-nestjs-shared';
3
+ import { Query, QueryOne } from '@klerick/json-api-nestjs';
4
+ /**
5
+ * Processes field restrictions for a single item
6
+ *
7
+ * This function:
8
+ * 1. Updates ability with item data for @input templates
9
+ * 2. Checks each field against ACL rules
10
+ * 3. Removes restricted fields from the item
11
+ * 4. Removes ACL-added fields that weren't requested by user
12
+ *
13
+ * @param item - Entity item to process (mutated in place)
14
+ * @param fieldsForCheck - Array of field paths to check
15
+ * @param extendAbility - ExtendAbility instance for permission checking
16
+ * @param query - Original user query
17
+ * @param aclQueryData - ACL query data (fields and include added by ACL)
18
+ * @returns Array of restricted field names
19
+ */
20
+ export declare function processItemFieldRestrictions<E extends object, IdKey extends string, Q extends QueryOne<E, IdKey> | Query<E, IdKey>>(item: E, fieldsForCheck: string[], extendAbility: ExtendAbility, query: Q, aclQueryData?: {
21
+ fields?: Q[QueryField.fields];
22
+ include?: Q[QueryField.include];
23
+ rulesForQuery?: Record<string, unknown>;
24
+ }): string[];
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processItemFieldRestrictions = processItemFieldRestrictions;
4
+ const ability_1 = require("@casl/ability");
5
+ const unset_deep_1 = require("./unset-deep");
6
+ const remove_acl_added_fields_1 = require("./remove-acl-added-fields");
7
+ /**
8
+ * Processes field restrictions for a single item
9
+ *
10
+ * This function:
11
+ * 1. Updates ability with item data for @input templates
12
+ * 2. Checks each field against ACL rules
13
+ * 3. Removes restricted fields from the item
14
+ * 4. Removes ACL-added fields that weren't requested by user
15
+ *
16
+ * @param item - Entity item to process (mutated in place)
17
+ * @param fieldsForCheck - Array of field paths to check
18
+ * @param extendAbility - ExtendAbility instance for permission checking
19
+ * @param query - Original user query
20
+ * @param aclQueryData - ACL query data (fields and include added by ACL)
21
+ * @returns Array of restricted field names
22
+ */
23
+ function processItemFieldRestrictions(item, fieldsForCheck, extendAbility, query, aclQueryData) {
24
+ // Update ability with item data for @input templates
25
+ extendAbility.updateWithInput(item);
26
+ const currentAction = extendAbility.action;
27
+ const restrictedFieldsForItem = [];
28
+ // Check each field
29
+ for (const field of fieldsForCheck) {
30
+ if (!extendAbility.can(currentAction, (0, ability_1.subject)(extendAbility.subject, item), field)) {
31
+ // Remove field from item
32
+ (0, unset_deep_1.unsetDeep)(item, field);
33
+ restrictedFieldsForItem.push(field);
34
+ }
35
+ }
36
+ // Remove ACL-added fields and relations that were not requested by user
37
+ if (aclQueryData) {
38
+ (0, remove_acl_added_fields_1.removeAclAddedFields)(item, query['fields'], aclQueryData.fields, query['include'], aclQueryData.include);
39
+ }
40
+ return restrictedFieldsForItem;
41
+ }
42
+ //# sourceMappingURL=process-item-field-restrictions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-item-field-restrictions.js","sourceRoot":"","sources":["../../../../../../../../libs/acl-permissions/nestjs-acl-permissions/src/lib/utils/orm-proxy/process-item-field-restrictions.ts"],"names":[],"mappings":";;AAuBA,oEAgDC;AAvED,2CAA0D;AAE1D,6CAAyC;AACzC,uEAAiE;AAIjE;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,4BAA4B,CAK1C,IAAO,EACP,cAAwB,EACxB,aAA4B,EAC5B,KAAQ,EACR,YAIC;IAED,qDAAqD;IACrD,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAEpC,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC;IAC3C,MAAM,uBAAuB,GAAa,EAAE,CAAC;IAE7C,mBAAmB;IACnB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IACE,CAAC,aAAa,CAAC,GAAG,CAChB,aAAa,EACb,IAAA,iBAAc,EAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,EAC3C,KAAK,CACN,EACD,CAAC;YACD,yBAAyB;YACzB,IAAA,sBAAS,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvB,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,IAAI,YAAY,EAAE,CAAC;QACjB,IAAA,8CAAoB,EAClB,IAAI,EACJ,KAAK,CAAC,QAAQ,CAAC,EACf,YAAY,CAAC,MAAM,EACnB,KAAK,CAAC,SAAS,CAAC,EAChB,YAAY,CAAC,OAAO,CACrB,CAAC;IACJ,CAAC;IAED,OAAO,uBAAuB,CAAC;AACjC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { Query, QueryOne } from '@klerick/json-api-nestjs';
2
+ import { QueryField } from '@klerick/json-api-nestjs-shared';
3
+ /**
4
+ * Removes ACL-added fields and relations from item that were not requested by user
5
+ *
6
+ * IMPORTANT: Must match the logic of mergeQueryWithAclData!
7
+ * Only removes fields/relations that were ACTUALLY ADDED by mergeQueryWithAclData.
8
+ *
9
+ * mergeQueryWithAclData adds ACL fields ONLY when userFields[relation] is an array.
10
+ * It does NOT add when: null, undefined, {}, missing key, or relation: null.
11
+ *
12
+ * @param item - Entity item to clean
13
+ * @param userFields - Fields requested by user (query.fields)
14
+ * @param aclFields - Fields added by ACL (aclQueryData.fields)
15
+ * @param userInclude - Relations requested by user (query.include)
16
+ * @param aclInclude - Relations added by ACL (aclQueryData.include)
17
+ *
18
+ * @example
19
+ * // Case 1: userFields: null → ACL didn't add fields, don't remove
20
+ * removeAclAddedFields(item, null, { target: ['role'] })
21
+ * // → nothing removed (null = all fields requested)
22
+ *
23
+ * // Case 2: userFields: { target: ['id'] } → ACL added 'role', remove it
24
+ * removeAclAddedFields(item, { target: ['id'] }, { target: ['role'] })
25
+ * // → removes 'role' from item
26
+ *
27
+ * // Case 3: ACL added include → remove entire relation
28
+ * removeAclAddedFields(item, null, null, [], ['profile'])
29
+ * // → removes profile relation (not requested by user)
30
+ */
31
+ export declare function removeAclAddedFields<E extends object, IdKey extends string, Q extends QueryOne<E, IdKey> | Query<E, IdKey>>(item: E, userFields?: Q[QueryField.fields], aclFields?: Q[QueryField.fields], userInclude?: Q[QueryField.include], aclInclude?: Q[QueryField.include]): void;