api-auth 2.0.0 → 2.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 +4 -4
- data/.travis.yml +35 -9
- data/CHANGELOG.md +7 -0
- data/Gemfile +4 -2
- data/VERSION +1 -1
- data/gemfiles/rails_5.gemfile +11 -0
- data/lib/api_auth/base.rb +2 -2
- data/lib/api_auth/headers.rb +1 -2
- data/lib/api_auth/railtie.rb +11 -4
- data/lib/api_auth/request_drivers/action_controller.rb +3 -4
- data/lib/api_auth/request_drivers/faraday.rb +3 -4
- data/lib/api_auth/request_drivers/httpi.rb +3 -4
- data/lib/api_auth/request_drivers/net_http.rb +2 -3
- data/lib/api_auth/request_drivers/rack.rb +3 -4
- data/lib/api_auth/request_drivers/rest_client.rb +3 -4
- data/spec/api_auth_spec.rb +25 -13
- data/spec/railtie_spec.rb +31 -7
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92c46c40ca59ec931c02893f62155ea3efdfba48
|
4
|
+
data.tar.gz: ac4c5514140b61f5df1b81408898413aef553cf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38370d16d830ae325f862f972b20d267da8135750e923520df5902662cae46b4244a79d1520ec15b9ca4722f76018f88bfbb874bc4b64fd44f70b36f8402d018
|
7
|
+
data.tar.gz: c3a16015aa11cd3da2b296d5729b3c7f0fccdea1e5a8005a98a4b7465e95944a951afdb9a474f182e1ff3df996d5d36e369f37f2cc60ed9e9eaf6c9e82c04985
|
data/.travis.yml
CHANGED
@@ -4,8 +4,9 @@ cache: bundler
|
|
4
4
|
rvm:
|
5
5
|
- 1.8.7-p374
|
6
6
|
- 1.9.3
|
7
|
-
- 2.1.
|
8
|
-
- 2.2.
|
7
|
+
- 2.1.9
|
8
|
+
- 2.2.5
|
9
|
+
- 2.3.1
|
9
10
|
gemfile:
|
10
11
|
- gemfiles/rails_23.gemfile
|
11
12
|
- gemfiles/rails_30.gemfile
|
@@ -14,6 +15,13 @@ gemfile:
|
|
14
15
|
- gemfiles/rails_4.gemfile
|
15
16
|
- gemfiles/rails_41.gemfile
|
16
17
|
- gemfiles/rails_42.gemfile
|
18
|
+
- gemfiles/rails_5.gemfile
|
19
|
+
env:
|
20
|
+
- TEST_SUITE=rake
|
21
|
+
|
22
|
+
script:
|
23
|
+
- bundle exec $TEST_SUITE
|
24
|
+
|
17
25
|
matrix:
|
18
26
|
exclude:
|
19
27
|
- rvm: 1.8.7-p374
|
@@ -22,20 +30,38 @@ matrix:
|
|
22
30
|
gemfile: gemfiles/rails_41.gemfile
|
23
31
|
- rvm: 1.8.7-p374
|
24
32
|
gemfile: gemfiles/rails_42.gemfile
|
25
|
-
- rvm:
|
33
|
+
- rvm: 1.8.7-p374
|
34
|
+
gemfile: gemfiles/rails_5.gemfile
|
35
|
+
- rvm: 1.9.3
|
36
|
+
gemfile: gemfiles/rails_5.gemfile
|
37
|
+
- rvm: 2.1.9
|
26
38
|
gemfile: gemfiles/rails_23.gemfile
|
27
|
-
- rvm: 2.1.
|
39
|
+
- rvm: 2.1.9
|
28
40
|
gemfile: gemfiles/rails_30.gemfile
|
29
|
-
- rvm: 2.1.
|
41
|
+
- rvm: 2.1.9
|
30
42
|
gemfile: gemfiles/rails_31.gemfile
|
31
|
-
- rvm: 2.
|
43
|
+
- rvm: 2.1.9
|
44
|
+
gemfile: gemfiles/rails_5.gemfile
|
45
|
+
- rvm: 2.2.5
|
46
|
+
gemfile: gemfiles/rails_23.gemfile
|
47
|
+
- rvm: 2.2.5
|
48
|
+
gemfile: gemfiles/rails_30.gemfile
|
49
|
+
- rvm: 2.2.5
|
50
|
+
gemfile: gemfiles/rails_31.gemfile
|
51
|
+
- rvm: 2.2.5
|
52
|
+
gemfile: gemfiles/rails_32.gemfile
|
53
|
+
- rvm: 2.3.1
|
32
54
|
gemfile: gemfiles/rails_23.gemfile
|
33
|
-
- rvm: 2.
|
55
|
+
- rvm: 2.3.1
|
34
56
|
gemfile: gemfiles/rails_30.gemfile
|
35
|
-
- rvm: 2.
|
57
|
+
- rvm: 2.3.1
|
36
58
|
gemfile: gemfiles/rails_31.gemfile
|
37
|
-
- rvm: 2.
|
59
|
+
- rvm: 2.3.1
|
38
60
|
gemfile: gemfiles/rails_32.gemfile
|
61
|
+
include:
|
62
|
+
- rvm: 2.3.1
|
63
|
+
gemfile: gemfiles/rails_5.gemfile
|
64
|
+
env: TEST_SUITE="rubocop lib/ spec/"
|
39
65
|
|
40
66
|
notifications:
|
41
67
|
email: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# 2.0.1 (2016-07-25)
|
2
|
+
- Support of `api_auth_options` in ActiveResource integration (#102 fwininger)
|
3
|
+
- Replace use of `#blank?` with `#nil?` to not depend on ActiveSupport (#114 packrat386)
|
4
|
+
- Fix Auth header matching to not match invalid SHA algorithms (#115 packrat386)
|
5
|
+
- Replace `alias_method_chain` with `alias_method` in the railtie since
|
6
|
+
alias_method_chain is deprecated in Rails 5 (#118 mlarraz)
|
7
|
+
|
1
8
|
# 2.0.0 (2016-05-11)
|
2
9
|
- IMPORTANT: 2.0.0 is backwards incompatible with the default settings of v1.x
|
3
10
|
v2.0.0 always includes the http method in the canonical string.
|
data/Gemfile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
3
|
|
4
|
-
gem
|
5
|
-
gem
|
4
|
+
gem 'rake', '< 11.0', :platforms => :ruby_18
|
5
|
+
gem 'tins', '< 1.7', :platforms => :ruby_19 # amatch dependency
|
6
|
+
|
7
|
+
gem 'rubocop', :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.0.1
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "actionpack", "~> 5.0.0"
|
6
|
+
gem "activeresource", "~> 5.0.0", git: 'https://github.com/rails/activeresource.git'
|
7
|
+
gem "activesupport", "~> 5.0.0"
|
8
|
+
|
9
|
+
gem "rubocop"
|
10
|
+
|
11
|
+
gemspec :path => "../"
|
data/lib/api_auth/base.rb
CHANGED
@@ -69,7 +69,7 @@ module ApiAuth
|
|
69
69
|
|
70
70
|
private
|
71
71
|
|
72
|
-
AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD[245]|SHA(?:1|224|256|384|512)
|
72
|
+
AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD[245]|SHA(?:1|224|256|384|512)?))? ([^:]+):(.+)$/
|
73
73
|
|
74
74
|
def request_too_old?(headers)
|
75
75
|
# 900 seconds is 15 minutes
|
@@ -83,7 +83,7 @@ module ApiAuth
|
|
83
83
|
match_data = parse_auth_header(headers.authorization_header)
|
84
84
|
return false unless match_data
|
85
85
|
|
86
|
-
digest = match_data[1].
|
86
|
+
digest = match_data[1].nil? ? 'SHA1' : match_data[1].upcase
|
87
87
|
raise InvalidRequestDigest if !options[:digest].nil? && !options[:digest].casecmp(digest).zero?
|
88
88
|
|
89
89
|
options = { :digest => digest }.merge(options)
|
data/lib/api_auth/headers.rb
CHANGED
data/lib/api_auth/railtie.rb
CHANGED
@@ -27,10 +27,12 @@ module ApiAuth
|
|
27
27
|
base.class_attribute :hmac_access_id
|
28
28
|
base.class_attribute :hmac_secret_key
|
29
29
|
base.class_attribute :use_hmac
|
30
|
+
base.class_attribute :api_auth_options
|
30
31
|
else
|
31
32
|
base.class_inheritable_accessor :hmac_access_id
|
32
33
|
base.class_inheritable_accessor :hmac_secret_key
|
33
34
|
base.class_inheritable_accessor :use_hmac
|
35
|
+
base.class_inheritable_accessor :api_auth_options
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -39,9 +41,11 @@ module ApiAuth
|
|
39
41
|
self.hmac_access_id = access_id
|
40
42
|
self.hmac_secret_key = secret_key
|
41
43
|
self.use_hmac = true
|
44
|
+
self.api_auth_options = options
|
42
45
|
|
43
46
|
class << self
|
44
|
-
|
47
|
+
alias_method :connection_without_auth, :connection
|
48
|
+
alias_method :connection, :connection_with_auth
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
@@ -50,6 +54,7 @@ module ApiAuth
|
|
50
54
|
c.hmac_access_id = hmac_access_id
|
51
55
|
c.hmac_secret_key = hmac_secret_key
|
52
56
|
c.use_hmac = use_hmac
|
57
|
+
c.api_auth_options = api_auth_options
|
53
58
|
c
|
54
59
|
end
|
55
60
|
end # class methods
|
@@ -60,9 +65,11 @@ module ApiAuth
|
|
60
65
|
|
61
66
|
module Connection
|
62
67
|
def self.included(base)
|
63
|
-
base.send :
|
68
|
+
base.send :alias_method, :request_without_auth, :request
|
69
|
+
base.send :alias_method, :request, :request_with_auth
|
70
|
+
|
64
71
|
base.class_eval do
|
65
|
-
attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
|
72
|
+
attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac, :api_auth_options
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
@@ -71,7 +78,7 @@ module ApiAuth
|
|
71
78
|
h = arguments.last
|
72
79
|
tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
|
73
80
|
tmp.body = arguments[0] if arguments.length > 1
|
74
|
-
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key)
|
81
|
+
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key, api_auth_options)
|
75
82
|
arguments.last['Content-MD5'] = tmp['Content-MD5'] if tmp['Content-MD5']
|
76
83
|
arguments.last['DATE'] = tmp['DATE']
|
77
84
|
arguments.last['Authorization'] = tmp['Authorization']
|
@@ -21,10 +21,9 @@ module ApiAuth
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def populate_content_md5
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
24
|
+
return unless @request.put? || @request.post?
|
25
|
+
@request.env['Content-MD5'] = calculated_md5
|
26
|
+
fetch_headers
|
28
27
|
end
|
29
28
|
|
30
29
|
def md5_mismatch?
|
@@ -21,10 +21,9 @@ module ApiAuth
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def populate_content_md5
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
24
|
+
return unless %w(POST PUT).include?(@request.method.to_s.upcase)
|
25
|
+
@request.headers['Content-MD5'] = calculated_md5
|
26
|
+
fetch_headers
|
28
27
|
end
|
29
28
|
|
30
29
|
def md5_mismatch?
|
@@ -20,10 +20,9 @@ module ApiAuth
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def populate_content_md5
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
23
|
+
return unless @request.body
|
24
|
+
@request.headers['Content-MD5'] = calculated_md5
|
25
|
+
fetch_headers
|
27
26
|
end
|
28
27
|
|
29
28
|
def md5_mismatch?
|
@@ -27,9 +27,8 @@ module ApiAuth
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def populate_content_md5
|
30
|
-
|
31
|
-
|
32
|
-
end
|
30
|
+
return unless @request.class::REQUEST_HAS_BODY
|
31
|
+
@request['Content-MD5'] = calculated_md5
|
33
32
|
end
|
34
33
|
|
35
34
|
def md5_mismatch?
|
@@ -26,10 +26,9 @@ module ApiAuth
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def populate_content_md5
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
29
|
+
return unless %w(POST PUT).include?(@request.request_method)
|
30
|
+
@request.env['Content-MD5'] = calculated_md5
|
31
|
+
fetch_headers
|
33
32
|
end
|
34
33
|
|
35
34
|
def md5_mismatch?
|
@@ -29,10 +29,9 @@ module ApiAuth
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def populate_content_md5
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
32
|
+
return unless [:post, :put].include?(@request.method)
|
33
|
+
@request.headers['Content-MD5'] = calculated_md5
|
34
|
+
save_headers
|
36
35
|
end
|
37
36
|
|
38
37
|
def md5_mismatch?
|
data/spec/api_auth_spec.rb
CHANGED
@@ -60,8 +60,7 @@ describe 'ApiAuth' do
|
|
60
60
|
Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
61
61
|
'content-type' => 'text/plain',
|
62
62
|
'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
|
63
|
-
'date' => Time.now.utc.httpdate
|
64
|
-
)
|
63
|
+
'date' => Time.now.utc.httpdate)
|
65
64
|
end
|
66
65
|
|
67
66
|
let(:canonical_string) { ApiAuth::Headers.new(request).canonical_string }
|
@@ -79,8 +78,7 @@ describe 'ApiAuth' do
|
|
79
78
|
new_request = Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
80
79
|
'content-type' => 'text/plain',
|
81
80
|
'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
|
82
|
-
'date' => Time.now.utc.httpdate
|
83
|
-
)
|
81
|
+
'date' => Time.now.utc.httpdate)
|
84
82
|
|
85
83
|
signature = hmac('123', new_request)
|
86
84
|
new_request['Authorization'] = "APIAuth 1044:#{signature}"
|
@@ -106,11 +104,10 @@ describe 'ApiAuth' do
|
|
106
104
|
end
|
107
105
|
|
108
106
|
it 'fails to validate if the date is invalid' do
|
109
|
-
request['date'] =
|
107
|
+
request['date'] = '٢٠١٤-٠٩-٠٨ ١٦:٣١:١٤ +٠٣٠٠'
|
110
108
|
expect(ApiAuth.authentic?(request, '123')).to eq false
|
111
109
|
end
|
112
110
|
|
113
|
-
|
114
111
|
it 'fails to validate if the request method differs' do
|
115
112
|
canonical_string = ApiAuth::Headers.new(request).canonical_string('POST')
|
116
113
|
signature = hmac('123', request, canonical_string)
|
@@ -123,20 +120,35 @@ describe 'ApiAuth' do
|
|
123
120
|
new_request = Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
|
124
121
|
'content-type' => 'text/plain',
|
125
122
|
'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
|
126
|
-
'date' => Time.now.utc.httpdate
|
127
|
-
)
|
123
|
+
'date' => Time.now.utc.httpdate)
|
128
124
|
canonical_string = ApiAuth::Headers.new(new_request).canonical_string
|
129
125
|
signature = hmac('123', new_request, canonical_string, 'sha256')
|
130
|
-
new_request['Authorization'] = "APIAuth-HMAC
|
126
|
+
new_request['Authorization'] = "APIAuth-HMAC-#{digest} 1044:#{signature}"
|
131
127
|
new_request
|
132
128
|
end
|
133
129
|
|
134
|
-
|
135
|
-
|
130
|
+
context 'valid request digest' do
|
131
|
+
let(:digest) { 'SHA256' }
|
132
|
+
|
133
|
+
context 'matching client digest' do
|
134
|
+
it 'validates matching digest' do
|
135
|
+
expect(ApiAuth.authentic?(request, '123', :digest => 'sha256')).to eq true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'different client digest' do
|
140
|
+
it 'raises an exception' do
|
141
|
+
expect { ApiAuth.authentic?(request, '123', :digest => 'sha512') }.to raise_error(ApiAuth::InvalidRequestDigest)
|
142
|
+
end
|
143
|
+
end
|
136
144
|
end
|
137
145
|
|
138
|
-
|
139
|
-
|
146
|
+
context 'invalid request digest' do
|
147
|
+
let(:digest) { 'SHA111' }
|
148
|
+
|
149
|
+
it 'fails validation' do
|
150
|
+
expect(ApiAuth.authentic?(request, '123', :digest => 'sha111')).to eq false
|
151
|
+
end
|
140
152
|
end
|
141
153
|
end
|
142
154
|
end
|
data/spec/railtie_spec.rb
CHANGED
@@ -62,7 +62,11 @@ describe 'Rails integration' do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'should permit a request with properly signed headers' do
|
65
|
-
request = ActionController::TestRequest.
|
65
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
66
|
+
ActionController::TestRequest.create
|
67
|
+
else
|
68
|
+
ActionController::TestRequest.new
|
69
|
+
end
|
66
70
|
request.env['DATE'] = Time.now.utc.httpdate
|
67
71
|
ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
|
68
72
|
response = generated_response(request, :index)
|
@@ -70,7 +74,11 @@ describe 'Rails integration' do
|
|
70
74
|
end
|
71
75
|
|
72
76
|
it 'should forbid a request with properly signed headers but timestamp > 15 minutes' do
|
73
|
-
request = ActionController::TestRequest.
|
77
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
78
|
+
ActionController::TestRequest.create
|
79
|
+
else
|
80
|
+
ActionController::TestRequest.new
|
81
|
+
end
|
74
82
|
request.env['DATE'] = 'Mon, 23 Jan 1984 03:29:56 GMT'
|
75
83
|
ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
|
76
84
|
response = generated_response(request, :index)
|
@@ -78,26 +86,42 @@ describe 'Rails integration' do
|
|
78
86
|
end
|
79
87
|
|
80
88
|
it "should insert a DATE header in the request when one hasn't been specified" do
|
81
|
-
request = ActionController::TestRequest.
|
89
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
90
|
+
ActionController::TestRequest.create
|
91
|
+
else
|
92
|
+
ActionController::TestRequest.new
|
93
|
+
end
|
82
94
|
ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
|
83
95
|
expect(request.headers['DATE']).not_to be_nil
|
84
96
|
end
|
85
97
|
|
86
98
|
it 'should forbid an unsigned request to a protected controller action' do
|
87
|
-
request = ActionController::TestRequest.
|
99
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
100
|
+
ActionController::TestRequest.create
|
101
|
+
else
|
102
|
+
ActionController::TestRequest.new
|
103
|
+
end
|
88
104
|
response = generated_response(request, :index)
|
89
105
|
expect(response.code).to eq('401')
|
90
106
|
end
|
91
107
|
|
92
108
|
it 'should forbid a request with a bogus signature' do
|
93
|
-
request = ActionController::TestRequest.
|
109
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
110
|
+
ActionController::TestRequest.create
|
111
|
+
else
|
112
|
+
ActionController::TestRequest.new
|
113
|
+
end
|
94
114
|
request.env['Authorization'] = 'APIAuth bogus:bogus'
|
95
115
|
response = generated_response(request, :index)
|
96
116
|
expect(response.code).to eq('401')
|
97
117
|
end
|
98
118
|
|
99
119
|
it 'should allow non-protected controller actions to function as before' do
|
100
|
-
request = ActionController::TestRequest.
|
120
|
+
request = if ActionController::TestRequest.respond_to?(:create)
|
121
|
+
ActionController::TestRequest.create
|
122
|
+
else
|
123
|
+
ActionController::TestRequest.new
|
124
|
+
end
|
101
125
|
response = generated_response(request, :public)
|
102
126
|
expect(response.code).to eq('200')
|
103
127
|
end
|
@@ -122,7 +146,7 @@ describe 'Rails integration' do
|
|
122
146
|
},
|
123
147
|
{ :id => '1' }.to_xml(:root => 'test_resource')
|
124
148
|
end
|
125
|
-
expect(ApiAuth).to receive(:sign!).with(anything, '1044', API_KEY_STORE['1044']).and_call_original
|
149
|
+
expect(ApiAuth).to receive(:sign!).with(anything, '1044', API_KEY_STORE['1044'], {}).and_call_original
|
126
150
|
TestResource.find(1)
|
127
151
|
end
|
128
152
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mauricio Gomes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -216,6 +216,7 @@ files:
|
|
216
216
|
- gemfiles/rails_4.gemfile
|
217
217
|
- gemfiles/rails_41.gemfile
|
218
218
|
- gemfiles/rails_42.gemfile
|
219
|
+
- gemfiles/rails_5.gemfile
|
219
220
|
- lib/api-auth.rb
|
220
221
|
- lib/api_auth.rb
|
221
222
|
- lib/api_auth/base.rb
|