-
Notifications
You must be signed in to change notification settings - Fork 39
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
Handle missing files during an export and open #566
Conversation
b1eba24
to
48c7f13
Compare
Note: this fixes an unhandled FileNotFoundError which crashes the app |
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.
this is nice! one other thought: we might want to mark the file as not downloaded such that the user could then redownload the file (right now it's still marked as downloaded in the database so the download button isn't shown)
48c7f13
to
4ac6354
Compare
I had to rebase due to conflicts. I addressed the PR comment about displaying the "Download" link when the file is missing during either an open or export operation. I also added some cleanup code after export using the new |
Finished writing unit tests. For manual testing, here's what you should do: Regression Test
Testing new behavior for File Open
Testing new behavior for File Export
|
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.
this looks great! from some testing in Qubes:
✅ Regression test: Opening multiple times in dispVM success
✅ Regression test: Export multiple times to USB drive success
✅ New behavior: after file is deleted, after open attempt an error message is shown and on the next sync, download link appears (we'll need to eventually update this file widget via a signal but let's leave this for a followup)
✅ New behavior: after file is deleted and download link appears, then file can be redownloaded and opened successfully
✅ New behavior: after file is deleted and export is clicked, after export an error message is shown and on next sync the download link appears
✅ New behavior: after file is deleted and download link appears, then file can be redownloaded and exported successfully
securedrop_client/logic.py
Outdated
storage.mark_as_not_downloaded(file_uuid, self.session) | ||
self.sync_api() | ||
logger.debug(msg) | ||
self.gui.update_error_status(msg) |
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.
hmm so we have this same stanza in three places (almost) repeated other than the msg having "export" or "open" - what do you think about adding another method for this logic called e.g. _check_if_file_exists
? I think it would also make reading this function a bit clearer. We could also make the error message generic so we don't even need to pass in the operation: "Could not complete action on file {}. File does not exist"
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.
I like your _check_if_file_exists
suggestion since we use it in three places: opening a file, preflight check, and exporting a file.
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.
actually thinking about this more, it would make more sense to verify the file system accurately reflects the local db during a sync rather than whenever the user tries to access the file. i'll modify the code so that we:
- check that the file exists and maybe use https://pypi.org/project/filelock/ so make sure it can't be accessed during open or export
- mark the file to be redownloaded if it's missing during a sync
securedrop_client/logic.py
Outdated
storage.mark_as_not_downloaded(file_uuid, self.session) | ||
self.sync_api() | ||
logger.debug(msg) | ||
self.gui.update_error_status(msg) |
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.
the other thing we need to decide is how to close the export dialog in the file not found case. some options:
- Add a little method on the
Export
object that closes theExportDialog
, which we can call from the controller. This would work, but I don't love this approach because there already is a method for handling errors in the export process which is via the pre_flight and usb failure signals. - At this failure stage, emit the pre_flight or usb export failure signal and modify
ExportDialog._update
to handle a new error status: when the file is not there. TheExportDialog
can just close in this case because we are showing the error in the main window. - Move this file not found logic to before the export dialog even pops up.
I'm a fan of either 2 or 3. What do you think?
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.
yeah, right now, we just wait for the gui to refresh before the dialog closes when the file is missing. i think using the failure signal makes the most sense since the file could be deleted while the dialog is open so it would be good to be able to have code in place to close the dialog upon a file missing error.
6d3e940
to
83d5e7f
Compare
this has been fixed and now syncing includes marking files as not downloaded if they are missing from the file system. this is useful if say a user decided to move a bunch of files in the data directory (people working in qubes often run linux commands so this is plausible but user testing will be helpful here) and now we will set them all to be marked as not downloaded rather than waiting unti lthe user tries to open one. |
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.
lgtm! Retested the export scenarios with the latest changes: the export UI does not appear in the file missing case and export to USB occurs without issue once the file is redownloaded
@@ -1799,6 +1799,10 @@ def _on_export_clicked(self): | |||
""" | |||
Called when the export button is clicked. | |||
""" | |||
if not self.controller.downloaded_file_exists(self.file.uuid): | |||
self.controller.sync_api() |
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.
do we need to resync the API? we could just update the file with is_downloaded=False
and then update the UI. I'll file a followup for this though since imho we'll should do this via sending a signal to FileWidget
which is a larger change
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.
I think maybe we could do both? Let's discuss in the followup ticket you opened.
Description
Tells the user that the file they're trying to export is missing from the file system. Next step is to show a Download link once again for the file that no longer exists on the filesystem, captured in this issue: #565