maestrano 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +17 -8
- data/LICENSE +1 -1
- data/README.md +91 -14
- data/lib/maestrano/account/bill.rb +1 -1
- data/lib/maestrano/account/recurring_bill.rb +1 -1
- data/lib/maestrano/api/object.rb +1 -0
- data/lib/maestrano/api/operation/base.rb +13 -15
- data/lib/maestrano/api/operation/create.rb +1 -1
- data/lib/maestrano/api/operation/delete.rb +1 -1
- data/lib/maestrano/api/operation/list.rb +1 -1
- data/lib/maestrano/api/operation/update.rb +1 -1
- data/lib/maestrano/connec/client.rb +6 -5
- data/lib/maestrano/preset.rb +23 -0
- data/lib/maestrano/saml/request.rb +4 -3
- data/lib/maestrano/saml/response.rb +3 -2
- data/lib/maestrano/sso/base_user.rb +3 -2
- data/lib/maestrano/sso/session.rb +3 -2
- data/lib/maestrano/sso.rb +18 -17
- data/lib/maestrano/version.rb +1 -1
- data/lib/maestrano.rb +59 -8
- data/test/maestrano/account/bill_test.rb +54 -13
- data/test/maestrano/account/user_test.rb +20 -0
- data/test/maestrano/connec/client_test.rb +210 -66
- data/test/maestrano/maestrano_test.rb +141 -4
- data/test/maestrano/saml/response_test.rb +83 -0
- data/test/maestrano/sso/session_test.rb +61 -0
- data/test/maestrano/sso_test.rb +246 -85
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a4a440ceef4d8beb0f34cd2b0969c9547568120
|
4
|
+
data.tar.gz: 0386626517b5da4d14258d9a47aa9d9b7ce91ddb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22a20f362b25e45debc2a744d2a9cc19c9511001bc771a9eca695527e8e2ee15dcd8ce4a2f3ae091da722e0904a16cbf17d5332b8fa48cc58a807135fb126aff
|
7
|
+
data.tar.gz: ddf8ad3e3b0f2b47606325c1b8a60c23c9a450f2e7f0d1d66f4a9897d3fa8ff04a498bc4841543442fbcd8b1839f9bfd38407567f2901dcba003eea259ca7ca4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
maestrano (0.
|
4
|
+
maestrano (0.12.0)
|
5
5
|
httparty (~> 0.13)
|
6
6
|
json (~> 1.8)
|
7
7
|
mime-types (~> 1.25)
|
@@ -12,10 +12,14 @@ PATH
|
|
12
12
|
GEM
|
13
13
|
remote: http://rubygems.org/
|
14
14
|
specs:
|
15
|
-
|
15
|
+
domain_name (0.5.24)
|
16
|
+
unf (>= 0.0.5, < 1.0.0)
|
17
|
+
http-cookie (1.0.2)
|
18
|
+
domain_name (~> 0.5)
|
19
|
+
httparty (0.13.5)
|
16
20
|
json (~> 1.8)
|
17
21
|
multi_xml (>= 0.5.2)
|
18
|
-
json (1.8.
|
22
|
+
json (1.8.3)
|
19
23
|
macaddr (1.7.1)
|
20
24
|
systemu (~> 2.6.2)
|
21
25
|
metaclass (0.0.4)
|
@@ -24,21 +28,26 @@ GEM
|
|
24
28
|
mocha (0.13.3)
|
25
29
|
metaclass (~> 0.0.1)
|
26
30
|
multi_xml (0.5.5)
|
27
|
-
netrc (0.10.
|
28
|
-
nokogiri (1.6.
|
31
|
+
netrc (0.10.3)
|
32
|
+
nokogiri (1.6.6.2)
|
29
33
|
mini_portile (~> 0.6.0)
|
30
34
|
rake (10.3.2)
|
31
|
-
rest-client (1.
|
35
|
+
rest-client (1.8.0)
|
36
|
+
http-cookie (>= 1.0.2, < 2.0)
|
32
37
|
mime-types (>= 1.16, < 3.0)
|
33
38
|
netrc (~> 0.7)
|
34
39
|
shoulda (2.11.3)
|
35
|
-
systemu (2.6.
|
40
|
+
systemu (2.6.5)
|
36
41
|
test-unit (2.5.5)
|
37
42
|
timecop (0.6.0)
|
38
|
-
|
43
|
+
unf (0.1.4)
|
44
|
+
unf_ext
|
45
|
+
unf_ext (0.0.7.1)
|
46
|
+
uuid (2.3.8)
|
39
47
|
macaddr (~> 1.0)
|
40
48
|
|
41
49
|
PLATFORMS
|
50
|
+
java
|
42
51
|
ruby
|
43
52
|
|
44
53
|
DEPENDENCIES
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -68,6 +68,12 @@ gem 'maestrano'
|
|
68
68
|
### Configuration
|
69
69
|
Once installed the first step is to create an initializer to configure the behaviour of the Maestrano gem - including setting your API key.
|
70
70
|
|
71
|
+
You can add configuration presets by putting additional configuration blocks in your maestrano.rb initializer. These additional presets can then be specified when doing particular action, such as initializing a Connec!™ client or triggering a SSO handshake. These presets are particularly useful if you are dealing with multiple Maestrano-style marketplaces (multi-enterprise integration).
|
72
|
+
|
73
|
+
If this is the first time you integrate with Maestrano, we recommend adopting a multi-tenant approach. All code samples in this documentation provide examples on how to handle multi-tenancy by scoping method calls to a specific configuration preset.
|
74
|
+
|
75
|
+
More information about multi-tenant integration can be found on [Our Multi-Tenant Integration Guide](https://maestrano.atlassian.net/wiki/display/CONNECAPIV2/Multi-Tenant+Integration)
|
76
|
+
|
71
77
|
The initializer should look like this:
|
72
78
|
```ruby
|
73
79
|
# Use this block to configure the behaviour of Maestrano
|
@@ -204,18 +210,52 @@ Maestrano.configure do |config|
|
|
204
210
|
# notified upon creation/update in Connec!™
|
205
211
|
#
|
206
212
|
# config.webhook.connec.subscriptions = {
|
207
|
-
# accounts:
|
208
|
-
# company:
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
213
|
+
# accounts: true,
|
214
|
+
# company: true,
|
215
|
+
# employees: false,
|
216
|
+
# events: false,
|
217
|
+
# event_orders: false,
|
218
|
+
# invoices: true,
|
219
|
+
# items: true,
|
220
|
+
# journals: false,
|
221
|
+
# opportunities: true,
|
222
|
+
# organizations: true,
|
223
|
+
# payments: false,
|
224
|
+
# pay_items: false,
|
225
|
+
# pay_schedules: false,
|
226
|
+
# pay_stubs: false,
|
227
|
+
# pay_runs: false,
|
228
|
+
# people: true,
|
229
|
+
# projects: false,
|
230
|
+
# purchase_orders: false,
|
231
|
+
# quotes: false,
|
232
|
+
# sales_orders: false,
|
233
|
+
# tax_codes: true,
|
234
|
+
# tax_rates: false,
|
235
|
+
# time_activities: false,
|
236
|
+
# time_sheets: false,
|
237
|
+
# venues: false,
|
238
|
+
# warehouses: false,
|
239
|
+
# work_locations: false
|
215
240
|
# }
|
216
241
|
end
|
217
242
|
```
|
218
243
|
|
244
|
+
If you need to support multiple marketplace providers, you can define configuration presets and switch between these at runtime:
|
245
|
+
```ruby
|
246
|
+
Maestrano['my-preset1'].configure do |config|
|
247
|
+
config.environment = 'production'
|
248
|
+
config.app.host = 'https://my-custom-provider1.com'
|
249
|
+
...
|
250
|
+
end
|
251
|
+
|
252
|
+
Maestrano['my-preset2'].configure do |config|
|
253
|
+
config.environment = 'production'
|
254
|
+
config.app.host = 'https://my-custom-provider2.com'
|
255
|
+
...
|
256
|
+
end
|
257
|
+
```
|
258
|
+
|
219
259
|
### Metadata Endpoint
|
220
260
|
Your configuration initializer is now all setup and shiny. Great! But need to know about it. Of course
|
221
261
|
we could propose a long and boring form on maestrano.com for you to fill all these details (especially the webhooks) but we thought it would be more convenient to fetch that automatically.
|
@@ -235,6 +275,8 @@ class MaestranoMetaDataController < ApplicationController
|
|
235
275
|
|
236
276
|
def metadata
|
237
277
|
render json: Maestrano.to_metadata
|
278
|
+
# Or using presets
|
279
|
+
# render json: Maestrano['my-preset'].to_metadata
|
238
280
|
end
|
239
281
|
|
240
282
|
private
|
@@ -252,6 +294,9 @@ end
|
|
252
294
|
```
|
253
295
|
|
254
296
|
## Single Sign-On Setup
|
297
|
+
|
298
|
+
> **Heads up!** Prefer to use OpenID rather than our SAML implementation? Just look at our [OpenID Guide](https://maestrano.atlassian.net/wiki/display/CONNECAPIV2/SSO+via+OpenID) to get started!
|
299
|
+
|
255
300
|
In order to get setup with single sign-on you will need a user model and a group model. It will also require you to write a controller for the init phase and consume phase of the single sign-on handshake.
|
256
301
|
|
257
302
|
You might wonder why we need a 'group' on top of a user. Well Maestrano works with businesses and as such expects your service to be able to manage groups of users. A group represents 1) a billing entity 2) a collaboration group. During the first single sign-on handshake both a user and a group should be created. Additional users logging in via the same group should then be added to this existing group (see controller setup below)
|
@@ -342,7 +387,7 @@ Your controller will need to have two actions: init and consume. The init action
|
|
342
387
|
The init action is all handled via Maestrano methods and should look like this:
|
343
388
|
```ruby
|
344
389
|
def init
|
345
|
-
redirect_to Maestrano::Saml::Request.new(params,session).redirect_url
|
390
|
+
redirect_to Maestrano::Saml::Request['my-preset'].new(params,session).redirect_url
|
346
391
|
end
|
347
392
|
```
|
348
393
|
The params variable should contain the GET parameters of the request. The session variable should be the actual client session.
|
@@ -351,7 +396,7 @@ Based on your application requirements the consume action might look like this:
|
|
351
396
|
```ruby
|
352
397
|
def consume
|
353
398
|
# Process the response and extract information
|
354
|
-
saml_response = Maestrano::Saml::Response.new(params[:SAMLResponse])
|
399
|
+
saml_response = Maestrano::Saml::Response['my-preset'].new(params[:SAMLResponse])
|
355
400
|
user_hash = Maestrano::SSO::BaseUser.new(saml_response).to_hash
|
356
401
|
group_hash = Maestrano::SSO::BaseGroup.new(saml_response).to_hash
|
357
402
|
membership_hash = Maestrano::SSO::BaseMembership.new(saml_response).to_hash
|
@@ -383,9 +428,9 @@ If you want your users to benefit from single logout then you should define the
|
|
383
428
|
|
384
429
|
```ruby
|
385
430
|
def verify_maestrano_session
|
386
|
-
if Maestrano.param(:sso_enabled)
|
387
|
-
if session && session[:maestrano] && !Maestrano::SSO::Session.new(session).valid?
|
388
|
-
redirect_to Maestrano::SSO.init_url
|
431
|
+
if Maestrano['my-preset'].param(:sso_enabled)
|
432
|
+
if session && session[:maestrano] && !Maestrano::SSO['my-preset']::Session.new(session).valid?
|
433
|
+
redirect_to Maestrano::SSO['my-preset'].init_url
|
389
434
|
end
|
390
435
|
end
|
391
436
|
true
|
@@ -658,6 +703,14 @@ bill = Maestrano::Account::Bill.retrieve("bill-f1d2s54")
|
|
658
703
|
bill.cancel
|
659
704
|
```
|
660
705
|
|
706
|
+
##### Using presets
|
707
|
+
|
708
|
+
All actions can be performed with presets, for instance to list all bills with presets
|
709
|
+
```ruby
|
710
|
+
bills = Maestrano::Account::Bill['my-preset'].all
|
711
|
+
bills.each { |b| puts b.id }
|
712
|
+
```
|
713
|
+
|
661
714
|
#### Recurring Bill
|
662
715
|
A recurring bill charges a given customer at a regular interval without you having to do anything.
|
663
716
|
|
@@ -822,6 +875,13 @@ rec_bill = Maestrano::Account::RecurringBill.retrieve("rbill-f1d2s54")
|
|
822
875
|
rec_bill.cancel
|
823
876
|
```
|
824
877
|
|
878
|
+
##### Using presets
|
879
|
+
|
880
|
+
All actions can be performed with presets, for instance to list all recurring bills with presets
|
881
|
+
```ruby
|
882
|
+
rec_bills = Maestrano::Account::RecurringBill['my-preset'].all
|
883
|
+
rec_bills.each { |b| puts b.id }
|
884
|
+
```
|
825
885
|
|
826
886
|
### Membership API
|
827
887
|
|
@@ -930,6 +990,13 @@ Access a single user by id
|
|
930
990
|
user = Maestrano::Account::User.retrieve("usr-f1d2s54");
|
931
991
|
```
|
932
992
|
|
993
|
+
##### Using presets
|
994
|
+
|
995
|
+
All actions can be performed with presets, for instance to list all users with presets
|
996
|
+
```ruby
|
997
|
+
users = Maestrano::Account::User['my-preset'].all
|
998
|
+
```
|
999
|
+
|
933
1000
|
#### Group
|
934
1001
|
A group represents a customer account and is composed of members (users) having access to your application. A group also represents a chargeable account (see Bill/RecurringBill). Typically you can remotely check if a group has entered a credit card on Maestrano.
|
935
1002
|
|
@@ -1065,6 +1132,12 @@ Access a single group by id
|
|
1065
1132
|
group = Maestrano::Account::Group.retrieve("usr-f1d2s54");
|
1066
1133
|
```
|
1067
1134
|
|
1135
|
+
##### Using presets
|
1136
|
+
|
1137
|
+
All actions can be performed with presets, for instance to list all groups with presets
|
1138
|
+
```ruby
|
1139
|
+
groups = Maestrano::Account::Group['my-preset'].all
|
1140
|
+
```
|
1068
1141
|
|
1069
1142
|
## Connec!™ Data Sharing
|
1070
1143
|
Maestrano offers the capability to share actual business data between applications via its data sharing platform Connec!™.
|
@@ -1096,6 +1169,10 @@ client.post('/organizations', { organizations: { name: "DoeCorp Inc."} })
|
|
1096
1169
|
|
1097
1170
|
# Update an organization
|
1098
1171
|
client.put('/organizations/e32303c1-5102-0132-661e-600308937d74', { organizations: { is_customer: true} })
|
1172
|
+
|
1173
|
+
# With presets
|
1174
|
+
client_presets = Maestrano::Connec::Client['my-preset'].new("cld-f7f5g4")
|
1175
|
+
client_presets.get('/organizations')
|
1099
1176
|
```
|
1100
1177
|
|
1101
1178
|
|
@@ -1127,6 +1204,6 @@ So if you have any question or need help integrating with us just let us know at
|
|
1127
1204
|
|
1128
1205
|
## License
|
1129
1206
|
|
1130
|
-
MIT License. Copyright
|
1207
|
+
MIT License. Copyright 2015 Maestrano Pty Ltd. https://maestrano.com
|
1131
1208
|
|
1132
1209
|
You are not granted rights or licenses to the trademarks of Maestrano.
|
@@ -5,7 +5,7 @@ module Maestrano
|
|
5
5
|
include Maestrano::API::Operation::Create
|
6
6
|
|
7
7
|
def cancel
|
8
|
-
response, api_token = Maestrano::API::Operation::Base.request(:delete, url, @api_token)
|
8
|
+
response, api_token = Maestrano::API::Operation::Base[self.class.preset].request(:delete, url, @api_token)
|
9
9
|
refresh_from(response, api_token)
|
10
10
|
self
|
11
11
|
end
|
@@ -5,7 +5,7 @@ module Maestrano
|
|
5
5
|
include Maestrano::API::Operation::Create
|
6
6
|
|
7
7
|
def cancel
|
8
|
-
response, api_token = Maestrano::API::Operation::Base.request(:delete, url, @api_token)
|
8
|
+
response, api_token = Maestrano::API::Operation::Base[self.class.preset].request(:delete, url, @api_token)
|
9
9
|
refresh_from(response, api_token)
|
10
10
|
self
|
11
11
|
end
|
data/lib/maestrano/api/object.rb
CHANGED
@@ -2,17 +2,15 @@ module Maestrano
|
|
2
2
|
module API
|
3
3
|
module Operation
|
4
4
|
module Base
|
5
|
-
|
6
|
-
|
7
|
-
# end
|
8
|
-
|
5
|
+
include Preset
|
6
|
+
|
9
7
|
def self.api_url(url='')
|
10
|
-
Maestrano.param('api.host') + Maestrano.param('api.base') + url
|
8
|
+
Maestrano[self.preset].param('api.host') + Maestrano[self.preset].param('api.base') + url
|
11
9
|
end
|
12
10
|
|
13
11
|
# Perform remote request
|
14
12
|
def self.request(method, url, api_token, params={}, headers={})
|
15
|
-
unless api_token ||= Maestrano.param('api_token')
|
13
|
+
unless api_token ||= Maestrano[self.preset].param('api_token')
|
16
14
|
raise Maestrano::API::Error::AuthenticationError.new('No API key provided.')
|
17
15
|
end
|
18
16
|
|
@@ -21,7 +19,7 @@ module Maestrano
|
|
21
19
|
if self.ssl_preflight_passed?
|
22
20
|
request_opts.update(
|
23
21
|
verify_ssl: OpenSSL::SSL::VERIFY_PEER,
|
24
|
-
ssl_ca_file: Maestrano.param('ssl_bundle_path')
|
22
|
+
ssl_ca_file: Maestrano[self.preset].param('ssl_bundle_path')
|
25
23
|
)
|
26
24
|
end
|
27
25
|
|
@@ -69,13 +67,13 @@ module Maestrano
|
|
69
67
|
private
|
70
68
|
|
71
69
|
def self.ssl_preflight_passed?
|
72
|
-
if !Maestrano.param('api.verify_ssl_certs')
|
70
|
+
if !Maestrano[self.preset].param('api.verify_ssl_certs')
|
73
71
|
#$stderr.puts "WARNING: Running without SSL cert verification. " +
|
74
72
|
# "Execute 'Maestrano.configure { |config| config.verify_ssl_certs = true' } to enable verification."
|
75
73
|
return false
|
76
|
-
elsif !Util.file_readable(Maestrano.param('ssl_bundle_path'))
|
74
|
+
elsif !Util.file_readable(Maestrano[self.preset].param('ssl_bundle_path'))
|
77
75
|
$stderr.puts "WARNING: Running without SSL cert verification " +
|
78
|
-
"because #{Maestrano.param('ssl_bundle_path')} isn't readable"
|
76
|
+
"because #{Maestrano[self.preset].param('ssl_bundle_path')} isn't readable"
|
79
77
|
|
80
78
|
return false
|
81
79
|
end
|
@@ -87,9 +85,9 @@ module Maestrano
|
|
87
85
|
@uname ||= get_uname
|
88
86
|
|
89
87
|
{
|
90
|
-
:bindings_version => Maestrano.param('api.version'),
|
91
|
-
:lang => Maestrano.param('api.lang'),
|
92
|
-
:lang_version => Maestrano.param('api.lang_version'),
|
88
|
+
:bindings_version => Maestrano[self.preset].param('api.version'),
|
89
|
+
:lang => Maestrano[self.preset].param('api.lang'),
|
90
|
+
:lang_version => Maestrano[self.preset].param('api.lang_version'),
|
93
91
|
:platform => RUBY_PLATFORM,
|
94
92
|
:publisher => 'maestrano',
|
95
93
|
:uname => @uname
|
@@ -110,12 +108,12 @@ module Maestrano
|
|
110
108
|
|
111
109
|
def self.request_headers(api_token)
|
112
110
|
headers = {
|
113
|
-
:user_agent => "Maestrano/v1 RubyBindings/#{Maestrano.param('api.version')}",
|
111
|
+
:user_agent => "Maestrano/v1 RubyBindings/#{Maestrano[self.preset].param('api.version')}",
|
114
112
|
:authorization => "Basic #{Base64.strict_encode64(api_token)}",
|
115
113
|
:content_type => 'application/x-www-form-urlencoded'
|
116
114
|
}
|
117
115
|
|
118
|
-
api_version = Maestrano.param('api_version')
|
116
|
+
api_version = Maestrano[self.preset].param('api_version')
|
119
117
|
headers[:maestrano_version] = api_version if api_version
|
120
118
|
|
121
119
|
begin
|
@@ -4,7 +4,7 @@ module Maestrano
|
|
4
4
|
module Create
|
5
5
|
module ClassMethods
|
6
6
|
def create(params={}, api_token=nil)
|
7
|
-
response, api_token = Maestrano::API::Operation::Base.request(:post, self.url, api_token, params)
|
7
|
+
response, api_token = Maestrano::API::Operation::Base[self.preset].request(:post, self.url, api_token, params)
|
8
8
|
Util.convert_to_maestrano_object(response, api_token)
|
9
9
|
end
|
10
10
|
end
|
@@ -3,7 +3,7 @@ module Maestrano
|
|
3
3
|
module Operation
|
4
4
|
module Delete
|
5
5
|
def delete(params = {})
|
6
|
-
response, api_token = Maestrano::API::Operation::Base.request(:delete, url, @api_token, params)
|
6
|
+
response, api_token = Maestrano::API::Operation::Base[self.class.preset].request(:delete, url, @api_token, params)
|
7
7
|
refresh_from(response, api_token)
|
8
8
|
self
|
9
9
|
end
|
@@ -4,7 +4,7 @@ module Maestrano
|
|
4
4
|
module List
|
5
5
|
module ClassMethods
|
6
6
|
def all(filters={}, api_token=nil)
|
7
|
-
response, api_token = Maestrano::API::Operation::Base.request(:get, url, api_token, filters)
|
7
|
+
response, api_token = Maestrano::API::Operation::Base[self.preset].request(:get, url, api_token, filters)
|
8
8
|
Util.convert_to_maestrano_object(response, api_token)
|
9
9
|
end
|
10
10
|
end
|
@@ -12,7 +12,7 @@ module Maestrano
|
|
12
12
|
if values.length > 0
|
13
13
|
values.delete(:id)
|
14
14
|
|
15
|
-
response, api_token = Maestrano::API::Operation::Base.request(:put, url, @api_token, values)
|
15
|
+
response, api_token = Maestrano::API::Operation::Base[self.class.preset].request(:put, url, @api_token, values)
|
16
16
|
refresh_from(response, api_token)
|
17
17
|
end
|
18
18
|
self
|
@@ -2,8 +2,8 @@ require 'httparty'
|
|
2
2
|
|
3
3
|
module Maestrano
|
4
4
|
module Connec
|
5
|
-
|
6
5
|
class Client
|
6
|
+
include Preset
|
7
7
|
include ::HTTParty
|
8
8
|
headers 'Accept' => 'application/vnd.api+json'
|
9
9
|
headers 'Content-Type' => 'application/vnd.api+json'
|
@@ -13,7 +13,7 @@ module Maestrano
|
|
13
13
|
|
14
14
|
def initialize(group_id)
|
15
15
|
@group_id = group_id
|
16
|
-
self.class.base_uri("#{Maestrano.param('connec.host')}#{Maestrano.param('connec.base_path')}")
|
16
|
+
self.class.base_uri("#{Maestrano[self.class.preset].param('connec.host')}#{Maestrano[self.class.preset].param('connec.base_path')}")
|
17
17
|
end
|
18
18
|
|
19
19
|
# Return the default options which includes
|
@@ -21,9 +21,10 @@ module Maestrano
|
|
21
21
|
def default_options
|
22
22
|
{
|
23
23
|
basic_auth: {
|
24
|
-
username: Maestrano.param('api.id'),
|
25
|
-
password: Maestrano.param('api.key')
|
26
|
-
}
|
24
|
+
username: Maestrano[self.class.preset].param('api.id'),
|
25
|
+
password: Maestrano[self.class.preset].param('api.key')
|
26
|
+
},
|
27
|
+
timeout: Maestrano[self.class.preset].param('connec.timeout')
|
27
28
|
}
|
28
29
|
end
|
29
30
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# When included, this module allows another module to be called setting a default preset
|
2
|
+
#
|
3
|
+
# Examples:
|
4
|
+
# Maestrano::Settings.new # Uses 'default' preset
|
5
|
+
# Maestrano['mypreset']::Settings.new # Uses 'mypreset'
|
6
|
+
module Maestrano
|
7
|
+
module Preset
|
8
|
+
def self.included(base)
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def [](preset)
|
14
|
+
define_singleton_method(:preset) { preset }
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def preset
|
19
|
+
'default'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -7,12 +7,13 @@ require "rexml/xpath"
|
|
7
7
|
|
8
8
|
module Maestrano
|
9
9
|
module Saml
|
10
|
-
|
10
|
+
include REXML
|
11
11
|
class Request
|
12
|
+
include Preset
|
12
13
|
attr_accessor :settings, :params, :session
|
13
|
-
|
14
|
+
|
14
15
|
def initialize(params = {}, session = {})
|
15
|
-
self.settings = Maestrano::SSO.saml_settings
|
16
|
+
self.settings = Maestrano::SSO[self.class.preset].saml_settings
|
16
17
|
self.params = params
|
17
18
|
self.session = session
|
18
19
|
end
|
@@ -4,8 +4,9 @@ require "nokogiri"
|
|
4
4
|
# Only supports SAML 2.0
|
5
5
|
module Maestrano
|
6
6
|
module Saml
|
7
|
-
|
8
7
|
class Response
|
8
|
+
include Preset
|
9
|
+
|
9
10
|
ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
|
10
11
|
PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
|
11
12
|
DSIG = "http://www.w3.org/2000/09/xmldsig#"
|
@@ -22,7 +23,7 @@ module Maestrano
|
|
22
23
|
@options = options
|
23
24
|
@response = (response =~ /^</) ? response : Base64.decode64(response)
|
24
25
|
@document = Maestrano::XMLSecurity::SignedDocument.new(@response)
|
25
|
-
@settings = Maestrano::SSO.saml_settings
|
26
|
+
@settings = Maestrano::SSO[self.class.preset].saml_settings
|
26
27
|
end
|
27
28
|
|
28
29
|
def is_valid?
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Maestrano
|
2
2
|
module SSO
|
3
3
|
class BaseUser
|
4
|
+
include Preset
|
4
5
|
attr_accessor :local_id
|
5
6
|
attr_reader :sso_session,:sso_session_recheck,
|
6
7
|
:group_uid,:group_role,:uid,:virtual_uid,:email,
|
@@ -26,7 +27,7 @@ module Maestrano
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def to_uid
|
29
|
-
if Maestrano.param('sso.creation_mode') == 'real'
|
30
|
+
if Maestrano[self.class.preset].param('sso.creation_mode') == 'real'
|
30
31
|
return self.uid
|
31
32
|
else
|
32
33
|
return self.virtual_uid
|
@@ -34,7 +35,7 @@ module Maestrano
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def to_email
|
37
|
-
if Maestrano.param('sso.creation_mode') == 'real'
|
38
|
+
if Maestrano[self.class.preset].param('sso.creation_mode') == 'real'
|
38
39
|
return self.email
|
39
40
|
else
|
40
41
|
return self.virtual_email
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Maestrano
|
2
2
|
module SSO
|
3
3
|
class Session
|
4
|
+
include Preset
|
4
5
|
attr_accessor :session, :uid, :session_token, :recheck, :group_uid
|
5
6
|
|
6
7
|
# Load a Maestrano::SSO::Session object from a
|
@@ -49,7 +50,7 @@ module Maestrano
|
|
49
50
|
# false otherwise
|
50
51
|
def perform_remote_check
|
51
52
|
# Get remote session info
|
52
|
-
url = Maestrano::SSO.session_check_url(self.uid, self.session_token)
|
53
|
+
url = Maestrano::SSO[self.class.preset].session_check_url(self.uid, self.session_token)
|
53
54
|
begin
|
54
55
|
response = RestClient.get(url)
|
55
56
|
response = JSON.parse(response)
|
@@ -78,7 +79,7 @@ module Maestrano
|
|
78
79
|
# a session should be restricted to maestrano users only
|
79
80
|
# within an application
|
80
81
|
def valid?(opts = {})
|
81
|
-
return true unless Maestrano.param('sso.slo_enabled')
|
82
|
+
return true unless Maestrano[self.class.preset].param('sso.slo_enabled')
|
82
83
|
return true if opts[:if_session] && (!self.session || (!self.session[:maestrano] && !self.session['maestrano']))
|
83
84
|
return false unless self.session
|
84
85
|
|
data/lib/maestrano/sso.rb
CHANGED
@@ -1,66 +1,67 @@
|
|
1
1
|
module Maestrano
|
2
2
|
module SSO
|
3
|
+
include Preset
|
3
4
|
|
4
5
|
# Return the saml_settings based on
|
5
6
|
# Maestrano configuration
|
6
7
|
def self.saml_settings
|
7
8
|
settings = Maestrano::Saml::Settings.new
|
8
9
|
settings.assertion_consumer_service_url = self.consume_url
|
9
|
-
settings.issuer = Maestrano.param('api.id')
|
10
|
+
settings.issuer = Maestrano[preset].param('api.id')
|
10
11
|
settings.idp_sso_target_url = self.idp_url
|
11
|
-
settings.idp_cert_fingerprint = Maestrano.param('sso_x509_fingerprint')
|
12
|
-
settings.name_identifier_format = Maestrano.param('sso_name_id_format')
|
12
|
+
settings.idp_cert_fingerprint = Maestrano[preset].param('sso_x509_fingerprint')
|
13
|
+
settings.name_identifier_format = Maestrano[preset].param('sso_name_id_format')
|
13
14
|
settings
|
14
15
|
end
|
15
16
|
|
16
17
|
# Build a new SAML Request
|
17
18
|
def self.build_request(get_params = {})
|
18
|
-
Maestrano::Saml::Request.new(get_params)
|
19
|
+
Maestrano::Saml::Request[preset].new(get_params)
|
19
20
|
end
|
20
21
|
|
21
22
|
# Build a new SAML response
|
22
23
|
def self.build_response(saml_post_param)
|
23
|
-
Maestrano::Saml::Response.new(saml_post_param)
|
24
|
+
Maestrano::Saml::Response[preset].new(saml_post_param)
|
24
25
|
end
|
25
26
|
|
26
27
|
def self.enabled?
|
27
|
-
!!Maestrano.param('sso.enabled')
|
28
|
+
!!Maestrano[preset].param('sso.enabled')
|
28
29
|
end
|
29
30
|
|
30
31
|
def self.init_url
|
31
|
-
host = Maestrano.param('sso.idm')
|
32
|
-
path = Maestrano.param('sso.init_path')
|
32
|
+
host = Maestrano[preset].param('sso.idm')
|
33
|
+
path = Maestrano[preset].param('sso.init_path')
|
33
34
|
return "#{host}#{path}"
|
34
35
|
end
|
35
36
|
|
36
37
|
def self.consume_url
|
37
|
-
host = Maestrano.param('sso.idm')
|
38
|
-
path = Maestrano.param('sso.consume_path')
|
38
|
+
host = Maestrano[preset].param('sso.idm')
|
39
|
+
path = Maestrano[preset].param('sso.consume_path')
|
39
40
|
return "#{host}#{path}"
|
40
41
|
end
|
41
42
|
|
42
43
|
def self.logout_url
|
43
|
-
host = Maestrano.param('api_host')
|
44
|
+
host = Maestrano[preset].param('api_host')
|
44
45
|
path = '/app_logout'
|
45
46
|
return "#{host}#{path}"
|
46
47
|
end
|
47
48
|
|
48
49
|
def self.unauthorized_url
|
49
|
-
host = Maestrano.param('api_host')
|
50
|
+
host = Maestrano[preset].param('api_host')
|
50
51
|
path = '/app_access_unauthorized'
|
51
52
|
return "#{host}#{path}";
|
52
53
|
end
|
53
54
|
|
54
55
|
def self.idp_url
|
55
|
-
host = Maestrano.param('api_host')
|
56
|
-
api_base = Maestrano.param('api_base')
|
56
|
+
host = Maestrano[preset].param('api_host')
|
57
|
+
api_base = Maestrano[preset].param('api_base')
|
57
58
|
endpoint = 'auth/saml'
|
58
59
|
return "#{host}#{api_base}#{endpoint}"
|
59
60
|
end
|
60
61
|
|
61
62
|
def self.session_check_url(user_uid,sso_session)
|
62
|
-
host = Maestrano.param('api_host')
|
63
|
-
api_base = Maestrano.param('api_base')
|
63
|
+
host = Maestrano[preset].param('api_host')
|
64
|
+
api_base = Maestrano[preset].param('api_base')
|
64
65
|
endpoint = 'auth/saml'
|
65
66
|
return URI.escape("#{host}#{api_base}#{endpoint}/#{user_uid}?session=#{sso_session}")
|
66
67
|
end
|
@@ -69,7 +70,7 @@ module Maestrano
|
|
69
70
|
# Takes the BaseUser hash representation and current session
|
70
71
|
# in arguments
|
71
72
|
def self.set_session(session, auth)
|
72
|
-
Maestrano::SSO::Session.from_user_auth_hash(session,auth).save
|
73
|
+
Maestrano::SSO::Session[preset].from_user_auth_hash(session,auth).save
|
73
74
|
end
|
74
75
|
|
75
76
|
# Destroy the maestrano session in http session
|
data/lib/maestrano/version.rb
CHANGED