aptible-auth 0.1.4 → 0.2.0

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
  SHA1:
3
- metadata.gz: db3c1ba550b3a777611816a3828b182d0e2d3a27
4
- data.tar.gz: 97fe3444852024e2c306c40a85ac900179a4bfb1
3
+ metadata.gz: 9ead7f15f6ad01c4a7b9b7bed9a8840b07afe5c2
4
+ data.tar.gz: 34335f77ccea4353b373664ba3682d79c7fcbba1
5
5
  SHA512:
6
- metadata.gz: 2e106b93c20c79b736d18a7d7def5d381a1b6a956fce65c60acf06363f96d8ee336627e5d897bbe791be543900a1bc16e4a8d32c54cfcc1153c2a2a983d6b9c9
7
- data.tar.gz: af94ac3a6532389de1a5daece03a11aee35441189dcc77ba63e9f9aca11a1a6c54f967a54d4314c5481118e2f42206a9dfd9fac7a01ca171259f7f4518e32e16
6
+ metadata.gz: baa2716fc686c7adb7f45087b8ab63d0aadf82c8a392d5176a25d84cfc799e4d74660acc267e5e0d0cf146d058a810c7e31b816a5d3d5ebf345bc7f8ee680a04
7
+ data.tar.gz: 4f73fa2447498ebaf7ea19373fbfc592fd6c320f7ed0f587212e759d50c71d10a4169f2e04d81a2ad8c868641f965a41799edb4ef2a9ab1a4f6d8be105f56b78
@@ -0,0 +1 @@
1
+ console: bundle exec pry -r aptible/auth
data/README.md CHANGED
@@ -16,7 +16,7 @@ Add the following lines to your application's Gemfile.
16
16
 
17
17
  The forked version of the OAuth2 gem is necessary until [intridea/oauth2#165](https://github.com/intridea/oauth2/pull/165) and [intridea/oauth2#166](https://github.com/intridea/oauth2/pull/166) are merged.
18
18
 
19
- The forked version of the HyperResource gem is necessary until [gamache/hyperresource#19](https://github.com/gamache/hyperresource/pull/19) is merged.
19
+ The forked version of the HyperResource gem is necessary until [gamache/hyperresource#22](https://github.com/gamache/hyperresource/pull/22) and [gamache/hyperresource#23](https://github.com/gamache/hyperresource/pull/23) are merged.
20
20
 
21
21
  And then run `bundle install`.
22
22
 
@@ -28,9 +28,9 @@ First, get a token:
28
28
  token = Aptible::Auth::Token.new(email: 'user0@example.com', password: 'password')
29
29
  ```
30
30
 
31
- Then, initialize a client:
31
+ Then, initialize a resource agent:
32
32
  ```ruby
33
- auth = Aptible::Auth::Client.new(token: token)
33
+ auth = Aptible::Auth::Resource.new(token: token)
34
34
  ```
35
35
 
36
36
  From here, you can interact with the Authorization API however you wish:
@@ -3,11 +3,10 @@ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  require 'English'
6
- require 'aptible/auth/version'
7
6
 
8
7
  Gem::Specification.new do |spec|
9
8
  spec.name = 'aptible-auth'
10
- spec.version = Aptible::Auth::VERSION
9
+ spec.version = '0.2.0'
11
10
  spec.authors = ['Frank Macreery']
12
11
  spec.email = ['frank@macreery.com']
13
12
  spec.description = 'Ruby client for auth.aptible.com'
@@ -23,6 +22,7 @@ Gem::Specification.new do |spec|
23
22
  spec.add_dependency 'oauth2'
24
23
  spec.add_dependency 'hyperresource'
25
24
  spec.add_dependency 'fridge'
25
+ spec.add_dependency 'activesupport'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.3'
28
28
  spec.add_development_dependency 'aptible-tasks', '>= 0.2.0'
@@ -1,13 +1,13 @@
1
- require 'aptible/auth/version'
2
- require 'aptible/auth/token'
3
- require 'aptible/auth/client'
4
-
5
1
  require 'gem_config'
2
+ require 'hyperresource'
3
+ require 'fridge'
6
4
 
7
5
  module Aptible
8
- module Auth
6
+ class Auth < HyperResource
9
7
  include GemConfig::Base
10
8
 
9
+ attr_accessor :token, :config
10
+
11
11
  with_configuration do
12
12
  has :root_url,
13
13
  classes: [String],
@@ -15,7 +15,62 @@ module Aptible
15
15
  end
16
16
 
17
17
  def self.public_key
18
- Client.new.get.public_key
18
+ Resource.new.get.public_key
19
+ end
20
+
21
+ def self.get_data_type_from_response(response)
22
+ return nil unless response && response.body
23
+ adapter.get_data_type_from_object(adapter.deserialize(response.body))
24
+ end
25
+
26
+ def self.adapter
27
+ Aptible::Auth::Adapter
28
+ end
29
+
30
+ def adapter
31
+ self.class.adapter
32
+ end
33
+
34
+ def initialize(options = {})
35
+ if options.is_a?(Hash)
36
+ self.token = options[:token]
37
+
38
+ options[:root] ||= config.root_url
39
+ options[:namespace] ||= 'Aptible::Auth'
40
+ options[:headers] ||= { 'Content-Type' => 'application/json' }
41
+ options[:headers].merge!(
42
+ 'Authorization' => "Bearer #{bearer_token}"
43
+ ) if options[:token]
44
+ end
45
+
46
+ super(options)
47
+ end
48
+
49
+ def find_by_url(url)
50
+ fail "URL must be rooted at #{root}" unless /^#{root}/.match url
51
+
52
+ resource = dup
53
+ resource.href = url.gsub(/^#{root}/, '')
54
+ resource.get
55
+ end
56
+
57
+ def organizations
58
+ orgs
59
+ end
60
+
61
+ def bearer_token
62
+ case token
63
+ when Aptible::Auth::Token then token.access_token
64
+ when Fridge::AccessToken then token.to_s
65
+ when String then token
66
+ end
67
+ end
68
+
69
+ def config
70
+ @config ||= Aptible::Auth.configuration
19
71
  end
20
72
  end
21
73
  end
74
+
75
+ require 'aptible/auth/adapter'
76
+ require 'aptible/auth/resource'
@@ -0,0 +1,23 @@
1
+ module Aptible
2
+ class Auth::Adapter < HyperResource::Adapter::HAL_JSON
3
+ class << self
4
+ # rubocop:disable MethodLength
5
+ def get_data_type_from_object(object)
6
+ return nil unless object
7
+
8
+ if (type = object['type'])
9
+ if type == 'org'
10
+ 'Organization'
11
+ elsif type.respond_to?(:camelize)
12
+ type.camelize
13
+ else
14
+ type[0].upcase + type[1..-1]
15
+ end
16
+ else
17
+ 'Resource'
18
+ end
19
+ end
20
+ # rubocop:enable MethodLength
21
+ end
22
+ end
23
+ end
@@ -1,38 +1,4 @@
1
- require 'hyperresource'
2
- require 'fridge'
3
-
4
1
  module Aptible
5
- module Auth
6
- class Client < HyperResource
7
- attr_accessor :token, :config
8
-
9
- def initialize(options = {})
10
- unless options.is_a?(Hash)
11
- fail ArgumentError, 'Call Aptible::Auth::Client.new with a Hash'
12
- end
13
- self.token = options[:token]
14
-
15
- options[:root] ||= config.root_url
16
- options[:headers] ||= { 'Content-Type' => 'application/json' }
17
- options[:headers].merge!(
18
- 'Authorization' => "Bearer #{bearer_token}"
19
- ) if options[:token]
20
-
21
- super(options)
22
- end
23
-
24
- def bearer_token
25
- # REVIEW: Should we really allow any token type here?
26
- case token
27
- when Aptible::Auth::Token then token.access_token
28
- when Fridge::AccessToken then token.to_s
29
- when String then token
30
- end
31
- end
32
-
33
- def config
34
- @config ||= Aptible::Auth.configuration
35
- end
36
- end
2
+ class Auth::Client < Auth::Resource
37
3
  end
38
4
  end
@@ -0,0 +1,4 @@
1
+ module Aptible
2
+ class Auth::Membership < Auth::Resource
3
+ end
4
+ end
@@ -0,0 +1,15 @@
1
+ module Aptible
2
+ class Auth::Resource < Auth
3
+ def self.find_by_url(url)
4
+ # REVIEW: Should exception be raised if return type mismatch?
5
+ new.find_by_url(url)
6
+ end
7
+ end
8
+ end
9
+
10
+ require 'aptible/auth/client'
11
+ require 'aptible/auth/membership'
12
+ require 'aptible/auth/role'
13
+ require 'aptible/auth/session'
14
+ require 'aptible/auth/token'
15
+ require 'aptible/auth/user'
@@ -0,0 +1,4 @@
1
+ module Aptible
2
+ class Auth::Role < Auth::Resource
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Aptible
2
+ class Auth::Session < Auth::Resource
3
+ end
4
+ end
@@ -1,79 +1,78 @@
1
1
  require 'oauth2'
2
2
 
3
3
  module Aptible
4
- module Auth
5
- class Token
6
- attr_accessor :client, :access_token, :refresh_token, :expires_at
4
+ class Auth::Token < Auth::Resource
5
+ attr_accessor :access_token, :refresh_token, :expires_at
7
6
 
8
- def initialize(options = {})
9
- oauth_params = {
10
- site: Aptible::Auth.configuration.root_url,
11
- token_url: '/tokens'
12
- }
13
- @client = OAuth2::Client.new(nil, nil, oauth_params)
14
-
15
- process_options(options)
16
- end
7
+ def self.create(options)
8
+ token = new
9
+ token.process_options(options)
10
+ token
11
+ end
17
12
 
18
- def authenticate_user(email, password, options = {})
19
- options[:scope] ||= 'manage'
20
- response = client.password.get_token(email, password, options)
21
- parse_oauth_response(response)
22
- end
13
+ def authenticate_user(email, password, options = {})
14
+ options[:scope] ||= 'manage'
15
+ response = oauth.password.get_token(email, password, options)
16
+ parse_oauth_response(response)
17
+ end
23
18
 
24
- def authenticate_client(id, secret, user, options = {})
25
- options[:scope] ||= 'manage'
26
- response = client.assertion.get_token({
27
- iss: id,
28
- sub: user
29
- }.merge(signing_params_from_secret(secret).merge(options)))
30
- parse_oauth_response(response)
31
- end
19
+ def authenticate_client(id, secret, subject, options = {})
20
+ options[:scope] ||= 'manage'
21
+ response = oauth.assertion.get_token({
22
+ iss: id,
23
+ sub: subject
24
+ }.merge(signing_params_from_secret(secret).merge(options)))
25
+ parse_oauth_response(response)
26
+ end
32
27
 
33
- private
28
+ def oauth
29
+ options = { site: config.root_url, token_url: '/tokens' }
30
+ @oauth ||= OAuth2::Client.new(nil, nil, options)
31
+ end
34
32
 
35
- def process_options(options)
36
- if (email = options.delete(:email)) &&
37
- (password = options.delete(:password))
38
- authenticate_user(email, password, options)
39
- elsif (client_id = options.delete(:client_id)) &&
40
- (client_secret = options.delete(:client_secret)) &&
41
- (user = options.delete(:user))
42
- authenticate_client(client_id, client_secret, user, options)
43
- end
33
+ def process_options(options)
34
+ if (email = options.delete(:email)) &&
35
+ (password = options.delete(:password))
36
+ authenticate_user(email, password, options)
37
+ elsif (client_id = options.delete(:client_id)) &&
38
+ (client_secret = options.delete(:client_secret)) &&
39
+ (subject = options.delete(:subject))
40
+ authenticate_client(client_id, client_secret, subject, options)
44
41
  end
42
+ end
45
43
 
46
- def parse_oauth_response(response)
47
- @access_token = response.token
48
- @refresh_token = response.refresh_token
49
- @expires_at = Time.at(response.expires_at)
50
- end
44
+ private
51
45
 
52
- def signing_params_from_secret(secret)
53
- private_key = parse_private_key(secret)
54
- {
55
- private_key: private_key,
56
- algorithm: "RS#{key_length(private_key) / 2}"
57
- }
58
- end
46
+ def parse_oauth_response(response)
47
+ @access_token = response.token
48
+ @refresh_token = response.refresh_token
49
+ @expires_at = Time.at(response.expires_at)
50
+ end
59
51
 
60
- def parse_private_key(string)
61
- if string =~ /\A-----/
62
- OpenSSL::PKey::RSA.new(string)
63
- else
64
- formatted_string = <<PRIVATE_KEY
65
- -----BEGIN RSA PRIVATE KEY-----
66
- #{string.scan(/.{1,64}/).join("\n")}
67
- -----END RSA PRIVATE KEY-----
68
- PRIVATE_KEY
69
- OpenSSL::PKey::RSA.new(formatted_string)
70
- end
71
- end
52
+ def signing_params_from_secret(secret)
53
+ private_key = parse_private_key(secret)
54
+ {
55
+ private_key: private_key,
56
+ algorithm: "RS#{key_length(private_key) / 2}"
57
+ }
58
+ end
72
59
 
73
- def key_length(private_key)
74
- # http://stackoverflow.com/questions/13747212
75
- private_key.n.num_bytes * 8
60
+ def parse_private_key(string)
61
+ if string =~ /\A-----/
62
+ OpenSSL::PKey::RSA.new(string)
63
+ else
64
+ formatted_string = <<-PRIVATE_KEY.gsub(/^\s+/, '')
65
+ -----BEGIN RSA PRIVATE KEY-----
66
+ #{string.scan(/.{1,64}/).join("\n")}
67
+ -----END RSA PRIVATE KEY-----
68
+ PRIVATE_KEY
69
+ OpenSSL::PKey::RSA.new(formatted_string)
76
70
  end
77
71
  end
72
+
73
+ def key_length(private_key)
74
+ # http://stackoverflow.com/questions/13747212
75
+ private_key.n.num_bytes * 8
76
+ end
78
77
  end
79
78
  end
@@ -0,0 +1,7 @@
1
+ module Aptible
2
+ class Auth::User < Auth::Resource
3
+ def verified?
4
+ !!attributes['verified']
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ # describe Aptible::Auth::Resource do
4
+ # end
@@ -1,32 +1,35 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Aptible::Auth::Token do
4
- let(:client) { double OAuth2::Client }
4
+ let(:oauth) { double OAuth2::Client }
5
5
  let(:response) { double OAuth2::AccessToken }
6
6
 
7
+ before { subject.stub(:oauth) { oauth } }
7
8
  before { response.stub(:token) }
8
9
  before { response.stub(:refresh_token) }
9
10
  before { response.stub(:expires_at) { Time.now.to_i } }
10
11
 
11
- describe '#initialize' do
12
+ describe '.create' do
12
13
  it 'should call #authenticate_user if passed :email and :password' do
13
14
  Aptible::Auth::Token.any_instance.should_receive(
14
15
  :authenticate_user
15
16
  ).with 'user@example.com', 'foobar', {}
16
- described_class.new(email: 'user@example.com', password: 'foobar')
17
+ described_class.create(email: 'user@example.com', password: 'foobar')
17
18
  end
18
19
 
19
20
  it 'should #authenticate_client if passed a client ID and secret' do
20
21
  Aptible::Auth::Token.any_instance.should_receive(
21
22
  :authenticate_client
22
23
  ).with 'id', 'secret', 'user@example.com', {}
23
- described_class.new(
24
+ described_class.create(
24
25
  client_id: 'id',
25
26
  client_secret: 'secret',
26
- user: 'user@example.com'
27
+ subject: 'user@example.com'
27
28
  )
28
29
  end
30
+ end
29
31
 
32
+ describe '#initialize' do
30
33
  it 'should not raise error if given no arguments' do
31
34
  expect { described_class.new }.not_to raise_error
32
35
  end
@@ -35,23 +38,22 @@ describe Aptible::Auth::Token do
35
38
  describe '#authenticate_user' do
36
39
  let(:args) { %w(user@example.com foobar) }
37
40
 
38
- before { subject.stub(:client) { client } }
39
- before { client.stub_chain(:password, :get_token) { response } }
41
+ before { oauth.stub_chain(:password, :get_token) { response } }
40
42
 
41
43
  it 'should use the password strategy' do
42
44
  params = { scope: 'manage' }
43
- expect(client.password).to receive(:get_token).with(*(args + [params]))
45
+ expect(oauth.password).to receive(:get_token).with(*(args + [params]))
44
46
  subject.authenticate_user(*args)
45
47
  end
46
48
 
47
49
  it 'should allow the token scope to be specified' do
48
50
  args << { scope: 'read' }
49
- expect(client.password).to receive(:get_token).with(*args)
51
+ expect(oauth.password).to receive(:get_token).with(*args)
50
52
  subject.authenticate_user(*args)
51
53
  end
52
54
 
53
55
  it 'should set the access_token' do
54
- client.stub_chain(:password, :get_token, :token) { 'access_token' }
56
+ oauth.stub_chain(:password, :get_token, :token) { 'access_token' }
55
57
  subject.authenticate_user(*args)
56
58
  expect(subject.access_token).to eq 'access_token'
57
59
  end
@@ -63,11 +65,10 @@ describe Aptible::Auth::Token do
63
65
  before do
64
66
  subject.stub(:signing_params_from_secret) { { algorithm: 'foobar' } }
65
67
  end
66
- before { subject.stub(:client) { client } }
67
- before { client.stub_chain(:assertion, :get_token) { response } }
68
+ before { oauth.stub_chain(:assertion, :get_token) { response } }
68
69
 
69
70
  it 'should use the assertion strategy' do
70
- expect(client.assertion).to receive(:get_token).with(
71
+ expect(oauth.assertion).to receive(:get_token).with(
71
72
  iss: 'id',
72
73
  sub: 'user@example.com',
73
74
  algorithm: 'foobar',
@@ -78,7 +79,7 @@ describe Aptible::Auth::Token do
78
79
 
79
80
  it 'should allow the token scope to be specified' do
80
81
  args << { scope: 'read' }
81
- expect(client.assertion).to receive(:get_token).with(
82
+ expect(oauth.assertion).to receive(:get_token).with(
82
83
  iss: 'id',
83
84
  sub: 'user@example.com',
84
85
  algorithm: 'foobar',
@@ -88,7 +89,7 @@ describe Aptible::Auth::Token do
88
89
  end
89
90
 
90
91
  it 'should set the access_token' do
91
- client.stub_chain(:assertion, :get_token, :token) { 'access_token' }
92
+ oauth.stub_chain(:assertion, :get_token, :token) { 'access_token' }
92
93
  subject.authenticate_client(*args)
93
94
  expect(subject.access_token).to eq 'access_token'
94
95
  end
@@ -17,8 +17,35 @@ describe Aptible::Auth do
17
17
 
18
18
  it 'should expose the server public key' do
19
19
  get = double 'get'
20
- Aptible::Auth::Client.any_instance.stub(:get) { get }
20
+ Aptible::Auth.any_instance.stub(:get) { get }
21
21
  expect(get).to receive :public_key
22
22
  described_class.public_key
23
23
  end
24
+
25
+ describe '#initialize' do
26
+ it 'should be a HyperResource instance' do
27
+ expect(subject).to be_a HyperResource
28
+ end
29
+ end
30
+
31
+ describe '#bearer_token' do
32
+ it 'should accept an Aptible::Auth::Token' do
33
+ token = Aptible::Auth::Token.new
34
+ token.stub(:access_token) { 'abtible_auth_token' }
35
+ subject.stub(:token) { token }
36
+ expect(subject.bearer_token).to eq token.access_token
37
+ end
38
+
39
+ it 'should accept an Fridge::AccessToken' do
40
+ token = Fridge::AccessToken.new
41
+ token.stub(:to_s) { 'fridge_access_token' }
42
+ subject.stub(:token) { token }
43
+ expect(subject.bearer_token).to eq token.to_s
44
+ end
45
+
46
+ it 'should accept a String' do
47
+ subject.stub(:token) { 'token' }
48
+ expect(subject.bearer_token).to eq 'token'
49
+ end
50
+ end
24
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aptible-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-19 00:00:00.000000000 Z
11
+ date: 2014-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gem_config
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activesupport
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -148,14 +162,20 @@ files:
148
162
  - .travis.yml
149
163
  - Gemfile
150
164
  - LICENSE.md
165
+ - Procfile
151
166
  - README.md
152
167
  - Rakefile
153
168
  - aptible-auth.gemspec
154
169
  - lib/aptible/auth.rb
170
+ - lib/aptible/auth/adapter.rb
155
171
  - lib/aptible/auth/client.rb
172
+ - lib/aptible/auth/membership.rb
173
+ - lib/aptible/auth/resource.rb
174
+ - lib/aptible/auth/role.rb
175
+ - lib/aptible/auth/session.rb
156
176
  - lib/aptible/auth/token.rb
157
- - lib/aptible/auth/version.rb
158
- - spec/aptible/auth/client_spec.rb
177
+ - lib/aptible/auth/user.rb
178
+ - spec/aptible/auth/resource_spec.rb
159
179
  - spec/aptible/auth/token_spec.rb
160
180
  - spec/aptible/auth_spec.rb
161
181
  - spec/shared/set_env.rb
@@ -185,7 +205,7 @@ signing_key:
185
205
  specification_version: 4
186
206
  summary: Ruby client for auth.aptible.com
187
207
  test_files:
188
- - spec/aptible/auth/client_spec.rb
208
+ - spec/aptible/auth/resource_spec.rb
189
209
  - spec/aptible/auth/token_spec.rb
190
210
  - spec/aptible/auth_spec.rb
191
211
  - spec/shared/set_env.rb
@@ -1,5 +0,0 @@
1
- module Aptible
2
- module Auth
3
- VERSION = '0.1.4'
4
- end
5
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Aptible::Auth::Client do
4
- describe '#initialize' do
5
- it 'should be a HyperResource instance' do
6
- expect(subject).to be_a HyperResource
7
- end
8
- end
9
-
10
- describe '#bearer_token' do
11
- it 'should accept an Aptible::Auth::Token' do
12
- token = Aptible::Auth::Token.new
13
- token.stub(:access_token) { 'abtible_auth_token' }
14
- subject.stub(:token) { token }
15
- expect(subject.bearer_token).to eq token.access_token
16
- end
17
-
18
- it 'should accept an Fridge::AccessToken' do
19
- token = Fridge::AccessToken.new
20
- token.stub(:to_s) { 'fridge_access_token' }
21
- subject.stub(:token) { token }
22
- expect(subject.bearer_token).to eq token.to_s
23
- end
24
-
25
- it 'should accept a String' do
26
- subject.stub(:token) { 'token' }
27
- expect(subject.bearer_token).to eq 'token'
28
- end
29
- end
30
- end