diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts index 09928f1d..703aae23 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts @@ -276,7 +276,6 @@ export const mockedDocument = async (page: Page, data: object) => { ancestors_link_role: null, created_at: '2021-09-01T09:00:00Z', user_role: 'owner', - user_roles: ['owner'], ...doc, }, }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid-dnd.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid-dnd.spec.ts index 69f97d68..32c43c2f 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-grid-dnd.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-grid-dnd.spec.ts @@ -158,7 +158,7 @@ test.describe('Doc grid dnd', () => { await expect(dragOverlay).toBeVisible(); await expect(dragOverlay).toHaveText( - 'You must have admin rights to move the document', + 'You must be the owner to move the document', ); await page.mouse.up(); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts index 7e29ce61..31e4161b 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts @@ -2,6 +2,7 @@ import { expect, test } from '@playwright/test'; import { + addNewMember, createDoc, expectLoginPage, keyCloakSignIn, @@ -12,8 +13,11 @@ import { import { clickOnAddRootSubPage, createRootSubPage } from './sub-pages-utils'; test.describe('Doc Tree', () => { - test('create new sub pages', async ({ page, browserName }) => { + test.beforeEach(async ({ page }) => { await page.goto('/'); + }); + + test('create new sub pages', async ({ page, browserName }) => { const [titleParent] = await createDoc( page, 'doc-tree-content', @@ -58,7 +62,6 @@ test.describe('Doc Tree', () => { }); test('check the reorder of sub pages', async ({ page, browserName }) => { - await page.goto('/'); await createDoc(page, 'doc-tree-content', browserName, 1); const addButton = page.getByRole('button', { name: 'New doc' }); await expect(addButton).toBeVisible(); @@ -165,7 +168,6 @@ test.describe('Doc Tree', () => { }); test('it detaches a document', async ({ page, browserName }) => { - await page.goto('/'); const [docParent] = await createDoc( page, 'doc-tree-detach', @@ -202,6 +204,55 @@ test.describe('Doc Tree', () => { await header.locator('h2').getByText('Docs').click(); await expect(page.getByText(docChild)).toBeVisible(); }); + + test('Only owner can detaches a document', async ({ page, browserName }) => { + const [docParent] = await createDoc( + page, + 'doc-tree-detach', + browserName, + 1, + ); + + await verifyDocName(page, docParent); + + await page.getByRole('button', { name: 'Share' }).click(); + + await addNewMember(page, 0, 'Owner', 'impress'); + + const list = page.getByTestId('doc-share-quick-search'); + const currentUser = list.getByTestId( + `doc-share-member-row-user@${browserName}.test`, + ); + const currentUserRole = currentUser.getByLabel('doc-role-dropdown'); + await currentUserRole.click(); + await page.getByLabel('Administrator').click(); + await list.click(); + + await page.getByRole('button', { name: 'Ok' }).click(); + + const { name: docChild } = await createRootSubPage( + page, + browserName, + 'doc-tree-detach-child', + ); + + const docTree = page.getByTestId('doc-tree'); + await expect(docTree.getByText(docChild)).toBeVisible(); + await docTree.click(); + const child = docTree + .getByRole('treeitem') + .locator('.--docs-sub-page-item') + .filter({ + hasText: docChild, + }); + await child.hover(); + const menu = child.getByText(`more_horiz`); + await menu.click(); + + await expect( + page.getByRole('menuitem', { name: 'Move to my docs' }), + ).toHaveAttribute('aria-disabled', 'true'); + }); }); test.describe('Doc Tree: Inheritance', () => { diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx index a1db947a..7c8c2ea8 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx @@ -70,7 +70,6 @@ export interface Doc { numchild: number; updated_at: string; user_role: Role; - user_roles: Role[]; abilities: { accesses_manage: boolean; accesses_view: boolean; diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx index add3753c..37fe8199 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx @@ -11,7 +11,12 @@ import { css } from 'styled-components'; import { Box, BoxButton, Icon } from '@/components'; -import { Doc, ModalRemoveDoc, useCopyDocLink } from '../../doc-management'; +import { + Doc, + ModalRemoveDoc, + Role, + useCopyDocLink, +} from '../../doc-management'; import { useCreateChildrenDoc } from '../api/useCreateChildren'; import { useDetachDoc } from '../api/useDetach'; import MoveDocIcon from '../assets/doc-extract-bold.svg'; @@ -70,7 +75,7 @@ export const DocTreeItemActions = ({ ? [ { label: t('Move to my docs'), - isDisabled: !doc.abilities.move, + isDisabled: doc.user_role !== Role.OWNER, icon: ( { const overlayText = useMemo(() => { if (!canDrag) { - return t('You must have admin rights to move the document'); + return t('You must be the owner to move the document'); } if (!canDrop) { return t('You must be at least the editor of the target document'); diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/hooks/useDragAndDrop.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/hooks/useDragAndDrop.tsx index 68b84425..81410c0f 100644 --- a/src/frontend/apps/impress/src/features/docs/docs-grid/hooks/useDragAndDrop.tsx +++ b/src/frontend/apps/impress/src/features/docs/docs-grid/hooks/useDragAndDrop.tsx @@ -9,7 +9,7 @@ import { } from '@dnd-kit/core'; import { useState } from 'react'; -import { Doc } from '@/docs/doc-management'; +import { Doc, Role } from '@/docs/doc-management'; export type DocDragEndData = { sourceDocumentId: string; @@ -26,7 +26,7 @@ export function useDragAndDrop(onDrag: (data: DocDragEndData) => void) { const [selectedDoc, setSelectedDoc] = useState(); const [canDrop, setCanDrop] = useState(); - const canDrag = !!selectedDoc?.abilities.move; + const canDrag = selectedDoc?.user_role === Role.OWNER; const mouseSensor = useSensor(MouseSensor, { activationConstraint }); const touchSensor = useSensor(TouchSensor, { activationConstraint }); diff --git a/src/frontend/apps/impress/src/features/service-worker/plugins/ApiPlugin.ts b/src/frontend/apps/impress/src/features/service-worker/plugins/ApiPlugin.ts index dfd5bd00..f050e98e 100644 --- a/src/frontend/apps/impress/src/features/service-worker/plugins/ApiPlugin.ts +++ b/src/frontend/apps/impress/src/features/service-worker/plugins/ApiPlugin.ts @@ -209,7 +209,6 @@ export class ApiPlugin implements WorkboxPlugin { }, link_reach: LinkReach.RESTRICTED, link_role: LinkRole.READER, - user_roles: [Role.OWNER], user_role: Role.OWNER, path: '', computed_link_reach: LinkReach.RESTRICTED,