🛂(frontend) only owner can make a child doc a main doc

We get some side effects when an admin
tries to make a child doc a main doc.
We ensure that only the owner can do this.
This commit is contained in:
Anthony LC
2025-07-09 11:43:21 +02:00
parent d15285d385
commit cd366213ca
8 changed files with 65 additions and 12 deletions

View File

@@ -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,
},
});

View File

@@ -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();

View File

@@ -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', () => {

View File

@@ -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;

View File

@@ -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: (
<Box
$css={css`

View File

@@ -136,7 +136,7 @@ export const DocGridContentList = ({ docs }: DocGridContentListProps) => {
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');

View File

@@ -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<Doc>();
const [canDrop, setCanDrop] = useState<boolean>();
const canDrag = !!selectedDoc?.abilities.move;
const canDrag = selectedDoc?.user_role === Role.OWNER;
const mouseSensor = useSensor(MouseSensor, { activationConstraint });
const touchSensor = useSensor(TouchSensor, { activationConstraint });

View File

@@ -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,