maitre_d 0.6.1 → 0.7.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
  SHA256:
3
- metadata.gz: 9eb99cbebe7410953efb631a11a6622f14f0fc7aff295916021c6737f8f263b8
4
- data.tar.gz: 208609d75dbaf42bf79313cba27b3e1755f0823e60629ee7a1f68334c631907e
3
+ metadata.gz: 764dc0a04e766ea678f0bde9321fd3328dd98a138094a129f36845c409dfad27
4
+ data.tar.gz: ae4e4c87d345644f054f6b8ff2c56ede552d77ebe98012612f665a72dc31e520
5
5
  SHA512:
6
- metadata.gz: 1fd86a0cfc61d67b37d20d7be85eed36e58d0067df94aad8fcc7be8f13eada94077049f96044810122dd35a1a62089b1826c73a2fb15ce2a0e5181ae8f5de6ac
7
- data.tar.gz: '09008f6dc9be814685295da03c416e39bcef6b4527947211deb58809bdfa2bceaef3aee1a78f8eca47be61960e55b695c52ca5f1a17eb43d766cf439abdf2c0a'
6
+ metadata.gz: c3a147e73fae54e2c366fd269aa1be216295e80dd909285b31e997501d592b2040591a8fc4e9204f4c034b7da36dc47cdcca89df2a07f0b089a0cb5e9102195a
7
+ data.tar.gz: 42b838f44359b580ef759979c7bf3fd67acfb477ffb6bc972b7ffe9585767ad09b1077619a01507bd358592020af2a01b5c17a784be9e3e3b29f37cb1e5c54e9
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.4
4
- - 2.4.1
3
+ - 2.6.6
4
+ - 2.7.2
5
5
  script: bundle exec rspec spec
@@ -1,8 +1,8 @@
1
1
  h1. Maître d'
2
2
 
3
- "!https://secure.travis-ci.org/flying-sphinx/maitre_d.png!":http://travis-ci.org/flying-sphinx/maitre_d
3
+ "!https://secure.travis-ci.org/flying-sphinx/maitre_d.svg!":http://travis-ci.org/flying-sphinx/maitre_d
4
4
 
5
- Rack APIs powered by Sliver for managing Heroku and CloudControl add-ons.
5
+ Rack APIs powered by Sliver for managing Heroku add-ons.
6
6
 
7
7
  Maître d' manages all the authorisation checking for API requests and provides simple hooks for you to write just the code you need to handle provisioning, plan changes, deprovisioning and single-sign-on (SSO) requests.
8
8
 
@@ -10,20 +10,17 @@ h2. Installing
10
10
 
11
11
  Add the following to your Gemfile:
12
12
 
13
- <pre><code>gem 'maitre_d', '~> 0.6.0'</code></pre>
13
+ <pre><code>gem 'maitre_d', '~> 0.7.0'</code></pre>
14
14
 
15
15
  h3. With Rails
16
16
 
17
- Add the appropriate Rack apps to your routes file:
17
+ Add the Rack app to your routes file:
18
18
 
19
- <pre><code># if you're supporting Heroku
20
- mount MaitreD::API.new(MaitreD::Heroku) => '/heroku'
21
- # if you're supporting CloudControl
22
- mount MaitreD::API.new(MaitreD::CloudControl) => '/cloudcontrol'</code></pre>
19
+ <pre><code>mount MaitreD::API.new(MaitreD::Heroku) => '/heroku'</code></pre>
23
20
 
24
21
  h3. Without Rails
25
22
 
26
- As shown above, you can use Maître d' Rack API for both Heroku and Cloud Control. Mount them to wherever you see fit. Once upon a time Heroku expected its endpoints to be at /heroku, but now things are a little more flexible.
23
+ As shown above, you can use Maître d' Rack API, mounting them to wherever you see fit. Once upon a time Heroku expected its endpoints to be at /heroku, but now things are a little more flexible.
27
24
 
28
25
  h2. Configuration
29
26
 
@@ -36,24 +33,15 @@ MaitreD::Heroku.configure do |config|
36
33
  config.password = 'random'
37
34
  config.sso_salt = 'gibberish'
38
35
  config.listener = HerokuListener
39
- end
40
-
41
- require 'maitre_d/cloud_control'
42
-
43
- MaitreD::CloudControl.configure do |config|
44
- config.id = 'addon-id'
45
- config.password = 'random'
46
- config.sso_salt = 'gibberish'
47
- config.listener = CloudControlListener
48
36
  end</code></pre>
49
37
 
50
- The listeners that are mentioned in the code above are classes, which will handle valid API requests. Read on for more details on how to set them up.
38
+ The listener that is mentioned in the code above is a class, which will handle valid API requests. Read on for more details on how to set them up.
51
39
 
52
40
  h2. Listeners
53
41
 
54
- Your listener classes should handle the following four methods:
42
+ Your listener class should handle the following four methods:
55
43
 
56
- h3. @provision(heroku_id, plan, region, callback_url, logplex_token, options)@
44
+ h3. @provision(params)@
57
45
 
58
46
  This gets called when the provider is requesting an app be provisioned within your service, and expects a hash to be returned with the following keys:
59
47
 
@@ -66,7 +54,7 @@ This gets called when the provider is requesting an app be provisioned within yo
66
54
  <dd>An optional message that will be displayed when your add-on is added via the command-line.</dd>
67
55
  </dl>
68
56
 
69
- h3. @plan_change(resource_id, heroku_id, plan)@
57
+ h3. @plan_change(resource_id, plan)@
70
58
 
71
59
  This gets called when an app is upgrading or downgrading from their current plan. You need to return a hash with the following keys:
72
60
 
@@ -95,13 +83,13 @@ Maître d' will check the token and timestamp provided, and sets up the nav-data
95
83
  Here's a very basic example:
96
84
 
97
85
  <pre><code>class HerokuListener
98
- def provision(heroku_id, plan, region, callback_url, logplex_token, options)
99
- plan = Plan.find_by_name plan
86
+ def provision(params)
87
+ plan = Plan.find_by_name params["plan"]
100
88
  widget = Widget.create(
101
- :heroku_id => heroku_id,
102
- :callback_url => callback_url,
89
+ :heroku_id => params["uuid"],
90
+ :callback_url => params["callback_url"],
103
91
  :plan => plan,
104
- :region => region
92
+ :region => params["region"]
105
93
  )
106
94
 
107
95
  {
@@ -111,9 +99,9 @@ Here's a very basic example:
111
99
  }
112
100
  end
113
101
 
114
- def plan_change(resource_id, heroku_id, plan)
102
+ def plan_change(resource_id, plan)
115
103
  plan = Plan.find_by_name plan
116
- widget = Widget.find resource_id
104
+ widget = Widget.find_by! heroku_id: resource_id
117
105
  widget.plan = plan
118
106
  widget.save
119
107
 
@@ -121,12 +109,12 @@ Here's a very basic example:
121
109
  end
122
110
 
123
111
  def deprovision(resource_id)
124
- widget = Widget.find resource_id
112
+ widget = Widget.find_by! heroku_id: resource_id
125
113
  widget.destroy
126
114
  end
127
115
 
128
116
  def single_sign_on(resource_id)
129
- widget = Widget.find resource_id
117
+ widget = Widget.find_by! heroku_id: resource_id
130
118
 
131
119
  {
132
120
  :uri => '/my/dashboard',
@@ -147,4 +135,4 @@ Contributions are very much welcome - but keep in mind the following:
147
135
 
148
136
  h2. Credits
149
137
 
150
- Copyright (c) 2011-2015, Maître d' is developed and maintained by Pat Allan, and is released under the open MIT Licence.
138
+ Copyright (c) 2011-2020, Maître d' is developed and maintained by Pat Allan, and is released under the open MIT Licence.
@@ -1,7 +1,7 @@
1
1
  class MaitreD::API::ChangePlan < MaitreD::API::Authenticated
2
2
  def call
3
3
  response.body = listener.plan_change(
4
- resource_id, provider_id, params['plan']
4
+ resource_id, params['plan']
5
5
  )
6
6
 
7
7
  super
@@ -10,6 +10,6 @@ class MaitreD::API::ChangePlan < MaitreD::API::Authenticated
10
10
  private
11
11
 
12
12
  def resource_id
13
- request.path[%r{resources/(\d+)}, 1]
13
+ request.path[%r{resources/([\w-]+)}, 1]
14
14
  end
15
15
  end
@@ -1,9 +1,6 @@
1
1
  class MaitreD::API::Create < MaitreD::API::Authenticated
2
2
  def call
3
- response.body = listener.provision(
4
- provider_id, params['plan'], params['region'],
5
- params['callback_url'], params['logplex_token'], params['options']
6
- )
3
+ response.body = listener.provision(params)
7
4
 
8
5
  super
9
6
  end
@@ -8,6 +8,6 @@ class MaitreD::API::Delete < MaitreD::API::Authenticated
8
8
  private
9
9
 
10
10
  def resource_id
11
- request.path[%r{resources/(\d+)}, 1]
11
+ request.path[%r{resources/([\w-]+)}, 1]
12
12
  end
13
13
  end
@@ -6,7 +6,7 @@ class MaitreD::API::SSO
6
6
  end
7
7
 
8
8
  def call
9
- hash = listener.single_sign_on params['id']
9
+ hash = listener.single_sign_on params['resource_id']
10
10
 
11
11
  hash[:session] ||= {}
12
12
  hash[:session].each { |key, value| session[key] = value }
@@ -13,7 +13,7 @@ class MaitreD::API::SSOGuard < Sliver::Hook
13
13
 
14
14
  def expected_token
15
15
  @expected_token ||= Digest::SHA1.hexdigest(
16
- "#{params['id']}:#{action.configuration.sso_salt}:#{params['timestamp']}"
16
+ "#{params['resource_id']}:#{action.configuration.sso_salt}:#{params['timestamp']}"
17
17
  ).to_s
18
18
  end
19
19
 
@@ -26,6 +26,6 @@ class MaitreD::API::SSOGuard < Sliver::Hook
26
26
  end
27
27
 
28
28
  def valid_token?
29
- expected_token == params['token']
29
+ expected_token == params['resource_token']
30
30
  end
31
31
  end
@@ -3,15 +3,13 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'maitre_d'
6
- s.version = '0.6.1'
6
+ s.version = '0.7.0'
7
7
  s.authors = ['Pat Allan']
8
8
  s.email = ['pat@freelancing-gods.com']
9
9
  s.homepage = 'http://github.com/flying-sphinx/maitre_d'
10
10
  s.summary = 'Rack APIs for Heroku add-ons'
11
11
  s.description = 'A Rack API (through Grape) for Heroku add-on providers.'
12
12
 
13
- s.rubyforge_project = "maitre_d"
14
-
15
13
  s.files = `git ls-files`.split("\n")
16
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -20,8 +18,8 @@ Gem::Specification.new do |s|
20
18
  s.add_runtime_dependency 'sliver', '~> 0.2.2'
21
19
  s.add_runtime_dependency 'multi_json', '>= 1.3.0'
22
20
 
23
- s.add_development_dependency 'combustion', '~> 0.5'
21
+ s.add_development_dependency 'combustion', '~> 1.3'
24
22
  s.add_development_dependency 'kensa', '2.1.0'
25
- s.add_development_dependency 'rails', '~> 4.2'
26
- s.add_development_dependency 'rspec-rails', '~> 3.6'
23
+ s.add_development_dependency 'rails', '~> 6.0'
24
+ s.add_development_dependency 'rspec-rails', '~> 4.0'
27
25
  end
@@ -17,36 +17,41 @@ describe 'Heroku Provisioning API', :type => :request do
17
17
  }
18
18
 
19
19
  it "returns a 401 if the HTTP authorisation does not match" do
20
- post '/heroku/resources', JSON.dump(params),
21
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
20
+ post '/heroku/resources',
21
+ :params => JSON.dump(params),
22
+ :headers => {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
22
23
 
23
24
  expect(response.status).to eq(401)
24
25
  end
25
26
 
26
27
  it "returns the resource id" do
27
- post '/heroku/resources', JSON.dump(params),
28
- {'HTTP_AUTHORIZATION' => authorisation}
28
+ post '/heroku/resources',
29
+ :params => JSON.dump(params),
30
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
29
31
 
30
32
  expect(json_response['id']).to eq('123')
31
33
  end
32
34
 
33
35
  it "returns the resource configuration" do
34
- post '/heroku/resources', JSON.dump(params),
35
- {'HTTP_AUTHORIZATION' => authorisation}
36
+ post '/heroku/resources',
37
+ :params => JSON.dump(params),
38
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
36
39
 
37
40
  expect(json_response['config']).to eq({'FOO_PROVISIONED' => "true"})
38
41
  end
39
42
 
40
43
  it "returns a custom message" do
41
- post '/heroku/resources', JSON.dump(params),
42
- {'HTTP_AUTHORIZATION' => authorisation}
44
+ post '/heroku/resources',
45
+ :params => JSON.dump(params),
46
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
43
47
 
44
48
  expect(json_response['message']).to eq('Add-on provisioned!')
45
49
  end
46
50
 
47
51
  it "returns the region if it exists" do
48
- post '/heroku/resources', JSON.dump(params.merge(:region => 'us-west')),
49
- {'HTTP_AUTHORIZATION' => authorisation}
52
+ post '/heroku/resources',
53
+ :params => JSON.dump(params.merge(:region => 'us-west')),
54
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
50
55
 
51
56
  expect(json_response['region']).to eq('us-west')
52
57
  end
@@ -58,22 +63,25 @@ describe 'Heroku Provisioning API', :type => :request do
58
63
  }
59
64
 
60
65
  it "returns a 401 if the HTTP authorisation does not match" do
61
- put '/heroku/resources/7', JSON.dump(params),
62
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
66
+ put '/heroku/resources/7',
67
+ :params => JSON.dump(params),
68
+ :headers => {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
63
69
 
64
70
  expect(response.status).to eq(401)
65
71
  end
66
72
 
67
73
  it "returns the new resource configuration" do
68
- put '/heroku/resources/7', JSON.dump(params),
69
- {'HTTP_AUTHORIZATION' => authorisation}
74
+ put '/heroku/resources/7',
75
+ :params => JSON.dump(params),
76
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
70
77
 
71
78
  expect(json_response['config']).to eq({'FOO_PROVISIONED' => "false"})
72
79
  end
73
80
 
74
81
  it "returns a custom message" do
75
- put '/heroku/resources/7', JSON.dump(params),
76
- {'HTTP_AUTHORIZATION' => authorisation}
82
+ put '/heroku/resources/7',
83
+ :params => JSON.dump(params),
84
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
77
85
 
78
86
  expect(json_response['message']).to eq('Add-on upgraded or downgraded.')
79
87
  end
@@ -81,20 +89,22 @@ describe 'Heroku Provisioning API', :type => :request do
81
89
 
82
90
  describe 'Deprovisioning' do
83
91
  it "returns a 401 if the HTTP authorisation does not match" do
84
- delete '/heroku/resources/28', {},
85
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
92
+ delete '/heroku/resources/28',
93
+ :headers => {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
86
94
 
87
95
  expect(response.status).to eq(401)
88
96
  end
89
97
 
90
98
  it "returns with a status of 200" do
91
- delete '/heroku/resources/28', {}, {'HTTP_AUTHORIZATION' => authorisation}
99
+ delete '/heroku/resources/28',
100
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
92
101
 
93
102
  expect(response.status).to eq(200)
94
103
  end
95
104
 
96
105
  it "returns a custom message" do
97
- delete '/heroku/resources/28', {}, {'HTTP_AUTHORIZATION' => authorisation}
106
+ delete '/heroku/resources/28',
107
+ :headers => {'HTTP_AUTHORIZATION' => authorisation}
98
108
 
99
109
  expect(json_response['message']).to eq('Add-on removed.')
100
110
  end
@@ -9,8 +9,10 @@ describe 'Heroku SSO API', :type => :request do
9
9
  }
10
10
 
11
11
  it "renders a 403 if the token is incorrect" do
12
- post '/heroku/resources/sso', :id => '789', :token => 'foo',
13
- :timestamp => timestamp, 'nav-data' => nav_data
12
+ post '/heroku/resources/sso', :params => {
13
+ :resource_id => '789', :resource_token => 'foo', :timestamp => timestamp,
14
+ 'nav-data' => nav_data
15
+ }
14
16
 
15
17
  expect(response.status).to eq(403)
16
18
  end
@@ -20,29 +22,37 @@ describe 'Heroku SSO API', :type => :request do
20
22
  pre_token = "789:#{MaitreD::Heroku.sso_salt}:#{timestamp.to_s}"
21
23
  token = Digest::SHA1.hexdigest(pre_token).to_s
22
24
 
23
- post '/heroku/resources/sso', :id => '789', :token => token,
24
- :timestamp => timestamp, 'nav-data' => nav_data
25
+ post '/heroku/resources/sso', :params => {
26
+ :resource_id => '789', :resource_token => token, :timestamp => timestamp,
27
+ 'nav-data' => nav_data
28
+ }
25
29
 
26
30
  expect(response.status).to eq(403)
27
31
  end
28
32
 
29
33
  it "sets the heroku nav data cookie" do
30
- post '/heroku/resources/sso', :id => '789', :token => token,
31
- :timestamp => timestamp, 'nav-data' => nav_data
34
+ post '/heroku/resources/sso', :params => {
35
+ :resource_id => '789', :resource_token => token, :timestamp => timestamp,
36
+ 'nav-data' => nav_data
37
+ }
32
38
 
33
39
  expect(cookies['heroku-nav-data']).to eq(nav_data)
34
40
  end
35
41
 
36
42
  it "redirects to the appropriate URL" do
37
- post '/heroku/resources/sso', :id => '789', :token => token,
38
- :timestamp => timestamp, 'nav-data' => nav_data
43
+ post '/heroku/resources/sso', :params => {
44
+ :resource_id => '789', :resource_token => token, :timestamp => timestamp,
45
+ 'nav-data' => nav_data
46
+ }
39
47
 
40
48
  expect(response).to redirect_to('/my/dashboard')
41
49
  end
42
50
 
43
51
  it "should set the provided session variables" do
44
- post '/heroku/resources/sso', :id => '789', :token => token,
45
- :timestamp => timestamp, 'nav-data' => nav_data
52
+ post '/heroku/resources/sso', :params => {
53
+ :resource_id => '789', :resource_token => token, :timestamp => timestamp,
54
+ 'nav-data' => nav_data
55
+ }
46
56
 
47
57
  expect(session[:app_id]).to eq('789')
48
58
  end
@@ -1,14 +1,14 @@
1
1
  class HerokuListener
2
- def provision(heroku_id, plan, region, callback_url, logplex_token, options)
2
+ def provision(params)
3
3
  {
4
4
  :id => '123',
5
5
  :config => {'FOO_PROVISIONED' => 'true'},
6
6
  :message => 'Add-on provisioned!',
7
- :region => region
7
+ :region => params["region"]
8
8
  }
9
9
  end
10
10
 
11
- def plan_change(resource_id, heroku_id, plan)
11
+ def plan_change(resource_id, plan)
12
12
  {
13
13
  :config => {'FOO_PROVISIONED' => 'false'},
14
14
  :message => 'Add-on upgraded or downgraded.'
@@ -1,6 +1,5 @@
1
1
  Rails.application.routes.draw do
2
- mount MaitreD::API.new(MaitreD::Heroku) => '/heroku'
3
- mount MaitreD::API.new(MaitreD::CloudControl) => '/cloudcontrol'
2
+ mount MaitreD::API.new(MaitreD::Heroku) => '/heroku'
4
3
 
5
4
  class Dashboard
6
5
  def self.call(env)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maitre_d
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-22 00:00:00.000000000 Z
11
+ date: 2020-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sliver
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.5'
47
+ version: '1.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.5'
54
+ version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: kensa
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -72,28 +72,28 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.2'
75
+ version: '6.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.2'
82
+ version: '6.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.6'
89
+ version: '4.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.6'
96
+ version: '4.0'
97
97
  description: A Rack API (through Grape) for Heroku add-on providers.
98
98
  email:
99
99
  - pat@freelancing-gods.com
@@ -119,16 +119,11 @@ files:
119
119
  - lib/maitre_d/api/delete.rb
120
120
  - lib/maitre_d/api/sso.rb
121
121
  - lib/maitre_d/api/sso_guard.rb
122
- - lib/maitre_d/cloud_control.rb
123
122
  - lib/maitre_d/heroku.rb
124
123
  - maitre_d.gemspec
125
- - spec/api/cloud_control/provisioning_spec.rb
126
- - spec/api/cloud_control/single_sign_on_spec.rb
127
124
  - spec/api/heroku/provisioning_spec.rb
128
125
  - spec/api/heroku/single_sign_on_spec.rb
129
- - spec/internal/app/listeners/cloud_control_listener.rb
130
126
  - spec/internal/app/listeners/heroku_listener.rb
131
- - spec/internal/config/initializers/cloud_control.rb
132
127
  - spec/internal/config/initializers/heroku.rb
133
128
  - spec/internal/config/routes.rb
134
129
  - spec/internal/log/.gitignore
@@ -152,19 +147,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
147
  - !ruby/object:Gem::Version
153
148
  version: '0'
154
149
  requirements: []
155
- rubyforge_project: maitre_d
156
- rubygems_version: 2.7.6
150
+ rubygems_version: 3.1.2
157
151
  signing_key:
158
152
  specification_version: 4
159
153
  summary: Rack APIs for Heroku add-ons
160
154
  test_files:
161
- - spec/api/cloud_control/provisioning_spec.rb
162
- - spec/api/cloud_control/single_sign_on_spec.rb
163
155
  - spec/api/heroku/provisioning_spec.rb
164
156
  - spec/api/heroku/single_sign_on_spec.rb
165
- - spec/internal/app/listeners/cloud_control_listener.rb
166
157
  - spec/internal/app/listeners/heroku_listener.rb
167
- - spec/internal/config/initializers/cloud_control.rb
168
158
  - spec/internal/config/initializers/heroku.rb
169
159
  - spec/internal/config/routes.rb
170
160
  - spec/internal/log/.gitignore
@@ -1,41 +0,0 @@
1
- module MaitreD::CloudControl
2
- def self.configure
3
- yield self
4
- end
5
-
6
- def self.listener
7
- @listener
8
- end
9
-
10
- def self.listener=(listener)
11
- @listener = listener
12
- end
13
-
14
- def self.id
15
- @id
16
- end
17
-
18
- def self.id=(id)
19
- @id = id
20
- end
21
-
22
- def self.password
23
- @password
24
- end
25
-
26
- def self.password=(password)
27
- @password = password
28
- end
29
-
30
- def self.sso_salt
31
- @sso_salt
32
- end
33
-
34
- def self.sso_salt=(salt)
35
- @sso_salt = salt
36
- end
37
-
38
- def self.provider_id_from(params)
39
- params['cloudcontrol_id']
40
- end
41
- end
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'CloudControl Provisioning API', :type => :request do
4
- let(:authorisation) { "Basic #{Base64.encode64('baz:qux')}" }
5
- let(:json_response) { JSON.parse response.body }
6
-
7
- describe 'Provisioning' do
8
- let(:params) {
9
- {
10
- :plan => 'basic',
11
- :callback_url => 'https://domain/vendor/apps/app123%40heroku.com',
12
- :cloudcontrol_id => 'app123@heroku.com'
13
- }
14
- }
15
-
16
- it "returns a 401 if the HTTP authorisation does not match" do
17
- post '/cloudcontrol/resources', JSON.dump(params),
18
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
19
-
20
- expect(response.status).to eq(401)
21
- end
22
-
23
- it "returns the resource id" do
24
- post '/cloudcontrol/resources', JSON.dump(params),
25
- {'HTTP_AUTHORIZATION' => authorisation}
26
-
27
- expect(json_response['id']).to eq('123')
28
- end
29
-
30
- it "returns the resource configuration" do
31
- post '/cloudcontrol/resources', JSON.dump(params),
32
- {'HTTP_AUTHORIZATION' => authorisation}
33
-
34
- expect(json_response['config']).to eq('FOO_PROVISIONED' => "true")
35
- end
36
-
37
- it "returns a custom message" do
38
- post '/cloudcontrol/resources', JSON.dump(params),
39
- {'HTTP_AUTHORIZATION' => authorisation}
40
-
41
- expect(json_response['message']).to eq('Add-on provisioned!')
42
- end
43
- end
44
-
45
- describe 'Changing Plans' do
46
- let(:params) {
47
- {:cloudcontrol_id => 'app123@heroku.com', :plan => 'premium'}
48
- }
49
-
50
- it "returns a 401 if the HTTP authorisation does not match" do
51
- put '/cloudcontrol/resources/7', JSON.dump(params),
52
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
53
-
54
- expect(response.status).to eq(401)
55
- end
56
-
57
- it "returns the new resource configuration" do
58
- put '/cloudcontrol/resources/7', JSON.dump(params),
59
- {'HTTP_AUTHORIZATION' => authorisation}
60
-
61
- expect(json_response['config']).to eq('FOO_PROVISIONED' => "false")
62
- end
63
-
64
- it "returns a custom message" do
65
- put '/cloudcontrol/resources/7', JSON.dump(params),
66
- {'HTTP_AUTHORIZATION' => authorisation}
67
-
68
- expect(json_response['message']).to eq('Add-on upgraded or downgraded.')
69
- end
70
- end
71
-
72
- describe 'Deprovisioning' do
73
- it "returns a 401 if the HTTP authorisation does not match" do
74
- delete '/cloudcontrol/resources/28', {},
75
- {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
76
-
77
- expect(response.status).to eq(401)
78
- end
79
-
80
- it "returns with a status of 200" do
81
- delete '/cloudcontrol/resources/28', {},
82
- {'HTTP_AUTHORIZATION' => authorisation}
83
-
84
- expect(response.status).to eq(200)
85
- end
86
-
87
- it "returns a custom message" do
88
- delete '/cloudcontrol/resources/28', {},
89
- {'HTTP_AUTHORIZATION' => authorisation}
90
-
91
- expect(json_response['message']).to eq('Add-on removed.')
92
- end
93
- end
94
- end
@@ -1,49 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'CloudControl SSO API', :type => :request do
4
- let(:timestamp) { Time.now.to_i }
5
- let(:nav_data) { 'heroku-nav-data-goes-here' }
6
- let(:token) {
7
- pre_token = "789:#{MaitreD::CloudControl.sso_salt}:#{timestamp.to_s}"
8
- Digest::SHA1.hexdigest(pre_token).to_s
9
- }
10
-
11
- it "renders a 403 if the token is incorrect" do
12
- post '/cloudcontrol/resources/sso', :id => '789', :token => 'foo',
13
- :timestamp => timestamp, 'nav-data' => nav_data
14
-
15
- expect(response.status).to eq(403)
16
- end
17
-
18
- it "renders a 403 if the timestamp is older than 5 minutes" do
19
- timestamp = 5.minutes.ago.to_i - 1
20
- pre_token = "789:#{MaitreD::CloudControl.sso_salt}:#{timestamp.to_s}"
21
- token = Digest::SHA1.hexdigest(pre_token).to_s
22
-
23
- post '/cloudcontrol/resources/sso', :id => '789', :token => token,
24
- :timestamp => timestamp, 'nav-data' => nav_data
25
-
26
- expect(response.status).to eq(403)
27
- end
28
-
29
- it "sets the heroku nav data cookie" do
30
- post '/cloudcontrol/resources/sso', :id => '789', :token => token,
31
- :timestamp => timestamp, 'nav-data' => nav_data
32
-
33
- expect(cookies['heroku-nav-data']).to eq(nav_data)
34
- end
35
-
36
- it "redirects to the appropriate URL" do
37
- post '/cloudcontrol/resources/sso', :id => '789', :token => token,
38
- :timestamp => timestamp, 'nav-data' => nav_data
39
-
40
- expect(response).to redirect_to('/my/dashboard')
41
- end
42
-
43
- it "should set the provided session variables" do
44
- post '/cloudcontrol/resources/sso', :id => '789', :token => token,
45
- :timestamp => timestamp, 'nav-data' => nav_data
46
-
47
- expect(session[:app_id]).to eq('789')
48
- end
49
- end
@@ -1,29 +0,0 @@
1
- class CloudControlListener
2
- def provision(cloud_control_id, plan, region, callback_url, logplex_token, options)
3
- {
4
- :id => '123',
5
- :config => {'FOO_PROVISIONED' => 'true'},
6
- :message => 'Add-on provisioned!'
7
- }
8
- end
9
-
10
- def plan_change(resource_id, cloud_control_id, plan)
11
- {
12
- :config => {'FOO_PROVISIONED' => 'false'},
13
- :message => 'Add-on upgraded or downgraded.'
14
- }
15
- end
16
-
17
- def deprovision(resource_id)
18
- {
19
- :message => 'Add-on removed.'
20
- }
21
- end
22
-
23
- def single_sign_on(resource_id)
24
- {
25
- :uri => '/my/dashboard',
26
- :session => {:app_id => resource_id}
27
- }
28
- end
29
- end
@@ -1,8 +0,0 @@
1
- require 'maitre_d/cloud_control'
2
-
3
- MaitreD::CloudControl.configure do |config|
4
- config.id = 'baz'
5
- config.password = 'qux'
6
- config.sso_salt = 'rock salt'
7
- config.listener = CloudControlListener
8
- end