-
Notifications
You must be signed in to change notification settings - Fork 898
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
Improve create picture validation #13697
Improve create picture validation #13697
Conversation
@@ -1,11 +1,26 @@ | |||
module Api | |||
class PicturesController < BaseController | |||
def create_resource(_type, _id, data) | |||
validate_picture_data(data) |
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.
Did you consider putting this validation in the Picture
model?
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.
@imtayadeway I did, actually. I actually looked into validating the actual content type to ensure it is a picture via Paperclip (they have built in validation for attachments that I thought I could leverage since we already use it) and some other methods. It wasn't that straight forward though, so I felt like I was going down a rabbit hole. However if you think that's the way I should go, I can spend more time on it.
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.
@jntullo I'm guessing that if there was (or ever is) a way to great a bogus picture outside of this controller, and that's not wanted for the same reason, then it may belong in the model. I am assuming here that this is the case, but I don't know if that is so. But if it is, is there a way to push what logic you have here down into the model and then maybe iterate on it to see if you can delegate to Paperclip as a follow up?
I'm 👍 with this. @imtayadeway ? |
@abellotti will have some updates up shortly 😄 |
use strict_decode to validate base64 encryption
picture | ||
raise 'requires content' unless data['content'] | ||
Picture.new(data.except('content')).tap do |picture| | ||
picture.content = Base64.strict_decode64(data['content']) |
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.
@imtayadeway strict_decode64 still doesn't like nils, so I had to keep in the requires content
validation
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.
@imtayadeway no it doesn't, so I raise requires content
if it's not present
spec/models/picture_spec.rb
Outdated
@@ -1,15 +1,25 @@ | |||
describe Picture do | |||
subject { FactoryGirl.build :picture } | |||
|
|||
before do |
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.
Did you consider doing subject { FactoryGirl.build(:picture, :content => "foo") }
above?
spec/models/picture_spec.rb
Outdated
@@ -90,6 +95,28 @@ | |||
end | |||
end | |||
|
|||
context '#create_from_base64' do |
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, but this should be .create_from_base64
@@ -13,7 +13,7 @@ | |||
let(:ra1) { FactoryGirl.create(:resource_action, :action => "Provision", :dialog => dialog1) } | |||
let(:ra2) { FactoryGirl.create(:resource_action, :action => "Retirement", :dialog => dialog2) } | |||
|
|||
let(:picture) { FactoryGirl.create(:picture, :extension => "jpg") } | |||
let(:picture) { FactoryGirl.create(:picture, :extension => "jpg", :content => 'foo') } |
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'm assuming that this needed to be added because it fails to create now that :content
is required. I think it would be a good idea to add this to the factory, and then this doesn't need to be changed (assuming that it doesn't test any behavior that's specific to the content)
spec/requests/api/picture_spec.rb
Outdated
let(:dialog1) { FactoryGirl.create(:dialog, :label => "ServiceDialog1") } | ||
let(:ra1) { FactoryGirl.create(:resource_action, :action => "Provision", :dialog => dialog1) } | ||
let(:picture) { FactoryGirl.create(:picture, :extension => "jpg") } | ||
let(:picture) { FactoryGirl.create(:picture, :extension => "jpg", :content => content) } |
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.
Doesn't this give the picture a with un-decoded content? Which I know probably doesn't matter, but it does help the next person looking at this 😄
@@ -63,26 +67,10 @@ def expect_result_to_include_picture_href(source_id) | |||
end | |||
|
|||
describe 'POST /api/pictures' do | |||
# one pixel png image encoded in Base64 |
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.
Even though this looks like gibberish, I sort of liked this because it was a technically a valid image, giving anyone looking for documentation in these specs some idea of what to expect. The shorter, valid base 64 code above may suffice though. @abellotti any thoughts?
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.
@imtayadeway strict_decode64
had some issues with all of the newlines. Apparently it might not have been base64 😳
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.
Ah, that makes sense. So you'd need a really really really long line 😝
Or, you could use this pattern:
"foo"\
"bar"\
"baz" # => "foobarbaz"
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.
Or, you could store the pixel as a fixture on the disk? I don't know.....could all be OTP
spec/factories/picture.rb
Outdated
@@ -1,4 +1,7 @@ | |||
FactoryGirl.define do | |||
factory :picture do | |||
after(:build) do |x| |
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.
Does content "foo"
not work here?
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.
@imtayadeway no
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 seems like a bug to me. It should use the custom setter internally
spec/models/picture_spec.rb
Outdated
@@ -1,15 +1,21 @@ | |||
describe Picture do | |||
subject { FactoryGirl.build :picture } | |||
subject { FactoryGirl.build(:picture, :content => 'foo') } |
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.
Is this change still needed, since you updated the factory?
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.
@imtayadeway nope. meant to remove this
@jntullo this is looking great. Couple of nits above, but 👍 |
In the latest commits, I didn't see the API tests, even though we're leveraging the model for picture validation, the API should have the 3 tests, missing extension, missing content and invalid picture (model validation failure caught by API and returning the BadRequestError). |
We should also have the model check for the extension existence and validity (png, jpg, svg). |
adding content to picture factory update specs
Checked commits jntullo/manageiq@2a47718~...cb92bf1 with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0 |
"MS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3Jp"\ | ||
"ZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpS"\ | ||
"REY+CjwveDp4bXBtZXRhPgpMwidZAAAADUlEQVQIHWNgYGCwBQAAQgA+3N0+"\ | ||
"xQAAAABJRU5ErkJggg==" |
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 the updates @jntullo, question about above change that is driven by using strict_decode64. does this mean we just broke compatibility with v2.3.0 or the old usage with \n would never really occur ? How does the current service-ui generate the content in these payloads ? Thanks.
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.
@abellotti the old usage with \n
would never occur. When thinking about it, not really sure why I put that there in the first place, it's a mistake on my part. The current service-ui isn't uploading pictures via the pictures API - yet
Thanks @jntullo 👍 |
When adding |
because of new validations added to Picture in ManageIQ/manageiq#13697, a Picture model always requires content and extension, and can't be created using argumentless Picture.new anymore. Updating CatalogController to either create the model directly, or update the existing one.
This PR improves validation for creating pictures via the api by:
Base64.strict_decode64
@miq-bot assign @abellotti
@miq-bot add_label enhancement, api
cc: @imtayadeway