mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add /attachments/removeUnused DocApi endpoint to hard delete all unused attachments in document
Summary: Adds methods to delete metadata rows based on timeDeleted. The flag expiredOnly determines if it only deletes attachments that were soft-deleted 7 days ago, or just all soft-deleted rows. Then any actual file data that doesn't have matching metadata is deleted. Test Plan: DocApi test Reviewers: paulfitz Reviewed By: paulfitz Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D3364
This commit is contained in:
@@ -1562,7 +1562,7 @@ function testDocApi() {
|
||||
let resp = await axios.post(`${docUrl}/apply`, actions, chimpy);
|
||||
assert.equal(resp.status, 200);
|
||||
|
||||
resp = await axios.post(`${docUrl}/attachments/updateUsed`, actions, chimpy);
|
||||
resp = await axios.post(`${docUrl}/attachments/updateUsed`, null, chimpy);
|
||||
assert.equal(resp.status, 200);
|
||||
|
||||
resp = await axios.get(`${docUrl}/tables/Table1/records`, chimpy);
|
||||
@@ -1670,6 +1670,57 @@ function testDocApi() {
|
||||
_.range(totalAttachments).map(index => ({id: index + 1, deleted: index >= totalUsedAttachments})),
|
||||
);
|
||||
});
|
||||
|
||||
it("POST /docs/{did}/attachments/removeUnused removes unused attachments", async function() {
|
||||
const wid = await getWorkspaceId(userApi, 'Private');
|
||||
const docId = await userApi.newDoc({name: 'TestDoc3'}, wid);
|
||||
const docUrl = `${serverUrl}/api/docs/${docId}`;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('upload', 'foobar', "hello.doc");
|
||||
formData.append('upload', '123456', "world.jpg");
|
||||
formData.append('upload', 'foobar', "hello2.doc");
|
||||
let resp = await axios.post(`${docUrl}/attachments`, formData,
|
||||
defaultsDeep({headers: formData.getHeaders()}, chimpy));
|
||||
assert.equal(resp.status, 200);
|
||||
assert.deepEqual(resp.data, [1, 2, 3]);
|
||||
|
||||
async function checkAttachmentIds(ids: number[]) {
|
||||
resp = await axios.get(
|
||||
`${docUrl}/tables/_grist_Attachments/records`,
|
||||
chimpy,
|
||||
);
|
||||
assert.equal(resp.status, 200);
|
||||
assert.deepEqual(resp.data.records.map((r: any) => r.id), ids);
|
||||
}
|
||||
|
||||
resp = await axios.patch(
|
||||
`${docUrl}/tables/_grist_Attachments/records`,
|
||||
{
|
||||
records: [
|
||||
{id: 1, fields: {timeDeleted: Date.now() / 1000 - 8 * 24 * 60 * 60}}, // 8 days ago, i.e. expired
|
||||
{id: 2, fields: {timeDeleted: Date.now() / 1000 - 6 * 24 * 60 * 60}}, // 6 days ago, i.e. not expired
|
||||
]
|
||||
},
|
||||
chimpy,
|
||||
);
|
||||
assert.equal(resp.status, 200);
|
||||
await checkAttachmentIds([1, 2, 3]);
|
||||
|
||||
// Remove the expired attachment (1)
|
||||
// It has a duplicate (3) that hasn't expired and thus isn't removed,
|
||||
// although they share the same fileIdent and row in _gristsys_Files.
|
||||
// So for now only the metadata is removed.
|
||||
resp = await axios.post(`${docUrl}/attachments/removeUnused?verifyfiles=1&expiredonly=1`, null, chimpy);
|
||||
assert.equal(resp.status, 200);
|
||||
await checkAttachmentIds([2, 3]);
|
||||
|
||||
// Remove the not expired attachments (2 and 3).
|
||||
// We didn't set a timeDeleted for 3, but it gets set automatically by updateUsedAttachments.
|
||||
resp = await axios.post(`${docUrl}/attachments/removeUnused?verifyfiles=1`, null, chimpy);
|
||||
await checkAttachmentIds([]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("GET /docs/{did}/download serves document", async function() {
|
||||
|
||||
Reference in New Issue
Block a user