-
-
Notifications
You must be signed in to change notification settings - Fork 419
Prevents documents being copied with external attachments #1433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
fccdb25
e372766
dbcb50b
ffe679b
d678b5e
43b7607
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2433,23 +2433,32 @@ function testDocApi(settings: { | |
|
||
}); | ||
|
||
async function addAttachmentsToDoc(docId: string, attachments: {name: string, contents: string}[], | ||
user: AxiosRequestConfig = chimpy) { | ||
const formData = new FormData(); | ||
for (const attachment of attachments) { | ||
formData.append('upload', attachment.contents, attachment.name); | ||
} | ||
const resp = await axios.post(`${serverUrl}/api/docs/${docId}/attachments`, formData, | ||
defaultsDeep({headers: formData.getHeaders()}, user)); | ||
assert.equal(resp.status, 200); | ||
assert.equal(resp.data.length, attachments.length); | ||
return resp; | ||
} | ||
|
||
describe('attachments', function () { | ||
it("POST /docs/{did}/attachments adds attachments", async function () { | ||
let formData = new FormData(); | ||
formData.append('upload', 'foobar', "hello.doc"); | ||
formData.append('upload', '123456', "world.jpg"); | ||
let resp = await axios.post(`${serverUrl}/api/docs/${docIds.TestDoc}/attachments`, formData, | ||
defaultsDeep({headers: formData.getHeaders()}, chimpy)); | ||
assert.equal(resp.status, 200); | ||
assert.deepEqual(resp.data, [1, 2]); | ||
const uploadResp = await addAttachmentsToDoc(docIds.TestDoc, [ | ||
{ name: 'hello.doc', contents: 'foobar' }, | ||
{ name: 'world.jpg', contents: '123456' }, | ||
], chimpy); | ||
assert.deepEqual(uploadResp.data, [1, 2]); | ||
|
||
// Another upload gets the next number. | ||
formData = new FormData(); | ||
formData.append('upload', 'abcdef', "hello.png"); | ||
resp = await axios.post(`${serverUrl}/api/docs/${docIds.TestDoc}/attachments`, formData, | ||
defaultsDeep({headers: formData.getHeaders()}, chimpy)); | ||
assert.equal(resp.status, 200); | ||
assert.deepEqual(resp.data, [3]); | ||
const upload2Resp = await addAttachmentsToDoc(docIds.TestDoc, [ | ||
{ name: 'hello.png', contents: 'abcdef' }, | ||
], chimpy); | ||
assert.deepEqual(upload2Resp.data, [3]); | ||
}); | ||
|
||
it("GET /docs/{did}/attachments lists attachment metadata", async function () { | ||
|
@@ -2753,14 +2762,11 @@ function testDocApi(settings: { | |
docId = await userApi.newDoc({name: 'TestDocExternalAttachments'}, wid); | ||
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"); | ||
const resp = await axios.post(`${docUrl}/attachments`, formData, | ||
defaultsDeep({headers: formData.getHeaders()}, chimpy)); | ||
assert.equal(resp.status, 200); | ||
assert.deepEqual(resp.data, [1, 2, 3]); | ||
await addAttachmentsToDoc(docId, [ | ||
{ name: 'hello.doc', contents: 'foobar' }, | ||
{ name: 'world.jpg', contents: '123456' }, | ||
{ name: 'hello2.doc', contents: 'foobar' } | ||
], chimpy); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You removed the last assert here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved it into the I'll re-add the exact ID check to be safe. |
||
}); | ||
|
||
after(async () => { | ||
|
@@ -2804,6 +2810,23 @@ function testDocApi(settings: { | |
locationSummary: "internal", | ||
}); | ||
}); | ||
|
||
it("POST /docs/{did}/copy fails when the document has external attachments", async function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about forking? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forking works correctly under the external attachments model - forks use their parent's document pool, so that doesn't need blocking. I did test with forks and the copy block, and "Save to copy" is also correctly blocked in a document fork. |
||
const worker1 = await userApi.getWorkerAPI(docId); | ||
await assert.isRejected(worker1.copyDoc(docId, undefined, 'copy'), /status 400/); | ||
}); | ||
|
||
it("POST /docs/{did} with sourceDocId fails to copy a document with external attachments", async function () { | ||
const chimpyWs = await userApi.newWorkspace({name: "Chimpy's Workspace"}, ORG_NAME); | ||
const resp = await axios.post(`${serverUrl}/api/docs`, { | ||
sourceDocumentId: docId, | ||
documentName: 'copy of TestDocExternalAttachments', | ||
asTemplate: false, | ||
workspaceId: chimpyWs | ||
}, chimpy); | ||
assert.equal(resp.status, 400); | ||
assert.match(resp.data.error, /external attachments/); | ||
}); | ||
}); | ||
}); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should /attachments/store also be canView for consistency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a little leakier, as it reveals (in the future) user label and maybe store type to unauthenticated users.
Happy with either, I'm not sure if that's a security concern or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said - all that info is in the downloaded Grist doc, thinking about it, so it's not private info. So yes, we could make it canView.