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
Weblab: files api unescaping and asset manager delete fix #14166
Weblab: files api unescaping and asset manager delete fix #14166
Conversation
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.
Overall approach looks good. It looks like we need new unit tests to go along with the files_api.rb changes. I'm also not sure whether the test_property_limits_enforced
failure on Circle is caused by your changes, but it's at least tangentially related so worth checking out.
shared/middleware/files_api.rb
Outdated
manifest_is_unchanged = false | ||
|
||
existing_entry = manifest.detect {|e| e['filename'].downcase == filename.downcase} | ||
existing_entry = manifest.detect {|e| e['filename'].downcase == CGI.unescape(filename).downcase} |
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.
Nit: Probably not very expensive, but since we're always going to call CGI.unescape
in this method we might as well only call it once and reuse the result - then we won't be doing it in a loop here. Likewise with the downcase
variant which shows up in a couple of loops.
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.
Updated
Added unit test for escaping. |
@@ -487,10 +487,11 @@ def files_put_file(encrypted_channel_id, filename, body) | |||
end | |||
new_entry_hash = JSON.parse new_entry_json | |||
# Replace downcased filename with original filename (to preserve case in the manifest) | |||
new_entry_hash['filename'] = filename | |||
new_entry_hash['filename'] = CGI.unescape(filename) |
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.
Codecov reports none of this code has been exercised, even though you just wrote a unit test. I suspected that coverage reporting for shared tests is broken, so I went ahead and pulled the branch to see if I could easily make this test fail by reversing your API changes.
It was harder to break than I expected, so I'm a little concerned that your new behavior isn't covered.
-
All of
test_files.rb
still passes if I delete all but one use ofdowncase
from thefiles_put_file
method (thedowncase
call on line 486 seems to be the one that's required to pass).test_case_insensitivity
fails if I remove that last use ofdowncase
. -
All of
test_files.rb
still passes if I delete all uses ofCGI.unescape
from thefiles_put_file
but use the existing VCR fixtures. If I run without VCRtest_escaping_insensitivity
still passes if I remove theCGI.unescape
call at line 507.
So I still think coverage might be broken since I was able to break the tests with some changes to these methods (@pcardune any ideas?), but I also think there are quite a few uncovered branches here that we should revisit. Let's not block the bugfix going in on getting this figured out, but do it as a follow-up instead.
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.
Thanks for looking in to this. One possible case that is probably not tested is the rename operation where the old name could be unescaped, though in practice that is hard to do since it is a query parameter.
However, the bigger issue that I had is that our test helper method get_object
doesn't like unescaped paths (probably at the Rack::Test::Methods
level). So the tests for now verify that creating files with either unescaped or escaped paths will both work equally well - and can be retrieved and deleted using escaped paths.
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 don't think tests in shared contribute to coverage reports at the moment, only tests in dashboard. So the coverage we are seeing here is probably from what dashboard tests are generating.
deleteAssetRow()
had a bug where it resetassets
based on the return value ofassetListStore.remove()
- which ignored the extension filtering that normally happens insideassetListStore.list()
. So nowdeleteAssetRow()
follows the pattern ofonUploadDone()
: it modifiesassetListStore
, then notifies that the assets have changed, then it updates theassets
by callingassetListStore.list()
with theallowedExtensions
parameter.{"filename":"puppy%20dog.jpeg"}
). We now standardize on storing unescaped filenames (e.g.{"filename":"puppy dog.jpeg"}
) and whenever we make explicit comparisons with entries in the manifest, we also unescape the filename we are comparing.