fix(editor): should not paste in readonly page mode (#11913)

### TL;DR

Prevent pasting content when a document is in readonly mode.

### What changed?

Added a check in the `PageClipboard` class to prevent pasting operations when the document is in readonly mode. The function now returns early if `this.std.store.readonly` is true, preventing any clipboard operations from being executed.

### How to test?

1. Open a document and add some content
2. Set the document to readonly mode: `document.querySelector('affine-page-root')!.doc.readonly = true`
3. Try to paste content into the document using:
   - Regular paste operation
   - Keyboard shortcut (Ctrl+V/Cmd+V)
4. Verify that no content is pasted and the document remains unchanged
5. Set the document back to editable mode and confirm pasting works again

### Why make this change?

This change ensures that documents in readonly mode maintain their integrity by preventing unintended modifications through clipboard operations. This is consistent with the expected behavior of readonly documents, where users should not be able to modify content through any means.
This commit is contained in:
doodlewind
2025-04-23 04:30:26 +00:00
parent 730ed16fc5
commit 1b2030b36a
2 changed files with 37 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ import {
import { setSelection } from '@affine-test/kit/utils/selection';
import type { CodeBlockComponent } from '@blocksuite/affine-block-code';
import type { ParagraphBlockComponent } from '@blocksuite/affine-block-paragraph';
import type { PageRootBlockComponent } from '@blocksuite/affine-block-root';
import type { BlockComponent } from '@blocksuite/std';
import { expect, type Page } from '@playwright/test';
@@ -434,3 +435,38 @@ test.describe('paste to code block', () => {
await verifyCodeBlockContent(page, 0, markdownText);
});
});
test.describe('paste in readonly mode', () => {
test('should not paste content when document is in readonly mode', async ({
page,
}) => {
await createParagraphBlocks(page, ['This is a test paragraph']);
const { blockIds } = await getParagraphIds(page);
const initialParagraphCount = blockIds.length;
await page.evaluate(() => {
const pageRoot = document.querySelector(
'affine-page-root'
) as PageRootBlockComponent;
pageRoot.doc.readonly = true;
});
await setSelection(page, blockIds[0], 0, blockIds[0], 4);
await pasteContent(page, {
'text/plain': ' - Added text that should not appear',
});
await verifyParagraphContent(page, 0, 'This is a test paragraph');
await pressEnter(page);
await pasteContent(page, { 'text/plain': 'This should not be pasted' });
const { blockIds: afterParagraphIds } = await getParagraphIds(page);
expect(afterParagraphIds.length).toBe(initialParagraphCount);
await setSelection(page, blockIds[0], 0, blockIds[0], 4);
await pasteByKeyboard(page);
await verifyParagraphContent(page, 0, 'This is a test paragraph');
});
});