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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 261ad3aa9e626f62f4b8ec843b0ec4516a157b083980cae0ed7c8641f16b5088
4
- data.tar.gz: 56d2f9ad45e5f6330999034ee7ac4667f5864bd0a2a745941f11edca0e840395
3
+ metadata.gz: e2bf6c96e9f79775fa1d3db3deb5ec5258a8c651e1b4fb8c1c3740c3f5ebd5b6
4
+ data.tar.gz: 90124d4aa0b3111cd4b52424c78b16f208d4179991e8dcfc52f48fc735483bba
5
5
  SHA512:
6
- metadata.gz: eac78f4ddab0dbb2d042c2d77ce424b512524cb0c1b31c5c956793e651441a4b2d93c1611a195eadfe53b4d377c1ad404a2190ee2b88add9a5867c40ba5c396e
7
- data.tar.gz: a0178eda449c5707522d441d680fd7ea7586fa21694a4ca7ea14a24b83543b9cfbcdf0613a00c2ad7d5f9cc10465ac3d767c8449dad6a18aaa44e85298fe96cd
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 (2.1.3)
5
- httparty (~> 0.21.0)
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.0)
11
- public_suffix (>= 2.0.2, < 5.0)
12
- crack (0.4.5)
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
- hashdiff (1.0.1)
16
- httparty (0.21.0)
17
- mini_mime (>= 1.0.0)
18
- multi_xml (>= 0.5.2)
19
- mini_mime (1.1.5)
20
- multi_xml (0.6.0)
21
- public_suffix (4.0.7)
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.2.5)
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
- webmock (3.14.0)
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.0)
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
@@ -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
- def handle_response(response)
8
- unless response.success?
9
- raise HTTParty::ResponseError, "Failed with status code #{response.code}"
10
- end
11
- response
12
- end
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
- @headers = {
19
- "User-Agent" => USER_AGENT,
20
- 'Content-Type' => 'application/json'
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
- def require_api_key
25
- Authsignal.configuration.api_secret_key || print_api_key_warning
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(action, options = {})
29
- actionCode = action[:action]
30
- idempotencyKey = ERB::Util.url_encode(action[:idempotencyKey])
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
- post(path, query: options, body: JSON.generate(body))
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 = "/users/#{ERB::Util.url_encode(user_id)}?redirectUrl=#{redirect_url}"
51
+ path = "users/#{url_encode(user_id)}?redirectUrl=#{redirect_url}"
41
52
  else
42
- path = "/users/#{ERB::Util.url_encode(user_id)}"
53
+ path = "users/#{url_encode(user_id)}"
43
54
  end
44
- get(path)
55
+ make_request(:get, path)
45
56
  end
46
57
 
47
58
  def update_user(user_id:, user:)
48
- post("/users/#{ERB::Util.url_encode(user_id)}", body: JSON.generate(user))
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("/users/#{ERB::Util.url_encode(user_id)}")
63
+ make_request(:delete, "users/#{url_encode(user_id)}")
53
64
  end
54
65
 
55
- def validate_challenge(user_id: nil, token:)
56
- path = "/validate"
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
- handle_response(response)
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("/users/#{ERB::Util.url_encode(user_id)}/actions/#{action}/#{ERB::Util.url_encode(idempotency_key)}")
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("/users/#{ERB::Util.url_encode(user_id)}", body: JSON.generate(user_payload))
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("/users/#{ERB::Util.url_encode(user_id)}/authenticators", body: JSON.generate(authenticator))
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("/users/#{ERB::Util.url_encode(user_id)}/authenticators/#{ERB::Util.url_encode(user_authenticator_id)}")
87
+ make_request(:delete, "users/#{url_encode(user_id)}/authenticators/#{url_encode(user_authenticator_id)}")
77
88
  end
78
89
 
79
- def get(path, query: {})
80
- self.class.get(path, headers: @headers, basic_auth: {username: @api_key})
81
- end
90
+ private
82
91
 
83
- def post(path, query: {}, body: {})
84
- self.class.post(path, headers: @headers, body: body, basic_auth: {username: @api_key})
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 delete(path, query: {}, body: {})
88
- self.class.delete(path, headers: @headers, body: body, basic_auth: {username: @api_key})
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Authsignal
4
- VERSION = "2.1.3"
4
+ VERSION = "3.0.1"
5
5
  end
data/lib/authsignal.rb CHANGED
@@ -1,10 +1,15 @@
1
- require "httparty"
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
- response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
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
- response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
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
- response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
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
- response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
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
- response.transform_keys { |key| underscore(key) }.transform_keys(&:to_sym)
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
- event = event.transform_keys { |key| camelize(key) }
68
+ response = Client.new.track(event)
69
+ handle_response(response)
70
+ end
67
71
 
68
- response = Client.new.track(event, options)
69
- success = response && response.success?
70
- if success
71
- puts("Tracked event! #{response.response.inspect}")
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
- puts("Track failure! #{response.response.inspect} #{response.body}")
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 validate_challenge(token:, user_id: nil)
83
- response = Client.new.validate_challenge(user_id: user_id, token: token)
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
- private
89
- def underscore(string)
90
- string.gsub(/::/, '/').
91
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
92
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
93
- tr("-", "_").
94
- downcase
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
- def camelize(symbol)
98
- string = symbol.to_s
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: 2.1.3
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-02 00:00:00.000000000 Z
11
+ date: 2024-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
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: 0.21.0
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: 0.21.0
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.0
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.0
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: