@mondaydotcomorg/monday-authorization 3.6.0-feat-shaime-support-entity-attributes-1-f58d933 → 3.6.0-feat-shaime-support-entity-attributes-3-0d092e0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authorization-attributes-ms-service.d.ts +68 -0
- package/dist/authorization-attributes-ms-service.d.ts.map +1 -0
- package/dist/authorization-attributes-ms-service.js +263 -0
- package/dist/authorization-attributes-service.d.ts +25 -47
- package/dist/authorization-attributes-service.d.ts.map +1 -1
- package/dist/authorization-attributes-service.js +32 -171
- package/dist/authorization-attributes-sns-service.d.ts +84 -0
- package/dist/authorization-attributes-sns-service.d.ts.map +1 -0
- package/dist/authorization-attributes-sns-service.js +196 -0
- package/dist/constants/sns.d.ts +12 -2
- package/dist/constants/sns.d.ts.map +1 -1
- package/dist/constants/sns.js +22 -2
- package/dist/entity-attribute-assignment.d.ts.map +1 -1
- package/dist/entity-attribute-assignment.js +0 -2
- package/dist/esm/authorization-attributes-ms-service.d.ts +68 -0
- package/dist/esm/authorization-attributes-ms-service.d.ts.map +1 -0
- package/dist/esm/authorization-attributes-ms-service.mjs +261 -0
- package/dist/esm/authorization-attributes-service.d.ts +25 -47
- package/dist/esm/authorization-attributes-service.d.ts.map +1 -1
- package/dist/esm/authorization-attributes-service.mjs +32 -167
- package/dist/esm/authorization-attributes-sns-service.d.ts +84 -0
- package/dist/esm/authorization-attributes-sns-service.d.ts.map +1 -0
- package/dist/esm/authorization-attributes-sns-service.mjs +190 -0
- package/dist/esm/constants/sns.d.ts +12 -2
- package/dist/esm/constants/sns.d.ts.map +1 -1
- package/dist/esm/constants/sns.mjs +17 -3
- package/dist/esm/entity-attribute-assignment.d.ts.map +1 -1
- package/dist/esm/entity-attribute-assignment.mjs +0 -2
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.mjs +5 -0
- package/dist/esm/resource-attribute-assignment.d.ts.map +1 -1
- package/dist/esm/resource-attribute-assignment.mjs +0 -2
- package/dist/esm/resource-attributes-constants.d.ts +2 -1
- package/dist/esm/resource-attributes-constants.d.ts.map +1 -1
- package/dist/esm/resource-attributes-constants.mjs +1 -0
- package/dist/esm/types/authorization-attributes-contracts.d.ts +2 -17
- package/dist/esm/types/authorization-attributes-contracts.d.ts.map +1 -1
- package/dist/esm/types/authorization-attributes-service.interface.d.ts +14 -25
- package/dist/esm/types/authorization-attributes-service.interface.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +4 -3
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/utils/assignment-schema.d.ts +51 -0
- package/dist/esm/utils/assignment-schema.d.ts.map +1 -0
- package/dist/esm/utils/assignment-schema.mjs +49 -0
- package/dist/esm/utils/resource-schema.d.ts +9 -0
- package/dist/esm/utils/resource-schema.d.ts.map +1 -0
- package/dist/esm/utils/resource-schema.mjs +16 -0
- package/dist/esm/utils/validation.d.ts +11 -3
- package/dist/esm/utils/validation.d.ts.map +1 -1
- package/dist/esm/utils/validation.mjs +50 -13
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/resource-attribute-assignment.d.ts.map +1 -1
- package/dist/resource-attribute-assignment.js +0 -2
- package/dist/resource-attributes-constants.d.ts +2 -1
- package/dist/resource-attributes-constants.d.ts.map +1 -1
- package/dist/resource-attributes-constants.js +1 -0
- package/dist/types/authorization-attributes-contracts.d.ts +2 -17
- package/dist/types/authorization-attributes-contracts.d.ts.map +1 -1
- package/dist/types/authorization-attributes-service.interface.d.ts +14 -25
- package/dist/types/authorization-attributes-service.interface.d.ts.map +1 -1
- package/dist/types/general.d.ts +4 -3
- package/dist/types/general.d.ts.map +1 -1
- package/dist/utils/assignment-schema.d.ts +51 -0
- package/dist/utils/assignment-schema.d.ts.map +1 -0
- package/dist/utils/assignment-schema.js +58 -0
- package/dist/utils/resource-schema.d.ts +9 -0
- package/dist/utils/resource-schema.d.ts.map +1 -0
- package/dist/utils/resource-schema.js +22 -0
- package/dist/utils/validation.d.ts +11 -3
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +50 -13
- package/package.json +1 -1
- package/src/authorization-attributes-ms-service.ts +397 -0
- package/src/authorization-attributes-service.ts +34 -222
- package/src/authorization-attributes-sns-service.ts +321 -0
- package/src/constants/sns.ts +19 -2
- package/src/entity-attribute-assignment.ts +0 -2
- package/src/index.ts +17 -0
- package/src/resource-attribute-assignment.ts +0 -2
- package/src/resource-attributes-constants.ts +1 -0
- package/src/types/authorization-attributes-contracts.ts +2 -24
- package/src/types/authorization-attributes-service.interface.ts +19 -31
- package/src/types/general.ts +4 -3
- package/src/utils/assignment-schema.ts +51 -0
- package/src/utils/resource-schema.ts +16 -0
- package/src/utils/validation.ts +76 -15
- package/dist/esm/utils/assigment-schema.d.ts +0 -29
- package/dist/esm/utils/assigment-schema.d.ts.map +0 -1
- package/dist/esm/utils/assigment-schema.mjs +0 -29
- package/dist/utils/assigment-schema.d.ts +0 -29
- package/dist/utils/assigment-schema.d.ts.map +0 -1
- package/dist/utils/assigment-schema.js +0 -36
- package/src/utils/assigment-schema.ts +0 -29
package/dist/utils/validation.js
CHANGED
|
@@ -2,7 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const Ajv = require('ajv');
|
|
4
4
|
const errors_argumentError = require('../errors/argument-error.js');
|
|
5
|
-
const
|
|
5
|
+
const utils_assignmentSchema = require('./assignment-schema.js');
|
|
6
|
+
const utils_resourceSchema = require('./resource-schema.js');
|
|
6
7
|
|
|
7
8
|
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
8
9
|
|
|
@@ -37,27 +38,63 @@ class ValidationUtils {
|
|
|
37
38
|
throw new errors_argumentError.ArgumentError('Invalid string array');
|
|
38
39
|
}
|
|
39
40
|
}
|
|
41
|
+
static validateResource(resource) {
|
|
42
|
+
const isValid = utils_resourceSchema.resourceSchema(resource);
|
|
43
|
+
if (!isValid) {
|
|
44
|
+
const errorMessage = this.formatValidationErrors(utils_resourceSchema.resourceSchema.errors);
|
|
45
|
+
throw new errors_argumentError.ArgumentError(errorMessage ? `Invalid resource: ${errorMessage}` : 'Invalid resource');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
40
48
|
/**
|
|
41
49
|
* Validates an attribute assignment object using a single AJV schema.
|
|
42
50
|
* Preserves legacy error messages for each field.
|
|
43
51
|
*/
|
|
44
|
-
static
|
|
45
|
-
const valid =
|
|
52
|
+
static validatUpsertResourceAssignment(resource) {
|
|
53
|
+
const valid = utils_assignmentSchema.resourceUpsertAssignmentSchema(resource);
|
|
54
|
+
if (!valid) {
|
|
55
|
+
const errorMessage = this.formatValidationErrors(utils_assignmentSchema.resourceUpsertAssignmentSchema.errors);
|
|
56
|
+
throw new errors_argumentError.ArgumentError(errorMessage
|
|
57
|
+
? `Invalid resource attribute assignment: ${errorMessage}`
|
|
58
|
+
: 'Invalid resource attribute assignment');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
static validatDeleteResourceAssignment(resource) {
|
|
62
|
+
const valid = utils_assignmentSchema.resourceDeleteAssignmentSchema(resource);
|
|
63
|
+
if (!valid) {
|
|
64
|
+
const errorMessage = this.formatValidationErrors(utils_assignmentSchema.resourceUpsertAssignmentSchema.errors);
|
|
65
|
+
throw new errors_argumentError.ArgumentError(errorMessage
|
|
66
|
+
? `Invalid resource attribute assignment: ${errorMessage}`
|
|
67
|
+
: 'Invalid resource attribute assignment');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
static validatUpsertEntityAssignment(entity) {
|
|
71
|
+
const valid = utils_assignmentSchema.entityUpsertAssignmentSchema(entity);
|
|
46
72
|
if (!valid) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
.join(', ');
|
|
50
|
-
throw new errors_argumentError.ArgumentError(`Invalid resource attribute assignment: ${errorMessages}`);
|
|
73
|
+
const errorMessage = this.formatValidationErrors(utils_assignmentSchema.entityUpsertAssignmentSchema.errors);
|
|
74
|
+
throw new errors_argumentError.ArgumentError(errorMessage ? `Invalid entity attribute assignment: ${errorMessage}` : 'Invalid entity attribute assignment');
|
|
51
75
|
}
|
|
52
76
|
}
|
|
53
|
-
static
|
|
54
|
-
const valid =
|
|
77
|
+
static validatDeleteEntityAssignment(entity) {
|
|
78
|
+
const valid = utils_assignmentSchema.entityDeleteAssignmentSchema(entity);
|
|
55
79
|
if (!valid) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
const errorMessage = this.formatValidationErrors(utils_assignmentSchema.entityDeleteAssignmentSchema.errors);
|
|
81
|
+
throw new errors_argumentError.ArgumentError(errorMessage ? `Invalid entity attribute assignment: ${errorMessage}` : 'Invalid entity attribute assignment');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Formats AJV validation errors into a readable error message
|
|
86
|
+
*/
|
|
87
|
+
static formatValidationErrors(errors) {
|
|
88
|
+
if (!errors || errors.length === 0) {
|
|
89
|
+
return '';
|
|
60
90
|
}
|
|
91
|
+
return errors
|
|
92
|
+
.map(err => {
|
|
93
|
+
const path = err.instancePath || (err.params && 'missingProperty' in err.params ? `/${err.params.missingProperty}` : '');
|
|
94
|
+
const message = err.message || 'validation failed';
|
|
95
|
+
return path ? `${path}: ${message}` : message;
|
|
96
|
+
})
|
|
97
|
+
.join('; ');
|
|
61
98
|
}
|
|
62
99
|
}
|
|
63
100
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "3.6.0-feat-shaime-support-entity-attributes-
|
|
3
|
+
"version": "3.6.0-feat-shaime-support-entity-attributes-3-0d092e0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { Api, HttpClient } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
+
import { signAuthorizationHeader } from '@mondaydotcomorg/monday-jwt';
|
|
3
|
+
import { ResourceAttributeAssignment } from './resource-attribute-assignment';
|
|
4
|
+
import { EntityAttributeAssignment } from './entity-attribute-assignment';
|
|
5
|
+
import {
|
|
6
|
+
AttributeOperation,
|
|
7
|
+
ResourceAttributeUpsertOperation,
|
|
8
|
+
ResourceAttributeDeleteOperation,
|
|
9
|
+
EntityAttributeUpsertOperation,
|
|
10
|
+
EntityAttributeDeleteOperation,
|
|
11
|
+
} from './types/authorization-attributes-contracts';
|
|
12
|
+
import { EntityType } from './entity-attributes-constants';
|
|
13
|
+
import { AuthorizationInternalService, logger } from './authorization-internal-service';
|
|
14
|
+
import { getAttributionsFromApi } from './attributions-service';
|
|
15
|
+
import { APP_NAME } from './constants';
|
|
16
|
+
import { ValidationUtils } from './utils/validation';
|
|
17
|
+
import { AuthorizationAttributesService } from './types/authorization-attributes-service.interface';
|
|
18
|
+
import { Resource } from './types/general';
|
|
19
|
+
|
|
20
|
+
const INTERNAL_APP_NAME = 'internal_ms';
|
|
21
|
+
const UPSERT_RESOURCE_ATTRIBUTES_PATH = '/attributes/{accountId}/resource';
|
|
22
|
+
const DELETE_RESOURCE_ATTRIBUTES_PATH = '/attributes/{accountId}/resource/{resourceType}/{resourceId}';
|
|
23
|
+
const UPSERT_ENTITY_ATTRIBUTES_PATH = '/attributes/{accountId}/entity';
|
|
24
|
+
const DELETE_ENTITY_ATTRIBUTES_PATH = '/attributes/{accountId}/entity/{entityType}/{entityId}';
|
|
25
|
+
|
|
26
|
+
interface DeleteRequestBody {
|
|
27
|
+
keys: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Service class for managing resource attributes in the authorization microservice.
|
|
32
|
+
* Provides synchronous HTTP operations to create/update and delete attributes on resources.
|
|
33
|
+
*/
|
|
34
|
+
export class AuthorizationAttributesMsService implements AuthorizationAttributesService {
|
|
35
|
+
private static LOG_TAG = 'authorization_attributes_ms';
|
|
36
|
+
private static httpClient: HttpClient | undefined = Api.getPart('httpClient');
|
|
37
|
+
|
|
38
|
+
constructor() {
|
|
39
|
+
if (!AuthorizationAttributesMsService.httpClient) {
|
|
40
|
+
AuthorizationAttributesMsService.httpClient = Api.getPart('httpClient');
|
|
41
|
+
if (!AuthorizationAttributesMsService.httpClient) {
|
|
42
|
+
throw new Error('HTTP client is not initialized');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Deletes a specific attribute from a resource synchronously.
|
|
49
|
+
* @param accountId The account ID
|
|
50
|
+
* @param resource Object with resourceType (string) and resourceId (number)
|
|
51
|
+
* @param attributeKey Attribute key string to delete
|
|
52
|
+
* @returns Promise<ResourceAttributeDeleteOperation>
|
|
53
|
+
*/
|
|
54
|
+
async deleteResourceAttributes(
|
|
55
|
+
accountId: number,
|
|
56
|
+
resource: Resource,
|
|
57
|
+
attributeKey: string,
|
|
58
|
+
_appName?: string,
|
|
59
|
+
_callerActionIdentifier?: string
|
|
60
|
+
): Promise<ResourceAttributeDeleteOperation> {
|
|
61
|
+
ValidationUtils.validateResource(resource);
|
|
62
|
+
ValidationUtils.validatDeleteResourceAssignment({
|
|
63
|
+
resourceType: resource.type,
|
|
64
|
+
resourceId: resource.id,
|
|
65
|
+
key: attributeKey,
|
|
66
|
+
});
|
|
67
|
+
await AuthorizationAttributesMsService.executeDeleteRequest(
|
|
68
|
+
accountId,
|
|
69
|
+
DELETE_RESOURCE_ATTRIBUTES_PATH,
|
|
70
|
+
{
|
|
71
|
+
resourceType: resource.type,
|
|
72
|
+
resourceId: resource.id,
|
|
73
|
+
},
|
|
74
|
+
[attributeKey],
|
|
75
|
+
'resource',
|
|
76
|
+
'deleteResourceAttributesSync'
|
|
77
|
+
);
|
|
78
|
+
return {
|
|
79
|
+
resourceType: resource.type,
|
|
80
|
+
resourceId: resource.id,
|
|
81
|
+
key: attributeKey,
|
|
82
|
+
operationType: AttributeOperation.DELETE,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Deletes a specific attribute from an entity synchronously.
|
|
88
|
+
* @param accountId The account ID
|
|
89
|
+
* @param entityType The entity type
|
|
90
|
+
* @param entityId The entity ID
|
|
91
|
+
* @param attributeKey Attribute key string to delete
|
|
92
|
+
* @returns Promise<EntityAttributeDeleteOperation>
|
|
93
|
+
*/
|
|
94
|
+
async deleteEntityAttributes(
|
|
95
|
+
accountId: number,
|
|
96
|
+
entityType: EntityType,
|
|
97
|
+
entityId: number,
|
|
98
|
+
attributeKey: string,
|
|
99
|
+
_appName?: string,
|
|
100
|
+
_callerActionIdentifier?: string
|
|
101
|
+
): Promise<EntityAttributeDeleteOperation> {
|
|
102
|
+
ValidationUtils.validateInteger(accountId);
|
|
103
|
+
await AuthorizationAttributesMsService.executeDeleteRequest(
|
|
104
|
+
accountId,
|
|
105
|
+
DELETE_ENTITY_ATTRIBUTES_PATH,
|
|
106
|
+
{
|
|
107
|
+
entityType,
|
|
108
|
+
entityId,
|
|
109
|
+
},
|
|
110
|
+
[attributeKey],
|
|
111
|
+
'entity',
|
|
112
|
+
'deleteEntityAttributesSync'
|
|
113
|
+
);
|
|
114
|
+
return {
|
|
115
|
+
entityType,
|
|
116
|
+
entityId,
|
|
117
|
+
key: attributeKey,
|
|
118
|
+
operationType: AttributeOperation.DELETE,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Updates a resource attribute (single operation - upsert only).
|
|
124
|
+
* @param accountId The account ID
|
|
125
|
+
* @param appName App name (required for interface compatibility, but not used in MS service)
|
|
126
|
+
* @param callerActionIdentifier Action identifier (required for interface compatibility, but not used in MS service)
|
|
127
|
+
* @param resourceAttributeOperation Operation to perform (must be UPSERT)
|
|
128
|
+
* @returns Promise<ResourceAttributeUpsertOperation> Processed operation
|
|
129
|
+
*/
|
|
130
|
+
async updateResourceAttributes(
|
|
131
|
+
accountId: number,
|
|
132
|
+
_appName: string,
|
|
133
|
+
_callerActionIdentifier: string,
|
|
134
|
+
resourceAttributeOperation: ResourceAttributeUpsertOperation
|
|
135
|
+
): Promise<ResourceAttributeUpsertOperation> {
|
|
136
|
+
ValidationUtils.validatUpsertResourceAssignment({
|
|
137
|
+
resourceId: resourceAttributeOperation.resourceId,
|
|
138
|
+
resourceType: resourceAttributeOperation.resourceType,
|
|
139
|
+
key: resourceAttributeOperation.key,
|
|
140
|
+
value: resourceAttributeOperation.value,
|
|
141
|
+
});
|
|
142
|
+
await AuthorizationAttributesMsService.executeUpsertRequest(
|
|
143
|
+
accountId,
|
|
144
|
+
[
|
|
145
|
+
new ResourceAttributeAssignment(
|
|
146
|
+
resourceAttributeOperation.resourceId,
|
|
147
|
+
resourceAttributeOperation.resourceType,
|
|
148
|
+
resourceAttributeOperation.key,
|
|
149
|
+
resourceAttributeOperation.value || ''
|
|
150
|
+
),
|
|
151
|
+
],
|
|
152
|
+
UPSERT_RESOURCE_ATTRIBUTES_PATH,
|
|
153
|
+
'resourceAttributeAssignments',
|
|
154
|
+
'resource',
|
|
155
|
+
'updateResourceAttributesSync'
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return resourceAttributeOperation;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Updates an entity attribute (single operation - upsert only).
|
|
163
|
+
* @param accountId The account ID
|
|
164
|
+
* @param appName App name (required for interface compatibility, but not used in MS service)
|
|
165
|
+
* @param callerActionIdentifier Action identifier (required for interface compatibility, but not used in MS service)
|
|
166
|
+
* @param entityAttributeOperation Operation to perform (must be UPSERT)
|
|
167
|
+
* @returns Promise<EntityAttributeUpsertOperation> Processed operation
|
|
168
|
+
*/
|
|
169
|
+
async updateEntityAttributes(
|
|
170
|
+
accountId: number,
|
|
171
|
+
_appName: string,
|
|
172
|
+
_callerActionIdentifier: string,
|
|
173
|
+
entityAttributeOperation: EntityAttributeUpsertOperation
|
|
174
|
+
): Promise<EntityAttributeUpsertOperation> {
|
|
175
|
+
// Validate before processing
|
|
176
|
+
ValidationUtils.validatUpsertEntityAssignment({
|
|
177
|
+
entityId: entityAttributeOperation.entityId,
|
|
178
|
+
entityType: entityAttributeOperation.entityType,
|
|
179
|
+
key: entityAttributeOperation.key,
|
|
180
|
+
value: entityAttributeOperation.value,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await AuthorizationAttributesMsService.executeUpsertRequest(
|
|
184
|
+
accountId,
|
|
185
|
+
[
|
|
186
|
+
new EntityAttributeAssignment(
|
|
187
|
+
entityAttributeOperation.entityId,
|
|
188
|
+
entityAttributeOperation.entityType,
|
|
189
|
+
entityAttributeOperation.key,
|
|
190
|
+
entityAttributeOperation.value
|
|
191
|
+
),
|
|
192
|
+
],
|
|
193
|
+
UPSERT_ENTITY_ATTRIBUTES_PATH,
|
|
194
|
+
'entityAttributeAssignments',
|
|
195
|
+
'entity',
|
|
196
|
+
'upsertEntityAttributesSync'
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
return entityAttributeOperation;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Replaces path template parameters with actual values
|
|
204
|
+
* @param template Path template with placeholders like {accountId}
|
|
205
|
+
* @param params Object with parameter names and values
|
|
206
|
+
* @returns Path with all placeholders replaced
|
|
207
|
+
*/
|
|
208
|
+
private static replacePathParams(template: string, params: Record<string, string | number>): string {
|
|
209
|
+
let path = template;
|
|
210
|
+
for (const [key, value] of Object.entries(params)) {
|
|
211
|
+
path = path.replace(`{${key}}`, String(value));
|
|
212
|
+
}
|
|
213
|
+
return path;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Generic helper for executing delete requests
|
|
218
|
+
*/
|
|
219
|
+
private static async executeDeleteRequest(
|
|
220
|
+
accountId: number,
|
|
221
|
+
pathTemplate: string,
|
|
222
|
+
pathParams: Record<string, string | number>,
|
|
223
|
+
keys: string[],
|
|
224
|
+
logPrefix: string,
|
|
225
|
+
methodName: string
|
|
226
|
+
): Promise<void> {
|
|
227
|
+
// Validate inputs
|
|
228
|
+
ValidationUtils.validateInteger(accountId);
|
|
229
|
+
ValidationUtils.validateStringArray(keys);
|
|
230
|
+
|
|
231
|
+
if (!keys.length) {
|
|
232
|
+
logger.warn({ tag: this.LOG_TAG, accountId, ...pathParams }, `${methodName} called with empty keys array`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const requestBody: DeleteRequestBody = { keys };
|
|
236
|
+
|
|
237
|
+
if (!AuthorizationAttributesMsService.httpClient) {
|
|
238
|
+
throw new Error('AuthorizationAttributesMsService: HTTP client is not initialized');
|
|
239
|
+
}
|
|
240
|
+
const path = AuthorizationAttributesMsService.replacePathParams(pathTemplate, { accountId, ...pathParams });
|
|
241
|
+
const headers = AuthorizationAttributesMsService.getRequestHeaders(accountId);
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
logger.info(
|
|
245
|
+
{ tag: AuthorizationAttributesMsService.LOG_TAG, accountId, ...pathParams, keys },
|
|
246
|
+
`Deleting ${logPrefix} attributes`
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
await AuthorizationAttributesMsService.httpClient.fetch(
|
|
250
|
+
{
|
|
251
|
+
url: {
|
|
252
|
+
appName: APP_NAME,
|
|
253
|
+
path,
|
|
254
|
+
},
|
|
255
|
+
method: 'DELETE',
|
|
256
|
+
headers,
|
|
257
|
+
body: JSON.stringify(requestBody),
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
261
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
logger.debug(
|
|
266
|
+
{ tag: AuthorizationAttributesMsService.LOG_TAG, accountId, ...pathParams, keys },
|
|
267
|
+
`Successfully deleted ${logPrefix} attributes`
|
|
268
|
+
);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
logger.error(
|
|
271
|
+
{
|
|
272
|
+
tag: AuthorizationAttributesMsService.LOG_TAG,
|
|
273
|
+
method: methodName,
|
|
274
|
+
accountId,
|
|
275
|
+
...pathParams,
|
|
276
|
+
error: err instanceof Error ? err.message : String(err),
|
|
277
|
+
},
|
|
278
|
+
`Failed in ${methodName}`
|
|
279
|
+
);
|
|
280
|
+
throw err;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Gets request headers including Authorization, Content-Type, and optional attribution headers
|
|
286
|
+
*/
|
|
287
|
+
private static getRequestHeaders(accountId: number, userId?: number): Record<string, string> {
|
|
288
|
+
const headers: Record<string, string> = {
|
|
289
|
+
'Content-Type': 'application/json',
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// Generate Authorization token
|
|
293
|
+
const authToken = signAuthorizationHeader({
|
|
294
|
+
appName: INTERNAL_APP_NAME,
|
|
295
|
+
accountId,
|
|
296
|
+
userId,
|
|
297
|
+
});
|
|
298
|
+
headers.Authorization = authToken;
|
|
299
|
+
|
|
300
|
+
// Add attribution headers if available
|
|
301
|
+
const attributionHeaders = getAttributionsFromApi();
|
|
302
|
+
for (const key in attributionHeaders) {
|
|
303
|
+
if (Object.prototype.hasOwnProperty.call(attributionHeaders, key)) {
|
|
304
|
+
headers[key] = attributionHeaders[key];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Add X-REQUEST-ID if available from context
|
|
309
|
+
try {
|
|
310
|
+
const tridentContext = Api.getPart('context');
|
|
311
|
+
if (tridentContext?.runtimeAttributions) {
|
|
312
|
+
const outgoingHeaders = tridentContext.runtimeAttributions.buildOutgoingHeaders('HTTP_INTERNAL');
|
|
313
|
+
if (outgoingHeaders) {
|
|
314
|
+
const attributionHeadersMap: Record<string, string> = {};
|
|
315
|
+
for (const [key, value] of outgoingHeaders) {
|
|
316
|
+
attributionHeadersMap[key] = value;
|
|
317
|
+
}
|
|
318
|
+
if (attributionHeadersMap['x-request-id']) {
|
|
319
|
+
headers['X-REQUEST-ID'] = attributionHeadersMap['x-request-id'];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
// Silently fail if context is not available
|
|
325
|
+
logger.debug({ tag: AuthorizationAttributesMsService.LOG_TAG, error }, 'Failed to get request ID from context');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Add X-REQUEST-START timestamp
|
|
329
|
+
headers['X-REQUEST-START'] = Math.floor(Date.now() / 1000).toString();
|
|
330
|
+
|
|
331
|
+
return headers;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Generic helper for executing upsert requests
|
|
336
|
+
*/
|
|
337
|
+
private static async executeUpsertRequest<T extends ResourceAttributeAssignment | EntityAttributeAssignment>(
|
|
338
|
+
accountId: number,
|
|
339
|
+
assignments: T[],
|
|
340
|
+
pathTemplate: string,
|
|
341
|
+
requestBodyKey: 'resourceAttributeAssignments' | 'entityAttributeAssignments',
|
|
342
|
+
logPrefix: string,
|
|
343
|
+
methodName: string
|
|
344
|
+
): Promise<void> {
|
|
345
|
+
const assignmentDto = assignments.map(assignment => assignment.toDataTransferObject());
|
|
346
|
+
|
|
347
|
+
const requestBody =
|
|
348
|
+
requestBodyKey === 'resourceAttributeAssignments'
|
|
349
|
+
? { resourceAttributeAssignments: assignmentDto }
|
|
350
|
+
: { entityAttributeAssignments: assignmentDto };
|
|
351
|
+
|
|
352
|
+
if (!AuthorizationAttributesMsService.httpClient) {
|
|
353
|
+
throw new Error('AuthorizationAttributesMsService: HTTP client is not initialized');
|
|
354
|
+
}
|
|
355
|
+
const path = AuthorizationAttributesMsService.replacePathParams(pathTemplate, { accountId });
|
|
356
|
+
const headers = AuthorizationAttributesMsService.getRequestHeaders(accountId);
|
|
357
|
+
|
|
358
|
+
try {
|
|
359
|
+
logger.info(
|
|
360
|
+
{ tag: AuthorizationAttributesMsService.LOG_TAG, accountId, count: assignments.length },
|
|
361
|
+
`Upserting ${logPrefix} attributes`
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
await AuthorizationAttributesMsService.httpClient.fetch(
|
|
365
|
+
{
|
|
366
|
+
url: {
|
|
367
|
+
appName: APP_NAME,
|
|
368
|
+
path,
|
|
369
|
+
},
|
|
370
|
+
method: 'POST',
|
|
371
|
+
headers,
|
|
372
|
+
body: JSON.stringify(requestBody),
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
376
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
logger.debug(
|
|
381
|
+
{ tag: AuthorizationAttributesMsService.LOG_TAG, accountId, count: assignments.length },
|
|
382
|
+
`Successfully upserted ${logPrefix} attributes`
|
|
383
|
+
);
|
|
384
|
+
} catch (err) {
|
|
385
|
+
logger.error(
|
|
386
|
+
{
|
|
387
|
+
tag: AuthorizationAttributesMsService.LOG_TAG,
|
|
388
|
+
method: methodName,
|
|
389
|
+
accountId,
|
|
390
|
+
error: err instanceof Error ? err.message : String(err),
|
|
391
|
+
},
|
|
392
|
+
`Failed in ${methodName}`
|
|
393
|
+
);
|
|
394
|
+
throw err;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|