maestrano 0.11.0 → 0.12.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 +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