authsignal-ruby 2.1.3 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.tool-versions +1 -0
- data/Gemfile.lock +26 -15
- data/README.md +54 -0
- data/lib/authsignal/api_error.rb +19 -0
- data/lib/authsignal/client.rb +57 -46
- data/lib/authsignal/configuration.rb +5 -2
- data/lib/authsignal/middleware/json_request.rb +30 -0
- data/lib/authsignal/middleware/json_response.rb +45 -0
- data/lib/authsignal/version.rb +1 -1
- data/lib/authsignal.rb +53 -42
- metadata +25 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2bf6c96e9f79775fa1d3db3deb5ec5258a8c651e1b4fb8c1c3740c3f5ebd5b6
|
4
|
+
data.tar.gz: 90124d4aa0b3111cd4b52424c78b16f208d4179991e8dcfc52f48fc735483bba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cb34330978dc710806be016761805b82c7cc442ab58752baf33ff62bff64a4476c7f62fce114e10f3dae144c100ae4fe05d167cd66435d3d38fdcb3adb63612
|
7
|
+
data.tar.gz: 5dca5b72d6c09fa2bfe78768d451661f6bad5d1188257a6d7523f51f389956c51214af1250c2f318706274b080c9a9ada019ad2f5e246f0daface09e05351096
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.3.5
|
data/Gemfile.lock
CHANGED
@@ -1,26 +1,36 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
authsignal-ruby (
|
5
|
-
|
4
|
+
authsignal-ruby (3.0.1)
|
5
|
+
faraday (>= 2)
|
6
|
+
faraday-retry (~> 2.2)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
addressable (2.8.
|
11
|
-
public_suffix (>= 2.0.2, <
|
12
|
-
|
11
|
+
addressable (2.8.7)
|
12
|
+
public_suffix (>= 2.0.2, < 7.0)
|
13
|
+
bigdecimal (3.1.8)
|
14
|
+
crack (1.0.0)
|
15
|
+
bigdecimal
|
13
16
|
rexml
|
14
17
|
diff-lcs (1.5.0)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
faraday (2.12.0)
|
19
|
+
faraday-net_http (>= 2.0, < 3.4)
|
20
|
+
json
|
21
|
+
logger
|
22
|
+
faraday-net_http (3.3.0)
|
23
|
+
net-http
|
24
|
+
faraday-retry (2.2.1)
|
25
|
+
faraday (~> 2.0)
|
26
|
+
hashdiff (1.1.1)
|
27
|
+
json (2.7.2)
|
28
|
+
logger (1.6.1)
|
29
|
+
net-http (0.4.1)
|
30
|
+
uri
|
31
|
+
public_suffix (6.0.1)
|
22
32
|
rake (13.0.6)
|
23
|
-
rexml (3.
|
33
|
+
rexml (3.3.8)
|
24
34
|
rspec (3.11.0)
|
25
35
|
rspec-core (~> 3.11.0)
|
26
36
|
rspec-expectations (~> 3.11.0)
|
@@ -34,7 +44,8 @@ GEM
|
|
34
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
35
45
|
rspec-support (~> 3.11.0)
|
36
46
|
rspec-support (3.11.0)
|
37
|
-
|
47
|
+
uri (0.13.1)
|
48
|
+
webmock (3.24.0)
|
38
49
|
addressable (>= 2.8.0)
|
39
50
|
crack (>= 0.3.2)
|
40
51
|
hashdiff (>= 0.4.0, < 2.0.0)
|
@@ -46,7 +57,7 @@ DEPENDENCIES
|
|
46
57
|
authsignal-ruby!
|
47
58
|
rake (~> 13.0)
|
48
59
|
rspec (~> 3.2)
|
49
|
-
webmock (~> 3.14
|
60
|
+
webmock (~> 3.14)
|
50
61
|
|
51
62
|
BUNDLED WITH
|
52
63
|
2.3.21
|
data/README.md
CHANGED
@@ -48,6 +48,12 @@ require 'authsignal'
|
|
48
48
|
Authsignal.setup do |config|
|
49
49
|
config.api_secret_key = ENV["AUTHSIGNAL_SECRET_KEY"]
|
50
50
|
config.base_uri = "https://au.signal.authsignal.com/v1"
|
51
|
+
|
52
|
+
# If you would like the Authsignal client to retry requests due to network issues
|
53
|
+
config.retry = true # default value: false
|
54
|
+
|
55
|
+
# If you would like to inspect raw request/response in development
|
56
|
+
config.debug = true # default value: false
|
51
57
|
end
|
52
58
|
```
|
53
59
|
|
@@ -57,12 +63,60 @@ Authsignal's server side signal API has four main api calls `track`, `get_action
|
|
57
63
|
|
58
64
|
For more details on these api calls, refer to our [official Ruby SDK docs](https://docs.authsignal.com/sdks/server/ruby#track).
|
59
65
|
|
66
|
+
Example:
|
67
|
+
```ruby
|
68
|
+
Authsignal.track user_id: 'AS_001', action: 'withdraw', idempotency_key: 'a_random_hash'
|
69
|
+
|
70
|
+
# returns:
|
71
|
+
# {
|
72
|
+
# success?: true,
|
73
|
+
# state: 'ALLOW',
|
74
|
+
# idempotency_key: 'a_random_hash',
|
75
|
+
# ... rest of payload ...
|
76
|
+
# }
|
77
|
+
```
|
78
|
+
|
79
|
+
### Response & Error handling
|
80
|
+
|
81
|
+
Authsignal client come with 2 flavors of responses, by default calling the signal APIs will returns payload in hash.
|
82
|
+
|
83
|
+
Example:
|
84
|
+
```ruby
|
85
|
+
Authsignal.enroll_verified_authenticator user_id: 'AS_001',
|
86
|
+
authenticator: {
|
87
|
+
oob_channel: 'INVALID', email: 'joebloke@authsignal.com'
|
88
|
+
}
|
89
|
+
|
90
|
+
# returns:
|
91
|
+
# {
|
92
|
+
# success?: false,
|
93
|
+
# status: 400,
|
94
|
+
# error: 'invalid_request',
|
95
|
+
# error_description: '/body/oobChannel must be equal to one of the allowed values'
|
96
|
+
# }
|
97
|
+
```
|
98
|
+
|
99
|
+
All signal APIs come with a bang(`!`) counterpart, which will raise `Authsignal::ApiError` when the request is unsuccessful.
|
100
|
+
|
101
|
+
|
102
|
+
Example:
|
103
|
+
```ruby
|
104
|
+
Authsignal.enroll_verified_authenticator! user_id: 'AS_001',
|
105
|
+
authenticator: {
|
106
|
+
oob_channel: 'INVALID', email: 'joebloke@authsignal.com'
|
107
|
+
}
|
108
|
+
|
109
|
+
# raise:
|
110
|
+
# <Authsignal::ApiError: invalid_request status: 400, error: invalid_request, description: /body/oobChannel must be equal to one o...
|
111
|
+
```
|
60
112
|
## Development
|
61
113
|
|
62
114
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` or `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
63
115
|
|
64
116
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
65
117
|
|
118
|
+
Log request/response against test server: `Authsignal.configuration.debug = true`
|
119
|
+
|
66
120
|
## License
|
67
121
|
|
68
122
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authsignal
|
4
|
+
class ApiError < StandardError
|
5
|
+
attr_reader :status, :error, :description
|
6
|
+
|
7
|
+
def initialize(message = "An unexpected API error occurred", status, error, description)
|
8
|
+
@status = status || 500
|
9
|
+
@error = error
|
10
|
+
@description = description
|
11
|
+
|
12
|
+
super(message)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{super} status: #{status}, error: #{error}, description: #{description}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/authsignal/client.rb
CHANGED
@@ -1,95 +1,102 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
module Authsignal
|
2
4
|
class Client
|
3
5
|
USER_AGENT = "Authsignal Ruby v#{Authsignal::VERSION}"
|
4
6
|
NO_API_KEY_MESSAGE = "No Authsignal API Secret Key Set"
|
5
|
-
include HTTParty
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
RETRY_OPTIONS = {
|
9
|
+
max: 3,
|
10
|
+
interval: 0.1,
|
11
|
+
interval_randomness: 0.5,
|
12
|
+
backoff_factor: 2,
|
13
|
+
}.freeze
|
14
|
+
private_constant :RETRY_OPTIONS
|
13
15
|
|
14
|
-
def initialize
|
15
|
-
self.class.base_uri Authsignal.configuration.base_uri
|
16
|
+
def initialize(retry_options: RETRY_OPTIONS)
|
16
17
|
@api_key = require_api_key
|
17
18
|
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
19
|
+
@client = Faraday.new do |builder|
|
20
|
+
builder.url_prefix = Authsignal.configuration.base_uri
|
21
|
+
builder.adapter :net_http
|
22
|
+
builder.request :authorization, :basic, @api_key, nil
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
builder.headers['Accept'] = 'application/json'
|
25
|
+
builder.headers['Content-Type'] = 'application/json'
|
26
|
+
builder.headers['User-Agent'] = USER_AGENT
|
27
|
+
|
28
|
+
builder.request :json
|
29
|
+
builder.response :json, parser_options: { symbolize_names: true }
|
30
|
+
|
31
|
+
builder.use Middleware::JsonRequest
|
32
|
+
builder.use Middleware::JsonResponse
|
33
|
+
|
34
|
+
builder.request :retry, retry_options if Authsignal.configuration.retry
|
35
|
+
builder.response :logger, ::Logger.new(STDOUT), bodies: true if Authsignal.configuration.debug
|
36
|
+
end
|
26
37
|
end
|
27
38
|
|
28
|
-
def track(
|
29
|
-
|
30
|
-
|
31
|
-
userId = ERB::Util.url_encode(action[:userId])
|
32
|
-
body = action.except(:userId, :actionCode)
|
33
|
-
path = "/users/#{userId}/actions/#{actionCode}"
|
39
|
+
def track(event)
|
40
|
+
user_id = url_encode(event[:user_id])
|
41
|
+
action = event[:action]
|
34
42
|
|
35
|
-
|
43
|
+
path = "users/#{user_id}/actions/#{action}"
|
44
|
+
body = event.except(:user_id)
|
45
|
+
|
46
|
+
make_request(:post, path, body: body)
|
36
47
|
end
|
37
48
|
|
38
49
|
def get_user(user_id:, redirect_url: nil)
|
39
50
|
if(redirect_url)
|
40
|
-
path = "
|
51
|
+
path = "users/#{url_encode(user_id)}?redirectUrl=#{redirect_url}"
|
41
52
|
else
|
42
|
-
path = "
|
53
|
+
path = "users/#{url_encode(user_id)}"
|
43
54
|
end
|
44
|
-
get
|
55
|
+
make_request(:get, path)
|
45
56
|
end
|
46
57
|
|
47
58
|
def update_user(user_id:, user:)
|
48
|
-
post
|
59
|
+
make_request(:post, "users/#{url_encode(user_id)}", body: user)
|
49
60
|
end
|
50
61
|
|
51
62
|
def delete_user(user_id:)
|
52
|
-
delete
|
63
|
+
make_request(:delete, "users/#{url_encode(user_id)}")
|
53
64
|
end
|
54
65
|
|
55
|
-
def validate_challenge(user_id: nil, token:)
|
56
|
-
path = "
|
57
|
-
|
58
|
-
response = post(path, query: {}, body: { userId: user_id, token: token }.to_json)
|
66
|
+
def validate_challenge(user_id: nil, token:, action: nil)
|
67
|
+
path = "validate"
|
59
68
|
|
60
|
-
|
69
|
+
make_request(:post, path, body: { user_id: user_id, token: token, action: action })
|
61
70
|
end
|
62
71
|
|
63
72
|
def get_action(user_id, action, idempotency_key)
|
64
|
-
get
|
73
|
+
make_request(:get, "users/#{url_encode(user_id)}/actions/#{action}/#{url_encode(idempotency_key)}")
|
65
74
|
end
|
66
75
|
|
76
|
+
##
|
77
|
+
# TODO: delete identify?
|
67
78
|
def identify(user_id, user_payload)
|
68
|
-
post
|
79
|
+
make_request(:post , "users/#{url_encode(user_id)}", body: user_payload)
|
69
80
|
end
|
70
81
|
|
71
82
|
def enroll_verified_authenticator(user_id, authenticator)
|
72
|
-
post
|
83
|
+
make_request(:post, "users/#{url_encode(user_id)}/authenticators", body: authenticator)
|
73
84
|
end
|
74
85
|
|
75
86
|
def delete_user_authenticator(user_id:, user_authenticator_id:)
|
76
|
-
delete
|
87
|
+
make_request(:delete, "users/#{url_encode(user_id)}/authenticators/#{url_encode(user_authenticator_id)}")
|
77
88
|
end
|
78
89
|
|
79
|
-
|
80
|
-
self.class.get(path, headers: @headers, basic_auth: {username: @api_key})
|
81
|
-
end
|
90
|
+
private
|
82
91
|
|
83
|
-
def
|
84
|
-
|
92
|
+
def make_request(method, path, body: nil, headers: nil)
|
93
|
+
@client.public_send(method, path, body, headers)
|
85
94
|
end
|
86
95
|
|
87
|
-
def
|
88
|
-
|
96
|
+
def url_encode(s)
|
97
|
+
ERB::Util.url_encode(s)
|
89
98
|
end
|
90
99
|
|
91
|
-
private
|
92
|
-
|
93
100
|
def version
|
94
101
|
Authsignal.configuration.version
|
95
102
|
end
|
@@ -97,5 +104,9 @@ module Authsignal
|
|
97
104
|
def print_api_key_warning
|
98
105
|
$stderr.puts(NO_API_KEY_MESSAGE)
|
99
106
|
end
|
107
|
+
|
108
|
+
def require_api_key
|
109
|
+
Authsignal.configuration.api_secret_key || print_api_key_warning
|
110
|
+
end
|
100
111
|
end
|
101
112
|
end
|
@@ -13,15 +13,18 @@ module Authsignal
|
|
13
13
|
end
|
14
14
|
|
15
15
|
config_option :api_secret_key
|
16
|
-
|
17
16
|
config_option :base_uri
|
17
|
+
config_option :debug
|
18
|
+
config_option :retry
|
18
19
|
|
19
20
|
def initialize
|
20
21
|
@config_values = {}
|
21
22
|
|
22
23
|
# set default attribute values
|
23
24
|
@defaults = OpenStruct.new({
|
24
|
-
base_uri: 'https://signal.authsignal.com/v1/'
|
25
|
+
base_uri: 'https://signal.authsignal.com/v1/',
|
26
|
+
retry: false,
|
27
|
+
debug: false
|
25
28
|
})
|
26
29
|
end
|
27
30
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authsignal
|
4
|
+
module Middleware
|
5
|
+
class JsonRequest < Faraday::Middleware
|
6
|
+
def on_request(env)
|
7
|
+
return if env.body.nil?
|
8
|
+
|
9
|
+
parsed_body = JSON.parse(env.body)
|
10
|
+
if parsed_body.is_a?(Hash)
|
11
|
+
env.body = camelcase_keys(parsed_body).to_json
|
12
|
+
end
|
13
|
+
rescue JSON::ParserError
|
14
|
+
# noop
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def camelcase_keys(hash)
|
20
|
+
hash.transform_keys { |key| snake_to_camel(key.to_s).to_sym }
|
21
|
+
end
|
22
|
+
|
23
|
+
def snake_to_camel(str)
|
24
|
+
str.split('_').inject([]) do |buffer, e|
|
25
|
+
buffer.push(buffer.empty? ? e : e.capitalize)
|
26
|
+
end.join
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authsignal
|
4
|
+
module Middleware
|
5
|
+
class JsonResponse < Faraday::Middleware
|
6
|
+
def on_complete(env)
|
7
|
+
##
|
8
|
+
# NOTE: Response header has "content-type: text/plain" atm
|
9
|
+
# Otherwise, we can safe guard with: env.response_headers['content-type'] =~ /application\/json/
|
10
|
+
parsed_body = JSON.parse(env.body)
|
11
|
+
if parsed_body.is_a?(Hash)
|
12
|
+
parsed_body.delete("actionCode") # Remove deprecated actionCode from response
|
13
|
+
env.body = transform_to_snake_case(parsed_body)
|
14
|
+
end
|
15
|
+
rescue JSON::ParserError
|
16
|
+
# noop
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def underscore(camelcased)
|
22
|
+
return camelcased.to_s unless /[A-Z-]|::/.match?(camelcased)
|
23
|
+
word = camelcased.to_s.gsub("::", "/")
|
24
|
+
word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
|
25
|
+
word.tr!("-", "_")
|
26
|
+
word.downcase!
|
27
|
+
word
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform_to_snake_case(value)
|
31
|
+
case value
|
32
|
+
when Array
|
33
|
+
value.map { |v| transform_to_snake_case(v) }
|
34
|
+
when Hash
|
35
|
+
value.transform_keys! { |k| underscore(k).to_sym }
|
36
|
+
value.each do |key, val|
|
37
|
+
value[key] = transform_to_snake_case(val)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/authsignal/version.rb
CHANGED
data/lib/authsignal.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
require "
|
2
|
-
|
1
|
+
require "faraday"
|
2
|
+
require "faraday/retry"
|
3
3
|
require "authsignal/version"
|
4
4
|
require "authsignal/client"
|
5
5
|
require "authsignal/configuration"
|
6
|
+
require "authsignal/api_error"
|
7
|
+
require "authsignal/middleware/json_response"
|
8
|
+
require "authsignal/middleware/json_request"
|
6
9
|
|
7
10
|
module Authsignal
|
11
|
+
NON_API_METHODS = [:setup, :configuration, :default_configuration]
|
12
|
+
|
8
13
|
class << self
|
9
14
|
attr_writer :configuration
|
10
15
|
|
@@ -16,88 +21,94 @@ module Authsignal
|
|
16
21
|
@configuration ||= Authsignal::Configuration.new
|
17
22
|
end
|
18
23
|
|
19
|
-
|
20
24
|
def default_configuration
|
21
25
|
configuration.defaults
|
22
26
|
end
|
23
27
|
|
24
28
|
def get_user(user_id:, redirect_url: nil)
|
25
29
|
response = Client.new.get_user(user_id: user_id, redirect_url: redirect_url)
|
26
|
-
|
30
|
+
|
31
|
+
handle_response(response)
|
27
32
|
end
|
28
33
|
|
29
34
|
def update_user(user_id:, user:)
|
30
35
|
response = Client.new.update_user(user_id: user_id, user: user)
|
31
|
-
|
36
|
+
|
37
|
+
handle_response(response)
|
32
38
|
end
|
33
39
|
|
34
40
|
def delete_user(user_id:)
|
35
41
|
response = Client.new.delete_user(user_id: user_id)
|
36
|
-
|
42
|
+
|
43
|
+
handle_response(response)
|
37
44
|
end
|
38
45
|
|
39
46
|
def get_action(user_id:, action:, idempotency_key:)
|
40
47
|
response = Client.new.get_action(user_id, action, idempotency_key)
|
41
|
-
|
48
|
+
|
49
|
+
handle_response(response)
|
42
50
|
end
|
43
51
|
|
44
52
|
def enroll_verified_authenticator(user_id:, authenticator:)
|
45
|
-
authenticator = authenticator.transform_keys { |key| camelize(key) }
|
46
53
|
response = Client.new.enroll_verified_authenticator(user_id, authenticator)
|
47
|
-
|
48
|
-
if response["authenticator"]
|
49
|
-
response["authenticator"] = response["authenticator"].transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
|
50
|
-
end
|
51
|
-
|
52
|
-
response = response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
|
53
54
|
|
54
|
-
response
|
55
|
+
handle_response(response)
|
55
56
|
end
|
56
57
|
|
57
58
|
def delete_user_authenticator(user_id:, user_authenticator_id: )
|
58
59
|
response = Client.new.delete_user_authenticator(user_id: user_id, user_authenticator_id: user_authenticator_id)
|
59
|
-
|
60
|
+
|
61
|
+
handle_response(response)
|
60
62
|
end
|
61
63
|
|
62
64
|
def track(event, options={})
|
63
65
|
raise ArgumentError, "Action Code is required" unless event[:action].to_s.length > 0
|
64
66
|
raise ArgumentError, "User ID value" unless event[:user_id].to_s.length > 0
|
65
67
|
|
66
|
-
|
68
|
+
response = Client.new.track(event)
|
69
|
+
handle_response(response)
|
70
|
+
end
|
67
71
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
+
def validate_challenge(token:, user_id: nil, action: nil)
|
73
|
+
response = Client.new.validate_challenge(user_id: user_id, token: token, action: action)
|
74
|
+
|
75
|
+
handle_response(response)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def handle_response(response)
|
81
|
+
if response.success?
|
82
|
+
handle_success_response(response)
|
72
83
|
else
|
73
|
-
|
84
|
+
handle_error_response(response)
|
74
85
|
end
|
75
|
-
|
76
|
-
response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
|
77
|
-
rescue => e
|
78
|
-
RuntimeError.new("Failed to track action")
|
79
|
-
false
|
80
86
|
end
|
81
87
|
|
82
|
-
def
|
83
|
-
response
|
84
|
-
|
85
|
-
return { user_id: response["userId"], is_valid: response["isValid"], state: response["state"], action: response["actionCode"] }
|
88
|
+
def handle_success_response(response)
|
89
|
+
response.body.merge(success?: true)
|
86
90
|
end
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
def handle_error_response(response)
|
93
|
+
case response.body
|
94
|
+
when Hash
|
95
|
+
response.body.merge(status: response.status, success?: false)
|
96
|
+
else
|
97
|
+
{ status: response&.status || 500, success?: false }
|
98
|
+
end
|
95
99
|
end
|
100
|
+
end
|
101
|
+
|
102
|
+
methods = Authsignal.singleton_class.public_instance_methods(false)
|
103
|
+
(methods - NON_API_METHODS).each do |method|
|
104
|
+
define_singleton_method("#{method}!") do |*args, **kwargs|
|
105
|
+
send(method, *args, **kwargs).tap do |response|
|
106
|
+
status = response[:status]
|
107
|
+
err = response[:error]
|
108
|
+
desc = response[:error_description]
|
96
109
|
|
97
|
-
|
98
|
-
|
99
|
-
string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
|
100
|
-
string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::").to_sym
|
110
|
+
raise ApiError.new(err, status, err, desc) unless response[:success?]
|
111
|
+
end
|
101
112
|
end
|
102
113
|
end
|
103
114
|
end
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authsignal-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- justinsoong
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday-retry
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
33
|
+
version: '2.2'
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
40
|
+
version: '2.2'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +72,14 @@ dependencies:
|
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: 3.14
|
75
|
+
version: '3.14'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: 3.14
|
82
|
+
version: '3.14'
|
69
83
|
description: Authsignal is a passwordless authentication/multifactor authentication
|
70
84
|
with modern factors like passkeys
|
71
85
|
email:
|
@@ -75,6 +89,7 @@ extensions: []
|
|
75
89
|
extra_rdoc_files: []
|
76
90
|
files:
|
77
91
|
- ".rspec"
|
92
|
+
- ".tool-versions"
|
78
93
|
- CHANGELOG.md
|
79
94
|
- Gemfile
|
80
95
|
- Gemfile.lock
|
@@ -85,8 +100,11 @@ files:
|
|
85
100
|
- bin/console
|
86
101
|
- bin/setup
|
87
102
|
- lib/authsignal.rb
|
103
|
+
- lib/authsignal/api_error.rb
|
88
104
|
- lib/authsignal/client.rb
|
89
105
|
- lib/authsignal/configuration.rb
|
106
|
+
- lib/authsignal/middleware/json_request.rb
|
107
|
+
- lib/authsignal/middleware/json_response.rb
|
90
108
|
- lib/authsignal/version.rb
|
91
109
|
homepage: https://github.com/authsignal/authsignal-ruby
|
92
110
|
licenses:
|