Skip to content

Commit 943300d

Browse files
[9.0] [Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces (elastic#214487) (elastic#215194)
# Backport This will backport the following commits from `main` to `9.0`: - [[Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces (elastic#214487)](elastic#214487) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Paul Tavares","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-03-19T15:12:59Z","message":"[Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces (elastic#214487)\n\n## Summary\n\n\n### Fleet\n\n- Exposed API route for bulk get package policies via the routes service\n- Created and exposed type `BulkGetPackagePoliciesRequestBody`\n\n<br/>\n\n\n### Security Solution\n\nThe following changes were made to Endpoint Artifacts in support of\nspaces:\n\n> [!NOTE]\n> Space awareness is currently behind feature flag:\n`endpointManagementSpaceAwarenessEnabled`\n\n\n- The policy assignment component, which is displayed on artifact's\nCreate and Update forms, now:\n- Displays the count of policies (if any) that are associated with the\nartifact, but not currently accessible in the active space (screen\ncapture 1️⃣ )\n- When a user does NOT have the Global Artifact privilege, the `Global`\ntoggle selection will be disabled and a tooltip is displayed. This\nchange also applies to the create form where the default selection will\nbe per-policy and the global button will be disabled. (screen capture\n2️⃣ )\n- Artifact policy assignments that are not accessible in active space\nare preserved when submitting an update to the artifact\n- The component was also refactored a bit to simplify its list of props\n- Artifact card policy assignment menu was adjusted to show any policy\nthat is not accessible to the user as \"disabled\" along with a tooltip\n(screen capture 3️⃣ )\n- The update artifact API was changed (via server-side extension point)\nto not error when validating policies that are not accessible in active\nspace if they were already associated with the item being updated.\n- Fixes a bug in the Find artifacts API (impact only when spaces was\nenabled) where an invalid filter was created when there was no policies\ncurrently shared with active space.","sha":"e11c3ecea5119202800d121a73765e26a41ff0a1","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","Team:Defend Workflows","backport:prev-minor","v9.1.0"],"title":"[Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces","number":214487,"url":"https://github.com/elastic/kibana/pull/214487","mergeCommit":{"message":"[Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces (elastic#214487)\n\n## Summary\n\n\n### Fleet\n\n- Exposed API route for bulk get package policies via the routes service\n- Created and exposed type `BulkGetPackagePoliciesRequestBody`\n\n<br/>\n\n\n### Security Solution\n\nThe following changes were made to Endpoint Artifacts in support of\nspaces:\n\n> [!NOTE]\n> Space awareness is currently behind feature flag:\n`endpointManagementSpaceAwarenessEnabled`\n\n\n- The policy assignment component, which is displayed on artifact's\nCreate and Update forms, now:\n- Displays the count of policies (if any) that are associated with the\nartifact, but not currently accessible in the active space (screen\ncapture 1️⃣ )\n- When a user does NOT have the Global Artifact privilege, the `Global`\ntoggle selection will be disabled and a tooltip is displayed. This\nchange also applies to the create form where the default selection will\nbe per-policy and the global button will be disabled. (screen capture\n2️⃣ )\n- Artifact policy assignments that are not accessible in active space\nare preserved when submitting an update to the artifact\n- The component was also refactored a bit to simplify its list of props\n- Artifact card policy assignment menu was adjusted to show any policy\nthat is not accessible to the user as \"disabled\" along with a tooltip\n(screen capture 3️⃣ )\n- The update artifact API was changed (via server-side extension point)\nto not error when validating policies that are not accessible in active\nspace if they were already associated with the item being updated.\n- Fixes a bug in the Find artifacts API (impact only when spaces was\nenabled) where an invalid filter was created when there was no policies\ncurrently shared with active space.","sha":"e11c3ecea5119202800d121a73765e26a41ff0a1"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214487","number":214487,"mergeCommit":{"message":"[Security Solution][Endpoint] Adjust Artifacts policy assignment component in support of spaces (elastic#214487)\n\n## Summary\n\n\n### Fleet\n\n- Exposed API route for bulk get package policies via the routes service\n- Created and exposed type `BulkGetPackagePoliciesRequestBody`\n\n<br/>\n\n\n### Security Solution\n\nThe following changes were made to Endpoint Artifacts in support of\nspaces:\n\n> [!NOTE]\n> Space awareness is currently behind feature flag:\n`endpointManagementSpaceAwarenessEnabled`\n\n\n- The policy assignment component, which is displayed on artifact's\nCreate and Update forms, now:\n- Displays the count of policies (if any) that are associated with the\nartifact, but not currently accessible in the active space (screen\ncapture 1️⃣ )\n- When a user does NOT have the Global Artifact privilege, the `Global`\ntoggle selection will be disabled and a tooltip is displayed. This\nchange also applies to the create form where the default selection will\nbe per-policy and the global button will be disabled. (screen capture\n2️⃣ )\n- Artifact policy assignments that are not accessible in active space\nare preserved when submitting an update to the artifact\n- The component was also refactored a bit to simplify its list of props\n- Artifact card policy assignment menu was adjusted to show any policy\nthat is not accessible to the user as \"disabled\" along with a tooltip\n(screen capture 3️⃣ )\n- The update artifact API was changed (via server-side extension point)\nto not error when validating policies that are not accessible in active\nspace if they were already associated with the item being updated.\n- Fixes a bug in the Find artifacts API (impact only when spaces was\nenabled) where an invalid filter was created when there was no policies\ncurrently shared with active space.","sha":"e11c3ecea5119202800d121a73765e26a41ff0a1"}}]}] BACKPORT--> Co-authored-by: Paul Tavares <[email protected]>
1 parent 0d226d3 commit 943300d

File tree

37 files changed

+926
-386
lines changed

37 files changed

+926
-386
lines changed

x-pack/platform/plugins/shared/fleet/common/services/routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ export const packagePolicyRouteService = {
155155
getOrphanedIntegrationPoliciesPath: () => {
156156
return PACKAGE_POLICY_API_ROUTES.ORPHANED_INTEGRATION_POLICIES;
157157
},
158+
159+
getBulkGetPath: (): string => {
160+
return PACKAGE_POLICY_API_ROUTES.BULK_GET_PATTERN;
161+
},
158162
};
159163

160164
export const agentPolicyRouteService = {

x-pack/platform/plugins/shared/fleet/common/types/rest_spec/package_policy.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
* 2.0.
66
*/
77

8+
import type { TypeOf } from '@kbn/config-schema';
9+
10+
import type { BulkGetPackagePoliciesRequestSchema } from '../../../server/types';
11+
812
import type {
913
PackagePolicy,
1014
NewPackagePolicy,
@@ -21,6 +25,9 @@ export interface GetPackagePoliciesRequest {
2125
}
2226

2327
export type GetPackagePoliciesResponse = ListResult<PackagePolicy>;
28+
export type BulkGetPackagePoliciesRequestBody = TypeOf<
29+
typeof BulkGetPackagePoliciesRequestSchema.body
30+
>;
2431
export type BulkGetPackagePoliciesResponse = BulkGetResult<PackagePolicy>;
2532

2633
export interface GetOnePackagePolicyRequest {

x-pack/solutions/security/plugins/security_solution/common/endpoint/service/artifacts/utils.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ export const isArtifactGlobal = (item: Partial<Pick<ExceptionListItemSchema, 'ta
2727
return (item.tags ?? []).includes(GLOBAL_ARTIFACT_TAG);
2828
};
2929

30-
export const isArtifactByPolicy = (item: Pick<ExceptionListItemSchema, 'tags'>): boolean => {
30+
export const isArtifactByPolicy = (
31+
item: Partial<Pick<ExceptionListItemSchema, 'tags'>>
32+
): boolean => {
3133
return !isArtifactGlobal(item);
3234
};
3335

34-
export const getPolicyIdsFromArtifact = (item: Pick<ExceptionListItemSchema, 'tags'>): string[] => {
36+
export const getPolicyIdsFromArtifact = (
37+
item: Partial<Pick<ExceptionListItemSchema, 'tags'>>
38+
): string[] => {
3539
const policyIds = [];
3640
const tags = item.tags ?? [];
3741

x-pack/solutions/security/plugins/security_solution/public/management/common/translations.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,3 +320,15 @@ export const CONFIRM_WARNING_MODAL_LABELS = (entryType: string) => {
320320
),
321321
};
322322
};
323+
324+
export const NO_PRIVILEGE_FOR_MANAGEMENT_OF_GLOBAL_ARTIFACT_MESSAGE = i18n.translate(
325+
'xpack.securitySolution.translations.noGlobalArtifactManagementAllowedMessage',
326+
{ defaultMessage: 'Management of global artifacts requires additional privilege' }
327+
);
328+
329+
export const ARTIFACT_POLICIES_NOT_ACCESSIBLE_IN_ACTIVE_SPACE_MESSAGE = (count: number): string =>
330+
i18n.translate('xpack.securitySolution.translations.artifactPoliciesNotAccessibleInActiveSpace', {
331+
defaultMessage:
332+
'This artifact is associated with {count} {count, plural, =1 {policy that is} other {policies that are}} not accessible in active space',
333+
values: { count },
334+
});

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,9 @@ describe.each([
203203

204204
policies = {
205205
'policy-1': {
206-
children: 'Policy one',
206+
children: 'Policy one title',
207207
'data-test-subj': 'policyMenuItem',
208+
href: 'http://some/path/to/policy-1',
208209
},
209210
};
210211
});
@@ -239,7 +240,11 @@ describe.each([
239240
).not.toBeNull();
240241

241242
expect(renderResult.getByTestId('policyMenuItem').textContent).toEqual(
242-
'Policy oneView details'
243+
'Policy one titleView details'
244+
);
245+
246+
expect((renderResult.getByTestId('policyMenuItem') as HTMLAnchorElement).href).toEqual(
247+
policies!['policy-1'].href
243248
);
244249
});
245250

@@ -259,12 +264,12 @@ describe.each([
259264
renderResult.getByTestId('testCard-subHeader-effectScope-popupMenu-popoverPanel')
260265
).not.toBeNull();
261266

262-
expect(renderResult.getByTestId('policyMenuItem').textContent).toEqual('Policy one');
267+
expect(renderResult.getByTestId('policyMenuItem').textContent).toEqual('Policy one title');
263268
});
264269
});
265270

266-
it('should display policy ID if no policy menu item found in `policies` prop', async () => {
267-
render();
271+
it('should display disabled button with policy ID if no policy menu item found in `policies` prop', async () => {
272+
render(); // Important: no polices provided to component on input
268273
await act(async () => {
269274
await fireEvent.click(
270275
renderResult.getByTestId('testCard-subHeader-effectScope-popupMenu-button')
@@ -275,7 +280,18 @@ describe.each([
275280
renderResult.getByTestId('testCard-subHeader-effectScope-popupMenu-popoverPanel')
276281
).not.toBeNull();
277282

278-
expect(renderResult.getByText('policy-1').textContent).not.toBeNull();
283+
expect(
284+
renderResult.getByTestId('testCard-subHeader-effectScope-popupMenu-item-0-truncateWrapper')
285+
.textContent
286+
).toEqual('policy-1');
287+
288+
expect(
289+
(
290+
renderResult.getByTestId(
291+
'testCard-subHeader-effectScope-popupMenu-item-0'
292+
) as HTMLButtonElement
293+
).disabled
294+
).toBe(true);
279295
});
280296

281297
it('should pass item to decorator function and display its result', () => {

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_entry_card/components/card_actions_flex_item.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ import React, { memo, useMemo } from 'react';
1010
import type { CommonProps } from '@elastic/eui';
1111
import { EuiFlexItem } from '@elastic/eui';
1212
import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
13+
import { NO_PRIVILEGE_FOR_MANAGEMENT_OF_GLOBAL_ARTIFACT_MESSAGE } from '../../../common/translations';
1314
import { useUserPrivileges } from '../../../../common/components/user_privileges';
14-
import {
15-
MANAGEMENT_OF_GLOBAL_ARTIFACT_NOT_ALLOWED_MESSAGE,
16-
MANAGEMENT_OF_SHARED_PER_POLICY_ARTIFACT_NOT_ALLOWED_MESSAGE,
17-
} from './translations';
15+
import { MANAGEMENT_OF_SHARED_PER_POLICY_ARTIFACT_NOT_ALLOWED_MESSAGE } from './translations';
1816
import { useSpaceId } from '../../../../common/hooks/use_space_id';
1917
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
2018
import { isArtifactGlobal } from '../../../../../common/endpoint/service/artifacts';
@@ -52,7 +50,7 @@ export const CardActionsFlexItem = memo<CardActionsFlexItemProps>(
5250
if (isGlobal) {
5351
return {
5452
isDisabled: true,
55-
disabledTooltip: MANAGEMENT_OF_GLOBAL_ARTIFACT_NOT_ALLOWED_MESSAGE,
53+
disabledTooltip: NO_PRIVILEGE_FOR_MANAGEMENT_OF_GLOBAL_ARTIFACT_MESSAGE,
5654
};
5755
}
5856

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_entry_card/components/effect_scope.tsx

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import type { CommonProps } from '@elastic/eui';
1111
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
1212
import styled from 'styled-components';
1313
import { FormattedMessage } from '@kbn/i18n-react';
14+
import { i18n } from '@kbn/i18n';
15+
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
1416
import { useUserPrivileges } from '../../../../common/components/user_privileges';
1517
import {
1618
GLOBAL_EFFECT_SCOPE,
@@ -28,6 +30,16 @@ import { useTestIdGenerator } from '../../../hooks/use_test_id_generator';
2830
// So something like: `<EffectScope perPolicyCount={3} />`
2931
// This should display it as "Applied to 3 policies", but NOT as a menu with links
3032

33+
const POLICY_DETAILS_NOT_ACCESSIBLE = i18n.translate(
34+
'xpack.securitySolution.effectScope.policyDetailsNotAccessible',
35+
{ defaultMessage: 'Policy is no longer accessible' }
36+
);
37+
38+
const POLICY_DETAILS_NOT_ACCESSIBLE_IN_ACTIVE_SPACE = i18n.translate(
39+
'xpack.securitySolution.effectScope.policyDetailsNotAccessibleInActiveSpace',
40+
{ defaultMessage: 'Policy is not accessible from the current space' }
41+
);
42+
3143
const StyledWithContextMenuShiftedWrapper = styled('div')`
3244
margin-left: -10px;
3345
`;
@@ -104,29 +116,46 @@ const WithContextMenu = memo<WithContextMenuProps>(
104116
'data-test-subj': dataTestSubj,
105117
}) => {
106118
const getTestId = useTestIdGenerator(dataTestSubj);
107-
108-
const hoverInfo = useMemo(
109-
() =>
110-
canReadPolicies ? (
111-
<StyledEuiButtonEmpty flush="right" size="s" iconSide="right" iconType="popout">
112-
<FormattedMessage
113-
id="xpack.securitySolution.contextMenuItemByRouter.viewDetails"
114-
defaultMessage="View details"
115-
/>
116-
</StyledEuiButtonEmpty>
117-
) : undefined,
118-
[canReadPolicies]
119+
const isSpacesEnabled = useIsExperimentalFeatureEnabled(
120+
'endpointManagementSpaceAwarenessEnabled'
119121
);
122+
123+
const menuItems: ContextMenuItemNavByRouterProps[] = useMemo(() => {
124+
return policies.map((policyMenuItem) => {
125+
const hasHref = Boolean(policyMenuItem.href);
126+
127+
return {
128+
...policyMenuItem,
129+
hoverInfo:
130+
hasHref && canReadPolicies ? (
131+
<StyledEuiButtonEmpty flush="right" size="s" iconSide="right" iconType="popout">
132+
<FormattedMessage
133+
id="xpack.securitySolution.contextMenuItemByRouter.viewDetails"
134+
defaultMessage="View details"
135+
/>
136+
</StyledEuiButtonEmpty>
137+
) : undefined,
138+
disabled: !hasHref,
139+
toolTipContent: !hasHref ? (
140+
<>
141+
{isSpacesEnabled
142+
? POLICY_DETAILS_NOT_ACCESSIBLE_IN_ACTIVE_SPACE
143+
: POLICY_DETAILS_NOT_ACCESSIBLE}
144+
</>
145+
) : undefined,
146+
};
147+
});
148+
}, [canReadPolicies, isSpacesEnabled, policies]);
149+
120150
return (
121151
<ContextMenuWithRouterSupport
122152
maxHeight="235px"
123153
fixedWidth={true}
124154
panelPaddingSize="none"
125-
items={policies}
155+
items={menuItems}
126156
anchorPosition={policies.length > 1 ? 'rightCenter' : 'rightUp'}
127157
data-test-subj={dataTestSubj}
128158
loading={loadingPoliciesList}
129-
hoverInfo={hoverInfo}
130159
button={
131160
<EuiButtonEmpty size="xs" data-test-subj={getTestId('button')}>
132161
{children}

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_entry_card/components/translations.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,6 @@ export const DESCRIPTION_LABEL = i18n.translate(
163163
}
164164
);
165165

166-
export const MANAGEMENT_OF_GLOBAL_ARTIFACT_NOT_ALLOWED_MESSAGE = i18n.translate(
167-
'xpack.securitySolution.translations.noGlobalArtifactManagementAllowedMessage',
168-
{ defaultMessage: 'Management of global artifacts requires additional privilege' }
169-
);
170-
171166
export const MANAGEMENT_OF_SHARED_PER_POLICY_ARTIFACT_NOT_ALLOWED_MESSAGE = i18n.translate(
172167
'xpack.securitySolution.translations.sharedPerPolicyArtifactNotAllowed',
173168
{

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.test.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,19 @@ describe('When the flyout is opened in the ArtifactListPage component', () => {
3636
let getLastFormComponentProps: ReturnType<
3737
typeof getFormComponentMock
3838
>['getLastFormComponentProps'];
39+
let setExperimentalFlag: AppContextTestRender['setExperimentalFlag'];
3940

4041
beforeEach(() => {
4142
const renderSetup = getArtifactListPageRenderingSetup();
4243

43-
({ history, coreStart, mockedApi, FormComponentMock, getLastFormComponentProps } = renderSetup);
44+
({
45+
history,
46+
coreStart,
47+
mockedApi,
48+
FormComponentMock,
49+
getLastFormComponentProps,
50+
setExperimentalFlag,
51+
} = renderSetup);
4452

4553
history.push('somepage?show=create');
4654

@@ -116,6 +124,36 @@ describe('When the flyout is opened in the ArtifactListPage component', () => {
116124
);
117125
});
118126

127+
it('should initialize form with a per-policy artifact when user does not have global artifact privilege and spaces is enabeld', async () => {
128+
setExperimentalFlag({ endpointManagementSpaceAwarenessEnabled: true });
129+
useUserPrivileges.mockReturnValue({
130+
...useUserPrivileges(),
131+
endpointPrivileges: getEndpointPrivilegesInitialStateMock({
132+
canManageGlobalArtifacts: false,
133+
}),
134+
});
135+
await render();
136+
137+
expect(FormComponentMock).toHaveBeenLastCalledWith(
138+
expect.objectContaining({
139+
item: {
140+
comments: [],
141+
description: '',
142+
entries: [],
143+
item_id: undefined,
144+
list_id: 'endpoint_trusted_apps',
145+
meta: expect.any(Object),
146+
name: '',
147+
namespace_type: 'agnostic',
148+
os_types: ['windows'],
149+
tags: [],
150+
type: 'simple',
151+
},
152+
}),
153+
expect.anything()
154+
);
155+
});
156+
119157
describe('and form data is valid', () => {
120158
beforeEach(async () => {
121159
const _renderAndWaitForFlyout = render;

x-pack/solutions/security/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_flyout.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import type { EuiFlyoutSize } from '@elastic/eui/src/components/flyout/flyout';
2727
import type { IHttpFetchError } from '@kbn/core-http-browser';
2828
import { useIsMounted } from '@kbn/securitysolution-hook-utils';
2929
import { useLocation } from 'react-router-dom';
30+
import { GLOBAL_ARTIFACT_TAG } from '../../../../../common/endpoint/service/artifacts';
31+
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
3032
import { useMarkInsightAsRemediated } from '../hooks/use_mark_workflow_insight_as_remediated';
3133
import type { WorkflowInsightRouteState } from '../../../pages/endpoint_hosts/types';
3234
import { useUrlParams } from '../../../hooks/use_url_params';
@@ -47,6 +49,7 @@ import { useIsArtifactAllowedPerPolicyUsage } from '../hooks/use_is_artifact_all
4749
import { useGetArtifact } from '../../../hooks/artifacts';
4850
import type { PolicyData } from '../../../../../common/endpoint/types';
4951
import { ArtifactConfirmModal } from './artifact_confirm_modal';
52+
import { useUserPrivileges } from '../../../../common/components/user_privileges';
5053

5154
export const ARTIFACT_FLYOUT_LABELS = Object.freeze({
5255
flyoutEditTitle: i18n.translate('xpack.securitySolution.artifactListPage.flyoutEditTitle', {
@@ -211,6 +214,11 @@ export const ArtifactFlyout = memo<ArtifactFlyoutProps>(
211214
const setUrlParams = useSetUrlParams();
212215
const { urlParams } = useUrlParams<ArtifactListPageUrlParams>();
213216
const isMounted = useIsMounted();
217+
const isSpaceAwarenessEnabled = useIsExperimentalFeatureEnabled(
218+
'endpointManagementSpaceAwarenessEnabled'
219+
);
220+
const canManageGlobalArtifacts =
221+
useUserPrivileges().endpointPrivileges.canManageGlobalArtifacts;
214222
const labels = useMemo<typeof ARTIFACT_FLYOUT_LABELS>(() => {
215223
return {
216224
...ARTIFACT_FLYOUT_LABELS,
@@ -255,9 +263,18 @@ export const ArtifactFlyout = memo<ArtifactFlyoutProps>(
255263
enabled: false,
256264
});
257265

258-
const [formState, setFormState] = useState<ArtifactFormComponentOnChangeCallbackProps>(
259-
createFormInitialState.bind(null, apiClient.listId, item)
260-
);
266+
const [formState, setFormState] = useState<ArtifactFormComponentOnChangeCallbackProps>(() => {
267+
const initialFormState = createFormInitialState(apiClient.listId, item);
268+
269+
// for Create Mode: If user is not able to manage global artifacts then the initial item should be per-policy
270+
if (!item && isSpaceAwarenessEnabled && !canManageGlobalArtifacts) {
271+
initialFormState.item.tags = (initialFormState.item.tags ?? []).filter(
272+
(tag) => tag !== GLOBAL_ARTIFACT_TAG
273+
);
274+
}
275+
276+
return initialFormState;
277+
});
261278
const showExpiredLicenseBanner = useIsArtifactAllowedPerPolicyUsage(
262279
{ tags: formState.item.tags ?? [] },
263280
formMode

0 commit comments

Comments
 (0)