From 09e56a418e3c6e459adb92127270c61f4c22b461 Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Fri, 24 Mar 2023 16:10:34 +0100 Subject: [PATCH] feat(frontend): deactivate alias buttons if user is not owner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These buttons and their functionality only work if the user is the owner, so it doesn't make sense to make it possible to press them otherwise… Signed-off-by: Philip Molares --- .../aliases-list-entry.test.tsx.snap | 60 +++++++++++++++++++ .../document-bar/aliases/aliases-add-form.tsx | 7 ++- .../aliases/aliases-list-entry.test.tsx | 31 +++++++++- .../aliases/aliases-list-entry.tsx | 6 +- frontend/src/test-utils/note-ownership.ts | 23 +++++++ 5 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 frontend/src/test-utils/note-ownership.ts diff --git a/frontend/src/components/editor-page/document-bar/aliases/__snapshots__/aliases-list-entry.test.tsx.snap b/frontend/src/components/editor-page/document-bar/aliases/__snapshots__/aliases-list-entry.test.tsx.snap index cd6cb2fdf..2277f6a9b 100644 --- a/frontend/src/components/editor-page/document-bar/aliases/__snapshots__/aliases-list-entry.test.tsx.snap +++ b/frontend/src/components/editor-page/document-bar/aliases/__snapshots__/aliases-list-entry.test.tsx.snap @@ -1,5 +1,65 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`AliasesListEntry disables button in AliasesListEntry if it's not primary 1`] = ` +
+
  • + test-primary +
    + + +
    +
  • +
    +`; + +exports[`AliasesListEntry disables button in AliasesListEntry if it's primary 1`] = ` +
    +
  • + test-primary +
    + + +
    +
  • +
    +`; + exports[`AliasesListEntry renders an AliasesListEntry that is not primary 1`] = `
  • { const { t } = useTranslation() const { showErrorNotification } = useUiNotifications() const noteId = useApplicationState((state) => state.noteDetails.id) + const isOwner = useIsOwner() const [newAlias, setNewAlias] = useState('') const onAddAlias = useCallback( @@ -54,6 +56,7 @@ export const AliasesAddForm: React.FC = () => { placeholder={t('editor.modal.aliases.addAlias') ?? undefined} onChange={onNewAliasInputChange} isInvalid={!newAliasValid} + disabled={!isOwner} required={true} {...testId('addAliasInput')} /> @@ -61,7 +64,7 @@ export const AliasesAddForm: React.FC = () => { type={'submit'} variant='light' className={'text-secondary ms-2'} - disabled={!newAliasValid || newAlias === ''} + disabled={!isOwner || !newAliasValid || newAlias === ''} title={t('editor.modal.aliases.addAlias') ?? undefined} {...testId('addAliasButton')}> diff --git a/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.test.tsx b/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.test.tsx index 81f391dd0..a03ac7767 100644 --- a/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.test.tsx +++ b/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.test.tsx @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import * as AliasModule from '../../../../api/alias' import type { Alias } from '../../../../api/alias/types' import * as NoteDetailsReduxModule from '../../../../redux/note-details/methods' +import { mockNoteOwnership } from '../../../../test-utils/note-ownership' import { mockI18n } from '../../../markdown-renderer/test-utils/mock-i18n' import * as useUiNotificationsModule from '../../../notifications/ui-notification-boundary' import { AliasesListEntry } from './aliases-list-entry' @@ -15,6 +16,8 @@ import React from 'react' jest.mock('../../../../api/alias') jest.mock('../../../../redux/note-details/methods') jest.mock('../../../notifications/ui-notification-boundary') +// This needs to be mocked here in addition to note-ownership.ts, because jest doesn't work otherwise +jest.mock('../../../../hooks/common/use-application-state') const deletePromise = Promise.resolve() const markAsPrimaryPromise = Promise.resolve({ name: 'mock', primaryAlias: true, noteId: 'mock' }) @@ -32,12 +35,13 @@ describe('AliasesListEntry', () => { }) }) - afterAll(() => { + afterEach(() => { jest.resetAllMocks() jest.resetModules() }) it('renders an AliasesListEntry that is primary', async () => { + mockNoteOwnership('test', 'test') const testAlias: Alias = { name: 'test-primary', primaryAlias: true, @@ -54,7 +58,19 @@ describe('AliasesListEntry', () => { expect(NoteDetailsReduxModule.updateMetadata).toBeCalled() }) + it("disables button in AliasesListEntry if it's primary", () => { + mockNoteOwnership('test2', 'test') + const testAlias: Alias = { + name: 'test-primary', + primaryAlias: true, + noteId: 'test-note-id' + } + const view = render() + expect(view.container).toMatchSnapshot() + }) + it('renders an AliasesListEntry that is not primary', async () => { + mockNoteOwnership('test', 'test') const testAlias: Alias = { name: 'test-non-primary', primaryAlias: false, @@ -77,4 +93,15 @@ describe('AliasesListEntry', () => { await markAsPrimaryPromise expect(NoteDetailsReduxModule.updateMetadata).toBeCalled() }) + + it("disables button in AliasesListEntry if it's not primary", () => { + mockNoteOwnership('test2', 'test') + const testAlias: Alias = { + name: 'test-primary', + primaryAlias: false, + noteId: 'test-note-id' + } + const view = render() + expect(view.container).toMatchSnapshot() + }) }) diff --git a/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.tsx b/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.tsx index 231c6e7ea..a765c4597 100644 --- a/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.tsx +++ b/frontend/src/components/editor-page/document-bar/aliases/aliases-list-entry.tsx @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import { deleteAlias, markAliasAsPrimary } from '../../../../api/alias' import type { Alias } from '../../../../api/alias/types' +import { useIsOwner } from '../../../../hooks/common/use-is-owner' import { updateMetadata } from '../../../../redux/note-details/methods' import { testId } from '../../../../utils/test-id' import { UiIcon } from '../../../common/icons/ui-icon' @@ -29,6 +30,7 @@ export interface AliasesListEntryProps { export const AliasesListEntry: React.FC = ({ alias }) => { const { t } = useTranslation() const { showErrorNotification } = useUiNotifications() + const isOwner = useIsOwner() const onRemoveClick = useCallback(() => { deleteAlias(alias.name) @@ -60,6 +62,7 @@ export const AliasesListEntry: React.FC = ({ alias }) =>