authsignal-ruby 2.1.3 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: