@@ -32,8 +32,18 @@ import {
32
32
CDMaterialFilterQuery ,
33
33
ImagePromotionMaterialInfo ,
34
34
EnvironmentListHelmResponse ,
35
+ UserGroupApproverType ,
36
+ ImageApprovalPolicyUserGroupDataType ,
37
+ ImageApprovalPolicyType ,
38
+ ImageApprovalUsersInfoDTO ,
39
+ UserApprovalMetadataType ,
40
+ UserApprovalConfigType ,
41
+ CDMaterialListModalServiceUtilProps ,
35
42
} from './Types'
36
43
import { ApiResourceType } from '../Pages'
44
+ import { getIsManualApprovalSpecific , sanitizeUserApprovalConfig , stringComparatorBySortOrder } from '@Shared/Helpers'
45
+ import { API_TOKEN_PREFIX } from '@Shared/constants'
46
+ import { DefaultUserKey } from '@Shared/types'
37
47
38
48
export const getTeamListMin = ( ) : Promise < TeamList > => {
39
49
// ignore active field
@@ -80,13 +90,35 @@ export function setImageTags(request, pipelineId: number, artifactId: number) {
80
90
return post ( `${ ROUTES . IMAGE_TAGGING } /${ pipelineId } /${ artifactId } ` , request )
81
91
}
82
92
83
- const cdMaterialListModal = (
84
- artifacts : any [ ] ,
85
- offset : number ,
86
- artifactId ?: number ,
87
- artifactStatus ?: string ,
88
- disableDefaultSelection ?: boolean ,
89
- ) => {
93
+ const sanitizeApprovalConfigFromApprovalMetadata = (
94
+ approvalMetadata : UserApprovalMetadataType ,
95
+ userApprovalConfig : UserApprovalConfigType ,
96
+ ) : UserApprovalMetadataType => {
97
+ if ( ! approvalMetadata ) {
98
+ return null
99
+ }
100
+
101
+ const approvedUsersData = approvalMetadata . approvedUsersData || [ ]
102
+ const unsanitizedApprovalConfig = approvalMetadata . approvalConfig || userApprovalConfig
103
+
104
+ return {
105
+ ...approvalMetadata ,
106
+ approvedUsersData : approvedUsersData . map ( ( userData ) => ( {
107
+ ...userData ,
108
+ userGroups : userData . userGroups ?. filter ( ( group ) => ! ! group ?. identifier && ! ! group ?. name ) ?? [ ] ,
109
+ } ) ) ,
110
+ approvalConfig : sanitizeUserApprovalConfig ( unsanitizedApprovalConfig ) ,
111
+ }
112
+ }
113
+
114
+ const cdMaterialListModal = ( {
115
+ artifacts,
116
+ offset,
117
+ artifactId,
118
+ artifactStatus,
119
+ disableDefaultSelection,
120
+ userApprovalConfig,
121
+ } : CDMaterialListModalServiceUtilProps ) => {
90
122
if ( ! artifacts || ! artifacts . length ) return [ ]
91
123
92
124
const markFirstSelected = offset === 0
@@ -130,7 +162,10 @@ const cdMaterialListModal = (
130
162
vulnerable : material . vulnerable ,
131
163
runningOnParentCd : material . runningOnParentCd ,
132
164
artifactStatus : artifactStatusValue ,
133
- userApprovalMetadata : material . userApprovalMetadata ,
165
+ userApprovalMetadata : sanitizeApprovalConfigFromApprovalMetadata (
166
+ material . userApprovalMetadata ,
167
+ userApprovalConfig ,
168
+ ) ,
134
169
triggeredBy : material . triggeredBy ,
135
170
isVirtualEnvironment : material . isVirtualEnvironment ,
136
171
imageComment : material . imageComment ,
@@ -175,19 +210,110 @@ const cdMaterialListModal = (
175
210
return materials
176
211
}
177
212
213
+ const getImageApprovalPolicyDetailsFromMaterialResult = ( cdMaterialsResult ) : ImageApprovalPolicyType => {
214
+ const approvalUsers : string [ ] = cdMaterialsResult . approvalUsers || [ ]
215
+ const userApprovalConfig = sanitizeUserApprovalConfig ( cdMaterialsResult . userApprovalConfig )
216
+ const isPolicyConfigured = getIsManualApprovalSpecific ( userApprovalConfig )
217
+ const imageApprovalUsersInfo : ImageApprovalUsersInfoDTO = cdMaterialsResult . imageApprovalUsersInfo || { }
218
+
219
+ const approvalUsersMap = approvalUsers . reduce (
220
+ ( acc , user ) => {
221
+ acc [ user ] = true
222
+ return acc
223
+ } ,
224
+ { } as Record < string , true > ,
225
+ )
226
+
227
+ const specificUsersAPIToken = userApprovalConfig . specificUsers . identifiers
228
+ . filter ( ( user ) => user . startsWith ( API_TOKEN_PREFIX ) )
229
+ . sort ( stringComparatorBySortOrder )
230
+ const specificUsersEmails = userApprovalConfig . specificUsers . identifiers
231
+ . filter ( ( user ) => ! user . startsWith ( API_TOKEN_PREFIX ) && user !== DefaultUserKey . system )
232
+ . sort ( stringComparatorBySortOrder )
233
+
234
+ const specificUsersData : ImageApprovalPolicyType [ 'specificUsersData' ] = {
235
+ dataStore : userApprovalConfig . specificUsers . identifiers . reduce (
236
+ ( acc , email ) => {
237
+ acc [ email ] = {
238
+ email,
239
+ hasAccess : approvalUsersMap [ email ] ?? false ,
240
+ }
241
+ return acc
242
+ } ,
243
+ { } as Record < string , UserGroupApproverType > ,
244
+ ) ,
245
+ requiredCount : userApprovalConfig . specificUsers . requiredCount ,
246
+ emails : specificUsersEmails . concat ( specificUsersAPIToken ) ,
247
+ }
248
+
249
+ const validGroups = userApprovalConfig . userGroups . map ( ( group ) => group . identifier )
250
+
251
+ // Have moved from Object.keys(imageApprovalUsersInfo) to approvalUsers since backend is not filtering out the users without approval
252
+ // TODO: This check should be on BE. Need to remove this once BE is updated
253
+ const usersList = approvalUsers . filter ( ( user ) => user !== DefaultUserKey . system )
254
+ const groupIdentifierToUsersMap = usersList . reduce (
255
+ ( acc , user ) => {
256
+ const userGroups = imageApprovalUsersInfo [ user ] || [ ]
257
+ userGroups . forEach ( ( group ) => {
258
+ if ( ! acc [ group . identifier ] ) {
259
+ acc [ group . identifier ] = { }
260
+ }
261
+ acc [ group . identifier ] [ user ] = true
262
+ } )
263
+ return acc
264
+ } ,
265
+ { } as Record < string , Record < string , true > > ,
266
+ )
267
+
268
+ return {
269
+ isPolicyConfigured,
270
+ specificUsersData,
271
+ userGroupData : userApprovalConfig . userGroups . reduce (
272
+ ( acc , group ) => {
273
+ const identifier = group . identifier
274
+ // No need of handling api tokens here since they are not part of user groups
275
+ const users = Object . keys ( groupIdentifierToUsersMap [ identifier ] || { } ) . sort ( stringComparatorBySortOrder )
276
+
277
+ acc [ identifier ] = {
278
+ dataStore : users . reduce (
279
+ ( acc , user ) => {
280
+ acc [ user ] = {
281
+ email : user ,
282
+ // As of now it will always be true, but UI has handled it in a way that can support false as well
283
+ hasAccess : approvalUsersMap [ user ] ?? false ,
284
+ }
285
+ return acc
286
+ } ,
287
+ { } as Record < string , UserGroupApproverType > ,
288
+ ) ,
289
+ requiredCount : group . requiredCount ,
290
+ emails : users ,
291
+ }
292
+
293
+ return acc
294
+ } ,
295
+ { } as Record < string , ImageApprovalPolicyUserGroupDataType > ,
296
+ ) ,
297
+ // Not sorting since would change them in approval info modal to name
298
+ validGroups,
299
+ }
300
+ }
301
+
178
302
const processCDMaterialsApprovalInfo = ( enableApproval : boolean , cdMaterialsResult ) : CDMaterialsApprovalInfo => {
179
303
if ( ! enableApproval || ! cdMaterialsResult ) {
180
304
return {
181
305
approvalUsers : [ ] ,
182
306
userApprovalConfig : null ,
183
307
canApproverDeploy : cdMaterialsResult ?. canApproverDeploy ?? false ,
308
+ imageApprovalPolicyDetails : null ,
184
309
}
185
310
}
186
311
187
312
return {
188
313
approvalUsers : cdMaterialsResult . approvalUsers ,
189
- userApprovalConfig : cdMaterialsResult . userApprovalConfig ,
314
+ userApprovalConfig : sanitizeUserApprovalConfig ( cdMaterialsResult . userApprovalConfig ) ,
190
315
canApproverDeploy : cdMaterialsResult . canApproverDeploy ?? false ,
316
+ imageApprovalPolicyDetails : getImageApprovalPolicyDetailsFromMaterialResult ( cdMaterialsResult ) ,
191
317
}
192
318
}
193
319
@@ -243,13 +369,14 @@ export const processCDMaterialServiceResponse = (
243
369
}
244
370
}
245
371
246
- const materials = cdMaterialListModal (
247
- cdMaterialsResult . ci_artifacts ,
248
- offset ?? 0 ,
249
- cdMaterialsResult . latest_wf_artifact_id ,
250
- cdMaterialsResult . latest_wf_artifact_status ,
372
+ const materials = cdMaterialListModal ( {
373
+ artifacts : cdMaterialsResult . ci_artifacts ,
374
+ offset : offset ?? 0 ,
375
+ artifactId : cdMaterialsResult . latest_wf_artifact_id ,
376
+ artifactStatus : cdMaterialsResult . latest_wf_artifact_status ,
251
377
disableDefaultSelection,
252
- )
378
+ userApprovalConfig : cdMaterialsResult . userApprovalConfig ,
379
+ } )
253
380
const approvalInfo = processCDMaterialsApprovalInfo (
254
381
stage === DeploymentNodeType . CD || stage === DeploymentNodeType . APPROVAL ,
255
382
cdMaterialsResult ,
0 commit comments