oauth2_api_client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19c17dc8d34436a95460c68a49a070600cc70cccb68336bb58c47ea10ec42efb
4
+ data.tar.gz: bfe18b660c1f56ed84ef4d26a9b277acb1bd3a50b135196b89988a4a676a0ff7
5
+ SHA512:
6
+ metadata.gz: 77f3e27e9d04b09ced28691dc76a48d3f00a47c76d8a6fbdd847bbb45097cc562dff75da161b25f4a2f39e84578aa361c41e24cb6ecb19a6a329b13f9685c899
7
+ data.tar.gz: 5917eb46b4d65536d2246597774734d8c6b815245c9babfa8818f0b76f289c5d415ddb60066e9af4cbf96821d7d16c821c125936c2476daf1399d763cfe31175
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ gemfiles/*.lock
19
+ irb.rb
@@ -0,0 +1,125 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Metrics/ParameterLists:
5
+ Enabled: false
6
+
7
+ Style/HashTransformValues:
8
+ Enabled: false
9
+
10
+ Style/HashTransformKeys:
11
+ Enabled: false
12
+
13
+ Style/HashEachMethods:
14
+ Enabled: true
15
+
16
+ Style/FrozenStringLiteralComment:
17
+ Enabled: false
18
+
19
+ Lint/RedundantRequireStatement:
20
+ Enabled: false
21
+
22
+ Layout/ArgumentAlignment:
23
+ EnforcedStyle: with_fixed_indentation
24
+
25
+ Layout/FirstArrayElementIndentation:
26
+ EnforcedStyle: consistent
27
+
28
+ Style/PercentLiteralDelimiters:
29
+ Enabled: false
30
+
31
+ Style/SpecialGlobalVars:
32
+ EnforcedStyle: use_english_names
33
+
34
+ Security/Eval:
35
+ Enabled: false
36
+
37
+ Style/WordArray:
38
+ EnforcedStyle: brackets
39
+
40
+ Style/ClassAndModuleChildren:
41
+ Enabled: false
42
+
43
+ Style/TrivialAccessors:
44
+ Enabled: false
45
+
46
+ Style/Alias:
47
+ Enabled: false
48
+
49
+ Style/StringLiteralsInInterpolation:
50
+ EnforcedStyle: double_quotes
51
+
52
+ Metrics/ClassLength:
53
+ Enabled: false
54
+
55
+ Naming/MethodParameterName:
56
+ Enabled: false
57
+
58
+ Style/SymbolArray:
59
+ EnforcedStyle: brackets
60
+
61
+ Layout/RescueEnsureAlignment:
62
+ Enabled: false
63
+
64
+ Layout/LineLength:
65
+ Enabled: false
66
+
67
+ Metrics/MethodLength:
68
+ Enabled: false
69
+
70
+ Metrics/ModuleLength:
71
+ Enabled: false
72
+
73
+ Style/ZeroLengthPredicate:
74
+ Enabled: false
75
+
76
+ Metrics/PerceivedComplexity:
77
+ Enabled: false
78
+
79
+ Metrics/AbcSize:
80
+ Enabled: false
81
+
82
+ Metrics/CyclomaticComplexity:
83
+ Enabled: false
84
+
85
+ Metrics/BlockLength:
86
+ Enabled: false
87
+
88
+ Metrics/BlockNesting:
89
+ Enabled: false
90
+
91
+ Style/NumericPredicate:
92
+ Enabled: false
93
+
94
+ Naming/AccessorMethodName:
95
+ Enabled: false
96
+
97
+ Naming/MemoizedInstanceVariableName:
98
+ Enabled: false
99
+
100
+ Style/StringLiterals:
101
+ EnforcedStyle: double_quotes
102
+
103
+ Style/Documentation:
104
+ Enabled: false
105
+
106
+ Naming/ConstantName:
107
+ Enabled: false
108
+
109
+ Style/MutableConstant:
110
+ Enabled: false
111
+
112
+ Layout/MultilineMethodCallIndentation:
113
+ EnforcedStyle: indented
114
+
115
+ Layout/ParameterAlignment:
116
+ EnforcedStyle: with_fixed_indentation
117
+
118
+ Lint/UnusedMethodArgument:
119
+ Enabled: false
120
+
121
+ Style/IfUnlessModifier:
122
+ Enabled: false
123
+
124
+ Style/RedundantBegin:
125
+ Enabled: false
@@ -0,0 +1,10 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - ruby-2.6.2
5
+ - ruby-2.7.1
6
+ install:
7
+ - travis_retry bundle install
8
+ script:
9
+ - bundle exec rspec
10
+ - bundle exec rubocop
@@ -0,0 +1,3 @@
1
+
2
+ # CHANGELOG
3
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Benjamin Vetter
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # oauth2_api_client
2
+
3
+ [![Build Status](https://secure.travis-ci.org/mrkamel/oauth2_api_client.svg?branch=master)](http://travis-ci.org/mrkamel/oauth2_api_client)
4
+ [![Gem Version](https://badge.fury.io/rb/oauth2_api_client.svg)](http://badge.fury.io/rb/oauth2_api_client)
5
+
6
+ Oauth2ApiClient is small, but powerful client around
7
+ [oauth2](https://github.com/oauth-xx/oauth2) and
8
+ [http-rb](https://github.com/httprb/http) to interact with APIs which use
9
+ oauth2 for authentication with automatic token caching and renewal.
10
+
11
+ ```ruby
12
+ client = Oauth2ApiClient.new(
13
+ base_url: "https://api.example.com/",
14
+ client_id: "the client id",
15
+ client_secret: "the client secret",
16
+ oauth_token_url: "https://auth.example.com/oauth2/token",
17
+ max_token_ttl: 3600, # optional
18
+ cache: Rails.cache # optional
19
+ )
20
+
21
+ client.post("/orders", json: { address: "..." }).status.success?
22
+ client.headers("User-Agent" => "API Client").timeout(read: 5, write: 5).get("/orders").parse
23
+ # ...
24
+ ```
25
+
26
+ ## Install
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'oauth2_api_client'
32
+ ```
33
+
34
+ and then execute
35
+
36
+ ```
37
+ $ bundle
38
+ ```
39
+
40
+ or install it via
41
+
42
+ ```
43
+ $ gem install oauth2_api_client
44
+ ```
45
+
46
+ ## Reference Docs
47
+
48
+ The reference docs can be found at
49
+ [http://www.rubydoc.info/github/mrkamel/oauth2_api_client](http://www.rubydoc.info/github/mrkamel/oauth2_api_client)
50
+
51
+ ## Semantic Versioning
52
+
53
+ Oauth2ApiClient is using Semantic Versioning: [SemVer](http://semver.org/)
54
+
55
+ ## Contributing
56
+
57
+ 1. Fork it
58
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
59
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
60
+ 4. Push to the branch (`git push origin my-new-feature`)
61
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "lib"
6
+ t.pattern = "test/**/*_test.rb"
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,117 @@
1
+ require "ruby2_keywords"
2
+ require "oauth2"
3
+ require "http"
4
+ require "ruby2_keywords"
5
+ require "active_support"
6
+
7
+ require "oauth2_api_client/version"
8
+ require "oauth2_api_client/http_error"
9
+
10
+ # The Oauth2ApiClient class is a client wrapped around the oauth2 and http-rb
11
+ # gem to interact with APIs using oauth2 for authentication with automatic
12
+ # token caching and renewal.
13
+
14
+ class Oauth2ApiClient
15
+ # Creates a new Oauth2ApiClient
16
+ #
17
+ # @param base_url [String] The base url of the API to interact with
18
+ # @param client_id [String] The client id to use for oauth2 authentication
19
+ # @param client_secret [String] The client secret to use for oauth2 authentication
20
+ # @param oauth_token_url [String] The url to obtain tokens from
21
+ # @param cache The cache instance to cache the tokens, e.g. `Rails.cache`.
22
+ # Defaults to `ActiveSupport::Cache::MemoryStore.new`
23
+ # @param max_token_ttl [#to_i] The max lifetime of the token in the cache
24
+ # @param base_request You can pass some http-rb rqeuest as the base. Useful,
25
+ # if some information needs to be passed with every request. Defaults to
26
+ # `HTTP`
27
+ #
28
+ # @example
29
+ # client = Oauth2ApiClient.new(
30
+ # base_url: "https://api.example.com/",
31
+ # client_id: "the client id",
32
+ # client_secret: "the client secret",
33
+ # oauth_token_url: "https://auth.example.com/oauth2/token",
34
+ # cache: Rails.cache,
35
+ # base_request: HTTP.headers("User-Agent" => "API client")
36
+ # )
37
+ #
38
+ # client.post("/orders", json: { address: "..." }).status.success?
39
+ # client.headers("User-Agent" => "API Client").timeout(read: 5, write: 5).get("/orders").parse
40
+
41
+ def initialize(base_url:, client_id:, client_secret:, oauth_token_url:, cache: ActiveSupport::Cache::MemoryStore.new, max_token_ttl: 3600, base_request: HTTP)
42
+ @base_url = base_url
43
+ @client_id = client_id
44
+ @client_secret = client_secret
45
+ @oauth_token_url = oauth_token_url
46
+ @max_token_ttl = max_token_ttl
47
+ @cache = cache
48
+ @request = base_request
49
+
50
+ oauth_uri = URI.parse(oauth_token_url)
51
+
52
+ @oauth_client = OAuth2::Client.new(
53
+ @client_id,
54
+ @client_secret,
55
+ site: URI.parse("#{oauth_uri.scheme}://#{oauth_uri.host}:#{oauth_uri.port}/").to_s,
56
+ token_url: oauth_uri.path
57
+ )
58
+ end
59
+
60
+ # Returns a oauth2 token to use for authentication
61
+ #
62
+ # @return [String] The token
63
+
64
+ def token
65
+ @cache.fetch(cache_key, expires_in: @max_token_ttl.to_i) do
66
+ @oauth_client.client_credentials.get_token.token
67
+ end
68
+ end
69
+
70
+ [:timeout, :headers, :cookies, :via, :encoding, :accept, :auth, :basic_auth].each do |method|
71
+ define_method method do |*args|
72
+ dup.tap do |client|
73
+ client.instance_variable_set(:@request, @request.send(method, *args))
74
+ end
75
+ end
76
+
77
+ ruby2_keywords method
78
+ end
79
+
80
+ [:get, :post, :put, :delete, :head, :options].each do |method|
81
+ define_method method do |path, options = {}|
82
+ execute(method, path, options)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def cache_key
89
+ @cache_key ||= ["oauth_api_client", @base_url, @oauth_token_url, @client_id].join("|")
90
+ end
91
+
92
+ def execute(verb, path, options = {})
93
+ with_retry do
94
+ response = @request.auth("Bearer #{token}").send(verb, URI.join(@base_url, path), options)
95
+
96
+ return response if response.status.success?
97
+
98
+ raise HttpError.new(response.status.to_s, response)
99
+ end
100
+ end
101
+
102
+ def with_retry
103
+ retried = false
104
+
105
+ begin
106
+ yield
107
+ rescue HttpError => e
108
+ @cache.delete(cache_key) if e.response.status.unauthorized?
109
+
110
+ raise(e) if retried || !e.response.status.unauthorized?
111
+
112
+ retried = true
113
+
114
+ retry
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,10 @@
1
+ class Oauth2ApiClient
2
+ class HttpError < StandardError
3
+ attr_reader :message, :response
4
+
5
+ def initialize(message, response)
6
+ @message = message
7
+ @response = response
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ class Oauth2ApiClient
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require "oauth2_api_client/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "oauth2_api_client"
8
+ spec.version = Oauth2ApiClient::VERSION
9
+ spec.authors = ["Benjamin Vetter"]
10
+ spec.email = ["vetter@flakks.com"]
11
+ spec.description = "Small but powerful client around oauth2 and http-rb to interact with APIs"
12
+ spec.summary = "Small but powerful client around oauth2 and http-rb to interact with APIs"
13
+ spec.homepage = "https://github.com/mrkamel/oauth2_api_client"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rubocop"
24
+ spec.add_development_dependency "timecop"
25
+ spec.add_development_dependency "webmock"
26
+
27
+ spec.add_dependency "activesupport"
28
+ spec.add_dependency "http"
29
+ spec.add_dependency "oauth2"
30
+ spec.add_dependency "ruby2_keywords"
31
+ end
@@ -0,0 +1,193 @@
1
+ require File.expand_path("./spec_helper", __dir__)
2
+
3
+ class HttpTestRequest
4
+ attr_accessor :calls
5
+
6
+ def initialize
7
+ self.calls = []
8
+ end
9
+
10
+ [:timeout, :headers, :cookies, :via, :encoding, :accept, :auth, :basic_auth].each do |method|
11
+ define_method method do |*args|
12
+ dup.tap do |request|
13
+ request.calls = calls + [[method, args]]
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ RSpec.describe Oauth2ApiClient do
20
+ before do
21
+ token_response = {
22
+ access_token: "access_token",
23
+ token_type: "bearer",
24
+ expires_in: 3600,
25
+ refresh_token: "refresh_token",
26
+ scope: "create"
27
+ }
28
+
29
+ stub_request(:post, "http://localhost/oauth2/token")
30
+ .to_return(status: 200, body: JSON.generate(token_response), headers: { "Content-Type" => "application/json" })
31
+ end
32
+
33
+ describe "#token" do
34
+ it "returns a oauth2 token" do
35
+ client = described_class.new(
36
+ base_url: "http://localhost/",
37
+ client_id: "client_id",
38
+ client_secret: "client_secret",
39
+ oauth_token_url: "http://localhost/oauth2/token"
40
+ )
41
+
42
+ expect(client.token).to eq("access_token")
43
+ end
44
+
45
+ it "returns the cached token if existing" do
46
+ cache = ActiveSupport::Cache::MemoryStore.new
47
+
48
+ allow(cache).to receive(:fetch).and_return("cached_token")
49
+
50
+ client = described_class.new(
51
+ base_url: "http://localhost/",
52
+ client_id: "client_id",
53
+ client_secret: "client_secret",
54
+ oauth_token_url: "http://localhost/oauth2/token",
55
+ cache: cache
56
+ )
57
+
58
+ expect(client.token).to eq("cached_token")
59
+ end
60
+
61
+ it "caches the token" do
62
+ cache = ActiveSupport::Cache::MemoryStore.new
63
+
64
+ allow(cache).to receive(:fetch).and_yield
65
+
66
+ client = described_class.new(
67
+ base_url: "http://localhost/",
68
+ client_id: "client_id",
69
+ client_secret: "client_secret",
70
+ oauth_token_url: "http://localhost/oauth2/token",
71
+ max_token_ttl: 60,
72
+ cache: cache
73
+ )
74
+
75
+ client.token
76
+
77
+ expect(cache).to have_received(:fetch).with("oauth_api_client|http://localhost/|http://localhost/oauth2/token|client_id", expires_in: 60)
78
+ end
79
+ end
80
+
81
+ [:timeout, :headers, :cookies, :via, :encoding, :accept, :auth, :basic_auth].each do |method|
82
+ describe "##{method}" do
83
+ it "creates a dupped instance" do
84
+ client = described_class.new(
85
+ base_url: "http://localhost/",
86
+ client_id: "client_id",
87
+ client_secret: "client_secret",
88
+ oauth_token_url: "http://localhost/oauth2/token",
89
+ base_request: HttpTestRequest.new
90
+ )
91
+
92
+ client1 = client.send(method, "key1")
93
+ client2 = client1.send(method, "key1")
94
+
95
+ expect(client1.object_id).not_to eq(client2.object_id)
96
+ end
97
+
98
+ it "extends the request" do
99
+ client = described_class.new(
100
+ base_url: "http://localhost/",
101
+ client_id: "client_id",
102
+ client_secret: "client_secret",
103
+ oauth_token_url: "http://localhost/oauth2/token",
104
+ base_request: HttpTestRequest.new
105
+ )
106
+
107
+ client1 = client.send(method, "key1")
108
+ client2 = client1.send(method, "key2")
109
+
110
+ expect(client1.instance_variable_get(:@request).calls).to eq([[method, ["key1"]]])
111
+ expect(client2.instance_variable_get(:@request).calls).to eq([[method, ["key1"]], [method, ["key2"]]])
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "request" do
117
+ it "prepends the base url" do
118
+ stub_request(:get, "http://localhost/path?key=value")
119
+ .to_return(status: 200, body: "ok")
120
+
121
+ client = described_class.new(
122
+ base_url: "http://localhost/",
123
+ client_id: "client_id",
124
+ client_secret: "client_secret",
125
+ oauth_token_url: "http://localhost/oauth2/token"
126
+ )
127
+
128
+ expect(client.get("/path", params: { key: "value" }).to_s).to eq("ok")
129
+ end
130
+
131
+ it "passes the token in the authentication header" do
132
+ stub_request(:get, "http://localhost/path")
133
+ .with(headers: { "Authorization" => "Bearer access_token" })
134
+ .to_return(status: 200, body: "ok", headers: {})
135
+
136
+ client = described_class.new(
137
+ base_url: "http://localhost/",
138
+ client_id: "client_id",
139
+ client_secret: "client_secret",
140
+ oauth_token_url: "http://localhost/oauth2/token"
141
+ )
142
+
143
+ expect(client.get("/path").to_s).to eq("ok")
144
+ end
145
+
146
+ it "invalidates the cached token when an http unauthorized status is returned" do
147
+ stub_request(:get, "http://localhost/path")
148
+ .to_return(status: 401, body: "unauthorized")
149
+
150
+ cache = ActiveSupport::Cache::MemoryStore.new
151
+
152
+ client = described_class.new(
153
+ base_url: "http://localhost/",
154
+ client_id: "client_id",
155
+ client_secret: "client_secret",
156
+ oauth_token_url: "http://localhost/oauth2/token",
157
+ cache: cache
158
+ )
159
+
160
+ expect { client.get("/path") }.to raise_error(described_class::HttpError)
161
+
162
+ expect(cache.read("oauth_api_client|http://localhost/|http://localhost/oauth2/token|client_id")).to be_nil
163
+ end
164
+
165
+ it "retries the request when an http unauthorized status is returned" do
166
+ stub_request(:get, "http://localhost/path")
167
+ .to_return({ status: 401, body: "unauthorized" }, { status: 200, body: "ok" })
168
+
169
+ client = described_class.new(
170
+ base_url: "http://localhost/",
171
+ client_id: "client_id",
172
+ client_secret: "client_secret",
173
+ oauth_token_url: "http://localhost/oauth2/token"
174
+ )
175
+
176
+ expect(client.get("/path").to_s).to eq("ok")
177
+ end
178
+
179
+ it "raises if the retried request also fails" do
180
+ stub_request(:get, "http://localhost/path")
181
+ .to_return(status: 401, body: "unauthorized")
182
+
183
+ client = described_class.new(
184
+ base_url: "http://localhost/",
185
+ client_id: "client_id",
186
+ client_secret: "client_secret",
187
+ oauth_token_url: "http://localhost/oauth2/token"
188
+ )
189
+
190
+ expect { client.get("/path") }.to raise_error(described_class::HttpError)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,5 @@
1
+ require "oauth2_api_client"
2
+ require "webmock/rspec"
3
+ require "timecop"
4
+
5
+ WebMock.disable_net_connect!
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oauth2_api_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin Vetter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: timecop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: http
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: oauth2
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: ruby2_keywords
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Small but powerful client around oauth2 and http-rb to interact with
140
+ APIs
141
+ email:
142
+ - vetter@flakks.com
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".rubocop.yml"
149
+ - ".travis.yml"
150
+ - CHANGELOG.md
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - lib/oauth2_api_client.rb
156
+ - lib/oauth2_api_client/http_error.rb
157
+ - lib/oauth2_api_client/version.rb
158
+ - oauth2_api_client.gemspec
159
+ - spec/oauth2_api_client_spec.rb
160
+ - spec/spec_helper.rb
161
+ homepage: https://github.com/mrkamel/oauth2_api_client
162
+ licenses:
163
+ - MIT
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubygems_version: 3.0.3
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: Small but powerful client around oauth2 and http-rb to interact with APIs
184
+ test_files:
185
+ - spec/oauth2_api_client_spec.rb
186
+ - spec/spec_helper.rb