Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions app/services/doc_auth/acuant/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,20 @@ def create_error_response(errors, exception)
end

def handle_expected_http_error(http_response)
error = case http_response.status
when 438
Errors::IMAGE_LOAD_FAILURE
when 439
Errors::PIXEL_DEPTH_FAILURE
when 440
Errors::IMAGE_SIZE_FAILURE
end

create_error_response({ general: [error] }, create_http_exception(http_response))
errors = errors_from_http_status(http_response.status)
create_error_response(errors, create_http_exception(http_response))
end

def errors_from_http_status(status)
error = case status
when 438
Errors::IMAGE_LOAD_FAILURE
when 439
Errors::PIXEL_DEPTH_FAILURE
when 440
Errors::IMAGE_SIZE_FAILURE
end
{ general: [error] }
Comment thread
dawei-nava marked this conversation as resolved.
end

def handle_invalid_response(http_response)
Expand Down
23 changes: 23 additions & 0 deletions app/services/doc_auth/acuant/requests/get_results_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ def metric_name
def timeout
IdentityConfig.store.acuant_get_results_timeout
end

def errors_from_http_status(status)
case status
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.

👍🏻

when 438
{
general: [Errors::IMAGE_LOAD_FAILURE],
front: [Errors::IMAGE_LOAD_FAILURE_FIELD],
back: [Errors::IMAGE_LOAD_FAILURE_FIELD],
}
when 439
{
general: [Errors::PIXEL_DEPTH_FAILURE],
front: [Errors::PIXEL_DEPTH_FAILURE_FIELD],
back: [Errors::PIXEL_DEPTH_FAILURE_FIELD],
}
when 440
{
general: [Errors::IMAGE_SIZE_FAILURE],
front: [Errors::IMAGE_SIZE_FAILURE_FIELD],
back: [Errors::IMAGE_SIZE_FAILURE_FIELD],
}
end
end
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions app/services/doc_auth/acuant/requests/upload_image_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@ def metric_name
def timeout
IdentityConfig.store.acuant_upload_image_timeout
end

def errors_from_http_status(status)
case status
when 438
{
general: [Errors::IMAGE_LOAD_FAILURE],
side.downcase.to_sym => [Errors::IMAGE_LOAD_FAILURE_FIELD],
}
when 439
{
general: [Errors::PIXEL_DEPTH_FAILURE],
side.downcase.to_sym => [Errors::PIXEL_DEPTH_FAILURE_FIELD],
}
when 440
{
general: [Errors::IMAGE_SIZE_FAILURE],
side.downcase.to_sym => [Errors::IMAGE_SIZE_FAILURE_FIELD],
}
end
end
end
end
end
Expand Down
7 changes: 7 additions & 0 deletions app/services/doc_auth/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ module DocAuth
module Errors
# HTTP Status Codes
IMAGE_LOAD_FAILURE = 'image_load_failure' # 438
IMAGE_LOAD_FAILURE_FIELD = 'image_load_failure_field' # 438
PIXEL_DEPTH_FAILURE = 'pixel_depth_failure' # 439
PIXEL_DEPTH_FAILURE_FIELD = 'pixel_depth_failure_field'
IMAGE_SIZE_FAILURE = 'image_size_failure' # 440
IMAGE_SIZE_FAILURE_FIELD = 'image_size_failure_field' # 440
# Network
NETWORK = 'network' # usually 500 or other unhandled error
# Alerts
Expand Down Expand Up @@ -80,6 +83,10 @@ module Errors

# rubocop:disable Layout/LineLength
USER_DISPLAY = {
# Http status
IMAGE_LOAD_FAILURE => { long_msg: IMAGE_LOAD_FAILURE, long_msg_plural: IMAGE_LOAD_FAILURE, field_msg: IMAGE_LOAD_FAILURE_FIELD },
PIXEL_DEPTH_FAILURE => { long_msg: PIXEL_DEPTH_FAILURE, long_msg_plural: PIXEL_DEPTH_FAILURE, field_msg: PIXEL_DEPTH_FAILURE_FIELD },
IMAGE_SIZE_FAILURE => { long_msg: IMAGE_SIZE_FAILURE, long_msg_plural: IMAGE_SIZE_FAILURE, field_msg: IMAGE_SIZE_FAILURE_FIELD },
# Image metrics
DPI_LOW => { long_msg: DPI_LOW_ONE_SIDE, long_msg_plural: DPI_LOW_BOTH_SIDES, field_msg: DPI_LOW_FIELD },
SHARP_LOW => { long_msg: SHARP_LOW_ONE_SIDE, long_msg_plural: SHARP_LOW_BOTH_SIDES, field_msg: SHARP_LOW_FIELD },
Expand Down
43 changes: 30 additions & 13 deletions app/services/doc_auth/mock/doc_auth_mock_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,25 +105,42 @@ def http_error_response(image, side)
data = parse_yaml(image.to_s)
status = data.dig('http_status', side)
return nil unless [500, 440, 438, 439].include?(status)
error = case status
when 438
Errors::IMAGE_LOAD_FAILURE
when 439
Errors::PIXEL_DEPTH_FAILURE
when 440
Errors::IMAGE_SIZE_FAILURE
when 500
Errors::NETWORK
end
return nil unless error
errors = { general: [error] }
errors = case status
when 438
{
general: [Errors::IMAGE_LOAD_FAILURE],
side.downcase.to_sym => [Errors::IMAGE_LOAD_FAILURE_FIELD],
}
when 439
{
general: [Errors::PIXEL_DEPTH_FAILURE],
side.downcase.to_sym => [Errors::PIXEL_DEPTH_FAILURE_FIELD],
}
when 440
{
general: [Errors::IMAGE_SIZE_FAILURE],
side.downcase.to_sym => [Errors::IMAGE_SIZE_FAILURE_FIELD],
}
when 500
{
general: [Errors::NETWORK],
}
end
return nil unless errors
errors = errors.tap do |h|
if h.has_key?(:result)
h[:front] = h[:result]
h[:back] = h[:result]
h.delete(:result)
end
end
message = [
self.class.name,
'Unexpected HTTP response',
status,
].join(' ')
exception = DocAuth::RequestError.new(message, status)
return DocAuth::Response.new(
DocAuth::Response.new(
success: false,
errors: errors,
exception: exception,
Expand Down
20 changes: 14 additions & 6 deletions app/services/doc_auth/mock/result_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,24 @@ def attention_with_barcode?
parsed_alerts == [ATTENTION_WITH_BARCODE_ALERT]
end

def self.create_image_error_response(status)
error = case status
def self.create_image_error_response(status, side)
errors = case status
when 438
Errors::IMAGE_LOAD_FAILURE
{
general: [Errors::IMAGE_LOAD_FAILURE],
side.to_sym => [Errors::IMAGE_LOAD_FAILURE_FIELD],
}
when 439
Errors::PIXEL_DEPTH_FAILURE
{
general: [Errors::PIXEL_DEPTH_FAILURE],
side.to_sym => [Errors::IMAGE_LOAD_FAILURE_FIELD],
}
when 440
Errors::IMAGE_SIZE_FAILURE
{
general: [Errors::IMAGE_SIZE_FAILURE],
side.to_sym => [Errors::IMAGE_SIZE_FAILURE_FIELD],
}
end
errors = { general: [error] }
message = [
'Unexpected HTTP response',
status,
Expand Down
23 changes: 16 additions & 7 deletions app/services/doc_auth_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,18 @@ module DocAuthRouter
DocAuth::Errors::GLARE_LOW_BOTH_SIDES => 'doc_auth.errors.glare.top_msg_plural',
# i18n-tasks-use t('doc_auth.errors.glare.failed_short')
DocAuth::Errors::GLARE_LOW_FIELD => 'doc_auth.errors.glare.failed_short',
# i18n-tasks-use t('doc_auth.errors.http.image_load')
DocAuth::Errors::IMAGE_LOAD_FAILURE => 'doc_auth.errors.http.image_load',
# i18n-tasks-use t('doc_auth.errors.http.pixel_depth')
DocAuth::Errors::PIXEL_DEPTH_FAILURE => 'doc_auth.errors.http.pixel_depth',
# i18n-tasks-use t('doc_auth.errors.http.image_size')
DocAuth::Errors::IMAGE_SIZE_FAILURE => 'doc_auth.errors.http.image_size',
# i18n-tasks-use t('doc_auth.errors.http.image_load.top_msg')
DocAuth::Errors::IMAGE_LOAD_FAILURE => 'doc_auth.errors.http.image_load.top_msg',
# i18n-tasks-use t('doc_auth.errors.http.image_load.failed_short')
DocAuth::Errors::IMAGE_LOAD_FAILURE_FIELD => 'doc_auth.errors.http.image_load.failed_short',
# i18n-tasks-use t('doc_auth.errors.http.pixel_depth.top_msg')
DocAuth::Errors::PIXEL_DEPTH_FAILURE => 'doc_auth.errors.http.pixel_depth.top_msg',
# i18n-tasks-use t('doc_auth.errors.http.pixel_depth.failed_short')
DocAuth::Errors::PIXEL_DEPTH_FAILURE_FIELD => 'doc_auth.errors.http.pixel_depth.failed_short',
# i18n-tasks-use t('doc_auth.errors.http.image_size.top_msg')
DocAuth::Errors::IMAGE_SIZE_FAILURE => 'doc_auth.errors.http.image_size.top_msg',
# i18n-tasks-use t('doc_auth.errors.http.image_size.failed_short')
DocAuth::Errors::IMAGE_SIZE_FAILURE_FIELD => 'doc_auth.errors.http.image_size.failed_short',
# i18n-tasks-use t('doc_auth.errors.general.fallback_field_level')
DocAuth::Errors::FALLBACK_FIELD_LEVEL => 'doc_auth.errors.general.fallback_field_level',
}.freeze
Expand Down Expand Up @@ -122,7 +128,9 @@ def translate_doc_auth_errors!(response)
error_keys = DocAuth::ErrorGenerator::ERROR_KEYS.dup

error_keys.each do |category|
response.errors[category]&.map! do |plain_error|
cat_errors = response.errors[category]
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.

I read the commit message, and that's an interesting bug! Glad you figured out a way to fix it. This looks good.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@eileen-nava , yeah very similar to the one we have with hash keys collision. Here I have some test case failed and some worked.

next unless cat_errors
translated_cat_errors = cat_errors.map do |plain_error|
error_key = ERROR_TRANSLATIONS[plain_error]
if error_key
I18n.t(error_key)
Expand All @@ -131,6 +139,7 @@ def translate_doc_auth_errors!(response)
I18n.t('doc_auth.errors.general.no_liveness')
end
end
response.errors[category] = translated_cat_errors
end
end

Expand Down
20 changes: 13 additions & 7 deletions config/locales/doc_auth/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,19 @@ en:
top_msg_plural: We couldn’t read your ID. Your photos may have glare. Make sure
that the flash on your camera is off and try taking new pictures.
http:
image_load: The image file that you added is not supported. Please take new
photos of your ID and try again.
image_size: Your image size is too large or too small. Please add images of your
ID that are about 2025 x 1275 pixels.
pixel_depth: The pixel depth of your image file is not supported. Please take
new photos of your ID and try again. Supported image pixel depth is
24-bit RGB.
image_load:
failed_short: Image file is not supported, please try again.
top_msg: The image file that you added is not supported. Please take new photos
of your ID and try again.
image_size:
failed_short: Image file is not supported, please try again.
top_msg: Your image size is too large or too small. Please add images of your ID
that are about 2025 x 1275 pixels.
pixel_depth:
failed_short: Image file is not supported, please try again.
top_msg: The pixel depth of your image file is not supported. Please take new
photos of your ID and try again. Supported image pixel depth is
24-bit RGB.
not_a_file: The selection was not a valid file.
pii:
birth_date_min_age: Your birthday does not meet the minimum age requirement.
Expand Down
23 changes: 14 additions & 9 deletions config/locales/doc_auth/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,20 @@ es:
tengan reflejos. Asegúrese de que el flash de su cámara esté
desactivado e intente tomar nuevas fotos.
http:
image_load: El archivo de imagen que ha añadido no es compatible. Por favor,
tome nuevas fotos de su identificación y vuelva a intentarlo.
image_size: El tamaño de la imagen es demasiado grande o demasiado pequeño.
Añada imágenes de su documento de identidad de unos 2025 x 1275
píxeles.
pixel_depth: No es compatible con la profundidad de píxeles de su archivo de
imagen. Tome nuevas fotos de su documento de identidad e inténtelo
nuevamente. La profundidad de píxeles de la imagen admitida es de 24
bits RGB.
image_load:
failed_short: El archivo de la imagen no es compatible. Inténtalo de nuevo.
top_msg: El archivo de imagen que ha añadido no es compatible. Por favor, tome
nuevas fotos de su identificación y vuelva a intentarlo.
image_size:
failed_short: El archivo de la imagen no es compatible. Inténtalo de nuevo.
top_msg: El tamaño de la imagen es demasiado grande o demasiado pequeño. Añada
imágenes de su documento de identidad de unos 2025 x 1275 píxeles.
pixel_depth:
failed_short: El archivo de la imagen no es compatible. Inténtalo de nuevo.
top_msg: No es compatible con la profundidad de píxeles de su archivo de imagen.
Tome nuevas fotos de su documento de identidad e inténtelo
nuevamente. La profundidad de píxeles de la imagen admitida es de 24
bits RGB.
not_a_file: La selección no era un archivo válido.
pii:
birth_date_min_age: Tu cumpleaños no cumple con el requisito de edad mínima.
Expand Down
26 changes: 16 additions & 10 deletions config/locales/doc_auth/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,22 @@ fr:
peuvent avoir des reflets. Assurez-vous que le flash de votre appareil
photo est désactivé puis essayez de prendre de nouvelles photos.
http:
image_load: Le fichier image que vous avez ajouté n’est pas pris en charge.
Veuillez prendre de nouvelles photos de votre pièce d’identité et
réessayer.
image_size: La taille de votre image est trop grande ou trop petite. Veuillez
ajouter des images de votre pièce d’identité d’environ 2025 x 1275
pixels.
pixel_depth: La profondeur de pixel de votre fichier image n’est pas supportée.
Veuillez prendre de nouvelles photos de votre pièce d’identité et
réessayer. La profondeur de pixel de l’image prise en charge est de 24
bits RGB.
image_load:
failed_short: Le fichier image n’est pas pris en charge, veuillez réessayer.
top_msg: Le fichier image que vous avez ajouté n’est pas pris en charge.
Veuillez prendre de nouvelles photos de votre pièce d’identité et
réessayer.
image_size:
failed_short: Le fichier image n’est pas pris en charge, veuillez réessayer.
top_msg: La taille de votre image est trop grande ou trop petite. Veuillez
ajouter des images de votre pièce d’identité d’environ 2025 x 1275
pixels.
pixel_depth:
failed_short: Le fichier image n’est pas pris en charge, veuillez réessayer.
top_msg: La profondeur de pixel de votre fichier image n’est pas supportée.
Veuillez prendre de nouvelles photos de votre pièce d’identité et
réessayer. La profondeur de pixel de l’image prise en charge est de
24 bits RGB.
not_a_file: La sélection n’était pas un fichier valide.
pii:
birth_date_min_age: Votre anniversaire ne correspond pas à l’âge minimum requis.
Expand Down
41 changes: 41 additions & 0 deletions spec/controllers/idv/image_uploads_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,47 @@
end
end

context 'when image upload fails with 4xx status' do
before do
status = 440
errors = { general: [DocAuth::Errors::IMAGE_SIZE_FAILURE],
front: [DocAuth::Errors::IMAGE_SIZE_FAILURE_FIELD] }
message = [
self.class.name,
'Unexpected HTTP response',
status,
].join(' ')
exception = DocAuth::RequestError.new(message, status)
response = DocAuth::Response.new(
success: false,
errors: errors,
exception: exception,
extra: { vendor: 'Mock' },
)
DocAuth::Mock::DocAuthMockClient.mock_response!(
method: :post_front_image,
response: response,
)
end

it 'returns error response' do
action
expect(response.status).to eq(400)
expect(json[:success]).to eq(false)
expect(json[:remaining_attempts]).to be_a_kind_of(Numeric)
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.

👍🏻

expect(json[:errors]).to eq [
{
field: 'general',
message: I18n.t('doc_auth.errors.http.image_size.top_msg'),
},
{
field: 'front',
message: I18n.t('doc_auth.errors.http.image_size.failed_short'),
},
]
end
end

context 'when image upload succeeds' do
it 'returns a successful response and modifies the session' do
action
Expand Down
Loading