Skip to content
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

Merged
merged 3 commits into from
Feb 3, 2017
Merged

Improve create picture validation #13697

merged 3 commits into from
Feb 3, 2017

Conversation

jntullo
Copy link

@jntullo jntullo commented Jan 30, 2017

This PR improves validation for creating pictures via the api by:

  • validating the presence of content
  • validating that the content is in the expected format (base64) via Base64.strict_decode64

@miq-bot assign @abellotti
@miq-bot add_label enhancement, api

cc: @imtayadeway

@@ -1,11 +1,26 @@
module Api
class PicturesController < BaseController
def create_resource(_type, _id, data)
validate_picture_data(data)
Copy link
Contributor

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?

Copy link
Author

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.

Copy link
Contributor

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?

@abellotti
Copy link
Member

I'm 👍 with this. @imtayadeway ?

@jntullo
Copy link
Author

jntullo commented Feb 1, 2017

@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'])
Copy link
Author

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

Copy link
Author

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

@@ -1,15 +1,25 @@
describe Picture do
subject { FactoryGirl.build :picture }

before do
Copy link
Contributor

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?

@@ -90,6 +95,28 @@
end
end

context '#create_from_base64' do
Copy link
Contributor

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') }
Copy link
Contributor

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)

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) }
Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Author

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 😳

Copy link
Contributor

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"

Copy link
Contributor

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

@@ -1,4 +1,7 @@
FactoryGirl.define do
factory :picture do
after(:build) do |x|
Copy link
Contributor

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?

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Contributor

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

@@ -1,15 +1,21 @@
describe Picture do
subject { FactoryGirl.build :picture }
subject { FactoryGirl.build(:picture, :content => 'foo') }
Copy link
Contributor

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?

Copy link
Author

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

@imtayadeway
Copy link
Contributor

@jntullo this is looking great. Couple of nits above, but 👍

@abellotti
Copy link
Member

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).

@abellotti
Copy link
Member

We should also have the model check for the extension existence and validity (png, jpg, svg).

adding content to picture factory

update specs
@miq-bot
Copy link
Member

miq-bot commented Feb 3, 2017

Checked commits jntullo/manageiq@2a47718~...cb92bf1 with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
5 files checked, 0 offenses detected
Everything looks good. 🍰

"MS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3Jp"\
"ZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpS"\
"REY+CjwveDp4bXBtZXRhPgpMwidZAAAADUlEQVQIHWNgYGCwBQAAQgA+3N0+"\
"xQAAAABJRU5ErkJggg=="
Copy link
Member

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.

Copy link
Author

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

@abellotti abellotti added this to the Sprint 54 Ending Feb 13, 2017 milestone Feb 3, 2017
@abellotti
Copy link
Member

Thanks @jntullo 👍

@abellotti abellotti merged commit 31d19f2 into ManageIQ:master Feb 3, 2017
@jntullo jntullo deleted the enhancement/pictures_api_validation branch February 3, 2017 15:26
@himdel
Copy link
Contributor

himdel commented Feb 3, 2017

When adding euwe/yes or euwe/no, please add the same to ManageIQ/manageiq-ui-classic#299.

martinpovolny pushed a commit to martinpovolny/manageiq-ui-classic that referenced this pull request Feb 7, 2017
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants