Skip to content

Commit d0ad573

Browse files
authored
Collection upload/deprecate - fix permission checks (#4015)
* Collection upload/deprecate - fix permission checks Issue: AAH-2439 Issue: AAH-2853 * CollectionHeader - move actions & permissions to CollectionDropdown * Search,NamespaceDetail - use CollectionDropdown * namespace detail respect namespace permissions * fix delete collectio/ns disabled message, use description * inline tryOpenDeleteModalWithConfirm * deleteFn in all 3 dropdowns * linter fix * namespace detail - use object permissions for upload,delete,edit * tests - constistent kebab-toggle click * cy.openHeaderKebab - and scroll to top first * Ratings: don't load scores outside community mode No-Issue * collection-kebab - switch to data-cy * scrollTo fix * aargh, is it a timing bug? * upload new version is no longer available without permissions * openHeaderKebab: add comment about the wait
1 parent 0d45b81 commit d0ad573

20 files changed

+427
-451
lines changed

CHANGES/2439.bug

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Collection upload/deprecate - fix permission checks

CHANGES/2853.bug

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Collection upload/deprecate - fix permission checks
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import { t } from '@lingui/macro';
2+
import { DropdownItem } from '@patternfly/react-core';
3+
import React from 'react';
4+
import { StatefulDropdown } from 'src/components';
5+
import { useContext } from 'src/loaders/app-context';
6+
import { DeleteCollectionUtils } from 'src/utilities';
7+
8+
interface IProps {
9+
collection;
10+
'data-cy'?: string;
11+
deletionBlocked?: boolean;
12+
namespace?;
13+
onCopyVersion?;
14+
onDelete?;
15+
onDeleteVersion?;
16+
onDeprecate?;
17+
onRemove?;
18+
onRemoveVersion?;
19+
onSign?;
20+
onSignVersion?;
21+
onUploadVersion?;
22+
version?: string;
23+
wrapper?;
24+
}
25+
26+
export const CollectionDropdown = ({
27+
collection,
28+
'data-cy': dataCy,
29+
deletionBlocked,
30+
namespace,
31+
onCopyVersion,
32+
onDelete,
33+
onDeleteVersion,
34+
onDeprecate,
35+
onRemove,
36+
onRemoveVersion,
37+
onSign,
38+
onSignVersion,
39+
onUploadVersion,
40+
version,
41+
wrapper,
42+
}: IProps) => {
43+
const {
44+
featureFlags: {
45+
can_create_signatures,
46+
can_upload_signatures,
47+
display_repositories,
48+
},
49+
hasPermission,
50+
user: { is_anonymous, is_superuser },
51+
} = useContext();
52+
53+
const hasObjectPermission = (permission) =>
54+
namespace?.related_fields?.my_permissions?.includes?.(permission);
55+
56+
const hasPerm = (permission) =>
57+
hasPermission(permission) ||
58+
hasObjectPermission(permission) ||
59+
is_superuser;
60+
61+
const canCopy = display_repositories && !is_anonymous;
62+
const canDelete =
63+
hasPerm('ansible.delete_collection') || hasPerm('galaxy.change_namespace');
64+
const canDeprecate = hasPerm('galaxy.change_namespace');
65+
const canRemove = canDelete && display_repositories;
66+
const canSign =
67+
can_create_signatures &&
68+
!can_upload_signatures &&
69+
hasPerm('galaxy.change_namespace') &&
70+
hasPerm('galaxy.upload_to_namespace');
71+
const canUpload = hasPerm('galaxy.upload_to_namespace');
72+
73+
const Wrapper =
74+
wrapper || (({ any, children }) => (any ? <>{children}</> : null));
75+
76+
const DeleteWrapper = ({
77+
addAlert,
78+
caption,
79+
collection,
80+
'data-cy': dataCy,
81+
openModal,
82+
skipCheck,
83+
}: {
84+
addAlert?;
85+
caption: string;
86+
collection?;
87+
'data-cy'?: string;
88+
openModal;
89+
skipCheck?;
90+
}) =>
91+
deletionBlocked ? (
92+
<DropdownItem
93+
isDisabled
94+
description={t`Cannot delete until collections that depend on this collection have been deleted.`}
95+
>
96+
{caption}
97+
</DropdownItem>
98+
) : (
99+
<DropdownItem
100+
data-cy={dataCy}
101+
onClick={() =>
102+
skipCheck
103+
? openModal()
104+
: DeleteCollectionUtils.countUsedbyDependencies(collection)
105+
.then((count) => {
106+
if (count) {
107+
addAlert({
108+
title: t`Cannot delete until collections that depend on this collection have been deleted.`,
109+
variant: 'warning',
110+
});
111+
return;
112+
}
113+
114+
openModal();
115+
})
116+
.catch(addAlert)
117+
}
118+
>
119+
{caption}
120+
</DropdownItem>
121+
);
122+
123+
const dropdownItems = [
124+
canDelete && onDelete && (
125+
<DeleteWrapper
126+
caption={t`Delete collection from system`}
127+
data-cy='delete-collection'
128+
key='delete-collection'
129+
{...onDelete}
130+
/>
131+
),
132+
canRemove && onRemove && (
133+
<DeleteWrapper
134+
caption={t`Remove collection from repository`}
135+
key='remove-collection'
136+
{...onRemove}
137+
/>
138+
),
139+
canDelete && onDeleteVersion && (
140+
<DropdownItem
141+
data-cy='delete-collection-version'
142+
key='delete-collection-version'
143+
onClick={onDeleteVersion}
144+
>
145+
{t`Delete version ${version} from system`}
146+
</DropdownItem>
147+
),
148+
canRemove && onRemoveVersion && (
149+
<DropdownItem key='remove-collection-version' onClick={onRemoveVersion}>
150+
{t`Remove version ${version} from repository`}
151+
</DropdownItem>
152+
),
153+
canSign && onSign && (
154+
<DropdownItem key='sign-collection' onClick={onSign}>
155+
{t`Sign collection`}
156+
</DropdownItem>
157+
),
158+
canSign && onSignVersion && (
159+
<DropdownItem key='sign-collection-version' onClick={onSignVersion}>
160+
{t`Sign version ${version}`}
161+
</DropdownItem>
162+
),
163+
canDeprecate && onDeprecate && (
164+
<DropdownItem onClick={onDeprecate} key='deprecate-collection'>
165+
{collection.is_deprecated ? t`Undeprecate` : t`Deprecate`}
166+
</DropdownItem>
167+
),
168+
canUpload && onUploadVersion && (
169+
<DropdownItem key='upload-collection-version' onClick={onUploadVersion}>
170+
{t`Upload new version`}
171+
</DropdownItem>
172+
),
173+
canCopy && onCopyVersion && (
174+
<DropdownItem
175+
key='copy-collection-version-to-repository-dropdown'
176+
onClick={onCopyVersion}
177+
data-cy='copy-collection-version-to-repository-dropdown'
178+
>
179+
{t`Copy version ${version} to repositories`}
180+
</DropdownItem>
181+
),
182+
].filter(Boolean);
183+
184+
return (
185+
<Wrapper any={dropdownItems.length}>
186+
<StatefulDropdown data-cy={dataCy} items={dropdownItems} />
187+
</Wrapper>
188+
);
189+
};

0 commit comments

Comments
 (0)