fix: Restore policy for documents too broad (#11279)

This commit is contained in:
Tom Moor
2026-01-26 22:46:02 -05:00
committed by GitHub
parent fcd40a93a4
commit 529b7e45de
2 changed files with 49 additions and 3 deletions
+6 -3
View File
@@ -211,7 +211,11 @@ allow(User, "delete", Document, (actor, document) =>
or(
can(actor, "unarchive", document),
can(actor, "update", document),
and(!document?.isWorkspaceTemplate, !document?.collection)
and(
!document?.isWorkspaceTemplate,
!document?.collection,
actor.id === document?.createdById
)
)
)
);
@@ -231,8 +235,7 @@ allow(User, "restore", Document, (actor, document) =>
and(
!!document?.isWorkspaceTemplate,
can(actor, "updateTemplate", actor.team)
),
!document?.collection
)
)
)
);
@@ -2998,6 +2998,31 @@ describe("#documents.restore", () => {
expect(body.data.collectionId).toEqual(collection.id);
});
it("should not allow restore of another user's trashed draft", async () => {
const user = await buildUser();
const anotherUser = await buildUser({ teamId: user.teamId });
const collection = await buildCollection({
userId: user.id,
teamId: user.teamId,
});
const document = await buildDraftDocument({
userId: anotherUser.id,
teamId: user.teamId,
collectionId: null,
});
await document.destroy();
const res = await server.post("/api/documents.restore", {
body: {
token: user.getJwtToken(),
id: document.id,
collectionId: collection.id,
},
});
expect(res.status).toEqual(403);
});
it("should allow restore of trashed documents", async () => {
const user = await buildUser();
const document = await buildDocument({
@@ -4496,6 +4521,24 @@ describe("#documents.delete", () => {
expect(deletedDoc?.deletedAt).toBeTruthy();
});
it("should not allow deleting another user's draft without collection", async () => {
const user = await buildUser();
const anotherUser = await buildUser({ teamId: user.teamId });
const document = await buildDraftDocument({
teamId: user.teamId,
userId: anotherUser.id,
collectionId: null,
});
const res = await server.post("/api/documents.delete", {
body: {
token: user.getJwtToken(),
id: document.id,
},
});
expect(res.status).toEqual(403);
});
it("should delete a draft under deleted collection", async () => {
const user = await buildUser();
const collection = await buildCollection({