Skip to content

LG-3204: Create Image Upload API#3985

Closed
ironman5366 wants to merge 23 commits intomasterfrom
will-3204
Closed

LG-3204: Create Image Upload API#3985
ironman5366 wants to merge 23 commits intomasterfrom
will-3204

Conversation

@ironman5366
Copy link
Copy Markdown
Contributor

This creates an API endpoint that images can be asynchronously uploaded to, to fulfill the Document Capture step.

The API endpoint is at /api/verify/upload, and it accepts a POST containing the JSON attributes front, back, and selfie. In this first version, it returns just a status of either success or error, and a string message which is an explanation of that status.

@ironman5366 ironman5366 marked this pull request as ready for review July 29, 2020 17:25
Comment on lines +55 to +60
def error_json(reason)
{
status: 'error',
message: reason,
}
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What status code are we returning in the error case? Is it still going to be 200 OK ?

Asking because it's something where we should probably want the status code to match the response status here, and in doing so, we could perform success / error handling on the basis of status code alone. i.e. we wouldn't need status at all, if the HTTP status code is enough of a signal.

@aduth
Copy link
Copy Markdown
Contributor

aduth commented Aug 6, 2020

I merged in master in 2bb4deb to bring the branch back up to date, resolving conflicts with some of the new logging changes (#4001, #4007), and to preemptively address an issue I'd encountered in starting to wire up the front-end to the new endpoint (#4013). I see some test failures related to the logging changes, which I'm unclear yet if are due to an incompatibility of the changes, or an error on my part in resolving the conflicts.

I pushed a few changes in ad271a0 and d6fda5f based on my prior feedback, incorporating the CSRF token management into the existing upload context, in a way that allows the upload implementation to receive the token as an argument automatically. d6fda5f replaces the stubbed upload implementation with a real one, using this new endpoint:

The form now sends and receives real data 🎉

submission complete

jmhooper added a commit that referenced this pull request Aug 10, 2020
**Why**: @ironman5366 introduced this pattern in that PR. It is very helpful for moving to the API. It can stands on its own and cleans things up. I moved the changes to this PR to help decompose that one a bit.
jmhooper added a commit that referenced this pull request Aug 10, 2020
**Why**: @ironman5366 introduced this pattern in that PR. It is very helpful for moving to the API. It can stands on its own and cleans things up. I moved the changes to this PR to help decompose that one a bit.
nil
end

def check_content_type(request)
Copy link
Copy Markdown
Contributor

@aduth aduth Aug 12, 2020

Choose a reason for hiding this comment

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

I marked my original comment as resolved, but flagging @zachmargolis's comment at #3985 (comment) for follow-up.

Also should we 415 for this? https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/415

**Why**: Type-checking for free
Comment on lines +5 to +6
api_upload = flow_session['api_upload']
response = (api_upload && api_upload['documents']) || post_form_images
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can take advantage of Hash#dig here I think:

Suggested change
api_upload = flow_session['api_upload']
response = (api_upload && api_upload['documents']) || post_form_images
response = flow_session.dig('api_upload', 'documents') || post_form_images

Comment on lines +13 to +14
selfie = selfie_image ? selfie_image.read : nil
post_images(front_image.read, back_image.read, selfie)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can do the nil-safe operator (or .try but I think rubocop prefers nil-safe these days)

Suggested change
selfie = selfie_image ? selfie_image.read : nil
post_images(front_image.read, back_image.read, selfie)
post_images(front_image.read, back_image.read, selfie_image&.read)

end

def handle_response(response)
if response.to_h[:success]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

usually our response objects have .success?

Suggested change
if response.to_h[:success]
if response.success?

Comment on lines +58 to +60
'front': 'front_image',
'back': 'back_image',
'selfie': 'selfie_image',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can drop the quotes on these keys, they're still symbols (and same for the others in this file)

Suggested change
'front': 'front_image',
'back': 'back_image',
'selfie': 'selfie_image',
front: 'front_image',
back: 'back_image',
selfie: 'selfie_image',

Comment on lines +47 to +53
def check_image_fields(request)
data = request.body.read
@front_image = data['front']
@back_image = data['back']
@selfie_image = data['selfie']
'Missing image keys' unless [@front_image, @back_image, @selfie_image].all?
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This has a side effect of setting the instance variables, so I think the name check_ is a little misleading.... honestly, the keys are straightforward I would consider not even setting them as instance variables at all and just checking for their presence

Comment on lines +35 to +40
steps = %i[check_content_type check_image_fields]
steps.each do |step|
err = method(step).call(request)
return error_json(err) if err
end
nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With only two steps.... I don't think this is a great use for this level of dynamic behavior, there are a few alternatives I would prefer (in order of most to least preferred)

  1. Let's make a Form object -- we do this is many other controllers, make a form object that performs the validations and returns useful error structures the controllers know how to render (LMK if you need a more detailed example)

  2. Move these into before actions, so that way they can just render and stop the chain (instead of having a loop to check for errors and stop)

     before_action :check_content_type, only: [:upload]
     before_action :check_image_fields, only[:upload]
  3. Just call the methods directly:

    error = check_content_type(request) || check_image_fields(request)
    error_json(err) ir err

post '/api/sms/receive' => 'sms#receive'

# Image upload API for doc auth
post '/api/verify/upload' => 'idv/image_upload#upload'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sometimes we try to stick to built-in rails method names/actions to be "RESTful"1 as much as we can, WDYT of renaming this to #create?


  1. I think "RESTful" is kind of a garbage term and can mean anything... in this case I'm just saying let's use the default names in rails for CRUD verbs

@zachmargolis
Copy link
Copy Markdown
Contributor

@aduth this is starting to diverge from master branch a bunch... I think it's time to close this branch out and I was planning on opening a new PR with just the backend changes for image uploading, is that OK with you?

@aduth
Copy link
Copy Markdown
Contributor

aduth commented Aug 13, 2020

@aduth this is starting to diverge from master branch a bunch... I think it's time to close this branch out and I was planning on opening a new PR with just the backend changes for image uploading, is that OK with you?

Sure, that's fine with me 👍

@aduth aduth deleted the will-3204 branch August 18, 2020 12:04
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.

4 participants