googleauth 0.8.0 → 0.8.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/.kokoro/build.sh +2 -34
- data/.kokoro/continuous/common.cfg +5 -0
- data/.kokoro/continuous/linux.cfg +1 -1
- data/.kokoro/osx.sh +2 -33
- data/.kokoro/presubmit/common.cfg +5 -0
- data/.kokoro/presubmit/linux.cfg +1 -1
- data/.kokoro/release.cfg +53 -0
- data/.kokoro/trampoline.sh +3 -23
- data/.kokoro/windows.sh +2 -30
- data/.rubocop.yml +7 -24
- data/CHANGELOG.md +24 -39
- data/Gemfile +14 -14
- data/README.md +21 -1
- data/Rakefile +84 -10
- data/googleauth.gemspec +23 -23
- data/lib/googleauth.rb +6 -6
- data/lib/googleauth/application_default.rb +11 -11
- data/lib/googleauth/client_id.rb +16 -16
- data/lib/googleauth/compute_engine.rb +27 -27
- data/lib/googleauth/credentials.rb +35 -37
- data/lib/googleauth/credentials_loader.rb +64 -67
- data/lib/googleauth/default_credentials.rb +18 -18
- data/lib/googleauth/iam.rb +9 -9
- data/lib/googleauth/json_key_reader.rb +6 -6
- data/lib/googleauth/scope_util.rb +11 -11
- data/lib/googleauth/service_account.rb +42 -42
- data/lib/googleauth/signet.rb +15 -17
- data/lib/googleauth/stores/file_token_store.rb +8 -8
- data/lib/googleauth/stores/redis_token_store.rb +17 -17
- data/lib/googleauth/token_store.rb +6 -6
- data/lib/googleauth/user_authorizer.rb +55 -59
- data/lib/googleauth/user_refresh.rb +27 -27
- data/lib/googleauth/version.rb +1 -1
- data/lib/googleauth/web_user_authorizer.rb +55 -56
- data/spec/googleauth/apply_auth_examples.rb +46 -46
- data/spec/googleauth/client_id_spec.rb +54 -54
- data/spec/googleauth/compute_engine_spec.rb +41 -41
- data/spec/googleauth/credentials_spec.rb +97 -97
- data/spec/googleauth/get_application_default_spec.rb +114 -114
- data/spec/googleauth/iam_spec.rb +25 -25
- data/spec/googleauth/scope_util_spec.rb +24 -24
- data/spec/googleauth/service_account_spec.rb +204 -194
- data/spec/googleauth/signet_spec.rb +37 -38
- data/spec/googleauth/stores/file_token_store_spec.rb +12 -12
- data/spec/googleauth/stores/redis_token_store_spec.rb +11 -11
- data/spec/googleauth/stores/store_examples.rb +16 -16
- data/spec/googleauth/user_authorizer_spec.rb +120 -121
- data/spec/googleauth/user_refresh_spec.rb +151 -146
- data/spec/googleauth/web_user_authorizer_spec.rb +66 -66
- data/spec/spec_helper.rb +19 -19
- metadata +4 -6
- data/.kokoro/common.cfg +0 -22
- data/.travis.yml +0 -40
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
|
-
require
|
|
31
|
-
require
|
|
32
|
-
require
|
|
33
|
-
require
|
|
30
|
+
require "googleauth/signet"
|
|
31
|
+
require "googleauth/credentials_loader"
|
|
32
|
+
require "googleauth/scope_util"
|
|
33
|
+
require "multi_json"
|
|
34
34
|
|
|
35
35
|
module Google
|
|
36
36
|
# Module Auth provides classes that provide Google-specific authorization
|
|
@@ -46,9 +46,9 @@ module Google
|
|
|
46
46
|
#
|
|
47
47
|
# cf [Application Default Credentials](http://goo.gl/mkAHpZ)
|
|
48
48
|
class UserRefreshCredentials < Signet::OAuth2::Client
|
|
49
|
-
TOKEN_CRED_URI =
|
|
50
|
-
AUTHORIZATION_URI =
|
|
51
|
-
REVOKE_TOKEN_URI =
|
|
49
|
+
TOKEN_CRED_URI = "https://oauth2.googleapis.com/token".freeze
|
|
50
|
+
AUTHORIZATION_URI = "https://accounts.google.com/o/oauth2/auth".freeze
|
|
51
|
+
REVOKE_TOKEN_URI = "https://oauth2.googleapis.com/revoke".freeze
|
|
52
52
|
extend CredentialsLoader
|
|
53
53
|
attr_reader :project_id
|
|
54
54
|
|
|
@@ -56,47 +56,47 @@ module Google
|
|
|
56
56
|
#
|
|
57
57
|
# @param json_key_io [IO] an IO from which the JSON key can be read
|
|
58
58
|
# @param scope [string|array|nil] the scope(s) to access
|
|
59
|
-
def self.make_creds
|
|
60
|
-
json_key_io, scope = options.values_at
|
|
61
|
-
user_creds = read_json_key
|
|
59
|
+
def self.make_creds options = {}
|
|
60
|
+
json_key_io, scope = options.values_at :json_key_io, :scope
|
|
61
|
+
user_creds = read_json_key json_key_io if json_key_io
|
|
62
62
|
user_creds ||= {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
"client_id" => ENV[CredentialsLoader::CLIENT_ID_VAR],
|
|
64
|
+
"client_secret" => ENV[CredentialsLoader::CLIENT_SECRET_VAR],
|
|
65
|
+
"refresh_token" => ENV[CredentialsLoader::REFRESH_TOKEN_VAR],
|
|
66
|
+
"project_id" => ENV[CredentialsLoader::PROJECT_ID_VAR]
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
new(token_credential_uri: TOKEN_CRED_URI,
|
|
70
|
-
client_id:
|
|
71
|
-
client_secret:
|
|
72
|
-
refresh_token:
|
|
73
|
-
project_id:
|
|
74
|
-
scope:
|
|
70
|
+
client_id: user_creds["client_id"],
|
|
71
|
+
client_secret: user_creds["client_secret"],
|
|
72
|
+
refresh_token: user_creds["refresh_token"],
|
|
73
|
+
project_id: user_creds["project_id"],
|
|
74
|
+
scope: scope)
|
|
75
75
|
.configure_connection(options)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Reads the client_id, client_secret and refresh_token fields from the
|
|
79
79
|
# JSON key.
|
|
80
|
-
def self.read_json_key
|
|
81
|
-
json_key = MultiJson.load
|
|
82
|
-
wanted = %w
|
|
80
|
+
def self.read_json_key json_key_io
|
|
81
|
+
json_key = MultiJson.load json_key_io.read
|
|
82
|
+
wanted = %w[client_id client_secret refresh_token]
|
|
83
83
|
wanted.each do |key|
|
|
84
|
-
raise "the json is missing the #{key} field" unless json_key.key?
|
|
84
|
+
raise "the json is missing the #{key} field" unless json_key.key? key
|
|
85
85
|
end
|
|
86
86
|
json_key
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
def initialize
|
|
89
|
+
def initialize options = {}
|
|
90
90
|
options ||= {}
|
|
91
91
|
options[:token_credential_uri] ||= TOKEN_CRED_URI
|
|
92
92
|
options[:authorization_uri] ||= AUTHORIZATION_URI
|
|
93
93
|
@project_id = options[:project_id]
|
|
94
94
|
@project_id ||= CredentialsLoader.load_gcloud_project_id
|
|
95
|
-
super
|
|
95
|
+
super options
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
# Revokes the credential
|
|
99
|
-
def revoke!
|
|
99
|
+
def revoke! options = {}
|
|
100
100
|
c = options[:connection] || Faraday.default_connection
|
|
101
101
|
|
|
102
102
|
retry_with_error do
|
|
@@ -119,7 +119,7 @@ module Google
|
|
|
119
119
|
# Scope to verify
|
|
120
120
|
# @return [Boolean]
|
|
121
121
|
# True if scope is granted
|
|
122
|
-
def includes_scope?
|
|
122
|
+
def includes_scope? required_scope
|
|
123
123
|
missing_scope = Google::Auth::ScopeUtil.normalize(required_scope) -
|
|
124
124
|
Google::Auth::ScopeUtil.normalize(scope)
|
|
125
125
|
missing_scope.empty?
|
data/lib/googleauth/version.rb
CHANGED
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
|
-
require
|
|
31
|
-
require
|
|
32
|
-
require
|
|
33
|
-
require
|
|
34
|
-
require
|
|
30
|
+
require "multi_json"
|
|
31
|
+
require "googleauth/signet"
|
|
32
|
+
require "googleauth/user_authorizer"
|
|
33
|
+
require "googleauth/user_refresh"
|
|
34
|
+
require "securerandom"
|
|
35
35
|
|
|
36
36
|
module Google
|
|
37
37
|
module Auth
|
|
@@ -66,21 +66,21 @@ module Google
|
|
|
66
66
|
# @see {Google::Auth::ControllerHelpers}
|
|
67
67
|
# @note Requires sessions are enabled
|
|
68
68
|
class WebUserAuthorizer < Google::Auth::UserAuthorizer
|
|
69
|
-
STATE_PARAM =
|
|
70
|
-
AUTH_CODE_KEY =
|
|
71
|
-
ERROR_CODE_KEY =
|
|
72
|
-
SESSION_ID_KEY =
|
|
73
|
-
CALLBACK_STATE_KEY =
|
|
74
|
-
CURRENT_URI_KEY =
|
|
75
|
-
XSRF_KEY =
|
|
76
|
-
SCOPE_KEY =
|
|
69
|
+
STATE_PARAM = "state".freeze
|
|
70
|
+
AUTH_CODE_KEY = "code".freeze
|
|
71
|
+
ERROR_CODE_KEY = "error".freeze
|
|
72
|
+
SESSION_ID_KEY = "session_id".freeze
|
|
73
|
+
CALLBACK_STATE_KEY = "g-auth-callback".freeze
|
|
74
|
+
CURRENT_URI_KEY = "current_uri".freeze
|
|
75
|
+
XSRF_KEY = "g-xsrf-token".freeze
|
|
76
|
+
SCOPE_KEY = "scope".freeze
|
|
77
77
|
|
|
78
|
-
NIL_REQUEST_ERROR =
|
|
79
|
-
NIL_SESSION_ERROR =
|
|
80
|
-
MISSING_AUTH_CODE_ERROR =
|
|
81
|
-
AUTHORIZATION_ERROR =
|
|
78
|
+
NIL_REQUEST_ERROR = "Request is required.".freeze
|
|
79
|
+
NIL_SESSION_ERROR = "Sessions must be enabled".freeze
|
|
80
|
+
MISSING_AUTH_CODE_ERROR = "Missing authorization code in request".freeze
|
|
81
|
+
AUTHORIZATION_ERROR = "Authorization error: %s".freeze
|
|
82
82
|
INVALID_STATE_TOKEN_ERROR =
|
|
83
|
-
|
|
83
|
+
"State token does not match expected value".freeze
|
|
84
84
|
|
|
85
85
|
class << self
|
|
86
86
|
attr_accessor :default
|
|
@@ -97,9 +97,9 @@ module Google
|
|
|
97
97
|
#
|
|
98
98
|
# @param [Rack::Request] request
|
|
99
99
|
# Current request
|
|
100
|
-
def self.handle_auth_callback_deferred
|
|
101
|
-
callback_state, redirect_uri = extract_callback_state
|
|
102
|
-
request.session[CALLBACK_STATE_KEY] = MultiJson.dump
|
|
100
|
+
def self.handle_auth_callback_deferred request
|
|
101
|
+
callback_state, redirect_uri = extract_callback_state request
|
|
102
|
+
request.session[CALLBACK_STATE_KEY] = MultiJson.dump callback_state
|
|
103
103
|
redirect_uri
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -114,8 +114,8 @@ module Google
|
|
|
114
114
|
# @param [String] callback_uri
|
|
115
115
|
# URL (either absolute or relative) of the auth callback. Defaults
|
|
116
116
|
# to '/oauth2callback'
|
|
117
|
-
def initialize
|
|
118
|
-
super
|
|
117
|
+
def initialize client_id, scope, token_store, callback_uri = nil
|
|
118
|
+
super client_id, scope, token_store, callback_uri
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
# Handle the result of the oauth callback. Exchanges the authorization
|
|
@@ -127,15 +127,15 @@ module Google
|
|
|
127
127
|
# Current request
|
|
128
128
|
# @return (Google::Auth::UserRefreshCredentials, String)
|
|
129
129
|
# credentials & next URL to redirect to
|
|
130
|
-
def handle_auth_callback
|
|
130
|
+
def handle_auth_callback user_id, request
|
|
131
131
|
callback_state, redirect_uri = WebUserAuthorizer.extract_callback_state(
|
|
132
132
|
request
|
|
133
133
|
)
|
|
134
|
-
WebUserAuthorizer.validate_callback_state
|
|
134
|
+
WebUserAuthorizer.validate_callback_state callback_state, request
|
|
135
135
|
credentials = get_and_store_credentials_from_code(
|
|
136
|
-
user_id:
|
|
137
|
-
code:
|
|
138
|
-
scope:
|
|
136
|
+
user_id: user_id,
|
|
137
|
+
code: callback_state[AUTH_CODE_KEY],
|
|
138
|
+
scope: callback_state[SCOPE_KEY],
|
|
139
139
|
base_url: request.url
|
|
140
140
|
)
|
|
141
141
|
[credentials, redirect_uri]
|
|
@@ -156,7 +156,7 @@ module Google
|
|
|
156
156
|
# not nil.
|
|
157
157
|
# @return [String]
|
|
158
158
|
# Authorization url
|
|
159
|
-
def get_authorization_url
|
|
159
|
+
def get_authorization_url options = {}
|
|
160
160
|
options = options.dup
|
|
161
161
|
request = options[:request]
|
|
162
162
|
raise NIL_REQUEST_ERROR if request.nil?
|
|
@@ -165,11 +165,11 @@ module Google
|
|
|
165
165
|
redirect_to = options[:redirect_to] || request.url
|
|
166
166
|
request.session[XSRF_KEY] = SecureRandom.base64
|
|
167
167
|
options[:state] = MultiJson.dump(
|
|
168
|
-
SESSION_ID_KEY
|
|
168
|
+
SESSION_ID_KEY => request.session[XSRF_KEY],
|
|
169
169
|
CURRENT_URI_KEY => redirect_to
|
|
170
170
|
)
|
|
171
171
|
options[:base_url] = request.url
|
|
172
|
-
super
|
|
172
|
+
super options
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
# Fetch stored credentials for the user.
|
|
@@ -186,32 +186,32 @@ module Google
|
|
|
186
186
|
# @raise [Signet::AuthorizationError]
|
|
187
187
|
# May raise an error if an authorization code is present in the session
|
|
188
188
|
# and exchange of the code fails
|
|
189
|
-
def get_credentials
|
|
190
|
-
if request.session.key?
|
|
189
|
+
def get_credentials user_id, request, scope = nil
|
|
190
|
+
if request.session.key? CALLBACK_STATE_KEY
|
|
191
191
|
# Note - in theory, no need to check required scope as this is
|
|
192
192
|
# expected to be called immediately after a return from authorization
|
|
193
|
-
state_json = request.session.delete
|
|
194
|
-
callback_state = MultiJson.load
|
|
195
|
-
WebUserAuthorizer.validate_callback_state
|
|
193
|
+
state_json = request.session.delete CALLBACK_STATE_KEY
|
|
194
|
+
callback_state = MultiJson.load state_json
|
|
195
|
+
WebUserAuthorizer.validate_callback_state callback_state, request
|
|
196
196
|
get_and_store_credentials_from_code(
|
|
197
|
-
user_id:
|
|
198
|
-
code:
|
|
199
|
-
scope:
|
|
197
|
+
user_id: user_id,
|
|
198
|
+
code: callback_state[AUTH_CODE_KEY],
|
|
199
|
+
scope: callback_state[SCOPE_KEY],
|
|
200
200
|
base_url: request.url
|
|
201
201
|
)
|
|
202
202
|
else
|
|
203
|
-
super
|
|
203
|
+
super user_id, scope
|
|
204
204
|
end
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
def self.extract_callback_state
|
|
208
|
-
state = MultiJson.load(request[STATE_PARAM] ||
|
|
207
|
+
def self.extract_callback_state request
|
|
208
|
+
state = MultiJson.load(request[STATE_PARAM] || "{}")
|
|
209
209
|
redirect_uri = state[CURRENT_URI_KEY]
|
|
210
210
|
callback_state = {
|
|
211
|
-
AUTH_CODE_KEY
|
|
211
|
+
AUTH_CODE_KEY => request[AUTH_CODE_KEY],
|
|
212
212
|
ERROR_CODE_KEY => request[ERROR_CODE_KEY],
|
|
213
213
|
SESSION_ID_KEY => state[SESSION_ID_KEY],
|
|
214
|
-
SCOPE_KEY
|
|
214
|
+
SCOPE_KEY => request[SCOPE_KEY]
|
|
215
215
|
}
|
|
216
216
|
[callback_state, redirect_uri]
|
|
217
217
|
end
|
|
@@ -226,12 +226,11 @@ module Google
|
|
|
226
226
|
# Error message if failed
|
|
227
227
|
# @param [Rack::Request] request
|
|
228
228
|
# Current request
|
|
229
|
-
def self.validate_callback_state
|
|
230
|
-
if state[AUTH_CODE_KEY].nil?
|
|
231
|
-
|
|
232
|
-
elsif state[ERROR_CODE_KEY]
|
|
229
|
+
def self.validate_callback_state state, request
|
|
230
|
+
raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR if state[AUTH_CODE_KEY].nil?
|
|
231
|
+
if state[ERROR_CODE_KEY]
|
|
233
232
|
raise Signet::AuthorizationError,
|
|
234
|
-
|
|
233
|
+
format(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY])
|
|
235
234
|
elsif request.session[XSRF_KEY] != state[SESSION_ID_KEY]
|
|
236
235
|
raise Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR
|
|
237
236
|
end
|
|
@@ -259,7 +258,7 @@ module Google
|
|
|
259
258
|
#
|
|
260
259
|
# @see {Google::Auth::WebUserAuthorizer}
|
|
261
260
|
class CallbackApp
|
|
262
|
-
LOCATION_HEADER =
|
|
261
|
+
LOCATION_HEADER = "Location".freeze
|
|
263
262
|
REDIR_STATUS = 302
|
|
264
263
|
ERROR_STATUS = 500
|
|
265
264
|
|
|
@@ -275,18 +274,18 @@ module Google
|
|
|
275
274
|
# Rack environment
|
|
276
275
|
# @return [Array]
|
|
277
276
|
# HTTP response
|
|
278
|
-
def self.call
|
|
279
|
-
request = Rack::Request.new
|
|
280
|
-
return_url = WebUserAuthorizer.handle_auth_callback_deferred
|
|
277
|
+
def self.call env
|
|
278
|
+
request = Rack::Request.new env
|
|
279
|
+
return_url = WebUserAuthorizer.handle_auth_callback_deferred request
|
|
281
280
|
if return_url
|
|
282
281
|
[REDIR_STATUS, { LOCATION_HEADER => return_url }, []]
|
|
283
282
|
else
|
|
284
|
-
[ERROR_STATUS, {}, [
|
|
283
|
+
[ERROR_STATUS, {}, ["No return URL is present in the request."]]
|
|
285
284
|
end
|
|
286
285
|
end
|
|
287
286
|
|
|
288
|
-
def call
|
|
289
|
-
self.class.call
|
|
287
|
+
def call env
|
|
288
|
+
self.class.call env
|
|
290
289
|
end
|
|
291
290
|
end
|
|
292
291
|
end
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
|
|
30
|
-
spec_dir = File.expand_path
|
|
31
|
-
$LOAD_PATH.unshift
|
|
30
|
+
spec_dir = File.expand_path File.join(File.dirname(__FILE__))
|
|
31
|
+
$LOAD_PATH.unshift spec_dir
|
|
32
32
|
$LOAD_PATH.uniq!
|
|
33
33
|
|
|
34
|
-
require
|
|
35
|
-
require
|
|
34
|
+
require "faraday"
|
|
35
|
+
require "spec_helper"
|
|
36
36
|
|
|
37
|
-
shared_examples
|
|
37
|
+
shared_examples "apply/apply! are OK" do
|
|
38
38
|
let(:auth_key) { :authorization }
|
|
39
39
|
|
|
40
40
|
# tests that use these examples need to define
|
|
@@ -43,103 +43,103 @@ shared_examples 'apply/apply! are OK' do
|
|
|
43
43
|
#
|
|
44
44
|
# @make_auth_stubs, which should stub out the expected http behaviour of the
|
|
45
45
|
# auth client
|
|
46
|
-
describe
|
|
47
|
-
let(:token) {
|
|
48
|
-
let
|
|
46
|
+
describe "#fetch_access_token" do
|
|
47
|
+
let(:token) { "1/abcdef1234567890" }
|
|
48
|
+
let :stub do
|
|
49
49
|
make_auth_stubs access_token: token
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
it
|
|
52
|
+
it "should set access_token to the fetched value" do
|
|
53
53
|
stub
|
|
54
54
|
@client.fetch_access_token!
|
|
55
55
|
expect(@client.access_token).to eq(token)
|
|
56
56
|
expect(stub).to have_been_requested
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
it
|
|
59
|
+
it "should notify refresh listeners after updating" do
|
|
60
60
|
stub
|
|
61
61
|
expect do |b|
|
|
62
62
|
@client.on_refresh(&b)
|
|
63
63
|
@client.fetch_access_token!
|
|
64
64
|
end.to yield_with_args(have_attributes(
|
|
65
|
-
access_token:
|
|
66
|
-
|
|
65
|
+
access_token: "1/abcdef1234567890"
|
|
66
|
+
))
|
|
67
67
|
expect(stub).to have_been_requested
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
describe
|
|
72
|
-
it
|
|
73
|
-
token =
|
|
71
|
+
describe "#apply!" do
|
|
72
|
+
it "should update the target hash with fetched access token" do
|
|
73
|
+
token = "1/abcdef1234567890"
|
|
74
74
|
stub = make_auth_stubs access_token: token
|
|
75
75
|
|
|
76
|
-
md = { foo:
|
|
77
|
-
@client.apply!
|
|
78
|
-
want = { :foo =>
|
|
76
|
+
md = { foo: "bar" }
|
|
77
|
+
@client.apply! md
|
|
78
|
+
want = { :foo => "bar", auth_key => "Bearer #{token}" }
|
|
79
79
|
expect(md).to eq(want)
|
|
80
80
|
expect(stub).to have_been_requested
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
describe
|
|
85
|
-
it
|
|
86
|
-
token =
|
|
84
|
+
describe "updater_proc" do
|
|
85
|
+
it "should provide a proc that updates a hash with the access token" do
|
|
86
|
+
token = "1/abcdef1234567890"
|
|
87
87
|
stub = make_auth_stubs access_token: token
|
|
88
|
-
md = { foo:
|
|
88
|
+
md = { foo: "bar" }
|
|
89
89
|
the_proc = @client.updater_proc
|
|
90
|
-
got = the_proc.call
|
|
91
|
-
want = { :foo =>
|
|
90
|
+
got = the_proc.call md
|
|
91
|
+
want = { :foo => "bar", auth_key => "Bearer #{token}" }
|
|
92
92
|
expect(got).to eq(want)
|
|
93
93
|
expect(stub).to have_been_requested
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
describe
|
|
98
|
-
it
|
|
99
|
-
token =
|
|
97
|
+
describe "#apply" do
|
|
98
|
+
it "should not update the original hash with the access token" do
|
|
99
|
+
token = "1/abcdef1234567890"
|
|
100
100
|
stub = make_auth_stubs access_token: token
|
|
101
101
|
|
|
102
|
-
md = { foo:
|
|
103
|
-
@client.apply
|
|
104
|
-
want = { foo:
|
|
102
|
+
md = { foo: "bar" }
|
|
103
|
+
@client.apply md
|
|
104
|
+
want = { foo: "bar" }
|
|
105
105
|
expect(md).to eq(want)
|
|
106
106
|
expect(stub).to have_been_requested
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
it
|
|
110
|
-
token =
|
|
109
|
+
it "should add the token to the returned hash" do
|
|
110
|
+
token = "1/abcdef1234567890"
|
|
111
111
|
stub = make_auth_stubs access_token: token
|
|
112
112
|
|
|
113
|
-
md = { foo:
|
|
114
|
-
got = @client.apply
|
|
115
|
-
want = { :foo =>
|
|
113
|
+
md = { foo: "bar" }
|
|
114
|
+
got = @client.apply md
|
|
115
|
+
want = { :foo => "bar", auth_key => "Bearer #{token}" }
|
|
116
116
|
expect(got).to eq(want)
|
|
117
117
|
expect(stub).to have_been_requested
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
it
|
|
121
|
-
token =
|
|
120
|
+
it "should not fetch a new token if the current is not expired" do
|
|
121
|
+
token = "1/abcdef1234567890"
|
|
122
122
|
stub = make_auth_stubs access_token: token
|
|
123
123
|
|
|
124
124
|
n = 5 # arbitrary
|
|
125
125
|
n.times do |_t|
|
|
126
|
-
md = { foo:
|
|
127
|
-
got = @client.apply
|
|
128
|
-
want = { :foo =>
|
|
126
|
+
md = { foo: "bar" }
|
|
127
|
+
got = @client.apply md
|
|
128
|
+
want = { :foo => "bar", auth_key => "Bearer #{token}" }
|
|
129
129
|
expect(got).to eq(want)
|
|
130
130
|
end
|
|
131
131
|
expect(stub).to have_been_requested
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
it
|
|
135
|
-
token1 =
|
|
136
|
-
token2 =
|
|
134
|
+
it "should fetch a new token if the current one is expired" do
|
|
135
|
+
token1 = "1/abcdef1234567890"
|
|
136
|
+
token2 = "2/abcdef1234567891"
|
|
137
137
|
|
|
138
138
|
[token1, token2].each do |t|
|
|
139
139
|
make_auth_stubs access_token: t
|
|
140
|
-
md = { foo:
|
|
141
|
-
got = @client.apply
|
|
142
|
-
want = { :foo =>
|
|
140
|
+
md = { foo: "bar" }
|
|
141
|
+
got = @client.apply md
|
|
142
|
+
want = { :foo => "bar", auth_key => "Bearer #{t}" }
|
|
143
143
|
expect(got).to eq(want)
|
|
144
144
|
@client.expires_at -= 3601 # default is to expire in 1hr
|
|
145
145
|
end
|