active_record_api-request 0.2.1 → 0.3.2

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: 50362697da6b9fa6cb9f864ccf8445d699751c3ac6186ac51b397a1a7c8d96b5
4
- data.tar.gz: c329f7ea4c3501dd6696c3bf35a6727dd417da3841904f47e655b3be6e9e7836
3
+ metadata.gz: 1bb4855eb0cc1e05c36a6cbf9f854e5e9f5d7295273c8ffdb2b3a818c010b1b8
4
+ data.tar.gz: 262c7a98bcf70e50279c2c19e28710780259fd3518168e6b1169b1f8616e6e93
5
5
  SHA512:
6
- metadata.gz: a64b9a39dc79bf9aec4d44d3c1f702648840e1ce4af75e4b3d69388b4a0f6524e12fd107dc88cbb60d46b7c121bcce4e7aa79f33d76e47a6438828930ff14098
7
- data.tar.gz: 62c66f196fed51c485e665ed89c155316dd6fefbbdb8fa7997c381a3e33f86d2bb2289ffe1bcc90540440327e379458cdce0136bd00fd44b4aa8ca32bdfdaf00
6
+ metadata.gz: 4863d724c7155740e6873cae1d1f0d1e51b8947810cbb31d57c99effd0c18c5fcefec930628402deaed14be4ea157d88eb7064ee89b55a87c998217b930242a6
7
+ data.tar.gz: bb3949e1090164cd04be0f4e06f9e26e0b01f88c065196e0fedfa7ef32cf941b0533349fd376ed9330c3c165de8033dd7eea412bf05fe332ba345099638c6554
@@ -10,6 +10,9 @@ module ActiveRecordApi
10
10
  autoload :Connection
11
11
  autoload :FaradayFollowNextLinks
12
12
  autoload :FaradayCacheServiceDown
13
- autoload :MicroServices
13
+ autoload :AuthError
14
+ autoload :FaradayAuthTokenRetry
15
+ autoload :TokenRetriever
16
+ autoload :TokenCache
14
17
  end
15
18
  end
@@ -0,0 +1,9 @@
1
+ require 'faraday_middleware'
2
+ #:nocov:#
3
+ module ActiveRecordApi
4
+ module Request
5
+ class AuthError < Faraday::ClientError
6
+ end
7
+ end
8
+ end
9
+ #:nocov:#
@@ -19,11 +19,12 @@ module ActiveRecordApi
19
19
  builder.options[:timeout] = 5
20
20
  builder.request :json
21
21
  builder.request :url_encoded
22
- builder.request :retry, max: 5, interval: 0.05, interval_randomness: 0.5, backoff_factor: 2
22
+ builder.request :retry, max: 5, interval: 0.05, interval_randomness: 0.5, backoff_factor: 2, exceptions: [ActiveRecordApi::Request::AuthError]
23
23
  builder.use FaradayCacheServiceDown, cache_store
24
24
  builder.use :http_cache, http_cache_options
25
25
  builder.use FaradayFollowNextLinks, 5
26
26
  builder.use FaradayMiddleware::FollowRedirects, standards_compliant: true
27
+ builder.use FaradayAuthTokenRetry, credentials: credentials, host: host, token_path: token_path, debug: debug
27
28
  builder.response :json, content_type: /\bjson$/
28
29
  builder.response :raise_error
29
30
  builder.response :logger if debug
@@ -1,4 +1,5 @@
1
1
  require 'active_attr'
2
+ #:nocov:#
2
3
 
3
4
  module ActiveRecordApi
4
5
  module Request
@@ -7,7 +8,7 @@ module ActiveRecordApi
7
8
  attr_writer :host, :token_path, :token, :email, :password, :headers
8
9
 
9
10
  def token
10
- @token ||= config(:token) || connection.post("#{host}/#{token_path}", credentials).body['token']
11
+ @token ||= config(:token)
11
12
  end
12
13
 
13
14
  def host
@@ -27,9 +28,13 @@ module ActiveRecordApi
27
28
  end
28
29
 
29
30
  def headers
30
- @headers ||= {
31
- 'Authorization' => "Bearer #{token}"
32
- }
31
+ @headers ||= {}.tap do |headers|
32
+ if token.present?
33
+ headers['Authorization'] = "Bearer #{token}"
34
+ else
35
+ headers['InjectToken'] = 'true'
36
+ end
37
+ end
33
38
  end
34
39
 
35
40
  def credentials
@@ -41,8 +46,14 @@ module ActiveRecordApi
41
46
  end
42
47
 
43
48
  def config(name)
44
- ENV["ACTIVE_RECORD_API_REQUEST_#{name.upcase}"] || Rails.application.credentials.try(:active_record_api_request).try(:[], name)
49
+ ENV["ACTIVE_RECORD_API_REQUEST_#{name.upcase}"] || credentials_config(name)
50
+ end
51
+
52
+ def credentials_config(name)
53
+ return unless defined? Rails
54
+ Rails.application.try(:credentials).try(:active_record_api_request).try(:[], name)
45
55
  end
46
56
  end
47
57
  end
48
58
  end
59
+ #:nocov:#
@@ -0,0 +1,38 @@
1
+ require 'faraday_middleware'
2
+ #:nocov:#
3
+
4
+ module ActiveRecordApi
5
+ module Request
6
+ class FaradayAuthTokenRetry < Faraday::Middleware
7
+ AUTH_KEY = 'Authorization'.freeze
8
+
9
+ attr_reader :credentials, :host, :token_path, :debug
10
+
11
+ def initialize(app, credentials: nil, host: nil, token_path: nil, debug: false)
12
+ super(app)
13
+ @credentials = credentials
14
+ @host = host
15
+ @token_path = token_path
16
+ @debug = debug
17
+ end
18
+
19
+ def call(env)
20
+ if env.request_headers['InjectToken'].present? && env.request_headers['InjectToken'] == 'true'
21
+ env.request_headers[AUTH_KEY] = "Bearer #{retrieve_token}"
22
+ end
23
+ @app.call(env)
24
+ rescue Faraday::ClientError => error
25
+ if error.response.try(:[], 'code') == 401
26
+ raise AuthError, error.response
27
+ else
28
+ raise error
29
+ end
30
+ end
31
+
32
+ def retrieve_token
33
+ TokenCache.new(debug: debug).fetch_token Proc.new { TokenRetriever.new(credentials: credentials, host: host, token_path: token_path, debug: debug).fetch_token }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ #:nocov:#
@@ -0,0 +1,65 @@
1
+ #:nocov:#
2
+ module ActiveRecordApi
3
+ module Request
4
+ class TokenCache
5
+ include ActiveAttr::Model
6
+ attr_accessor :debug
7
+
8
+ def fetch_token(token_proc)
9
+ retrieve_token_from_redis(token_proc)
10
+ end
11
+
12
+ def retrieve_token_from_redis(token_proc)
13
+ debug_log 'looking?'
14
+ return token_proc.call() unless defined? AUTH_REDIS_POOL
15
+ debug_log 'looking for token in cache'
16
+ AUTH_REDIS_POOL.with do |client|
17
+ @redis_client = client
18
+ @token = nil
19
+ @retry = 0
20
+ while @token.nil? && @retry < 5
21
+ @retry += 1
22
+ @token = @redis_client.get('auth_token')
23
+ debug_log "retry ##{@retry}"
24
+ debug_log "found token: #{@token}"
25
+ if @token.nil?
26
+ if acquire_lock
27
+ begin
28
+ debug_log "acquired lock"
29
+ @token = token_proc.call()
30
+ @redis_client.set 'auth_token', @token
31
+ ensure
32
+ debug_log 'releasing lock'
33
+ release_lock
34
+ end
35
+ else
36
+ debug_log 'waiting for token to be cached'
37
+ sleep 3
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def debug_log(message)
45
+ Rails.logger.info message if debug
46
+ end
47
+
48
+ def acquire_lock
49
+ @redis_client.set 'auth_token_lock', unique_key, nx: true, ex: 60
50
+ current_lock_value = @redis_client.get 'auth_token_lock'
51
+ Rails.logger.info "#{current_lock_value} == #{unique_key}" if debug
52
+ current_lock_value == unique_key
53
+ end
54
+
55
+ def release_lock
56
+ @redis_client.del 'auth_token_lock'
57
+ end
58
+
59
+ def unique_key
60
+ @unique_key ||= rand.to_s
61
+ end
62
+ end
63
+ end
64
+ end
65
+ #:nocov:#
@@ -0,0 +1,19 @@
1
+ #:nocov:#
2
+ module ActiveRecordApi
3
+ module Request
4
+ class TokenRetriever < Methods
5
+ attr_accessor :credentials, :host, :token_path
6
+
7
+ alias_method :path, :token_path
8
+
9
+ def fetch_token
10
+ post(payload: credentials)
11
+ end
12
+
13
+ def headers
14
+ @headers ||= {}
15
+ end
16
+ end
17
+ end
18
+ end
19
+ #:nocov:#
@@ -1,5 +1,5 @@
1
1
  module ActiveRecordApi
2
2
  module Request
3
- VERSION = '0.2.1'.freeze
3
+ VERSION = '0.3.2'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_api-request
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Full Measure Education
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-19 00:00:00.000000000 Z
11
+ date: 2019-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -176,12 +176,15 @@ files:
176
176
  - README.md
177
177
  - Rakefile
178
178
  - lib/active_record_api/request.rb
179
+ - lib/active_record_api/request/auth_error.rb
179
180
  - lib/active_record_api/request/connection.rb
180
181
  - lib/active_record_api/request/credentials.rb
182
+ - lib/active_record_api/request/faraday_auth_token_retry.rb
181
183
  - lib/active_record_api/request/faraday_cache_service_down.rb
182
184
  - lib/active_record_api/request/faraday_follow_next_links.rb
183
185
  - lib/active_record_api/request/methods.rb
184
- - lib/active_record_api/request/micro_services.rb
186
+ - lib/active_record_api/request/token_cache.rb
187
+ - lib/active_record_api/request/token_retriever.rb
185
188
  - lib/active_record_api/request/version.rb
186
189
  homepage: https://gitlab.com/fullmeasure/public/gems/active_record_api-request
187
190
  licenses:
@@ -1,15 +0,0 @@
1
- module ActiveRecordApi
2
- module Request
3
- module MicroServices
4
- MICRO_SERVICE_PATHS.each do |path_hash|
5
- klass = Class.new(Methods) do
6
- define_method :path do
7
- "#{path_hash[:service_path]}/#{path_hash[:model_path]}"
8
- end
9
- end
10
- klass_name = klass.new.path.tr('/', '_').gsub(/[^a-z_]/i, '').camelcase
11
- const_set klass_name, klass
12
- end
13
- end
14
- end
15
- end