maitre_d 0.2.0 → 0.3.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1e79119958343605dabd87304c21e2e9c770711b
4
+ data.tar.gz: 4ed73d17abf94091dfb18e566984637699e8569a
5
+ SHA512:
6
+ metadata.gz: 36feafdb16cd476413a95b34da6dfc675c43fa47772b04d6ec34117aeb71c42646556700920582689dda9fa845667451c93f8812408d340e14cd76eb5fe6cb3a
7
+ data.tar.gz: aa9b728329779092e8f1482e50db5dbfe45751cce6957135ec35f8d7f959b162cd55fbcd0e093db3534b7bf82249becbccdc3604981f217dc780b61b5d7c10bd
data/.travis.yml CHANGED
@@ -1,7 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
6
- - ree
7
4
  script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -1,9 +1,5 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'combustion',
4
- :git => 'git://github.com/pat/combustion',
5
- :ref => 'd7a6836269a8fb528bc3721e9b8c06b5a62ef3cc'
6
-
7
3
  gemspec
8
4
 
9
5
  # Until a new Grape release is out:
data/HISTORY CHANGED
@@ -1,3 +1,7 @@
1
+ 0.3.0 - July 27th 2013
2
+ * No longer supporting 1.8.7/ree/1.9.2. Use 1.9.3 or 2.0.0.
3
+ * Broadstack support.
4
+
1
5
  0.2.0 - December 12th 2012
2
6
  * Support region parameter from Heroku.
3
7
  * Adding tentative CloudControl support.
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  Rails.application.routes.draw do
2
+ mount MaitreD::Broadstack::API => '/broadstack'
2
3
  mount MaitreD::Heroku::API => '/heroku'
3
4
  mount MaitreD::CloudControl::API => '/cloudcontrol'
4
5
  mount MaitreD::Opperator::API => '/opperator'
data/lib/maitre_d.rb CHANGED
@@ -3,6 +3,7 @@ require 'grape'
3
3
  module MaitreD
4
4
  end
5
5
 
6
+ require 'maitre_d/broadstack'
6
7
  require 'maitre_d/heroku'
7
8
  require 'maitre_d/cloud_control'
8
9
  require 'maitre_d/opperator'
@@ -0,0 +1,40 @@
1
+ module MaitreD::Broadstack
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
+ end
38
+
39
+ require 'maitre_d/broadstack/api_helpers'
40
+ require 'maitre_d/broadstack/api'
@@ -0,0 +1,49 @@
1
+ class MaitreD::Broadstack::API < Grape::API
2
+ helpers MaitreD::Broadstack::APIHelpers
3
+
4
+ resources :sso do
5
+ post do
6
+ error!('403 Forbidden', 403) unless valid_token? && valid_timestamp?
7
+
8
+ hash = listener.single_sign_on(params[:id])
9
+
10
+ hash[:session] ||= {}
11
+ hash[:session].each { |key, value| session[key] = value }
12
+
13
+ if env['action_dispatch.cookies']
14
+ env['action_dispatch.cookies']['heroku-nav-data'] = params['nav-data']
15
+ else
16
+ Rack::Utils.set_cookie_header! header, 'heroku-nav-data',
17
+ :value => params['nav-data']
18
+ end
19
+
20
+ status 302
21
+ header 'Location', hash[:uri]
22
+ end
23
+ end
24
+
25
+ resources :resources do
26
+ post do
27
+ authenticate!
28
+
29
+ listener.provision(
30
+ provider_id, params[:plan], params[:region],
31
+ params[:callback_url], params[:logplex_token], params[:options]
32
+ )
33
+ end
34
+
35
+ put ':id' do
36
+ authenticate!
37
+
38
+ listener.plan_change(
39
+ params[:id], provider_id, params[:plan]
40
+ )
41
+ end
42
+
43
+ delete ':id' do
44
+ authenticate!
45
+
46
+ listener.deprovision params[:id]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,44 @@
1
+ module MaitreD::Broadstack::APIHelpers
2
+ def authenticate!
3
+ error!('401 Unauthorized', 401) unless valid_authorization?
4
+ end
5
+
6
+ def listener
7
+ MaitreD::Broadstack.listener.new
8
+ end
9
+
10
+ def provider_id
11
+ params[:broadstack_id]
12
+ end
13
+
14
+ def session
15
+ env['rack.session']
16
+ end
17
+
18
+ def valid_timestamp?
19
+ params[:timestamp].to_i >= (Time.now - 5*60).to_i
20
+ end
21
+
22
+ def valid_token?
23
+ expected_token == params[:token]
24
+ end
25
+
26
+ private
27
+
28
+ def expected_token
29
+ @expected_token ||= Digest::SHA1.hexdigest(
30
+ "#{params[:id]}:#{MaitreD::Broadstack.sso_salt}:#{params[:timestamp]}"
31
+ ).to_s
32
+ end
33
+
34
+ def valid_authorization?
35
+ valid_authorization.strip == env['HTTP_AUTHORIZATION'].strip
36
+ end
37
+
38
+ def valid_authorization
39
+ encoded_authorization = Base64.encode64(
40
+ "#{MaitreD::Broadstack.id}:#{MaitreD::Broadstack.password}"
41
+ )
42
+ "Basic #{encoded_authorization}"
43
+ end
44
+ end
data/maitre_d.gemspec CHANGED
@@ -3,7 +3,7 @@ $:.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.2.0'
6
+ s.version = '0.3.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'
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ['lib']
19
19
 
20
+ s.add_development_dependency 'combustion', '0.5.1'
20
21
  s.add_development_dependency 'kensa', '1.3.0'
21
22
  s.add_development_dependency 'rails', '3.1.3'
22
23
  s.add_development_dependency 'rspec-rails', '2.7.0'
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Broadstack Provisioning API' do
4
+ let(:authorisation) { "Basic #{Base64.encode64('foo:bar')}" }
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%40broadstack.com',
12
+ :broadstack_id => 'app123@broadstack.com'
13
+ }
14
+ }
15
+
16
+ it "returns a 401 if the HTTP authorisation does not match" do
17
+ post '/broadstack/resources', params,
18
+ {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
19
+
20
+ response.status.should == 401
21
+ end
22
+
23
+ it "returns the resource id" do
24
+ post '/broadstack/resources', params, {'HTTP_AUTHORIZATION' => authorisation}
25
+
26
+ json_response['id'].should == '123'
27
+ end
28
+
29
+ it "returns the resource configuration" do
30
+ post '/broadstack/resources', params, {'HTTP_AUTHORIZATION' => authorisation}
31
+
32
+ json_response['config'].should == {'FOO_PROVISIONED' => "true"}
33
+ end
34
+
35
+ it "returns a custom message" do
36
+ post '/broadstack/resources', params, {'HTTP_AUTHORIZATION' => authorisation}
37
+
38
+ json_response['message'].should == 'Add-on provisioned!'
39
+ end
40
+
41
+ it "returns the region if it exists" do
42
+ post '/broadstack/resources', params.merge(:region => 'us-west'),
43
+ {'HTTP_AUTHORIZATION' => authorisation}
44
+
45
+ json_response['region'].should == 'us-west'
46
+ end
47
+ end
48
+
49
+ describe 'Changing Plans' do
50
+ let(:params) {
51
+ {:broadstack_id => 'app123@broadstack.com', :plan => 'premium'}
52
+ }
53
+
54
+ it "returns a 401 if the HTTP authorisation does not match" do
55
+ put '/broadstack/resources/7', params,
56
+ {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
57
+
58
+ response.status.should == 401
59
+ end
60
+
61
+ it "returns the new resource configuration" do
62
+ put '/broadstack/resources/7', params, {'HTTP_AUTHORIZATION' => authorisation}
63
+
64
+ json_response['config'].should == {'FOO_PROVISIONED' => "false"}
65
+ end
66
+
67
+ it "returns a custom message" do
68
+ put '/broadstack/resources/7', params, {'HTTP_AUTHORIZATION' => authorisation}
69
+
70
+ json_response['message'].should == 'Add-on upgraded or downgraded.'
71
+ end
72
+ end
73
+
74
+ describe 'Deprovisioning' do
75
+ it "returns a 401 if the HTTP authorisation does not match" do
76
+ delete '/broadstack/resources/28', {},
77
+ {'HTTP_AUTHORIZATION' => 'Basic foobarbaz'}
78
+
79
+ response.status.should == 401
80
+ end
81
+
82
+ it "returns with a status of 200" do
83
+ delete '/broadstack/resources/28', {}, {'HTTP_AUTHORIZATION' => authorisation}
84
+
85
+ response.status.should == 200
86
+ end
87
+
88
+ it "returns a custom message" do
89
+ delete '/broadstack/resources/28', {}, {'HTTP_AUTHORIZATION' => authorisation}
90
+
91
+ json_response['message'].should == 'Add-on removed.'
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Broadstack SSO API' do
4
+ let(:timestamp) { Time.now.to_i }
5
+ let(:nav_data) { 'heroku-nav-data-goes-here' }
6
+ let(:token) {
7
+ pre_token = "789:sea 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 '/broadstack/sso', :token => 'foo', :id => '789',
13
+ :timestamp => timestamp, 'nav-data' => nav_data
14
+
15
+ response.status.should == 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:sea salt:#{timestamp.to_s}"
21
+ token = Digest::SHA1.hexdigest(pre_token).to_s
22
+
23
+ post '/broadstack/sso', :token => token, :id => '789',
24
+ :timestamp => timestamp, 'nav-data' => nav_data
25
+
26
+ response.status.should == 403
27
+ end
28
+
29
+ it "sets the heroku nav data cookie" do
30
+ post '/broadstack/sso', :token => token, :id => '789',
31
+ :timestamp => timestamp, 'nav-data' => nav_data
32
+
33
+ cookies['heroku-nav-data'].should == nav_data
34
+ end
35
+
36
+ it "redirects to the appropriate URL" do
37
+ post '/broadstack/sso', :token => token, :id => '789',
38
+ :timestamp => timestamp, 'nav-data' => nav_data
39
+
40
+ response.should redirect_to('/my/dashboard')
41
+ end
42
+
43
+ it "should set the provided session variables" do
44
+ post '/broadstack/sso', :token => token, :id => '789',
45
+ :timestamp => timestamp, 'nav-data' => nav_data
46
+
47
+ session[:app_id].should == '789'
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ class BroadstackListener
2
+ def provision(heroku_id, plan, region, callback_url, logplex_token, options)
3
+ {
4
+ :id => '123',
5
+ :config => {'FOO_PROVISIONED' => 'true'},
6
+ :message => 'Add-on provisioned!',
7
+ :region => region
8
+ }
9
+ end
10
+
11
+ def plan_change(resource_id, heroku_id, plan)
12
+ {
13
+ :config => {'FOO_PROVISIONED' => 'false'},
14
+ :message => 'Add-on upgraded or downgraded.'
15
+ }
16
+ end
17
+
18
+ def deprovision(resource_id)
19
+ {
20
+ :message => 'Add-on removed.'
21
+ }
22
+ end
23
+
24
+ def single_sign_on(resource_id)
25
+ {
26
+ :uri => '/my/dashboard',
27
+ :session => {:app_id => resource_id}
28
+ }
29
+ end
30
+ end
@@ -0,0 +1,6 @@
1
+ MaitreD::Broadstack.configure do |config|
2
+ config.id = 'foo'
3
+ config.password = 'bar'
4
+ config.sso_salt = 'sea salt'
5
+ config.listener = BroadstackListener
6
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
- require 'rubygems'
2
- require 'bundler'
1
+ require 'bundler/setup'
3
2
 
4
- Bundler.require :default, :development
3
+ require 'combustion'
4
+ require 'maitre_d'
5
5
 
6
6
  Combustion.initialize! :action_controller
7
7
 
metadata CHANGED
@@ -1,20 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maitre_d
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Pat Allan
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-12-12 00:00:00.000000000 Z
11
+ date: 2013-07-27 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: combustion
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.1
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.1
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: kensa
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
31
  - - '='
20
32
  - !ruby/object:Gem::Version
@@ -22,7 +34,6 @@ dependencies:
22
34
  type: :development
23
35
  prerelease: false
24
36
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
37
  requirements:
27
38
  - - '='
28
39
  - !ruby/object:Gem::Version
@@ -30,7 +41,6 @@ dependencies:
30
41
  - !ruby/object:Gem::Dependency
31
42
  name: rails
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
45
  - - '='
36
46
  - !ruby/object:Gem::Version
@@ -38,7 +48,6 @@ dependencies:
38
48
  type: :development
39
49
  prerelease: false
40
50
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
51
  requirements:
43
52
  - - '='
44
53
  - !ruby/object:Gem::Version
@@ -46,7 +55,6 @@ dependencies:
46
55
  - !ruby/object:Gem::Dependency
47
56
  name: rspec-rails
48
57
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
58
  requirements:
51
59
  - - '='
52
60
  - !ruby/object:Gem::Version
@@ -54,7 +62,6 @@ dependencies:
54
62
  type: :development
55
63
  prerelease: false
56
64
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
65
  requirements:
59
66
  - - '='
60
67
  - !ruby/object:Gem::Version
@@ -78,6 +85,9 @@ files:
78
85
  - config.ru
79
86
  - config/routes.rb
80
87
  - lib/maitre_d.rb
88
+ - lib/maitre_d/broadstack.rb
89
+ - lib/maitre_d/broadstack/api.rb
90
+ - lib/maitre_d/broadstack/api_helpers.rb
81
91
  - lib/maitre_d/cloud_control.rb
82
92
  - lib/maitre_d/cloud_control/api.rb
83
93
  - lib/maitre_d/cloud_control/api_helpers.rb
@@ -91,14 +101,18 @@ files:
91
101
  - lib/maitre_d/opperator/api_helpers.rb
92
102
  - lib/maitre_d/opperator/listener.rb
93
103
  - maitre_d.gemspec
104
+ - spec/api/broadstack/provisioning_spec.rb
105
+ - spec/api/broadstack/single_sign_on_spec.rb
94
106
  - spec/api/cloud_control/provisioning_spec.rb
95
107
  - spec/api/cloud_control/single_sign_on_spec.rb
96
108
  - spec/api/heroku/provisioning_spec.rb
97
109
  - spec/api/heroku/single_sign_on_spec.rb
98
110
  - spec/api/opperator/provisioning_spec.rb
111
+ - spec/internal/app/listeners/broadstack_listener.rb
99
112
  - spec/internal/app/listeners/cloud_control_listener.rb
100
113
  - spec/internal/app/listeners/heroku_listener.rb
101
114
  - spec/internal/app/listeners/opperator_listener.rb
115
+ - spec/internal/config/initializers/broadstack.rb
102
116
  - spec/internal/config/initializers/cloud_control.rb
103
117
  - spec/internal/config/initializers/heroku.rb
104
118
  - spec/internal/config/initializers/opperator.rb
@@ -108,37 +122,40 @@ files:
108
122
  - spec/spec_helper.rb
109
123
  homepage: http://github.com/flying-sphinx/maitre_d
110
124
  licenses: []
125
+ metadata: {}
111
126
  post_install_message:
112
127
  rdoc_options: []
113
128
  require_paths:
114
129
  - lib
115
130
  required_ruby_version: !ruby/object:Gem::Requirement
116
- none: false
117
131
  requirements:
118
- - - ! '>='
132
+ - - '>='
119
133
  - !ruby/object:Gem::Version
120
134
  version: '0'
121
135
  required_rubygems_version: !ruby/object:Gem::Requirement
122
- none: false
123
136
  requirements:
124
- - - ! '>='
137
+ - - '>='
125
138
  - !ruby/object:Gem::Version
126
139
  version: '0'
127
140
  requirements: []
128
141
  rubyforge_project: maitre_d
129
- rubygems_version: 1.8.23
142
+ rubygems_version: 2.0.2
130
143
  signing_key:
131
- specification_version: 3
144
+ specification_version: 4
132
145
  summary: Rack API and Rails Engine for Heroku and Opperator add-ons
133
146
  test_files:
147
+ - spec/api/broadstack/provisioning_spec.rb
148
+ - spec/api/broadstack/single_sign_on_spec.rb
134
149
  - spec/api/cloud_control/provisioning_spec.rb
135
150
  - spec/api/cloud_control/single_sign_on_spec.rb
136
151
  - spec/api/heroku/provisioning_spec.rb
137
152
  - spec/api/heroku/single_sign_on_spec.rb
138
153
  - spec/api/opperator/provisioning_spec.rb
154
+ - spec/internal/app/listeners/broadstack_listener.rb
139
155
  - spec/internal/app/listeners/cloud_control_listener.rb
140
156
  - spec/internal/app/listeners/heroku_listener.rb
141
157
  - spec/internal/app/listeners/opperator_listener.rb
158
+ - spec/internal/config/initializers/broadstack.rb
142
159
  - spec/internal/config/initializers/cloud_control.rb
143
160
  - spec/internal/config/initializers/heroku.rb
144
161
  - spec/internal/config/initializers/opperator.rb