Skip to content

Commit cd69c51

Browse files
committed
chore: Update package version to 0.2.6-beta-5
1 parent e4d76c0 commit cd69c51

File tree

5 files changed

+129
-67
lines changed

5 files changed

+129
-67
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "0.2.6-beta-4",
3+
"version": "0.2.6-beta-5",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Common/Common.service.ts

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ import {
3434
EnvironmentListHelmResponse,
3535
UserGroupApproverType,
3636
ImageApprovalPolicyUserGroupDataType,
37-
ManualApprovalType,
38-
UserApprovalConfigType,
37+
ImageApprovalPolicyType,
38+
ImageApprovalUsersInfoDTO,
3939
} from './Types'
4040
import { ApiResourceType } from '../Pages'
41+
import { getIsManualApprovalSpecific, sanitizeUserApprovalConfig, stringComparatorBySortOrder } from '@Shared/Helpers'
42+
import { API_TOKEN_PREFIX } from '@Shared/constants'
43+
import { DefaultUserKey } from '@Shared/types'
4144

4245
export const getTeamListMin = (): Promise<TeamList> => {
4346
// ignore active field
@@ -84,7 +87,13 @@ export function setImageTags(request, pipelineId: number, artifactId: number) {
8487
return post(`${ROUTES.IMAGE_TAGGING}/${pipelineId}/${artifactId}`, request)
8588
}
8689

87-
const cdMaterialListModal = (artifacts: any[], offset: number, artifactId?: number, artifactStatus?: string, disableDefaultSelection?: boolean) => {
90+
const cdMaterialListModal = (
91+
artifacts: any[],
92+
offset: number,
93+
artifactId?: number,
94+
artifactStatus?: string,
95+
disableDefaultSelection?: boolean,
96+
) => {
8897
if (!artifacts || !artifacts.length) return []
8998

9099
const markFirstSelected = offset === 0
@@ -173,29 +182,91 @@ const cdMaterialListModal = (artifacts: any[], offset: number, artifactId?: numb
173182
return materials
174183
}
175184

176-
const SPECIFIC_EMAILS = [
177-
'specific-email-1@devtron.ai',
178-
'specific-email-2@devtron.ai',
179-
'specific-email-3@devtron.ai',
180-
'specific-email-4@devtron.ai',
181-
]
182-
183-
const VALID_GROUPS = [
184-
'managers',
185-
'security',
186-
'devops',
187-
'developers',
188-
]
189-
190-
export const sanitizeUserApprovalConfig = (userApprovalConfig: UserApprovalConfigType): UserApprovalConfigType => ({
191-
requiredCount: userApprovalConfig?.requiredCount ?? 0,
192-
type: userApprovalConfig?.type ?? ManualApprovalType.notConfigured,
193-
specificUsers: {
194-
identifiers: userApprovalConfig?.specificUsers?.identifiers ?? [],
195-
requiredCount: userApprovalConfig?.specificUsers?.identifiers?.length ?? 0,
196-
},
197-
userGroups: userApprovalConfig?.userGroups ?? [],
198-
})
185+
const getImageApprovalPolicyDetailsFromMaterialResult = (cdMaterialsResult): ImageApprovalPolicyType => {
186+
const approvalUsers: string[] = cdMaterialsResult.approvalUsers || []
187+
const userApprovalConfig = sanitizeUserApprovalConfig(cdMaterialsResult.userApprovalConfig)
188+
const isPolicyConfigured = getIsManualApprovalSpecific(userApprovalConfig)
189+
const imageApprovalUsersInfo: ImageApprovalUsersInfoDTO = cdMaterialsResult.imageApprovalUsersInfo || {}
190+
191+
const approvalUsersMap = approvalUsers.reduce(
192+
(acc, user) => {
193+
acc[user] = true
194+
return acc
195+
},
196+
{} as Record<string, true>,
197+
)
198+
199+
const specificUsersAPIToken = userApprovalConfig.specificUsers.identifiers
200+
.filter((user) => user.startsWith(API_TOKEN_PREFIX))
201+
.sort(stringComparatorBySortOrder)
202+
const specificUsersEmails = userApprovalConfig.specificUsers.identifiers
203+
.filter((user) => !user.startsWith(API_TOKEN_PREFIX) && user !== DefaultUserKey.system)
204+
.sort(stringComparatorBySortOrder)
205+
206+
const specificUsersData: ImageApprovalPolicyType['specificUsersData'] = {
207+
dataStore: userApprovalConfig.specificUsers.identifiers.reduce(
208+
(acc, email) => {
209+
acc[email] = {
210+
email,
211+
hasAccess: approvalUsersMap[email] ?? false,
212+
}
213+
return acc
214+
},
215+
{} as Record<string, UserGroupApproverType>,
216+
),
217+
requiredCount: userApprovalConfig.specificUsers.requiredCount,
218+
emails: specificUsersEmails.concat(specificUsersAPIToken),
219+
}
220+
221+
const validGroups = userApprovalConfig.userGroups.map((group) => group.identifier)
222+
223+
const usersList = Object.keys(imageApprovalUsersInfo).filter((user) => user !== DefaultUserKey.system)
224+
const userToGroupMap = usersList.reduce(
225+
(acc, user) => {
226+
const userGroups = imageApprovalUsersInfo[user] || []
227+
userGroups.forEach((group) => {
228+
if (!acc[group.identifier]) {
229+
acc[group.identifier] = {}
230+
}
231+
acc[group.identifier][user] = true
232+
})
233+
return acc
234+
},
235+
{} as Record<string, Record<string, true>>,
236+
)
237+
238+
return {
239+
isPolicyConfigured,
240+
specificUsersData,
241+
userGroupData: userApprovalConfig.userGroups.reduce(
242+
(acc, group) => {
243+
const identifier = group.identifier
244+
// No need of handling api tokens here since they are not part of user groups
245+
const users = Object.keys(userToGroupMap[identifier] || {}).sort(stringComparatorBySortOrder)
246+
247+
acc[identifier] = {
248+
dataStore: users.reduce(
249+
(acc, user) => {
250+
acc[user] = {
251+
email: user,
252+
hasAccess: approvalUsersMap[user] ?? false,
253+
}
254+
return acc
255+
},
256+
{} as Record<string, UserGroupApproverType>,
257+
),
258+
requiredCount: group.requiredCount,
259+
emails: users,
260+
}
261+
262+
return acc
263+
},
264+
{} as Record<string, ImageApprovalPolicyUserGroupDataType>,
265+
),
266+
// Not sorting since would change them in approval info modal to name
267+
validGroups,
268+
}
269+
}
199270

200271
const processCDMaterialsApprovalInfo = (enableApproval: boolean, cdMaterialsResult): CDMaterialsApprovalInfo => {
201272
if (!enableApproval || !cdMaterialsResult) {
@@ -211,41 +282,7 @@ const processCDMaterialsApprovalInfo = (enableApproval: boolean, cdMaterialsResu
211282
approvalUsers: cdMaterialsResult.approvalUsers,
212283
userApprovalConfig: sanitizeUserApprovalConfig(cdMaterialsResult.userApprovalConfig),
213284
canApproverDeploy: cdMaterialsResult.canApproverDeploy ?? false,
214-
imageApprovalPolicyDetails: {
215-
isPolicyConfigured: true,
216-
specificUsersData: {
217-
dataStore: SPECIFIC_EMAILS.reduce((acc, email, index) => {
218-
acc[email] = {
219-
email,
220-
hasAccess: index % 2 === 0,
221-
}
222-
return acc
223-
}, {} as Record<string, UserGroupApproverType>),
224-
requiredCount: SPECIFIC_EMAILS.length,
225-
// TODO: Sort these arrays
226-
emails: SPECIFIC_EMAILS,
227-
},
228-
userGroupData: VALID_GROUPS.reduce((acc, userGroup) => {
229-
// TODO: Sort these arrays
230-
const emails = [`${userGroup}-1@devtron.ai`, `${userGroup}-2@devtron.ai`, `${userGroup}-3@devtron.ai`]
231-
232-
acc[userGroup] = {
233-
dataStore: emails.reduce((acc, email, index) => {
234-
acc[email] = {
235-
email,
236-
hasAccess: index % 2 === 0,
237-
}
238-
return acc
239-
}, {} as Record<string, UserGroupApproverType>),
240-
requiredCount: emails.length,
241-
emails,
242-
}
243-
return acc
244-
}, {} as Record<string, ImageApprovalPolicyUserGroupDataType>),
245-
// TODO: getUserGroupList
246-
// TODO: Sort these arrays
247-
validGroups: VALID_GROUPS,
248-
}
285+
imageApprovalPolicyDetails: getImageApprovalPolicyDetailsFromMaterialResult(cdMaterialsResult),
249286
}
250287
}
251288

@@ -430,8 +467,8 @@ export const getResourceGroupListRaw = (clusterId: string): Promise<ResponseType
430467
}
431468

432469
export function getNamespaceListMin(clusterIdsCsv: string): Promise<EnvironmentListHelmResponse> {
433-
const URL = `${ROUTES.NAMESPACE}/autocomplete?ids=${clusterIdsCsv}`
434-
return get(URL)
470+
const URL = `${ROUTES.NAMESPACE}/autocomplete?ids=${clusterIdsCsv}`
471+
return get(URL)
435472
}
436473
export function getWebhookEventsForEventId(eventId: string | number) {
437474
const URL = `${ROUTES.GIT_HOST_EVENT}/${eventId}`

src/Common/Types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,16 @@ export interface ImageApprovalPolicyUserGroupDataType {
338338
emails: string[]
339339
}
340340

341-
interface ImageApprovalPolicyType {
341+
export interface ImageApprovalPolicyType {
342342
isPolicyConfigured: boolean
343343
specificUsersData: ImageApprovalPolicyUserGroupDataType
344344
userGroupData: Record<string, ImageApprovalPolicyUserGroupDataType>
345345
// Assuming name of groups are unique
346346
validGroups: string[]
347347
}
348+
349+
export type ImageApprovalUsersInfoDTO = Record<string, Pick<UserGroupDTO, 'identifier' | 'name'>[]>
350+
348351
// TODO: Need to verify this change for all impacting areas
349352
export interface UserApprovalConfigType {
350353
type: ManualApprovalType

src/Shared/Helpers.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ import Tippy from '@tippyjs/react'
2020
import moment from 'moment'
2121
import {
2222
handleUTCTime,
23+
ManualApprovalType,
2324
mapByKey,
2425
MaterialInfo,
2526
PATTERNS,
2627
shallowEqual,
2728
SortingOrder,
29+
UserApprovalConfigType,
2830
ZERO_TIME_STRING,
2931
} from '../Common'
3032
import {
@@ -760,3 +762,23 @@ export const getFileNameFromHeaders = (headers: Headers) =>
760762
?.find((n) => n.includes('filename='))
761763
?.replace('filename=', '')
762764
.trim()
765+
766+
export const sanitizeUserApprovalConfig = (userApprovalConfig: UserApprovalConfigType): UserApprovalConfigType => ({
767+
requiredCount: userApprovalConfig?.requiredCount ?? 0,
768+
type: userApprovalConfig?.type ?? ManualApprovalType.notConfigured,
769+
specificUsers: {
770+
identifiers: userApprovalConfig?.specificUsers?.identifiers ?? [],
771+
requiredCount: userApprovalConfig?.specificUsers?.identifiers?.length ?? 0,
772+
},
773+
userGroups: userApprovalConfig?.userGroups ?? [],
774+
})
775+
776+
/**
777+
* Manual approval is considered configured only if the type is not notConfigured
778+
*/
779+
export const getIsManualApprovalConfigured = (userApprovalConfig?: Pick<UserApprovalConfigType, 'type'>) =>
780+
// Added null check for backward compatibility
781+
!!userApprovalConfig?.type && userApprovalConfig.type !== ManualApprovalType.notConfigured
782+
783+
export const getIsManualApprovalSpecific = (userApprovalConfig?: Pick<UserApprovalConfigType, 'type'>) =>
784+
getIsManualApprovalConfigured(userApprovalConfig) && userApprovalConfig.type === ManualApprovalType.specific

0 commit comments

Comments
 (0)