Skip to content

Commit 2862e41

Browse files
tiagoapoloCopilot
andauthored
fix: permissions not revoked after view project disabled (#5438)
Co-authored-by: Copilot <[email protected]>
1 parent c412d10 commit 2862e41

File tree

2 files changed

+160
-60
lines changed

2 files changed

+160
-60
lines changed

frontend/common/utils/utils.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ const Utils = Object.assign({}, require('./base/_utils'), {
109109
)
110110
},
111111

112+
capitalize(str: string) {
113+
if (!str) return ""
114+
return str.charAt(0).toUpperCase() + str.slice(1)
115+
},
116+
112117
changeRequestsEnabled(value: number | null | undefined) {
113118
return typeof value === 'number'
114119
},
@@ -132,7 +137,6 @@ const Utils = Object.assign({}, require('./base/_utils'), {
132137
if (value > 0.002) return 'HIGH' as PConfidence
133138
return 'VERY_HIGH' as PConfidence
134139
},
135-
136140
copyToClipboard: async (
137141
value: string,
138142
successMessage?: string,

frontend/web/components/EditPermissions.tsx

Lines changed: 155 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ import classNames from 'classnames'
6161
import OrganisationProvider from 'common/providers/OrganisationProvider'
6262
import { useHasPermission } from 'common/providers/Permission'
6363
import PlanBasedAccess from './PlanBasedAccess'
64-
import { useGetTagsQuery } from 'common/services/useTag'
6564
import { components } from 'react-select'
6665
import { SingleValueProps } from 'react-select/lib/components/SingleValue'
6766
import AddEditTags from './tags/AddEditTags'
6867
import { RouterChildContext } from 'react-router'
68+
import Utils from 'common/utils/utils'
6969

7070
const Project = require('common/project')
7171

@@ -159,6 +159,46 @@ const withAdminPermissions = (InnerComponent: any) => {
159159
}
160160
return WrappedComponent
161161
}
162+
163+
type RemoveViewPermissionModalProps = {
164+
level: string
165+
onConfirm: () => void
166+
onCancel: () => void
167+
}
168+
169+
const RemoveViewPermissionModal = ({
170+
level,
171+
onCancel,
172+
onConfirm,
173+
}: RemoveViewPermissionModalProps) => {
174+
return (
175+
<div>
176+
<div>
177+
Removing <b>view {level} permission</b> will remove all other user
178+
permissions for this {level}.
179+
</div>
180+
<div className='text-right mt-2'>
181+
<Button
182+
className='mr-2'
183+
onClick={() => {
184+
onCancel()
185+
}}
186+
>
187+
Cancel
188+
</Button>
189+
<Button
190+
theme='danger'
191+
onClick={() => {
192+
onConfirm()
193+
}}
194+
>
195+
Confirm
196+
</Button>
197+
</div>
198+
</div>
199+
)
200+
}
201+
162202
const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
163203
forwardRef((props: EditPermissionModalType) => {
164204
const {
@@ -199,11 +239,6 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
199239
? props.parentId
200240
: undefined
201241

202-
const { data: tags, isLoading: tagsLoading } = useGetTagsQuery(
203-
{ projectId: `${projectId}` },
204-
{ skip: !projectId },
205-
)
206-
207242
const [permissionWasCreated, setPermissionWasCreated] =
208243
useState<boolean>(false)
209244
const [rolesSelected, setRolesSelected] = useState<
@@ -260,29 +295,52 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
260295
}, [groupWithRolesDataSuccesfull])
261296

262297
const processResults = (results: (UserPermission | GroupPermission)[]) => {
298+
const findPermissionByGroup = () => {
299+
return find(
300+
results || [],
301+
(r) => (r as GroupPermission).group.id === group?.id,
302+
)
303+
}
304+
305+
const findPermissionByRole = () => {
306+
return find(
307+
results || [],
308+
(r) => (r as GroupPermission).role === role?.id,
309+
)
310+
}
311+
312+
const findPermissionByUser = () => {
313+
return find(
314+
results || [],
315+
(r) => (r as UserPermission).user?.id === user?.id,
316+
)
317+
}
318+
263319
const foundPermission = isGroup
264-
? find(
265-
results || [],
266-
(r) => (r as GroupPermission).group.id === group?.id,
267-
)
320+
? findPermissionByGroup()
268321
: role
269-
? find(results || [], (r) => (r as GroupPermission).role === role?.id)
270-
: find(
271-
results || [],
272-
(r) => (r as UserPermission).user?.id === user?.id,
273-
)
274-
const permissions =
275-
(role && (level === 'project' || level === 'environment')
276-
? foundPermission?.permissions
277-
: (foundPermission?.permissions || []).map((v) => ({
278-
permission_key: v,
279-
tags: [],
280-
}))) || []
322+
? findPermissionByRole()
323+
: findPermissionByUser()
324+
325+
const isProjectOrEnvironmentRole =
326+
role && (level === 'project' || level === 'environment')
327+
328+
const processPermissions = () => {
329+
if (isProjectOrEnvironmentRole) {
330+
return foundPermission?.permissions || []
331+
}
332+
333+
return (foundPermission?.permissions || []).map((v) => ({
334+
permission_key: v,
335+
tags: [],
336+
}))
337+
}
338+
281339
return {
282340
...(foundPermission || {}),
283341
group: group?.id,
284342
//Since role permissions and other permissions are different in data structure, adjust permissions to match
285-
permissions,
343+
permissions: processPermissions(),
286344
user: user?.id,
287345
} as EntityPermissions
288346
}
@@ -464,7 +522,7 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
464522
})
465523
}
466524
//eslint-disable-next-line
467-
}, [])
525+
}, [])
468526

469527
const admin = () => entityPermissions && entityPermissions.admin
470528

@@ -490,22 +548,32 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
490548
return 'GRANTED'
491549
}
492550

551+
const requiresViewPermission = (permissionKey: string) => {
552+
return (
553+
level !== 'organisation' &&
554+
permissionKey !== `VIEW_${level.toUpperCase()}`
555+
)
556+
}
557+
493558
const save = useCallback(() => {
494-
const entityId =
495-
typeof entityPermissions.id === 'undefined' ? '' : entityPermissions.id
559+
const entityId = entityPermissions.id ?? ''
496560
setValueChanged(false)
497561
if (!role) {
498562
const url = isGroup
499563
? `${level}s/${id}/user-group-permissions/${entityId}`
500564
: `${level}s/${id}/user-permissions/${entityId}`
565+
566+
const permissions = entityPermissions.permissions.map(
567+
(v) => v.permission_key,
568+
)
569+
const payload = {
570+
...entityPermissions,
571+
permissions,
572+
}
573+
501574
setSaving(true)
502575
const action = entityId ? 'put' : 'post'
503-
_data[action](`${Project.api}${url}${entityId && '/'}`, {
504-
...entityPermissions,
505-
permissions: entityPermissions.permissions.map(
506-
(v) => v.permission_key,
507-
),
508-
})
576+
_data[action](`${Project.api}${url}${entityId && '/'}`, payload)
509577
.then(
510578
(
511579
res: Omit<EntityPermissions, 'permissions'> & {
@@ -519,11 +587,7 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
519587
tags: [],
520588
})),
521589
})
522-
toast(
523-
`${
524-
level.charAt(0).toUpperCase() + level.slice(1)
525-
} Permissions Saved`,
526-
)
590+
toast(`${Utils.capitalize(level)} Permissions Saved`)
527591
onSave?.()
528592
},
529593
)
@@ -640,26 +704,31 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
640704
updatedPermissions.splice(index, 1)
641705
}
642706

643-
setEntityPermissions({
707+
return setEntityPermissions({
644708
...entityPermissions,
645709
permissions: updatedPermissions,
646710
})
647-
} else {
648-
const newEntityPermissions = { ...entityPermissions }
711+
}
649712

650-
const index = newEntityPermissions.permissions.findIndex(
651-
(v) => v.permission_key === key,
652-
)
653-
if (index === -1) {
654-
newEntityPermissions.permissions.push({
655-
permission_key: key,
656-
tags: [],
657-
})
658-
} else {
659-
newEntityPermissions.permissions.splice(index, 1)
660-
}
661-
setEntityPermissions(newEntityPermissions)
713+
const newEntityPermissions = { ...entityPermissions }
714+
715+
const index = newEntityPermissions.permissions.findIndex(
716+
(v) => v.permission_key === key,
717+
)
718+
if (index === -1) {
719+
newEntityPermissions.permissions.push({
720+
permission_key: key,
721+
tags: [],
722+
})
723+
} else if (
724+
level !== 'organisation' &&
725+
key === `VIEW_${level.toUpperCase()}`
726+
) {
727+
newEntityPermissions.permissions = []
728+
} else {
729+
newEntityPermissions.permissions.splice(index, 1)
662730
}
731+
setEntityPermissions(newEntityPermissions)
663732
}
664733

665734
const toggleAdmin = () => {
@@ -855,10 +924,11 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
855924
items={permissions}
856925
renderRow={(p) => {
857926
const levelUpperCase = level.toUpperCase()
858-
const disabled =
859-
level !== 'organisation' &&
860-
p.key !== `VIEW_${levelUpperCase}` &&
861-
!hasPermission(`VIEW_${levelUpperCase}`)
927+
const viewPermission = `VIEW_${levelUpperCase}`
928+
const isPermissionDisabled =
929+
requiresViewPermission(p.key) &&
930+
!hasPermission(viewPermission)
931+
862932
const permission = entityPermissions.permissions.find(
863933
(v) => v.permission_key === p.key,
864934
)
@@ -897,7 +967,7 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
897967
selectPermissions(p.key, v.value)
898968
}}
899969
className='react-select select-sm'
900-
disabled={disabled || admin() || saving}
970+
disabled={isPermissionDisabled || admin() || saving}
901971
options={
902972
p.supports_tag
903973
? permissionOptions
@@ -912,11 +982,37 @@ const _EditPermissionsModal: FC<EditPermissionModalType> = withAdminPermissions(
912982
<Switch
913983
data-test={`permission-switch-${p.key}`}
914984
onChange={() => {
985+
if (
986+
level !== 'organisation' &&
987+
p.key === viewPermission &&
988+
hasPermission(viewPermission) &&
989+
entityPermissions.permissions.length > 1
990+
) {
991+
return openModal2(
992+
`Remove View ${Utils.capitalize(
993+
level,
994+
)} Permission`,
995+
<RemoveViewPermissionModal
996+
level={level}
997+
onConfirm={() => {
998+
setValueChanged(true)
999+
togglePermission(p.key)
1000+
closeModal2()
1001+
}}
1002+
onCancel={() => {
1003+
closeModal2()
1004+
}}
1005+
/>,
1006+
)
1007+
}
1008+
9151009
setValueChanged(true)
9161010
togglePermission(p.key)
9171011
}}
918-
disabled={disabled || admin() || saving}
919-
checked={!disabled && hasPermission(p.key)}
1012+
disabled={isPermissionDisabled || admin() || saving}
1013+
checked={
1014+
!isPermissionDisabled && hasPermission(p.key)
1015+
}
9201016
/>
9211017
)}
9221018
</Row>

0 commit comments

Comments
 (0)