feat: check permissions in realtime code and frontend

Signed-off-by: Philip Molares <philip.molares@udo.edu>
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Philip Molares 2023-03-26 14:51:18 +02:00 committed by Tilman Vatteroth
parent 24f1b2a361
commit c2f41118b6
27 changed files with 287 additions and 66 deletions

View file

@ -4,8 +4,9 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as AliasModule from '../../../../api/alias'
import * as useApplicationStateModule from '../../../../hooks/common/use-application-state'
import * as NoteDetailsReduxModule from '../../../../redux/note-details/methods'
import type { NoteDetails } from '../../../../redux/note-details/types/note-details'
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 { AliasesAddForm } from './aliases-add-form'
@ -25,12 +26,12 @@ describe('AliasesAddForm', () => {
await mockI18n()
jest.spyOn(AliasModule, 'addAlias').mockImplementation(() => addPromise)
jest.spyOn(NoteDetailsReduxModule, 'updateMetadata').mockImplementation(() => Promise.resolve())
jest.spyOn(useApplicationStateModule, 'useApplicationState').mockReturnValue('mock-note')
jest.spyOn(useUiNotificationsModule, 'useUiNotifications').mockReturnValue({
showErrorNotification: jest.fn(),
dismissNotification: jest.fn(),
dispatchUiNotification: jest.fn()
})
mockNoteOwnership('test', 'test', { noteDetails: { id: 'mock-note' } as NoteDetails })
})
afterAll(() => {

View file

@ -5,7 +5,7 @@
*/
import { UiIcon } from '../../../common/icons/ui-icon'
import type { PermissionDisabledProps } from './permission-disabled.prop'
import { AccessLevel } from './types'
import { AccessLevel } from '@hedgedoc/commons'
import React, { useMemo } from 'react'
import { Button, ToggleButtonGroup } from 'react-bootstrap'
import { Eye as IconEye } from 'react-bootstrap-icons'

View file

@ -9,7 +9,7 @@ import { setNotePermissionsFromServer } from '../../../../redux/note-details/met
import { IconButton } from '../../../common/icon-button/icon-button'
import { useUiNotifications } from '../../../notifications/ui-notification-boundary'
import type { PermissionDisabledProps } from './permission-disabled.prop'
import { AccessLevel, SpecialGroup } from './types'
import { AccessLevel, SpecialGroup } from '@hedgedoc/commons'
import React, { useCallback, useMemo } from 'react'
import { ToggleButtonGroup } from 'react-bootstrap'
import { Eye as IconEye } from 'react-bootstrap-icons'

View file

@ -3,7 +3,6 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import type { NoteUserPermissionEntry } from '../../../../api/notes/types'
import { removeUserPermission, setUserPermission } from '../../../../api/permissions'
import { getUser } from '../../../../api/users'
import { useApplicationState } from '../../../../hooks/common/use-application-state'
@ -13,7 +12,8 @@ import { UserAvatarForUser } from '../../../common/user-avatar/user-avatar-for-u
import { useUiNotifications } from '../../../notifications/ui-notification-boundary'
import type { PermissionDisabledProps } from './permission-disabled.prop'
import { PermissionEntryButtons, PermissionType } from './permission-entry-buttons'
import { AccessLevel } from './types'
import type { NoteUserPermissionEntry } from '@hedgedoc/commons'
import { AccessLevel } from '@hedgedoc/commons'
import React, { useCallback } from 'react'
import { useAsync } from 'react-use'

View file

@ -7,7 +7,7 @@ import { useApplicationState } from '../../../../hooks/common/use-application-st
import { useIsOwner } from '../../../../hooks/common/use-is-owner'
import type { PermissionDisabledProps } from './permission-disabled.prop'
import { PermissionEntrySpecialGroup } from './permission-entry-special-group'
import { AccessLevel, SpecialGroup } from './types'
import { AccessLevel, SpecialGroup } from '@hedgedoc/commons'
import React, { Fragment, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next'

View file

@ -1,15 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export enum AccessLevel {
NONE,
READ_ONLY,
WRITEABLE
}
export enum SpecialGroup {
EVERYONE = '_EVERYONE',
LOGGED_IN = '_LOGGED_IN'
}

View file

@ -6,6 +6,7 @@
import { useApplicationState } from '../../../hooks/common/use-application-state'
import { ORIGIN, useBaseUrl } from '../../../hooks/common/use-base-url'
import { useDarkModeState } from '../../../hooks/common/use-dark-mode-state'
import { useMayEdit } from '../../../hooks/common/use-may-edit'
import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
import { findLanguageByCodeBlockName } from '../../markdown-renderer/extensions/base/code-block-markdown-extension/find-language-by-code-block-name'
import type { ScrollProps } from '../synced-scroll/scroll-props'
@ -130,6 +131,7 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
const darkModeActivated = useDarkModeState()
const editorOrigin = useBaseUrl(ORIGIN.EDITOR)
const isSynced = useApplicationState((state) => state.realtimeStatus.isSynced)
const mayEdit = useMayEdit()
useEffect(() => {
const listener = messageTransporter.doAsSoonAsConnected(() => messageTransporter.sendReady())
@ -144,11 +146,11 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
onTouchStart={onMakeScrollSource}
onMouseEnter={onMakeScrollSource}
{...cypressId('editor-pane')}
{...cypressAttribute('editor-ready', String(updateViewContextExtension !== null && isSynced))}>
{...cypressAttribute('editor-ready', String(updateViewContextExtension !== null && isSynced && mayEdit))}>
<MaxLengthWarning />
<ToolBar />
<ReactCodeMirror
editable={updateViewContextExtension !== null && isSynced}
editable={updateViewContextExtension !== null && isSynced && mayEdit}
placeholder={t('editor.placeholder', { host: editorOrigin }) ?? ''}
extensions={extensions}
width={'100%'}