Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to
- ✨(frontend) Can print a doc #1832
- ✨(backend) manage reconciliation requests for user accounts #1878
- 👷(CI) add GHCR workflow for forked repo testing #1851
- ⚡️(backend) remove content from Document serializer when asked #1910
- ✨(backend) allow the duplication of subpages #1893
- ✨(backend) Onboarding docs for new users #1891
- 🩺(trivy) add trivyignore file and add minimatch CVE #1915
Expand Down
12 changes: 10 additions & 2 deletions src/backend/core/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,16 @@ def get_fields(self):
fields = super().get_fields()

request = self.context.get("request")
if request and request.method == "POST":
fields["id"].read_only = False
if request:
if request.method == "POST":
fields["id"].read_only = False
if (
serializers.BooleanField().to_internal_value(
request.query_params.get("without_content", False)
)
is True
):
del fields["content"]

return fields

Expand Down
45 changes: 45 additions & 0 deletions src/backend/core/tests/documents/test_api_documents_retrieve.py
Original file line number Diff line number Diff line change
Expand Up @@ -1057,3 +1057,48 @@ def test_api_documents_retrieve_permanently_deleted_related(role, depth):

assert response.status_code == 404
assert response.json() == {"detail": "Not found."}


def test_api_documents_retrieve_without_content():
"""
Test retrieve using without_content query string should remove the content in the response
"""

user = factories.UserFactory()

document = factories.DocumentFactory(creator=user, users=[(user, "owner")])

client = APIClient()
client.force_login(user)

with mock.patch("core.models.Document.content") as mock_document_content:
response = client.get(
f"/api/v1.0/documents/{document.id!s}/?without_content=true"
)

assert response.status_code == 200

payload = response.json()
assert "content" not in payload
mock_document_content.assert_not_called()


def test_api_documents_retrieve_without_content_invalid_value():
"""
Test retrieve using without_content query string but an invalid value
should return a 400
"""

user = factories.UserFactory()

document = factories.DocumentFactory(creator=user, users=[(user, "owner")])

client = APIClient()
client.force_login(user)

response = client.get(
f"/api/v1.0/documents/{document.id!s}/?without_content=invalid-value"
)
assert response.status_code == 400

assert response.json() == ["Must be a valid boolean."]
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const LinkSelected = ({
isEditable,
updateInlineContent,
}: LinkSelectedProps) => {
const { data: doc } = useDoc({ id: docId });
const { data: doc } = useDoc({ id: docId, withoutContent: true });

/**
* Update the content title if the referenced doc title changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import { Doc } from '../types';

export type DocParams = {
id: string;
withoutContent?: boolean;
};

export const getDoc = async ({ id }: DocParams): Promise<Doc> => {
const response = await fetchAPI(`documents/${id}/`);
export const getDoc = async ({
id,
withoutContent,
}: DocParams): Promise<Doc> => {
const params = withoutContent ? '?without_content=true' : '';
const response = await fetchAPI(`documents/${id}/${params}`);

if (!response.ok) {
throw new APIError('Failed to get the doc', await errorCauses(response));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface Doc {
title?: string;
children?: Doc[];
childrenCount?: number;
content: Base64;
content?: Base64;
created_at: string;
creator: string;
deleted_at: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ describe('CollaborationBackend', () => {
const { fetchDocument } = await import('@/api/collaborationBackend');
const documentId = 'test-document-123';

await fetchDocument(documentId, { cookie: 'test-cookie' });
await fetchDocument(
{ name: documentId, withoutContent: true },
{ cookie: 'test-cookie' },
);

expect(axiosGetSpy).toHaveBeenCalledWith(
`http://app-dev:8000/api/v1.0/documents/${documentId}/`,
`http://app-dev:8000/api/v1.0/documents/${documentId}/?without_content=true`,
expect.objectContaining({
headers: expect.objectContaining({
'X-Y-Provider-Key': 'test-yprovider-key',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ describe('Server Tests', () => {
wsHocus.stopConnectionAttempt();
expect(data.reason).toBe('permission-denied');
expect(fetchDocumentMock).toHaveBeenCalledExactlyOnceWith(
room,
{ name: room, withoutContent: true },
expect.any(Object),
);
wsHocus.webSocket?.close();
Expand Down Expand Up @@ -273,7 +273,7 @@ describe('Server Tests', () => {
wsHocus.stopConnectionAttempt();
expect(data.reason).toBe('permission-denied');
expect(fetchDocumentMock).toHaveBeenCalledExactlyOnceWith(
room,
{ name: room, withoutContent: true },
expect.any(Object),
);
wsHocus.webSocket?.close();
Expand Down Expand Up @@ -322,7 +322,7 @@ describe('Server Tests', () => {
wsHocus.destroy();

expect(fetchDocumentMock).toHaveBeenCalledWith(
room,
{ name: room, withoutContent: true },
expect.any(Object),
);

Expand Down Expand Up @@ -371,7 +371,7 @@ describe('Server Tests', () => {
wsHocus.destroy();

expect(fetchDocumentMock).toHaveBeenCalledWith(
room,
{ name: room, withoutContent: true },
expect.any(Object),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Base64 = string;
interface Doc {
id: string;
title?: string;
content: Base64;
content?: Base64;
creator: string;
is_favorite: boolean;
link_reach: 'restricted' | 'public' | 'authenticated';
Expand Down Expand Up @@ -74,10 +74,11 @@ async function fetch<T>(
}

export function fetchDocument(
name: string,
{ name, withoutContent }: { name: string; withoutContent?: boolean },
requestHeaders: IncomingHttpHeaders,
): Promise<Doc> {
return fetch<Doc>(`/api/v1.0/documents/${name}/`, requestHeaders);
const params = withoutContent ? '?without_content=true' : '';
return fetch<Doc>(`/api/v1.0/documents/${name}/${params}`, requestHeaders);
}

export function fetchCurrentUser(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ export const hocuspocusServer = new Server({
let canEdit;

try {
const document = await fetchDocument(documentName, requestHeaders);
const document = await fetchDocument(
{ name: documentName, withoutContent: true },
requestHeaders,
);

if (!document.abilities.retrieve) {
logger(
Expand Down
Loading