human_error 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/human_error.rb +21 -19
- data/lib/human_error/configuration.rb +27 -7
- data/lib/human_error/error.rb +60 -28
- data/lib/human_error/errors/authentication_errors/duplicate_authentication_error.rb +8 -8
- data/lib/human_error/errors/authentication_errors/invalid_token_error.rb +8 -8
- data/lib/human_error/errors/authentication_errors/invalid_username_or_password_error.rb +8 -8
- data/lib/human_error/errors/crud_errors/association_error.rb +8 -9
- data/lib/human_error/errors/crud_errors/resource_not_found_error.rb +8 -8
- data/lib/human_error/errors/crud_errors/resource_persistence_error.rb +8 -8
- data/lib/human_error/errors/request_errors/parameter_missing_error.rb +40 -0
- data/lib/human_error/errors/request_errors/unpermitted_parameters_error.rb +46 -0
- data/lib/human_error/rescuable_resource.rb +30 -47
- data/lib/human_error/verifiable_resource.rb +36 -0
- data/lib/human_error/version.rb +1 -1
- data/spec/lib/human_error/configuration_spec.rb +13 -26
- data/spec/lib/human_error/error_spec.rb +135 -1
- data/spec/lib/human_error/errors/authentication_errors/duplicate_authentication_error_spec.rb +8 -13
- data/spec/lib/human_error/errors/authentication_errors/invalid_token_error_spec.rb +8 -12
- data/spec/lib/human_error/errors/authentication_errors/invalid_username_or_password_error_spec.rb +8 -13
- data/spec/lib/human_error/errors/crud_errors/association_error_spec.rb +8 -16
- data/spec/lib/human_error/errors/crud_errors/resource_not_found_error_spec.rb +9 -17
- data/spec/lib/human_error/errors/crud_errors/resource_persistence_error_spec.rb +9 -17
- data/spec/lib/human_error/errors/request_errors/parameter_missing_error_spec.rb +55 -0
- data/spec/lib/human_error/errors/request_errors/unpermitted_parameters_error_spec.rb +62 -0
- data/spec/lib/human_error_spec.rb +4 -57
- metadata +26 -12
- data/lib/human_error/error_code_directory.rb +0 -20
- data/lib/human_error/errors.rb +0 -9
- data/lib/human_error/errors/request_error.rb +0 -48
- data/lib/human_error/knowledgebase_id_directory.rb +0 -20
- data/lib/human_error/verifiable_model.rb +0 -30
- data/spec/lib/human_error/errors/request_error_spec.rb +0 -95
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce3584e03d830added3a0b58d9fa67995aba2b62
|
4
|
+
data.tar.gz: ce828a6fd224bc186e2da06ce1c007ea3cbad3fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2383d7ae1f37c0ae716b39526cd6ade1365f09ffd9eaeb5784957e26f8cfa46e77c1593f64a0afc71c4e93627096d363887b31550125cfdd73be29d8b803ccb5
|
7
|
+
data.tar.gz: cb3efadd3dd1f368b5889474b27ca8830bd971470b18c4888589f09bcbddae1877a133f1d903268d6f14647273cf038aeaa1daeb970adc1848d3cfc1c4183209
|
data/lib/human_error.rb
CHANGED
@@ -1,31 +1,29 @@
|
|
1
|
-
require 'human_error/
|
1
|
+
require 'human_error/configuration'
|
2
2
|
require 'human_error/error'
|
3
|
-
require 'human_error/errors'
|
3
|
+
require 'human_error/errors/authentication_error'
|
4
|
+
require 'human_error/errors/authentication_errors/duplicate_authentication_error'
|
5
|
+
require 'human_error/errors/authentication_errors/invalid_token_error'
|
6
|
+
require 'human_error/errors/authentication_errors/invalid_username_or_password_error'
|
7
|
+
require 'human_error/errors/crud_error'
|
8
|
+
require 'human_error/errors/crud_errors/association_error'
|
9
|
+
require 'human_error/errors/crud_errors/resource_not_found_error'
|
10
|
+
require 'human_error/errors/crud_errors/resource_persistence_error'
|
11
|
+
require 'human_error/errors/request_errors/parameter_missing_error'
|
12
|
+
require 'human_error/errors/request_errors/unpermitted_parameters_error'
|
4
13
|
require 'human_error/rescuable_resource'
|
5
|
-
require 'human_error/
|
14
|
+
require 'human_error/verifiable_resource'
|
15
|
+
require 'human_error/version'
|
6
16
|
|
7
17
|
class HumanError
|
8
|
-
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
self.configuration = Configuration.new
|
12
|
-
|
13
|
-
yield configuration if block_given?
|
14
|
-
end
|
15
|
-
|
16
|
-
def fetch(error_type)
|
18
|
+
def self.fetch(error_type)
|
17
19
|
Object.const_get("HumanError::Errors::#{error_type}")
|
18
20
|
end
|
19
21
|
|
20
|
-
def build(error_type, overrides = {})
|
21
|
-
overrides = configuration.to_h.merge(overrides)
|
22
|
-
|
22
|
+
def self.build(error_type, overrides = {})
|
23
23
|
fetch(error_type).new(overrides)
|
24
24
|
end
|
25
25
|
|
26
|
-
def convert(original_error, overrides = {})
|
27
|
-
overrides = configuration.to_h.merge(overrides)
|
28
|
-
|
26
|
+
def self.convert(original_error, overrides = {})
|
29
27
|
case original_error.class.name
|
30
28
|
when 'ActiveRecord::InvalidForeignKey'
|
31
29
|
fetch('AssociationError').convert(original_error, overrides)
|
@@ -34,10 +32,14 @@ class HumanError
|
|
34
32
|
when 'ActiveRecord::RecordInvalid',
|
35
33
|
'ActiveRecord::RecordNotSaved'
|
36
34
|
fetch('ResourcePersistenceError').convert(original_error, overrides)
|
35
|
+
when 'ActionController::ParameterMissing',
|
36
|
+
fetch('ParameterMissingError').convert(original_error, overrides)
|
37
|
+
when 'ActionController::UnpermittedParameters'
|
38
|
+
fetch('UnpermittedParametersError').convert(original_error, overrides)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
def raise(error_type, **args)
|
42
|
+
def self.raise(error_type, **args)
|
41
43
|
Kernel.raise build(error_type, **args)
|
42
44
|
end
|
43
45
|
end
|
@@ -1,16 +1,36 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
1
3
|
class HumanError
|
2
4
|
class Configuration
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_accessor :url_mappings
|
8
|
+
|
9
|
+
def external_documentation_urls
|
10
|
+
@external_documentation_urls ||= url_mappings['external_documentation_urls']
|
11
|
+
end
|
12
|
+
|
13
|
+
def developer_documentation_urls
|
14
|
+
@developer_documentation_urls ||= url_mappings['developer_documentation_urls']
|
15
|
+
end
|
6
16
|
|
7
17
|
def to_h
|
8
18
|
{
|
9
|
-
|
10
|
-
|
11
|
-
api_version: api_version,
|
19
|
+
external_documentation_urls: external_documentation_urls,
|
20
|
+
developer_documentation_urls: developer_documentation_urls,
|
12
21
|
}
|
13
22
|
end
|
23
|
+
|
24
|
+
def url_mappings
|
25
|
+
@url_mappings ||= {
|
26
|
+
'external_documentation_urls' => {},
|
27
|
+
'developer_documentation_urls' => {},
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def configuration
|
33
|
+
Configuration.instance
|
14
34
|
end
|
15
35
|
|
16
36
|
def self.configure
|
@@ -18,6 +38,6 @@ class HumanError
|
|
18
38
|
end
|
19
39
|
|
20
40
|
def self.configuration
|
21
|
-
|
41
|
+
Configuration.instance
|
22
42
|
end
|
23
43
|
end
|
data/lib/human_error/error.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'human_error/configuration'
|
3
|
-
require 'human_error/
|
4
|
-
require 'human_error/knowledgebase_id_directory'
|
3
|
+
require 'human_error/utilities/string'
|
5
4
|
|
6
5
|
class HumanError
|
7
6
|
module Error
|
@@ -13,41 +12,80 @@ module Error
|
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
|
-
attr_accessor :
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
15
|
+
attr_accessor :id,
|
16
|
+
:external_documentation_url,
|
17
|
+
:developer_documentation_url,
|
18
|
+
:http_status,
|
20
19
|
:code,
|
20
|
+
:title,
|
21
|
+
:detail,
|
22
|
+
:source,
|
21
23
|
:message
|
22
24
|
|
23
25
|
def initialize(**args)
|
24
|
-
self.api_version = configuration.api_version
|
25
|
-
self.api_error_documentation_url = configuration.api_error_documentation_url
|
26
|
-
self.knowledgebase_url = configuration.knowledgebase_url
|
27
|
-
|
28
26
|
args.each do |variable, value|
|
29
|
-
|
27
|
+
public_send("#{variable}=", value)
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
|
31
|
+
def as_json(_options = {})
|
32
|
+
{
|
33
|
+
errors: [
|
34
|
+
{
|
35
|
+
id: id,
|
36
|
+
links: {
|
37
|
+
about: external_documentation_url,
|
38
|
+
documentation: developer_documentation_url,
|
39
|
+
},
|
40
|
+
status: http_status,
|
41
|
+
code: code,
|
42
|
+
title: title,
|
43
|
+
detail: detail,
|
44
|
+
source: source,
|
45
|
+
},
|
46
|
+
],
|
47
|
+
}
|
35
48
|
end
|
36
49
|
|
37
|
-
def
|
38
|
-
|
50
|
+
def to_json(_options = {})
|
51
|
+
JSON.dump(as_json)
|
39
52
|
end
|
40
53
|
|
41
|
-
def
|
42
|
-
|
54
|
+
def id
|
55
|
+
@id ||= SecureRandom.uuid
|
43
56
|
end
|
44
57
|
|
45
|
-
def
|
46
|
-
|
58
|
+
def external_documentation_url
|
59
|
+
@external_documentation_url ||= configuration.external_documentation_urls[code]
|
47
60
|
end
|
48
61
|
|
49
|
-
def
|
50
|
-
|
62
|
+
def developer_documentation_url
|
63
|
+
@developer_documentation_url ||= configuration.developer_documentation_urls[code]
|
64
|
+
end
|
65
|
+
|
66
|
+
def http_status
|
67
|
+
@http_status ||= 500
|
68
|
+
end
|
69
|
+
|
70
|
+
alias_method :status, :http_status
|
71
|
+
|
72
|
+
def code
|
73
|
+
@code ||= HumanError::Utilities::String.
|
74
|
+
underscore(self.class.name).
|
75
|
+
gsub(%r{\A[^/]+/}, '').
|
76
|
+
gsub(%r{/}, '.')
|
77
|
+
end
|
78
|
+
|
79
|
+
def title
|
80
|
+
@title ||= self.class.name
|
81
|
+
end
|
82
|
+
|
83
|
+
def detail
|
84
|
+
@detail ||= 'The server encountered an error.'
|
85
|
+
end
|
86
|
+
|
87
|
+
def source
|
88
|
+
@source ||= {}
|
51
89
|
end
|
52
90
|
|
53
91
|
def message
|
@@ -55,13 +93,7 @@ module Error
|
|
55
93
|
end
|
56
94
|
|
57
95
|
def to_s
|
58
|
-
@message ||
|
59
|
-
rescue NoMethodError
|
60
|
-
super
|
61
|
-
end
|
62
|
-
|
63
|
-
def developer_message
|
64
|
-
fail NoMethodError, 'This method must be implemented in a subclass'
|
96
|
+
@message || detail
|
65
97
|
end
|
66
98
|
|
67
99
|
def self.included(base)
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'human_error/errors/request_error'
|
2
1
|
require 'human_error/errors/authentication_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class DuplicateAuthenticationError <
|
5
|
+
class DuplicateAuthenticationError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include AuthenticationError
|
8
8
|
|
9
9
|
attr_accessor :provider,
|
@@ -14,23 +14,23 @@ class DuplicateAuthenticationError < RequestError
|
|
14
14
|
409
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def title
|
18
|
+
'Duplicate Authentication'
|
19
|
+
end
|
20
|
+
|
21
|
+
def detail
|
18
22
|
'The authentication you attempted to register has already been registered by ' \
|
19
23
|
'another user. We do not currently support allowing multiple users to be connected ' \
|
20
24
|
'to the same authentication.'
|
21
25
|
end
|
22
26
|
|
23
|
-
def
|
27
|
+
def source
|
24
28
|
{
|
25
29
|
'provider' => provider,
|
26
30
|
'provider_user_id' => provider_user_id,
|
27
31
|
'user_id' => user_id,
|
28
32
|
}
|
29
33
|
end
|
30
|
-
|
31
|
-
def friendly_message
|
32
|
-
"Sorry! Someone else has already registered this #{provider} login."
|
33
|
-
end
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'human_error/errors/request_error'
|
2
1
|
require 'human_error/errors/authentication_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class InvalidTokenError <
|
5
|
+
class InvalidTokenError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include AuthenticationError
|
8
8
|
|
9
9
|
attr_accessor :authentication_token
|
@@ -12,18 +12,18 @@ class InvalidTokenError < RequestError
|
|
12
12
|
401
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def title
|
16
|
+
'Invalid Token'
|
17
|
+
end
|
18
|
+
|
19
|
+
def detail
|
16
20
|
'The token you attempted to use for this request is invalid for this resource. ' \
|
17
21
|
'Please double-check and try again.'
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
24
|
+
def source
|
21
25
|
{ token: '[FILTERED]' }
|
22
26
|
end
|
23
|
-
|
24
|
-
def friendly_message
|
25
|
-
'Sorry! You are not authorized to view this.'
|
26
|
-
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'human_error/errors/request_error'
|
2
1
|
require 'human_error/errors/authentication_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class InvalidUsernameOrPasswordError <
|
5
|
+
class InvalidUsernameOrPasswordError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include AuthenticationError
|
8
8
|
|
9
9
|
attr_accessor :username
|
@@ -12,18 +12,18 @@ class InvalidUsernameOrPasswordError < RequestError
|
|
12
12
|
401
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def title
|
16
|
+
'Invalid Username/Password'
|
17
|
+
end
|
18
|
+
|
19
|
+
def detail
|
16
20
|
'Either the username or password passed in or this request is invalid. Please ' \
|
17
21
|
'double-check and try again.'
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
24
|
+
def source
|
21
25
|
{ username: username, password: '[FILTERED]' }
|
22
26
|
end
|
23
|
-
|
24
|
-
def friendly_message
|
25
|
-
'Either your email or password is incorrect. Please double-check and try again.'
|
26
|
-
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'human_error/errors/crud_error'
|
2
|
-
require 'human_error/errors/request_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class AssociationError <
|
5
|
+
class AssociationError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include CrudError
|
8
8
|
|
9
9
|
attr_accessor :association_name,
|
@@ -33,22 +33,21 @@ class AssociationError < RequestError
|
|
33
33
|
422
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def title
|
37
|
+
'Association Error'
|
38
|
+
end
|
39
|
+
|
40
|
+
def detail
|
37
41
|
"The #{association_name} that you attempted to associate with " \
|
38
42
|
"the #{resource_name} was not valid."
|
39
43
|
end
|
40
44
|
|
41
|
-
def
|
45
|
+
def source
|
42
46
|
{
|
43
47
|
resource_name => attributes,
|
44
48
|
"#{association_name} id" => association_id,
|
45
49
|
}
|
46
50
|
end
|
47
|
-
|
48
|
-
def friendly_message
|
49
|
-
"Sorry! There was a problem when we tried to set the #{association_name} on " \
|
50
|
-
"that #{resource_name}."
|
51
|
-
end
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'human_error/errors/crud_error'
|
2
|
-
require 'human_error/errors/request_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class ResourceNotFoundError <
|
5
|
+
class ResourceNotFoundError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include CrudError
|
8
8
|
|
9
9
|
def self.convert(original_error, overrides = {})
|
@@ -30,19 +30,19 @@ class ResourceNotFoundError < RequestError
|
|
30
30
|
404
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
33
|
+
def title
|
34
|
+
'Resource Not Found'
|
35
|
+
end
|
36
|
+
|
37
|
+
def detail
|
34
38
|
"The #{resource_name} you attempted to #{action} for this request is either " \
|
35
39
|
'not authorized for the authenticated user or does not exist.'
|
36
40
|
end
|
37
41
|
|
38
|
-
def
|
42
|
+
def source
|
39
43
|
{ "#{resource_name_underscored}_id" => resource_id }
|
40
44
|
end
|
41
45
|
|
42
|
-
def friendly_message
|
43
|
-
"Sorry! The #{resource_name} you tried to #{action} does not exist."
|
44
|
-
end
|
45
|
-
|
46
46
|
def action
|
47
47
|
@action || 'access'
|
48
48
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'human_error/errors/crud_error'
|
2
|
-
require 'human_error/errors/request_error'
|
3
2
|
|
4
3
|
class HumanError
|
5
4
|
module Errors
|
6
|
-
class ResourcePersistenceError <
|
5
|
+
class ResourcePersistenceError < RuntimeError
|
6
|
+
include Error
|
7
7
|
include CrudError
|
8
8
|
|
9
9
|
attr_accessor :errors,
|
@@ -29,21 +29,21 @@ class ResourcePersistenceError < RequestError
|
|
29
29
|
422
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def title
|
33
|
+
'Resource Persistence Error'
|
34
|
+
end
|
35
|
+
|
36
|
+
def detail
|
33
37
|
"One or more of the attributes on the #{resource_name} you attempted " \
|
34
38
|
"to #{action} is invalid."
|
35
39
|
end
|
36
40
|
|
37
|
-
def
|
41
|
+
def source
|
38
42
|
{
|
39
43
|
'errors' => errors,
|
40
44
|
'attributes' => attributes,
|
41
45
|
}
|
42
46
|
end
|
43
|
-
|
44
|
-
def friendly_message
|
45
|
-
"Sorry! We had a problem when tried to #{action} that #{resource_name}."
|
46
|
-
end
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|