From ca9661c091acd43b3dcd2408df22321d6662b07b Mon Sep 17 00:00:00 2001 From: MHMD <45968454+dou-mhmd@users.noreply.github.com> Date: Fri, 16 Oct 2026 10:40:31 +0000 Subject: [PATCH] fix(editor): Keep the used-in rows on the credential sharing tab when personal-space sharing is disabled (#41207) --- .../CredentialSharing.ee.test.ts | 94 +++++++++++++++---- .../CredentialEdit/CredentialSharing.ee.vue | 33 +++++-- 2 files changed, 102 insertions(+), 25 deletions(-) diff --git a/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.test.ts b/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.test.ts index 646068a42cb..26a65c8554d 100644 --- a/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.test.ts +++ b/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.test.ts @@ -1058,8 +1058,8 @@ describe('CredentialSharing.ee', () => { expect(queryByTestId('project-sharing-unshared-item')).not.toBeInTheDocument(); }); - it('does not show used-in projects when the viewer cannot share', () => { - getDependenciesMock.mockReturnValue({ + describe('when the viewer cannot share', () => { + const usedInMarketing = { dependencies: [ { id: 'wf-1', @@ -1069,24 +1069,86 @@ describe('CredentialSharing.ee', () => { }, ], inaccessibleCount: 0, + }; + + it('keeps the used-in row and disables the Share button when sharing is disabled in personal spaces', async () => { + getDependenciesMock.mockReturnValue(usedInMarketing); + + const credential = createCredential({ + homeProject: ownerPersonalProject, + sharedWithProjects: [], + }); + const { getByTestId, findAllByText } = renderComponent({ + props: { + credentialId: credential.id, + credentialData: {}, + credentialPermissions: { share: false }, + credential, + modalBus: createEventBus(), + }, + }); + + expect(fetchDependenciesMock).toHaveBeenCalledWith([credential.id], 'credential'); + + const row = getByTestId('project-sharing-unshared-item'); + expect(row).toHaveTextContent('Marketing'); + expect(row).toHaveTextContent('Used in "Email summary"'); + + const share = getByTestId('credential-used-in-project-share'); + expect(share).toBeDisabled(); + + await userEvent.hover(share.parentElement as HTMLElement); + expect( + await findAllByText("You don't have permission to share personal credentials"), + ).not.toHaveLength(0); }); - const credential = createCredential({ - homeProject: ownerPersonalProject, - sharedWithProjects: [], - }); - const { queryByTestId } = renderComponent({ - props: { - credentialId: credential.id, - credentialData: {}, - credentialPermissions: { share: false }, - credential, - modalBus: createEventBus(), - }, + it('does not share the project when the disabled Share button is clicked', async () => { + getDependenciesMock.mockReturnValue(usedInMarketing); + + const credential = createCredential({ + homeProject: ownerPersonalProject, + sharedWithProjects: [], + }); + const { getByTestId, emitted } = renderComponent({ + props: { + credentialId: credential.id, + credentialData: {}, + credentialPermissions: { share: false }, + credential, + modalBus: createEventBus(), + }, + }); + + await userEvent.click(getByTestId('credential-used-in-project-share')); + + expect(emitted()['update:modelValue']).toBeUndefined(); + expect(getByTestId('project-sharing-unshared-item')).toBeInTheDocument(); }); - expect(queryByTestId('project-sharing-unshared-item')).not.toBeInTheDocument(); - expect(fetchDependenciesMock).not.toHaveBeenCalled(); + it('shows a disabled Share button without the personal-space tooltip when the credential lives in a team project', async () => { + getDependenciesMock.mockReturnValue(usedInMarketing); + + const credential = createCredential({ sharedWithProjects: [] }); + const { getByTestId, queryByText } = renderComponent({ + props: { + credentialId: credential.id, + credentialData: {}, + credentialPermissions: { share: false }, + credential, + modalBus: createEventBus(), + }, + }); + + expect(getByTestId('project-sharing-unshared-item')).toBeInTheDocument(); + const share = getByTestId('credential-used-in-project-share'); + expect(share).toBeDisabled(); + + await userEvent.hover(share.parentElement as HTMLElement); + expect( + queryByText("You don't have permission to share personal credentials"), + ).not.toBeInTheDocument(); + }); }); it('does not fetch or show used-in projects when the flag is disabled', () => { diff --git a/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue b/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue index fe2d0b1dfd5..b6ffd7e3fc2 100644 --- a/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue +++ b/packages/frontend/editor-ui/src/features/credentials/components/CredentialEdit/CredentialSharing.ee.vue @@ -156,13 +156,18 @@ const confirmRemoval = computed(() => { const { fetchDependencies, getDependencies } = useDependencies(); onMounted(() => { - if (isCredSharingEnabled.value && props.credentialPermissions.share) { + if (isCredSharingEnabled.value) { void fetchDependencies([props.credentialId], 'credential'); } }); +/** + * Projects where the credential is used without a share. The rows stay visible + * when the viewer cannot share: where a credential is used is audit information, + * so the share permission only gates the Share button. + */ const usedInProjects = computed(() => { - if (!isCredSharingEnabled.value || !props.credentialPermissions.share) return []; + if (!isCredSharingEnabled.value) return []; const deps = getDependencies(props.credentialId, 'credential'); if (!deps) return []; @@ -215,6 +220,12 @@ function usedInProjectName(project: Pick) { } function usedInShareTooltip(project: ProjectSharingData) { + if (!props.credentialPermissions.share) { + return isPersonalSpaceRestricted.value + ? i18n.baseText('credentialEdit.credentialSharing.info.personalSpaceRestricted') + : ''; + } + const name = usedInProjectName(project); if (hasInstanceWideUse(project)) { @@ -373,13 +384,17 @@ function goToUpgrade() { :disabled="!usedInShareTooltip(project)" placement="top" > - - {{ i18n.baseText('credentialEdit.credentialSharing.share') }} - + + + + {{ i18n.baseText('credentialEdit.credentialSharing.share') }} + +