@mondaydotcomorg/monday-authorization 3.5.2-feat-shaime-support-entity-attributes-4-ddec1d3 → 3.5.2-feat-shaime-support-entity-attributes-3-6202ab7

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 (89) hide show
  1. package/dist/authorization-attributes-ms-service.d.ts +1 -17
  2. package/dist/authorization-attributes-ms-service.d.ts.map +1 -1
  3. package/dist/authorization-attributes-ms-service.js +47 -58
  4. package/dist/authorization-attributes-sns-service.d.ts +2 -23
  5. package/dist/authorization-attributes-sns-service.d.ts.map +1 -1
  6. package/dist/authorization-attributes-sns-service.js +11 -49
  7. package/dist/base-attribute-assignment.d.ts +6 -7
  8. package/dist/base-attribute-assignment.d.ts.map +1 -1
  9. package/dist/base-attribute-assignment.js +5 -7
  10. package/dist/entity-attribute-assignment.d.ts +4 -8
  11. package/dist/entity-attribute-assignment.d.ts.map +1 -1
  12. package/dist/entity-attribute-assignment.js +4 -3
  13. package/dist/errors/argument-error.d.ts.map +1 -1
  14. package/dist/errors/argument-error.js +0 -1
  15. package/dist/esm/authorization-attributes-ms-service.d.ts +1 -17
  16. package/dist/esm/authorization-attributes-ms-service.d.ts.map +1 -1
  17. package/dist/esm/authorization-attributes-ms-service.mjs +47 -58
  18. package/dist/esm/authorization-attributes-sns-service.d.ts +2 -23
  19. package/dist/esm/authorization-attributes-sns-service.d.ts.map +1 -1
  20. package/dist/esm/authorization-attributes-sns-service.mjs +11 -49
  21. package/dist/esm/base-attribute-assignment.d.ts +6 -7
  22. package/dist/esm/base-attribute-assignment.d.ts.map +1 -1
  23. package/dist/esm/base-attribute-assignment.mjs +5 -7
  24. package/dist/esm/entity-attribute-assignment.d.ts +4 -8
  25. package/dist/esm/entity-attribute-assignment.d.ts.map +1 -1
  26. package/dist/esm/entity-attribute-assignment.mjs +4 -3
  27. package/dist/esm/errors/argument-error.d.ts.map +1 -1
  28. package/dist/esm/errors/argument-error.mjs +0 -1
  29. package/dist/esm/resource-attribute-assignment.d.ts +3 -7
  30. package/dist/esm/resource-attribute-assignment.d.ts.map +1 -1
  31. package/dist/esm/resource-attribute-assignment.mjs +3 -2
  32. package/dist/esm/resource-attributes-constants.d.ts +9 -9
  33. package/dist/esm/resource-attributes-constants.d.ts.map +1 -1
  34. package/dist/esm/resource-attributes-constants.mjs +2 -2
  35. package/dist/esm/testKit/index.d.ts +4 -4
  36. package/dist/esm/testKit/index.d.ts.map +1 -1
  37. package/dist/esm/types/authorization-attributes-contracts.d.ts +1 -2
  38. package/dist/esm/types/authorization-attributes-contracts.d.ts.map +1 -1
  39. package/dist/esm/types/authorization-attributes-service.interface.d.ts +2 -16
  40. package/dist/esm/types/authorization-attributes-service.interface.d.ts.map +1 -1
  41. package/dist/esm/types/general.d.ts +1 -1
  42. package/dist/esm/types/general.d.ts.map +1 -1
  43. package/dist/esm/utils/assigment-schema.d.ts +23 -0
  44. package/dist/esm/utils/assigment-schema.d.ts.map +1 -0
  45. package/dist/esm/utils/assigment-schema.mjs +29 -0
  46. package/dist/esm/utils/resource-schema.d.ts +17 -0
  47. package/dist/esm/utils/resource-schema.d.ts.map +1 -0
  48. package/dist/esm/utils/resource-schema.mjs +16 -0
  49. package/dist/esm/utils/validation.d.ts +9 -28
  50. package/dist/esm/utils/validation.d.ts.map +1 -1
  51. package/dist/esm/utils/validation.mjs +39 -121
  52. package/dist/resource-attribute-assignment.d.ts +3 -7
  53. package/dist/resource-attribute-assignment.d.ts.map +1 -1
  54. package/dist/resource-attribute-assignment.js +3 -2
  55. package/dist/resource-attributes-constants.d.ts +9 -9
  56. package/dist/resource-attributes-constants.d.ts.map +1 -1
  57. package/dist/resource-attributes-constants.js +2 -2
  58. package/dist/testKit/index.d.ts +4 -4
  59. package/dist/testKit/index.d.ts.map +1 -1
  60. package/dist/types/authorization-attributes-contracts.d.ts +1 -2
  61. package/dist/types/authorization-attributes-contracts.d.ts.map +1 -1
  62. package/dist/types/authorization-attributes-service.interface.d.ts +2 -16
  63. package/dist/types/authorization-attributes-service.interface.d.ts.map +1 -1
  64. package/dist/types/general.d.ts +1 -1
  65. package/dist/types/general.d.ts.map +1 -1
  66. package/dist/utils/assigment-schema.d.ts +23 -0
  67. package/dist/utils/assigment-schema.d.ts.map +1 -0
  68. package/dist/utils/assigment-schema.js +36 -0
  69. package/dist/utils/resource-schema.d.ts +17 -0
  70. package/dist/utils/resource-schema.d.ts.map +1 -0
  71. package/dist/utils/resource-schema.js +22 -0
  72. package/dist/utils/validation.d.ts +9 -28
  73. package/dist/utils/validation.d.ts.map +1 -1
  74. package/dist/utils/validation.js +39 -121
  75. package/package.json +1 -1
  76. package/src/authorization-attributes-ms-service.ts +93 -117
  77. package/src/authorization-attributes-sns-service.ts +14 -69
  78. package/src/base-attribute-assignment.ts +10 -26
  79. package/src/entity-attribute-assignment.ts +9 -6
  80. package/src/errors/argument-error.ts +0 -1
  81. package/src/resource-attribute-assignment.ts +10 -12
  82. package/src/resource-attributes-constants.ts +2 -2
  83. package/src/testKit/index.ts +5 -5
  84. package/src/types/authorization-attributes-contracts.ts +1 -1
  85. package/src/types/authorization-attributes-service.interface.ts +2 -33
  86. package/src/types/general.ts +1 -1
  87. package/src/utils/assigment-schema.ts +29 -0
  88. package/src/utils/resource-schema.ts +21 -0
  89. package/src/utils/validation.ts +51 -140
@@ -6,16 +6,16 @@ import {
6
6
  AttributeOperation,
7
7
  ResourceAttributeOperation,
8
8
  EntityAttributeOperation,
9
+ ResourceAttributeResponse,
9
10
  } from './types/authorization-attributes-contracts';
10
11
  import { EntityType } from './entity-attributes-constants';
11
- import { ArgumentError } from './errors/argument-error';
12
12
  import { AuthorizationInternalService, logger } from './authorization-internal-service';
13
13
  import { getAttributionsFromApi } from './attributions-service';
14
14
  import { APP_NAME } from './constants';
15
15
  import { ValidationUtils } from './utils/validation';
16
16
  import { AuthorizationAttributesService } from './types/authorization-attributes-service.interface';
17
17
  import { Resource } from './types/general';
18
- import { StringNullableChain } from 'lodash';
18
+
19
19
  const INTERNAL_APP_NAME = 'internal_ms';
20
20
  const UPSERT_RESOURCE_ATTRIBUTES_PATH = '/attributes/{accountId}/resource';
21
21
  const DELETE_RESOURCE_ATTRIBUTES_PATH = '/attributes/{accountId}/resource/{resourceType}/{resourceId}';
@@ -32,34 +32,7 @@ interface DeleteRequestBody {
32
32
  */
33
33
  export class AuthorizationAttributesMsService implements AuthorizationAttributesService {
34
34
  private static LOG_TAG = 'authorization_attributes_ms';
35
- private static httpClient: HttpClient | null = Api.getPart('httpClient') ?? null;
36
-
37
- public static destroyHttpClient(): void {
38
- AuthorizationAttributesMsService.httpClient = null;
39
- }
40
-
41
- /**
42
- * Creates or updates resource attributes synchronously.
43
- * @param accountId The account ID
44
- * @param resourceAttributeAssignments Array of ResourceAttributeAssignment objects
45
- * @returns Promise<void>
46
- */
47
- async upsertResourceAttributes(
48
- accountId: number,
49
- resourceAttributeAssignments: ResourceAttributeAssignment[],
50
- _appName?: string,
51
- _callerActionIdentifier?: string
52
- ): Promise<void> {
53
- return AuthorizationAttributesMsService.executeUpsertRequest(
54
- accountId,
55
- resourceAttributeAssignments,
56
- UPSERT_RESOURCE_ATTRIBUTES_PATH,
57
- 'resourceAttributeAssignments',
58
- ResourceAttributeAssignment,
59
- 'resource',
60
- 'upsertResourceAttributes'
61
- );
62
- }
35
+ private static httpClient: HttpClient | undefined = Api.getPart('httpClient');
63
36
 
64
37
  /**
65
38
  * Deletes specific attributes from a resource synchronously.
@@ -76,41 +49,16 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
76
49
  _callerActionIdentifier?: string
77
50
  ): Promise<void> {
78
51
  ValidationUtils.validateResource(resource);
79
- ValidationUtils.validateStringArray(attributeKeys);
80
52
  return AuthorizationAttributesMsService.executeDeleteRequest(
81
53
  accountId,
82
54
  DELETE_RESOURCE_ATTRIBUTES_PATH,
83
55
  {
84
56
  resourceType: resource.type,
85
- resourceId: resource.id as number,
57
+ resourceId: resource.id,
86
58
  },
87
59
  attributeKeys,
88
60
  'resource',
89
- 'deleteResourceAttributesSync',
90
- { resource }
91
- );
92
- }
93
-
94
- /**
95
- * Creates or updates entity attributes synchronously.
96
- * @param accountId The account ID
97
- * @param entityAttributeAssignments Array of EntityAttributeAssignment objects
98
- * @returns Promise<void>
99
- */
100
- async upsertEntityAttributes(
101
- accountId: number,
102
- entityAttributeAssignments: EntityAttributeAssignment[],
103
- _appName?: string,
104
- _callerActionIdentifier?: string
105
- ): Promise<void> {
106
- return AuthorizationAttributesMsService.executeUpsertRequest(
107
- accountId,
108
- entityAttributeAssignments,
109
- UPSERT_ENTITY_ATTRIBUTES_PATH,
110
- 'entityAttributeAssignments',
111
- EntityAttributeAssignment,
112
- 'entity',
113
- 'upsertEntityAttributesSync'
61
+ 'deleteResourceAttributesSync'
114
62
  );
115
63
  }
116
64
 
@@ -130,11 +78,7 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
130
78
  _appName?: string,
131
79
  _callerActionIdentifier?: string
132
80
  ): Promise<void> {
133
- if (!entityType || typeof entityType !== 'string' || entityType.trim() === '') {
134
- throw new ArgumentError(`entityType must be a non-empty string, got: ${entityType}`);
135
- }
136
- ValidationUtils.validateInteger(entityId);
137
-
81
+ ValidationUtils.validateInteger(accountId);
138
82
  return AuthorizationAttributesMsService.executeDeleteRequest(
139
83
  accountId,
140
84
  DELETE_ENTITY_ATTRIBUTES_PATH,
@@ -144,8 +88,7 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
144
88
  },
145
89
  attributeKeys,
146
90
  'entity',
147
- 'deleteEntityAttributesSync',
148
- { entityType, entityId }
91
+ 'deleteEntityAttributesSync'
149
92
  );
150
93
  }
151
94
 
@@ -165,39 +108,38 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
165
108
  _callerActionIdentifier: string,
166
109
  resourceAttributeOperations: ResourceAttributeOperation[]
167
110
  ): Promise<ResourceAttributeOperation[]> {
168
- const processedOperations: ResourceAttributeOperation[] = [];
169
-
170
- for (const operation of resourceAttributeOperations) {
171
- if (operation.operationType === AttributeOperation.UPSERT) {
172
- if (!operation.resourceId) {
173
- throw new ArgumentError('resourceId is required for upsert operation');
111
+ // Process all operations in parallel using Promise.all
112
+ await Promise.all(
113
+ resourceAttributeOperations.map(async operation => {
114
+ ValidationUtils.validateResourceAssignment({
115
+ resourceId: operation.resourceId,
116
+ resourceType: operation.resourceType,
117
+ key: operation.key,
118
+ value: operation.value || '',
119
+ });
120
+ if (operation.operationType === AttributeOperation.UPSERT) {
121
+ await this.upsertResourceAttributes(accountId, [
122
+ new ResourceAttributeAssignment(
123
+ operation.resourceId,
124
+ operation.resourceType,
125
+ operation.key,
126
+ operation.value || ''
127
+ ),
128
+ ]);
129
+ } else if (operation.operationType === AttributeOperation.DELETE) {
130
+ await this.deleteResourceAttributes(
131
+ accountId,
132
+ {
133
+ type: operation.resourceType,
134
+ id: operation.resourceId,
135
+ },
136
+ [operation.key]
137
+ );
174
138
  }
175
- await this.upsertResourceAttributes(accountId, [
176
- new ResourceAttributeAssignment(
177
- operation.resourceId,
178
- operation.resourceType,
179
- operation.key,
180
- operation.value || ''
181
- ),
182
- ]);
183
- processedOperations.push(operation);
184
- } else if (operation.operationType === AttributeOperation.DELETE) {
185
- if (!operation.resourceId) {
186
- throw new ArgumentError('resourceId is required for delete operation');
187
- }
188
- await this.deleteResourceAttributes(
189
- accountId,
190
- {
191
- type: operation.resourceType,
192
- id: operation.resourceId,
193
- },
194
- [operation.key]
195
- );
196
- processedOperations.push(operation);
197
- }
198
- }
139
+ })
140
+ );
199
141
 
200
- return processedOperations;
142
+ return resourceAttributeOperations;
201
143
  }
202
144
 
203
145
  /**
@@ -216,20 +158,40 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
216
158
  _callerActionIdentifier: string,
217
159
  entityAttributeOperations: EntityAttributeOperation[]
218
160
  ): Promise<EntityAttributeOperation[]> {
219
- const processedOperations: EntityAttributeOperation[] = [];
220
- for (const operation of entityAttributeOperations) {
221
- if (operation.operationType === 'upsert') {
222
- await this.upsertEntityAttributes(accountId, [
223
- new EntityAttributeAssignment(operation.entityId, operation.entityType, operation.key, operation.value || ''),
224
- ]);
225
- processedOperations.push(operation);
226
- } else if (operation.operationType === 'delete') {
227
- await this.deleteEntityAttributes(accountId, operation.entityType, operation.entityId, [operation.key]);
228
- processedOperations.push(operation);
229
- }
230
- }
161
+ // Process all operations in parallel using Promise.all
162
+ await Promise.all(
163
+ entityAttributeOperations.map(async operation => {
164
+ // Validate before processing
165
+ ValidationUtils.validateEntityAssignment({
166
+ entityId: operation.entityId,
167
+ entityType: operation.entityType,
168
+ key: operation.key,
169
+ value: operation.value || '',
170
+ });
171
+
172
+ if (operation.operationType === 'upsert') {
173
+ await AuthorizationAttributesMsService.executeUpsertRequest(
174
+ accountId,
175
+ [
176
+ new EntityAttributeAssignment(
177
+ operation.entityId,
178
+ operation.entityType,
179
+ operation.key,
180
+ operation.value || ''
181
+ ),
182
+ ],
183
+ UPSERT_ENTITY_ATTRIBUTES_PATH,
184
+ 'entityAttributeAssignments',
185
+ 'entity',
186
+ 'upsertEntityAttributesSync'
187
+ );
188
+ } else if (operation.operationType === 'delete') {
189
+ await this.deleteEntityAttributes(accountId, operation.entityType, operation.entityId, [operation.key]);
190
+ }
191
+ })
192
+ );
231
193
 
232
- return processedOperations;
194
+ return entityAttributeOperations;
233
195
  }
234
196
 
235
197
  /**
@@ -255,8 +217,7 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
255
217
  pathParams: Record<string, string | number>,
256
218
  keys: string[],
257
219
  logPrefix: string,
258
- methodName: string,
259
- context: Record<string, any> = {}
220
+ methodName: string
260
221
  ): Promise<void> {
261
222
  // Validate inputs
262
223
  ValidationUtils.validateInteger(accountId);
@@ -307,7 +268,6 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
307
268
  method: methodName,
308
269
  accountId,
309
270
  ...pathParams,
310
- ...context,
311
271
  error: err instanceof Error ? err.message : String(err),
312
272
  },
313
273
  `Failed in ${methodName}`
@@ -374,15 +334,9 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
374
334
  assignments: T[],
375
335
  pathTemplate: string,
376
336
  requestBodyKey: 'resourceAttributeAssignments' | 'entityAttributeAssignments',
377
- assignmentClass: abstract new (...args: any[]) => T,
378
337
  logPrefix: string,
379
338
  methodName: string
380
339
  ): Promise<void> {
381
- ValidationUtils.validateInteger(accountId);
382
- ValidationUtils.validateArrayTypeOf(assignments, assignmentClass);
383
- if (!assignments.length) {
384
- return;
385
- }
386
340
  const assignmentDto = assignments.map(assignment => assignment.toDataTransferObject());
387
341
 
388
342
  const requestBody =
@@ -435,4 +389,26 @@ export class AuthorizationAttributesMsService implements AuthorizationAttributes
435
389
  throw err;
436
390
  }
437
391
  }
392
+
393
+ private async upsertResourceAttributes(
394
+ accountId: number,
395
+ resourceAttributeAssignments: ResourceAttributeAssignment[]
396
+ ): Promise<ResourceAttributeResponse> {
397
+ const attributionHeaders = getAttributionsFromApi();
398
+ if (!AuthorizationAttributesMsService.httpClient) {
399
+ throw new Error('AuthorizationAttributesMsService: HTTP client is not initialized');
400
+ }
401
+ return await AuthorizationAttributesMsService.httpClient.fetch<ResourceAttributeResponse>({
402
+ url: {
403
+ appName: APP_NAME,
404
+ path: UPSERT_RESOURCE_ATTRIBUTES_PATH.replace('{accountId}', accountId.toString()),
405
+ },
406
+ method: 'POST',
407
+ headers: {
408
+ 'Content-Type': 'application/json',
409
+ ...attributionHeaders,
410
+ },
411
+ body: JSON.stringify({ resourceAttributeAssignments }),
412
+ });
413
+ }
438
414
  }
@@ -1,12 +1,10 @@
1
1
  import chunk from 'lodash/chunk.js';
2
2
  import { getTopicAttributes, sendToSns } from '@mondaydotcomorg/monday-sns';
3
3
  import {
4
- ResourceAttributeAssignment,
5
4
  ResourceAttributeOperation,
6
5
  EntityAttributeOperation,
7
6
  AttributeOperation,
8
7
  } from './types/authorization-attributes-contracts';
9
- import { EntityAttributeAssignment } from './entity-attribute-assignment';
10
8
  import { Resource } from './types/general';
11
9
  import { logger } from './authorization-internal-service';
12
10
  import {
@@ -20,9 +18,10 @@ import {
20
18
  ENTITY_SNS_DEV_TEST_NAME,
21
19
  SnsTopicType,
22
20
  } from './constants/sns';
23
- import type { TopicAttributesMap } from 'aws-sdk/clients/sns';
24
21
  import { AuthorizationAttributesService } from './types/authorization-attributes-service.interface';
25
22
  import { EntityType } from './entity-attributes-constants';
23
+ import { ValidationUtils } from './utils/validation';
24
+ import type { TopicAttributesMap } from 'aws-sdk/clients/sns';
26
25
 
27
26
  /**
28
27
  * Service class for managing resource attributes asynchronously via SNS.
@@ -41,31 +40,6 @@ export class AuthorizationAttributesSnsService implements AuthorizationAttribute
41
40
  this.entitySnsArn = AuthorizationAttributesSnsService.getSnsTopicArn(SnsTopicType.ENTITY);
42
41
  }
43
42
 
44
- /**
45
- * Async function to upsert resource attributes using SNS.
46
- * Sends the updates request to SNS and returns before the change actually took place.
47
- * @param accountId The account ID
48
- * @param appName App name of the calling app
49
- * @param callerActionIdentifier Action identifier
50
- * @param resourceAttributeAssignments Array of resource attribute assignments to upsert
51
- * @return Promise with array of sent operations
52
- */
53
- async upsertResourceAttributes(
54
- accountId: number,
55
- resourceAttributeAssignments: ResourceAttributeAssignment[],
56
- appName?: string,
57
- callerActionIdentifier?: string
58
- ): Promise<ResourceAttributeOperation[]> {
59
- if (!appName || !callerActionIdentifier) {
60
- throw new Error('appName and callerActionIdentifier are required for SNS service');
61
- }
62
- const operations: ResourceAttributeOperation[] = resourceAttributeAssignments.map(assignment => ({
63
- ...assignment,
64
- operationType: AttributeOperation.UPSERT,
65
- }));
66
- return this.updateResourceAttributes(accountId, appName, callerActionIdentifier, operations);
67
- }
68
-
69
43
  /**
70
44
  * Async function to delete resource attributes using SNS.
71
45
  * Sends the updates request to SNS and returns before the change actually took place.
@@ -90,7 +64,7 @@ export class AuthorizationAttributesSnsService implements AuthorizationAttribute
90
64
  key =>
91
65
  ({
92
66
  resourceType: resource.type,
93
- resourceId: resource.id!,
67
+ resourceId: resource.id,
94
68
  key,
95
69
  operationType: AttributeOperation.DELETE,
96
70
  } as ResourceAttributeOperation)
@@ -98,36 +72,6 @@ export class AuthorizationAttributesSnsService implements AuthorizationAttribute
98
72
  return this.updateResourceAttributes(accountId, appName, callerActionIdentifier, operations);
99
73
  }
100
74
 
101
- /**
102
- * Async function to upsert entity attributes using SNS.
103
- * Sends the updates request to SNS and returns before the change actually took place.
104
- * @param accountId The account ID
105
- * @param appName App name of the calling app
106
- * @param callerActionIdentifier Action identifier
107
- * @param entityAttributeAssignments Array of entity attribute assignments to upsert
108
- * @return Promise with array of sent operations
109
- */
110
- async upsertEntityAttributes(
111
- accountId: number,
112
- entityAttributeAssignments: EntityAttributeAssignment[],
113
- appName?: string,
114
- callerActionIdentifier?: string
115
- ): Promise<EntityAttributeOperation[]> {
116
- if (!appName || !callerActionIdentifier) {
117
- throw new Error('appName and callerActionIdentifier are required for SNS service');
118
- }
119
- const operations: EntityAttributeOperation[] = entityAttributeAssignments.map(assignment => {
120
- return {
121
- entityId: assignment.entityId,
122
- entityType: assignment.entityType,
123
- key: assignment.attributeKey,
124
- value: assignment.attributeValue,
125
- operationType: AttributeOperation.UPSERT,
126
- };
127
- });
128
- return this.updateEntityAttributes(accountId, appName, callerActionIdentifier, operations);
129
- }
130
-
131
75
  /**
132
76
  * Async function to delete entity attributes using SNS.
133
77
  * Sends the updates request to SNS and returns before the change actually took place.
@@ -141,7 +85,7 @@ export class AuthorizationAttributesSnsService implements AuthorizationAttribute
141
85
  */
142
86
  async deleteEntityAttributes(
143
87
  accountId: number,
144
- entityType: EntityType | string,
88
+ entityType: EntityType,
145
89
  entityId: number,
146
90
  attributeKeys: string[],
147
91
  appName?: string,
@@ -150,15 +94,16 @@ export class AuthorizationAttributesSnsService implements AuthorizationAttribute
150
94
  if (!appName || !callerActionIdentifier) {
151
95
  throw new Error('appName and callerActionIdentifier are required for SNS service');
152
96
  }
153
- const operations: EntityAttributeOperation[] = attributeKeys.map(
154
- key =>
155
- ({
156
- entityType: entityType,
157
- entityId,
158
- key,
159
- operationType: AttributeOperation.DELETE,
160
- } as EntityAttributeOperation)
161
- );
97
+ const operations: EntityAttributeOperation[] = attributeKeys.map(key => {
98
+ ValidationUtils.validateEntityAssignment({ entityId, entityType, key, value: '' });
99
+ return {
100
+ entityType: entityType,
101
+ entityId,
102
+ key,
103
+ operationType: AttributeOperation.DELETE,
104
+ value: '',
105
+ };
106
+ });
162
107
  return this.updateEntityAttributes(accountId, appName, callerActionIdentifier, operations);
163
108
  }
164
109
 
@@ -1,36 +1,20 @@
1
- import { ValidationUtils } from './utils/validation';
2
1
  import isEqual from 'lodash/isEqual.js';
3
- import { EntityAttributeAssignment, ResourceAttributeDelete } from './types/authorization-attributes-contracts';
4
2
 
5
3
  /**
6
4
  * Base class for attribute assignments (Resource or Entity)
7
5
  * Provides common validation and functionality
8
6
  */
9
- export abstract class BaseAttributeAssignment<TId extends number, TType extends string> {
10
- public readonly id: TId;
11
- public readonly type: TType;
7
+ export abstract class BaseAttributeAssignment<T, R> {
8
+ public readonly id: number;
9
+ public readonly type: T;
12
10
  public readonly attributeKey: string;
13
11
  public readonly attributeValue: string;
14
12
 
15
- constructor(
16
- id: TId,
17
- type: string,
18
- attributeKey: string,
19
- attributeValue: string,
20
- validTypes: readonly string[],
21
- idFieldName: string,
22
- typeFieldName: string
23
- ) {
24
- const validated = ValidationUtils.validateAssignment<TType>(
25
- { id, type, attributeKey, attributeValue },
26
- validTypes as readonly TType[],
27
- { id: idFieldName, type: typeFieldName }
28
- );
29
-
30
- this.id = validated.id as TId;
31
- this.type = validated.type as TType;
32
- this.attributeKey = validated.attributeKey;
33
- this.attributeValue = validated.attributeValue;
13
+ constructor(id: number, type: T, attributeKey: string, attributeValue: string) {
14
+ this.id = id;
15
+ this.type = type;
16
+ this.attributeKey = attributeKey;
17
+ this.attributeValue = attributeValue;
34
18
  }
35
19
 
36
20
  /**
@@ -38,9 +22,9 @@ export abstract class BaseAttributeAssignment<TId extends number, TType extends
38
22
  * @param other Another assignment instance
39
23
  * @returns true if all properties are equal
40
24
  */
41
- equals(other: BaseAttributeAssignment<TId, TType>): boolean {
25
+ equals(other: BaseAttributeAssignment<T, R>): boolean {
42
26
  return isEqual(this, other);
43
27
  }
44
28
 
45
- abstract toDataTransferObject(): EntityAttributeAssignment | ResourceAttributeDelete;
29
+ abstract toDataTransferObject(): R;
46
30
  }
@@ -1,17 +1,20 @@
1
- import { ENTITY_TYPES, EntityType } from './entity-attributes-constants';
1
+ import { EntityType } from './entity-attributes-constants';
2
2
  import { BaseAttributeAssignment } from './base-attribute-assignment';
3
+ import { EntityAttributeAssignment as EntityAttributeAssignmentContract } from './types/authorization-attributes-contracts';
4
+ import { ValidationUtils } from './utils/validation';
3
5
 
4
- export class EntityAttributeAssignment extends BaseAttributeAssignment<number, EntityType> {
6
+ export class EntityAttributeAssignment extends BaseAttributeAssignment<EntityType, EntityAttributeAssignmentContract> {
5
7
  public readonly entityId: number;
6
8
  public readonly entityType: EntityType;
7
9
 
8
- constructor(entityId: number, entityType: string, attributeKey: string, attributeValue: string) {
9
- super(entityId, entityType, attributeKey, attributeValue, ENTITY_TYPES, 'entityId', 'entityType');
10
+ constructor(entityId: number, entityType: EntityType, attributeKey: string, attributeValue: string) {
11
+ ValidationUtils.validateEntityAssignment({ entityId, entityType, key: attributeKey, value: attributeValue });
12
+ super(entityId, entityType, attributeKey, attributeValue);
10
13
  this.entityId = entityId;
11
- this.entityType = this.type;
14
+ this.entityType = entityType;
12
15
  }
13
16
 
14
- toDataTransferObject() {
17
+ toDataTransferObject(): EntityAttributeAssignmentContract {
15
18
  return {
16
19
  entityId: this.entityId,
17
20
  entityType: this.entityType,
@@ -2,6 +2,5 @@ export class ArgumentError extends Error {
2
2
  constructor(message: string) {
3
3
  super(message);
4
4
  this.name = 'ArgumentError';
5
- Object.setPrototypeOf(this, ArgumentError.prototype);
6
5
  }
7
6
  }
@@ -1,25 +1,23 @@
1
- import { RESOURCE_TYPES, ResourceType } from './resource-attributes-constants';
1
+ import { ResourceType } from './resource-attributes-constants';
2
2
  import { BaseAttributeAssignment } from './base-attribute-assignment';
3
+ import { ResourceAttributeAssignment as ResourceAttributeAssignmentContract } from './types/authorization-attributes-contracts';
4
+ import { ValidationUtils } from './utils/validation';
3
5
 
4
- export class ResourceAttributeAssignment extends BaseAttributeAssignment<number, ResourceType> {
6
+ export class ResourceAttributeAssignment extends BaseAttributeAssignment<
7
+ ResourceType,
8
+ ResourceAttributeAssignmentContract
9
+ > {
5
10
  public readonly resourceId: number;
6
11
  public readonly resourceType: ResourceType;
7
12
 
8
13
  constructor(resourceId: number, resourceType: ResourceType, attributeKey: string, attributeValue: string) {
9
- super(
10
- resourceId,
11
- resourceType,
12
- attributeKey,
13
- attributeValue,
14
- Object.values(RESOURCE_TYPES),
15
- 'resourceId',
16
- 'resourceType'
17
- );
14
+ ValidationUtils.validateResourceAssignment({ resourceId, resourceType, key: attributeKey, value: attributeValue });
15
+ super(resourceId, resourceType, attributeKey, attributeValue);
18
16
  this.resourceId = resourceId;
19
17
  this.resourceType = this.type;
20
18
  }
21
19
 
22
- toDataTransferObject() {
20
+ toDataTransferObject(): ResourceAttributeAssignmentContract {
23
21
  return {
24
22
  resourceId: this.resourceId,
25
23
  resourceType: this.resourceType,
@@ -1,4 +1,4 @@
1
- export const RESOURCE_ATTRIBUTES_CONSTANTS = {
1
+ export const RESOURCE_ATTRIBUTES_CONSTANTS = Object.freeze({
2
2
  ACCOUNT_RESOURCE_ATTRIBUTES: {
3
3
  ENABLE_MEMBERS_INVITE_FROM_NON_AUTH_DOMAIN: 'enable_members_invite_from_non_auth_domain',
4
4
  },
@@ -9,7 +9,7 @@ export const RESOURCE_ATTRIBUTES_CONSTANTS = {
9
9
  IS_SYNCABLE_CHILD_ENTITY: 'is_syncable_child_entity',
10
10
  SYSTEM_ENTITY_TYPE: 'system_entity_type',
11
11
  },
12
- } as const;
12
+ });
13
13
 
14
14
  export enum ResourceType {
15
15
  Account = 'account',
@@ -1,4 +1,4 @@
1
- import { BaseRequest, BaseResponse, ContextGetter, Resource, ResourceGetter } from '../types/general';
1
+ import { Action, BaseRequest, BaseResponse, ContextGetter, Resource, ResourceGetter } from '../types/general';
2
2
  import { defaultContextGetter } from '../authorization-middleware';
3
3
  import { AuthorizationInternalService } from '../authorization-internal-service';
4
4
  import type { NextFunction } from 'express';
@@ -7,11 +7,11 @@ export type TestPermittedAction = {
7
7
  accountId: number;
8
8
  userId: number;
9
9
  resources: Resource[];
10
- action: string;
10
+ action: Action;
11
11
  };
12
12
 
13
13
  let testPermittedActions: TestPermittedAction[] = [];
14
- export const addTestPermittedAction = (accountId: number, userId: number, resources: Resource[], action: string) => {
14
+ export const addTestPermittedAction = (accountId: number, userId: number, resources: Resource[], action: Action) => {
15
15
  testPermittedActions.push({ accountId, userId, resources, action });
16
16
  };
17
17
 
@@ -19,7 +19,7 @@ export const clearTestPermittedActions = () => {
19
19
  testPermittedActions = [];
20
20
  };
21
21
 
22
- const isActionAuthorized = (accountId: number, userId: number, resources: Resource[], action: string) => {
22
+ const isActionAuthorized = (accountId: number, userId: number, resources: Resource[], action: Action) => {
23
23
  // If no resources to check, deny access
24
24
  if (resources.length === 0) {
25
25
  return { isAuthorized: false };
@@ -46,7 +46,7 @@ const isActionAuthorized = (accountId: number, userId: number, resources: Resour
46
46
  };
47
47
 
48
48
  export const getTestAuthorizationMiddleware = (
49
- action: string,
49
+ action: Action,
50
50
  resourceGetter: ResourceGetter,
51
51
  contextGetter?: ContextGetter
52
52
  ) => {
@@ -2,7 +2,7 @@ import { Resource } from './general';
2
2
  import type { EntityType } from '../entity-attributes-constants';
3
3
  import type { ResourceType } from '../resource-attributes-constants';
4
4
 
5
- interface AttributeAssignment {
5
+ export interface AttributeAssignment {
6
6
  key: string;
7
7
  value: string;
8
8
  }