enhancement(permissions): show alert when permission is overridden by another

Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2023-08-13 23:56:41 +02:00
parent 626a6c7426
commit dfcf662a85
5 changed files with 64 additions and 18 deletions

View file

@ -423,7 +423,8 @@
"error": "There was an error changing the owner of this note.",
"placeholder": "Enter username of new note owner",
"button": "Change the owner of this note"
}
},
"inconsistent": "This permission is overridden by another permission"
},
"shareLink": {
"title": "Share link",

View file

@ -15,10 +15,12 @@ import React, { useCallback, useMemo } from 'react'
import { ToggleButtonGroup } from 'react-bootstrap'
import { Eye as IconEye, Pencil as IconPencil, SlashCircle as IconSlashCircle } from 'react-bootstrap-icons'
import { useTranslation } from 'react-i18next'
import { PermissionInconsistentAlert } from './permission-inconsistent-alert'
export interface PermissionEntrySpecialGroupProps {
level: AccessLevel
type: SpecialGroup
inconsistent?: boolean
}
/**
@ -27,11 +29,13 @@ export interface PermissionEntrySpecialGroupProps {
* @param level The access level that is currently set for the group.
* @param type The type of the special group. Must be either {@link SpecialGroup.EVERYONE} or {@link SpecialGroup.LOGGED_IN}.
* @param disabled If the user is not the owner, functionality is disabled.
* @param inconsistent Whether to show the inconsistency alert icon or not
*/
export const PermissionEntrySpecialGroup: React.FC<PermissionEntrySpecialGroupProps & PermissionDisabledProps> = ({
level,
type,
disabled
disabled,
inconsistent
}) => {
const noteId = useApplicationState((state) => state.noteDetails?.primaryAddress)
const { t } = useTranslation()
@ -88,6 +92,7 @@ export const PermissionEntrySpecialGroup: React.FC<PermissionEntrySpecialGroupPr
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
<span>{name}</span>
<div>
<PermissionInconsistentAlert show={inconsistent ?? false} />
<ToggleButtonGroup type='radio' name='edit-mode'>
<IconButton
icon={IconSlashCircle}

View file

@ -13,9 +13,10 @@ import { useUiNotifications } from '../../../../../notifications/ui-notification
import type { PermissionDisabledProps } from './permission-disabled.prop'
import { PermissionEntryButtons, PermissionType } from './permission-entry-buttons'
import type { NoteUserPermissionEntry } from '@hedgedoc/commons'
import { AccessLevel } from '@hedgedoc/commons'
import React, { useCallback } from 'react'
import { AccessLevel, SpecialGroup } from '@hedgedoc/commons'
import React, { useCallback, useMemo } from 'react'
import { useAsync } from 'react-use'
import { PermissionInconsistentAlert } from './permission-inconsistent-alert'
export interface PermissionEntryUserProps {
entry: NoteUserPermissionEntry
@ -33,6 +34,16 @@ export const PermissionEntryUser: React.FC<PermissionEntryUserProps & Permission
}) => {
const noteId = useApplicationState((state) => state.noteDetails?.primaryAddress)
const { showErrorNotification } = useUiNotifications()
const groupPermissions = useApplicationState((state) => state.noteDetails.permissions.sharedToGroups)
const permissionInconsistent = useMemo(() => {
const everyonePermission = groupPermissions.find((group) => group.groupName === (SpecialGroup.EVERYONE as string))
const loggedInPermission = groupPermissions.find((group) => group.groupName === (SpecialGroup.LOGGED_IN as string))
return (
(everyonePermission && everyonePermission.canEdit && !entry.canEdit) ||
(loggedInPermission && loggedInPermission.canEdit && !entry.canEdit)
)
}, [groupPermissions, entry])
const onRemoveEntry = useCallback(() => {
if (!noteId) {
@ -79,6 +90,8 @@ export const PermissionEntryUser: React.FC<PermissionEntryUserProps & Permission
<ShowIf condition={!loading && !error}>
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
<UserAvatarForUser user={value} />
<div className={'d-flex flex-row align-items-center'}>
<PermissionInconsistentAlert show={permissionInconsistent ?? false} />
<PermissionEntryButtons
type={PermissionType.USER}
currentSetting={entry.canEdit ? AccessLevel.WRITEABLE : AccessLevel.READ_ONLY}
@ -88,6 +101,7 @@ export const PermissionEntryUser: React.FC<PermissionEntryUserProps & Permission
onRemove={onRemoveEntry}
disabled={disabled}
/>
</div>
</li>
</ShowIf>
)

View file

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React from 'react'
import { UiIcon } from '../../../../../common/icons/ui-icon'
import { ExclamationTriangleFill as IconExclamationTriangleFill } from 'react-bootstrap-icons'
import type { SimpleAlertProps } from '../../../../../common/simple-alert/simple-alert-props'
import { useTranslatedText } from '../../../../../../hooks/common/use-translated-text'
/**
* Alert that is shown when the permissions are inconsistent.
*
* @param show true to show the alert, false otherwise.
*/
export const PermissionInconsistentAlert: React.FC<SimpleAlertProps> = ({ show }) => {
const message = useTranslatedText('editor.modal.permissions.inconsistent')
if (!show) {
return null
}
return <UiIcon icon={IconExclamationTriangleFill} className={'text-warning me-2'} title={message} />
}

View file

@ -29,16 +29,17 @@ export const PermissionSectionSpecialGroups: React.FC<PermissionDisabledProps> =
const groupLoggedIn = groupPermissions.find((entry) => entry.groupName === (SpecialGroup.LOGGED_IN as string))
return {
everyone: groupEveryone
everyoneLevel: groupEveryone
? groupEveryone.canEdit
? AccessLevel.WRITEABLE
: AccessLevel.READ_ONLY
: AccessLevel.NONE,
loggedIn: groupLoggedIn
loggedInLevel: groupLoggedIn
? groupLoggedIn.canEdit
? AccessLevel.WRITEABLE
: AccessLevel.READ_ONLY
: AccessLevel.NONE
: AccessLevel.NONE,
loggedInInconsistentAlert: groupEveryone && (!groupLoggedIn || (groupEveryone.canEdit && !groupLoggedIn.canEdit))
}
}, [groupPermissions])
@ -53,12 +54,13 @@ export const PermissionSectionSpecialGroups: React.FC<PermissionDisabledProps> =
</h5>
<ul className={'list-group'}>
<PermissionEntrySpecialGroup
level={specialGroupEntries.loggedIn}
level={specialGroupEntries.loggedInLevel}
type={SpecialGroup.LOGGED_IN}
disabled={!isOwner}
inconsistent={specialGroupEntries.loggedInInconsistentAlert}
/>
<PermissionEntrySpecialGroup
level={specialGroupEntries.everyone}
level={specialGroupEntries.everyoneLevel}
type={SpecialGroup.EVERYONE}
disabled={disabled}
/>