mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2026-08-07 07:14:49 +00:00
fix(frontend): conditionally hide create note button on 404 page
The 404 page for notes renders a button to create a note with the requested alias. This button was previously rendered unconditionally, and therefore rendered even when the user (or guest) didn't have any permission to create notes. The button is now hidden when no permission to create notes is existing. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
committed by
Philip Molares
parent
02f5682643
commit
5b7fa9aaba
+2
@@ -38,6 +38,8 @@ exports[`create non existing note hint renders an button as initial state 1`] =
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`create non existing note hint renders nothing for a guest without note creation permission 1`] = `<div />`;
|
||||||
|
|
||||||
exports[`create non existing note hint renders nothing if no note id has been provided 1`] = `<div />`;
|
exports[`create non existing note hint renders nothing if no note id has been provided 1`] = `<div />`;
|
||||||
|
|
||||||
exports[`create non existing note hint shows an error message if note couldn't be created 1`] = `
|
exports[`create non existing note hint shows an error message if note couldn't be created 1`] = `
|
||||||
|
|||||||
+28
-1
@@ -4,15 +4,19 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import * as createNoteWithPrimaryAliasModule from '../../../api/notes'
|
import * as createNoteWithPrimaryAliasModule from '../../../api/notes'
|
||||||
|
import { AuthProviderType, PermissionLevel } from '@hedgedoc/commons'
|
||||||
|
import { mockAppState } from '../../../test-utils/mock-app-state'
|
||||||
import { mockI18n } from '../../../test-utils/mock-i18n'
|
import { mockI18n } from '../../../test-utils/mock-i18n'
|
||||||
|
import * as UseFrontendConfigMock from '../frontend-config-context/use-frontend-config'
|
||||||
import { CreateNonExistingNoteHint } from './create-non-existing-note-hint'
|
import { CreateNonExistingNoteHint } from './create-non-existing-note-hint'
|
||||||
import type { NoteInterface, NoteMetadataInterface } from '@hedgedoc/commons'
|
import type { FrontendConfigInterface, NoteInterface, NoteMetadataInterface } from '@hedgedoc/commons'
|
||||||
import { waitForOtherPromisesToFinish } from '@hedgedoc/commons'
|
import { waitForOtherPromisesToFinish } from '@hedgedoc/commons'
|
||||||
import { act, render, screen, waitFor } from '@testing-library/react'
|
import { act, render, screen, waitFor } from '@testing-library/react'
|
||||||
import { Mock } from 'ts-mockery'
|
import { Mock } from 'ts-mockery'
|
||||||
|
|
||||||
jest.mock('../../../api/notes')
|
jest.mock('../../../api/notes')
|
||||||
jest.mock('../../../hooks/common/use-single-string-url-parameter')
|
jest.mock('../../../hooks/common/use-single-string-url-parameter')
|
||||||
|
jest.mock('../frontend-config-context/use-frontend-config')
|
||||||
|
|
||||||
describe('create non existing note hint', () => {
|
describe('create non existing note hint', () => {
|
||||||
const mockedNoteId = 'mockedNoteId'
|
const mockedNoteId = 'mockedNoteId'
|
||||||
@@ -45,6 +49,13 @@ describe('create non existing note hint', () => {
|
|||||||
await mockI18n()
|
await mockI18n()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockAppState({ user: { authProvider: AuthProviderType.LOCAL } })
|
||||||
|
jest
|
||||||
|
.spyOn(UseFrontendConfigMock, 'useFrontendConfig')
|
||||||
|
.mockReturnValue(Mock.of<FrontendConfigInterface>({ guestAccess: PermissionLevel.FULL }))
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
jest.resetAllMocks()
|
||||||
jest.resetModules()
|
jest.resetModules()
|
||||||
@@ -60,6 +71,22 @@ describe('create non existing note hint', () => {
|
|||||||
expect(view.container).toMatchSnapshot()
|
expect(view.container).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('renders nothing for a guest without note creation permission', async () => {
|
||||||
|
mockAppState({ user: { authProvider: AuthProviderType.GUEST } })
|
||||||
|
jest
|
||||||
|
.spyOn(UseFrontendConfigMock, 'useFrontendConfig')
|
||||||
|
.mockReturnValue(Mock.of<FrontendConfigInterface>({ guestAccess: PermissionLevel.WRITE }))
|
||||||
|
const onNoteCreatedCallback = jest.fn()
|
||||||
|
const view = render(
|
||||||
|
<CreateNonExistingNoteHint
|
||||||
|
noteId={mockedNoteId}
|
||||||
|
onNoteCreated={onNoteCreatedCallback}></CreateNonExistingNoteHint>
|
||||||
|
)
|
||||||
|
await waitForOtherPromisesToFinish()
|
||||||
|
expect(onNoteCreatedCallback).not.toBeCalled()
|
||||||
|
expect(view.container).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
it('renders an button as initial state', async () => {
|
it('renders an button as initial state', async () => {
|
||||||
mockCreateNoteWithPrimaryAlias()
|
mockCreateNoteWithPrimaryAlias()
|
||||||
const onNoteCreatedCallback = jest.fn()
|
const onNoteCreatedCallback = jest.fn()
|
||||||
|
|||||||
+6
-1
@@ -4,8 +4,10 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import { createNoteWithPrimaryAlias } from '../../../api/notes'
|
import { createNoteWithPrimaryAlias } from '../../../api/notes'
|
||||||
|
import { useIsLoggedIn } from '../../../hooks/common/use-is-logged-in'
|
||||||
import { testId } from '../../../utils/test-id'
|
import { testId } from '../../../utils/test-id'
|
||||||
import { UiIcon } from '../icons/ui-icon'
|
import { UiIcon } from '../icons/ui-icon'
|
||||||
|
import { useFrontendConfig } from '../frontend-config-context/use-frontend-config'
|
||||||
import React, { useCallback, useEffect } from 'react'
|
import React, { useCallback, useEffect } from 'react'
|
||||||
import { Alert, Button } from 'react-bootstrap'
|
import { Alert, Button } from 'react-bootstrap'
|
||||||
import {
|
import {
|
||||||
@@ -15,6 +17,7 @@ import {
|
|||||||
} from 'react-bootstrap-icons'
|
} from 'react-bootstrap-icons'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { useAsyncFn } from 'react-use'
|
import { useAsyncFn } from 'react-use'
|
||||||
|
import { PermissionLevel } from '@hedgedoc/commons'
|
||||||
|
|
||||||
export interface CreateNonExistingNoteHintProps {
|
export interface CreateNonExistingNoteHintProps {
|
||||||
onNoteCreated: () => void
|
onNoteCreated: () => void
|
||||||
@@ -30,6 +33,8 @@ export interface CreateNonExistingNoteHintProps {
|
|||||||
*/
|
*/
|
||||||
export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps> = ({ onNoteCreated, noteId }) => {
|
export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps> = ({ onNoteCreated, noteId }) => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
|
const guestAccessLevel = useFrontendConfig().guestAccess
|
||||||
|
const isLoggedIn = useIsLoggedIn()
|
||||||
|
|
||||||
const [returnState, createNote] = useAsyncFn(async () => {
|
const [returnState, createNote] = useAsyncFn(async () => {
|
||||||
if (noteId !== undefined) {
|
if (noteId !== undefined) {
|
||||||
@@ -47,7 +52,7 @@ export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps>
|
|||||||
}
|
}
|
||||||
}, [onNoteCreated, returnState.value])
|
}, [onNoteCreated, returnState.value])
|
||||||
|
|
||||||
if (noteId === undefined) {
|
if (noteId === undefined || (!isLoggedIn && guestAccessLevel !== PermissionLevel.FULL)) {
|
||||||
return null
|
return null
|
||||||
} else if (returnState.value) {
|
} else if (returnState.value) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user