Skip to content

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

Merged
merged 6 commits into from
Feb 17, 2025

Conversation

Spoffy
Copy link
Contributor

@Spoffy Spoffy commented Feb 7, 2025

Context

When external attachments are uploaded, they are placed in a folder in the external storage called a 'document pool', which is specific to the document it was uploaded.

When a document is copied, the new copy has a different document pool. This means any external attachments in the document will be broken, and show as unavailable.

Proposed solution

This blocks the copying of documents with external attachments, until copy behaviour can be implemented in the future.

Related issues

#1021

Has this been tested?

  • 👍 yes, I added tests to the test suite
  • 💭 no, because this PR is a draft and still needs work
  • 🙅 no, because this is not relevant here
  • 🙋 no, because I need help

@Spoffy
Copy link
Contributor Author

Spoffy commented Feb 7, 2025

This may seem like an odd place to add this check to (the fetchDoc function), but it's only used right now by functions which do copying.

This felt like an okay approach for now, but I'm open to refactors if desired, such as renaming the function or creating a new copyDoc function which wraps it.

@@ -2803,6 +2809,23 @@ function testDocApi(settings: {
locationSummary: "internal",
});
});

it("POST /docs/{did}/copy fails when the document has external attachments", async function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about forking?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 attachmentsLocation: DocAttachmentsLocation = (await transferStatusResponse.json()).locationSummary;
if (attachmentsLocation !== 'internal' && attachmentsLocation !== 'none') {
throw new ApiError("Cannot copy a document with external attachments", 400);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the options object you have template parameter. When it is passed here as true it means that user wants to copy the structure, not the data. So in this case it should be allowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really good catch, thanks :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be sorted now :)

@Spoffy Spoffy force-pushed the spoffy/external-attachments-copy-block branch from 1f7fdee to fccdb25 Compare February 11, 2025 14:41
@@ -534,7 +534,7 @@ export class DocWorkerApi {
}));

// Returns the status of any current / pending attachment transfers
this._app.get('/api/docs/:docId/attachments/transferStatus', isOwner, withDoc(async (activeDoc, req, res) => {
this._app.get('/api/docs/:docId/attachments/transferStatus', canView, withDoc(async (activeDoc, req, res) => {
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@berhalak berhalak self-requested a review February 13, 2025 12:58
Copy link
Contributor

@berhalak berhalak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. One comment for tests.

{ name: 'hello.doc', contents: 'foobar' },
{ name: 'world.jpg', contents: '123456' },
{ name: 'hello2.doc', contents: 'foobar' }
], chimpy);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed the last assert here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it into the addAttachmentsToDoc function - although it's now a length check rather than an exact ID check.

I'll re-add the exact ID check to be safe.

@Spoffy Spoffy merged commit c0f307c into main Feb 17, 2025
12 checks passed
@Spoffy Spoffy deleted the spoffy/external-attachments-copy-block branch February 17, 2025 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants