maestrano-connector-rails 2.0.0.pre.RC11 → 2.0.0.pre.RC12
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +1 -1
- data/VERSION +1 -1
- data/app/controllers/maestrano/account/group_users_controller.rb +2 -2
- data/app/controllers/maestrano/account/groups_controller.rb +1 -1
- data/app/controllers/maestrano/connec_controller.rb +39 -24
- data/app/controllers/maestrano/synchronizations_controller.rb +3 -3
- data/app/models/maestrano/connector/rails/concerns/connector_logger.rb +4 -2
- data/app/models/maestrano/connector/rails/organization.rb +2 -0
- data/db/migrate/20161018155513_add_org_uid_to_organization.rb +5 -0
- data/maestrano-connector-rails.gemspec +7 -7
- data/spec/dummy/db/schema.rb +2 -1
- data/spec/models/connector_logger_spec.rb +9 -4
- data/spec/models/organization_spec.rb +21 -2
- data/template/Procfile +2 -2
- data/template/application-sample.yml +13 -2
- data/template/database.yml +4 -4
- data/template/gitignore +4 -1
- data/template/maestrano.rb +2 -174
- data/template/maestrano_connector_template.rb +11 -6
- data/template/routes.rb +13 -2
- metadata +7 -7
- data/template/factories.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d95bff19220474be447576fb4048e63d48e1266
|
4
|
+
data.tar.gz: 75565ee7992093efd5a77fe20052f9dc17d1b953
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b673778a40d4dfc9b0e002fc54360c9e729e052aeffc244aebff563672e40f545f0232530ad6848333833229e6d2d839131e76b36abb84867a2d8dc53e23e16
|
7
|
+
data.tar.gz: d9644a034bfed0f31440df9aa33315a8a493dcf7aa58898304b33693bc9bf13fd95f0a4cc14b8cc7ef82f14e625d1f952a0b9414993903ab318ec5a35a4f558d
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,8 @@
|
|
7
7
|
* Follow migration steps up to framework version 1.5.0
|
8
8
|
* Replace ocurrences of `@organizations` with `current_organization` in `home_index.haml`
|
9
9
|
* In spec_helper.rb add the line `require 'maestrano_connector_rails/factories.rb'`
|
10
|
+
* Add optional hash of parameters to be logged by ConnectorLogger
|
11
|
+
* Add Maestrano Organization UID to the logs
|
10
12
|
|
11
13
|
### Developer Platform registration to be detailed
|
12
14
|
|
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.0.pre.
|
1
|
+
2.0.0.pre.RC12
|
@@ -7,8 +7,8 @@ class Maestrano::Account::GroupUsersController < Maestrano::Rails::WebHookContro
|
|
7
7
|
group_uid = params[:group_id]
|
8
8
|
|
9
9
|
# Get the entities
|
10
|
-
user = Maestrano::Connector::Rails::User.
|
11
|
-
organization = Maestrano::Connector::Rails::Organization.
|
10
|
+
user = Maestrano::Connector::Rails::User.find_by(uid: user_uid, tenant: params[:tenant] || 'default')
|
11
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: group_uid, tenant: params[:tenant] || 'default')
|
12
12
|
|
13
13
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "remove user from group, user_uid=\"#{user_uid}\", group_uid=\"#{group_uid}\"")
|
14
14
|
|
@@ -6,7 +6,7 @@ class Maestrano::Account::GroupsController < Maestrano::Rails::WebHookController
|
|
6
6
|
org_uid = params[:id]
|
7
7
|
|
8
8
|
# Get entity
|
9
|
-
organization = Maestrano::Connector::Rails::Organization.
|
9
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: org_uid, tenant: params[:tenant] || 'default')
|
10
10
|
|
11
11
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, 'delete organization')
|
12
12
|
|
@@ -6,21 +6,10 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
6
6
|
next Maestrano::Connector::Rails::ConnectorLogger.log('info', nil, "Received notification from Connec! for unknow entity: #{entity_name}") unless entity_class_hash
|
7
7
|
|
8
8
|
entities.each do |entity|
|
9
|
-
organization = Maestrano::Connector::Rails::Organization.
|
9
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: entity[:group_id], tenant: params[:tenant])
|
10
10
|
|
11
11
|
begin
|
12
|
-
|
13
|
-
next Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received notification from Connec! for an unknown organization, organization_uid=\"#{entity[:group_id]}\", tenant=\"#{params[:tenant]}\"")
|
14
|
-
end
|
15
|
-
|
16
|
-
if organization.oauth_uid.blank?
|
17
|
-
next Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received notification from Connec! for an organization not linked, organization_uid=\"#{entity[:group_id]}\", tenant=\"#{params[:tenant]}\"")
|
18
|
-
end
|
19
|
-
|
20
|
-
unless organization.sync_enabled && organization.synchronized_entities[entity_class_hash[:name].to_sym]
|
21
|
-
next Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Skipping notification from Connec! webhook, entity_name=\"#{entity_name}\"")
|
22
|
-
end
|
23
|
-
|
12
|
+
next unless valid_organization?(organization, entity_class_hash)
|
24
13
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Processing entity from Connec! webhook, entity_name=\"#{entity_name}\", data=\"#{entity}\"")
|
25
14
|
|
26
15
|
connec_client = Maestrano::Connector::Rails::ConnecHelper.get_client(organization)
|
@@ -31,18 +20,9 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
31
20
|
entity_instance.before_sync(last_synchronization_date)
|
32
21
|
|
33
22
|
# Build expected input for consolidate_and_map_data
|
34
|
-
|
35
|
-
connec_hash_of_entities = Maestrano::Connector::Rails::ComplexEntity.build_hash_with_entities(entity_instance.class.connec_entities_names, entity_name, ->(name) { name.parameterize('_').pluralize }, [entity])
|
36
|
-
filtered_entities = entity_instance.filter_connec_entities(connec_hash_of_entities)
|
37
|
-
|
38
|
-
empty_external_hash = Maestrano::Connector::Rails::ComplexEntity.build_empty_hash(entity_instance.class.external_entities_names)
|
39
|
-
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, empty_external_hash)
|
40
|
-
else
|
41
|
-
filtered_entities = entity_instance.filter_connec_entities([entity])
|
42
|
-
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, [])
|
43
|
-
end
|
44
|
-
entity_instance.push_entities_to_external(mapped_entity[:connec_entities])
|
23
|
+
mapped_entity = map_entity(entity_class_hash, entity_instance, entity_name, entity)
|
45
24
|
|
25
|
+
entity_instance.push_entities_to_external(mapped_entity[:connec_entities])
|
46
26
|
entity_instance.after_sync(last_synchronization_date)
|
47
27
|
rescue => e
|
48
28
|
Maestrano::Connector::Rails::ConnectorLogger.log('warn', organization, "error processing notification entity_name=\"#{entity_name}\", message=\"#{e.message}\", #{e.backtrace.join("\n")}")
|
@@ -58,6 +38,25 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
58
38
|
|
59
39
|
private
|
60
40
|
|
41
|
+
def valid_organization?(organization, entity_class_hash)
|
42
|
+
if organization.nil?
|
43
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received notification from Connec! for an unknown organization, organization_uid=\"#{entity[:group_id]}\", tenant=\"#{params[:tenant]}\"")
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
if organization.oauth_uid.blank?
|
48
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received notification from Connec! for an organization not linked, organization_uid=\"#{entity[:group_id]}\", tenant=\"#{params[:tenant]}\"")
|
49
|
+
return false
|
50
|
+
end
|
51
|
+
|
52
|
+
unless organization.sync_enabled && organization.synchronized_entities[entity_class_hash[:name].to_sym]
|
53
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Skipping notification from Connec! webhook, entity_name=\"#{entity_name}\"")
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
61
60
|
def find_entity_class(entity_name)
|
62
61
|
Maestrano::Connector::Rails::External.entities_list.each do |entity_name_from_list|
|
63
62
|
clazz = "Entities::#{entity_name_from_list.singularize.titleize.split.join}".constantize
|
@@ -70,4 +69,20 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
70
69
|
end
|
71
70
|
nil
|
72
71
|
end
|
72
|
+
|
73
|
+
def map_entity(entity_class_hash, entity_instance, entity_name, entity)
|
74
|
+
# Build expected input for consolidate_and_map_data
|
75
|
+
if entity_class_hash[:is_complex]
|
76
|
+
connec_hash_of_entities = Maestrano::Connector::Rails::ComplexEntity.build_hash_with_entities(entity_instance.class.connec_entities_names, entity_name, ->(name) { name.parameterize('_').pluralize }, [entity])
|
77
|
+
filtered_entities = entity_instance.filter_connec_entities(connec_hash_of_entities)
|
78
|
+
|
79
|
+
empty_external_hash = Maestrano::Connector::Rails::ComplexEntity.build_empty_hash(entity_instance.class.external_entities_names)
|
80
|
+
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, empty_external_hash)
|
81
|
+
else
|
82
|
+
filtered_entities = entity_instance.filter_connec_entities([entity])
|
83
|
+
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, [])
|
84
|
+
end
|
85
|
+
|
86
|
+
mapped_entity
|
87
|
+
end
|
73
88
|
end
|
@@ -2,7 +2,7 @@ class Maestrano::SynchronizationsController < Maestrano::Rails::WebHookControlle
|
|
2
2
|
def show
|
3
3
|
tenant = params[:tenant]
|
4
4
|
uid = params[:id]
|
5
|
-
organization = Maestrano::Connector::Rails::Organization.
|
5
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
|
6
6
|
return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
|
7
7
|
|
8
8
|
status = organization_status organization
|
@@ -14,7 +14,7 @@ class Maestrano::SynchronizationsController < Maestrano::Rails::WebHookControlle
|
|
14
14
|
tenant = params[:tenant]
|
15
15
|
uid = params[:group_id]
|
16
16
|
opts = params[:opts] || {}
|
17
|
-
organization = Maestrano::Connector::Rails::Organization.
|
17
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
|
18
18
|
return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
|
19
19
|
|
20
20
|
status = organization_status(organization)
|
@@ -30,7 +30,7 @@ class Maestrano::SynchronizationsController < Maestrano::Rails::WebHookControlle
|
|
30
30
|
def toggle_sync
|
31
31
|
tenant = params[:tenant]
|
32
32
|
uid = params[:group_id]
|
33
|
-
organization = Maestrano::Connector::Rails::Organization.
|
33
|
+
organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
|
34
34
|
return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
|
35
35
|
|
36
36
|
organization.toggle(:sync_enabled)
|
@@ -2,8 +2,10 @@ module Maestrano::Connector::Rails::Concerns::ConnectorLogger
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
module ClassMethods
|
5
|
-
def log(level, organization, msg)
|
6
|
-
|
5
|
+
def log(level, organization, msg, params = {})
|
6
|
+
line = "uid=\"#{organization&.uid}\", org_uid=\"#{organization&.org_uid}\", tenant=\"#{organization&.tenant}\""
|
7
|
+
line = "#{line}, #{params.map { |k, v| "#{k}=\"#{v}\"" }.join(', ')}" unless params.blank?
|
8
|
+
Rails.logger.method(level).call("#{line}, message=\"#{msg}\"")
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -4,6 +4,8 @@ module Maestrano::Connector::Rails
|
|
4
4
|
maestrano_group_via :provider, :uid, :tenant do |group, maestrano|
|
5
5
|
group.name = (maestrano.name.blank? ? 'Default Group name' : maestrano.name)
|
6
6
|
group.tenant = 'default' # To be set from SSO parameter
|
7
|
+
group.org_uid = maestrano.org_uid # Maestrano organization UID
|
8
|
+
|
7
9
|
# group.country_alpha2 = maestrano.country
|
8
10
|
# group.free_trial_end_at = maestrano.free_trial_end_at
|
9
11
|
# group.some_required_field = 'some-appropriate-default-value'
|
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: maestrano-connector-rails 2.0.0.pre.
|
5
|
+
# stub: maestrano-connector-rails 2.0.0.pre.RC12 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "maestrano-connector-rails"
|
9
|
-
s.version = "2.0.0.pre.
|
9
|
+
s.version = "2.0.0.pre.RC12"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Maestrano"]
|
14
|
-
s.date = "2016-10-
|
14
|
+
s.date = "2016-10-18"
|
15
15
|
s.description = "Maestrano is the next generation marketplace for SME applications. See https://sme.maestrano.com for details."
|
16
16
|
s.email = "developers@maestrano.com"
|
17
17
|
s.executables = ["rails"]
|
@@ -79,6 +79,7 @@ Gem::Specification.new do |s|
|
|
79
79
|
"db/migrate/20160614114401_add_date_filtering_limit_to_organization.rb",
|
80
80
|
"db/migrate/20160614160654_add_encryption_on_oauth_keys.rb",
|
81
81
|
"db/migrate/20161011005751_add_unique_index_on_organization_oauth_uid.rb",
|
82
|
+
"db/migrate/20161018155513_add_org_uid_to_organization.rb",
|
82
83
|
"lib/generators/connector/USAGE",
|
83
84
|
"lib/generators/connector/complex_entity_generator.rb",
|
84
85
|
"lib/generators/connector/install_generator.rb",
|
@@ -200,7 +201,6 @@ Gem::Specification.new do |s|
|
|
200
201
|
"template/Procfile",
|
201
202
|
"template/application-sample.yml",
|
202
203
|
"template/database.yml",
|
203
|
-
"template/factories.rb",
|
204
204
|
"template/gitignore",
|
205
205
|
"template/maestrano.rb",
|
206
206
|
"template/maestrano_connector_template.rb",
|
@@ -248,7 +248,7 @@ Gem::Specification.new do |s|
|
|
248
248
|
s.add_development_dependency(%q<activerecord-jdbcsqlite3-adapter>, [">= 0"])
|
249
249
|
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
250
250
|
s.add_development_dependency(%q<shoulda-matchers>, [">= 0"])
|
251
|
-
s.add_development_dependency(%q<rubocop>, ["
|
251
|
+
s.add_development_dependency(%q<rubocop>, ["~> 0.43"])
|
252
252
|
s.add_development_dependency(%q<timecop>, [">= 0"])
|
253
253
|
s.add_development_dependency(%q<github_changelog_generator>, [">= 0"])
|
254
254
|
else
|
@@ -276,7 +276,7 @@ Gem::Specification.new do |s|
|
|
276
276
|
s.add_dependency(%q<activerecord-jdbcsqlite3-adapter>, [">= 0"])
|
277
277
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
278
278
|
s.add_dependency(%q<shoulda-matchers>, [">= 0"])
|
279
|
-
s.add_dependency(%q<rubocop>, ["
|
279
|
+
s.add_dependency(%q<rubocop>, ["~> 0.43"])
|
280
280
|
s.add_dependency(%q<timecop>, [">= 0"])
|
281
281
|
s.add_dependency(%q<github_changelog_generator>, [">= 0"])
|
282
282
|
end
|
@@ -305,7 +305,7 @@ Gem::Specification.new do |s|
|
|
305
305
|
s.add_dependency(%q<activerecord-jdbcsqlite3-adapter>, [">= 0"])
|
306
306
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
307
307
|
s.add_dependency(%q<shoulda-matchers>, [">= 0"])
|
308
|
-
s.add_dependency(%q<rubocop>, ["
|
308
|
+
s.add_dependency(%q<rubocop>, ["~> 0.43"])
|
309
309
|
s.add_dependency(%q<timecop>, [">= 0"])
|
310
310
|
s.add_dependency(%q<github_changelog_generator>, [">= 0"])
|
311
311
|
end
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20161018155513) do
|
15
15
|
|
16
16
|
create_table "id_maps", force: :cascade do |t|
|
17
17
|
t.string "connec_id"
|
@@ -38,6 +38,7 @@ ActiveRecord::Schema.define(version: 20160614152139) do
|
|
38
38
|
t.string "provider"
|
39
39
|
t.string "uid"
|
40
40
|
t.string "name"
|
41
|
+
t.string "org_uid"
|
41
42
|
t.string "tenant"
|
42
43
|
t.string "oauth_provider"
|
43
44
|
t.string "oauth_uid"
|
@@ -12,10 +12,15 @@ describe Maestrano::Connector::Rails::ConnectorLogger do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'includes the organization uid and tenant' do
|
15
|
-
expect(
|
16
|
-
|
15
|
+
expect(Rails.logger).to receive(:info).with("uid=\"#{organization.uid}\", org_uid=\"#{organization.org_uid}\", tenant=\"#{organization.tenant}\", message=\"msg\"")
|
16
|
+
|
17
17
|
subject.log('info', organization, 'msg')
|
18
18
|
end
|
19
|
-
end
|
20
19
|
|
21
|
-
|
20
|
+
it 'includes extra params' do
|
21
|
+
expect(Rails.logger).to receive(:info).with("uid=\"#{organization.uid}\", org_uid=\"#{organization.org_uid}\", tenant=\"#{organization.tenant}\", foo=\"bar\", message=\"msg\"")
|
22
|
+
|
23
|
+
subject.log('info', organization, 'msg', foo: :bar)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -11,7 +11,7 @@ describe Maestrano::Connector::Rails::Organization do
|
|
11
11
|
# Indexes
|
12
12
|
it { should have_db_index([:uid, :tenant]) }
|
13
13
|
|
14
|
-
#Associations
|
14
|
+
# Associations
|
15
15
|
it { should have_many(:user_organization_rels) }
|
16
16
|
it { should have_many(:users) }
|
17
17
|
it { should have_many(:id_maps).dependent(:destroy) }
|
@@ -113,7 +113,26 @@ describe Maestrano::Connector::Rails::Organization do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
describe 'from_omniauth' do
|
116
|
-
|
116
|
+
let(:saml_hash) { {provider: :maestrano, uid: 'cld-1234', info: {org_uid: 'org-abcd', name: 'My Company'}} }
|
117
|
+
let(:tenant) { 'mytenant' }
|
118
|
+
|
119
|
+
let(:subject) { Maestrano::Connector::Rails::Organization.find_or_create_for_maestrano(saml_hash, tenant) }
|
120
|
+
|
121
|
+
context 'with a new organization' do
|
122
|
+
it 'creates an organization from SAML parameters' do
|
123
|
+
expect(subject.name).to eql('My Company')
|
124
|
+
expect(subject.org_uid).to eql('org-abcd')
|
125
|
+
expect(subject.tenant).to eql(tenant)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with an existing organization' do
|
130
|
+
let!(:organization) { create(:organization, provider: :maestrano, tenant: tenant, uid: 'cld-1234') }
|
131
|
+
|
132
|
+
it 'find the organization from SAML parameters' do
|
133
|
+
expect(subject).to eql(organization)
|
134
|
+
end
|
135
|
+
end
|
117
136
|
end
|
118
137
|
|
119
138
|
describe 'last_three_synchronizations_failed?' do
|
data/template/Procfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
web:
|
2
|
-
worker:
|
1
|
+
web: bin/puma -t 5:5 -p $PORT -e $RACK_ENV
|
2
|
+
worker: bin/sidekiq
|
@@ -1,2 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
encryption_key1: ''
|
2
|
+
encryption_key2: ''
|
3
|
+
|
4
|
+
SIDEKIQ_USERNAME: admin
|
5
|
+
SIDEKIQ_PASSWORD: password
|
6
|
+
|
7
|
+
REDIS_URL: redis://localhost:6379/0/connector-myapp
|
8
|
+
|
9
|
+
MNO_DEVPL_HOST: https://dev-platform.maestrano.com
|
10
|
+
MNO_DEVPL_API_PATH: /api/config/v1/marketplaces
|
11
|
+
MNO_DEVPL_ENV_NAME: connector-myapp
|
12
|
+
MNO_DEVPL_ENV_KEY:
|
13
|
+
MNO_DEVPL_ENV_SECRET:
|
data/template/database.yml
CHANGED
@@ -19,13 +19,13 @@ test:
|
|
19
19
|
database: db/test.sqlite3
|
20
20
|
|
21
21
|
production:
|
22
|
-
adapter:
|
22
|
+
adapter: mysql2
|
23
23
|
url: <%= ENV['DATABASE_URL'] %>
|
24
|
-
encoding:
|
24
|
+
encoding: utf8
|
25
25
|
pool: 5
|
26
26
|
|
27
27
|
uat:
|
28
|
-
adapter:
|
28
|
+
adapter: mysql2
|
29
29
|
url: <%= ENV['DATABASE_URL'] %>
|
30
|
-
encoding:
|
30
|
+
encoding: utf8
|
31
31
|
pool: 5
|
data/template/gitignore
CHANGED
data/template/maestrano.rb
CHANGED
@@ -1,174 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
Maestrano[tenant].configure do |config|
|
4
|
-
# ==> Environment configuration
|
5
|
-
# The environment to connect to.
|
6
|
-
# If set to 'production' then all Single Sign-On (SSO) and API requests
|
7
|
-
# will be made to maestrano.com
|
8
|
-
# If set to 'test' then requests will be made to api-sandbox.maestrano.io
|
9
|
-
# The api-sandbox allows you to easily test integration scenarios.
|
10
|
-
# More details on http://api-sandbox.maestrano.io
|
11
|
-
#
|
12
|
-
config.environment = Settings[tenant][:environment]
|
13
|
-
|
14
|
-
# ==> Application host
|
15
|
-
# This is your application host (e.g: my-app.com) which is ultimately
|
16
|
-
# used to redirect users to the right SAML url during SSO handshake.
|
17
|
-
#
|
18
|
-
config.app.host = Settings.app_host
|
19
|
-
|
20
|
-
# ==> App ID & API key
|
21
|
-
# Your application App ID and API key which you can retrieve on http://maestrano.com
|
22
|
-
# via your cloud partner dashboard.
|
23
|
-
# For testing you can retrieve/generate an api.id and api.key from the API Sandbox directly
|
24
|
-
# on http://api-sandbox.maestrano.io
|
25
|
-
#
|
26
|
-
config.api.host = Settings[tenant][:api_host]
|
27
|
-
config.connec.host = Settings[tenant][:connec_host]
|
28
|
-
config.api.id = ENV[Settings[tenant][:api_id]]
|
29
|
-
config.api.key = ENV[Settings[tenant][:api_key]]
|
30
|
-
|
31
|
-
config.sso.x509_certificate = Settings[tenant][:x509_certificate]
|
32
|
-
config.sso.x509_fingerprint = Settings[tenant][:x509_fingerprint]
|
33
|
-
|
34
|
-
# => Synchronizations endpoints
|
35
|
-
config.app.synchronization_status_path = "/maestrano/#{tenant}/synchronizations/:cld-uid"
|
36
|
-
config.app.synchronization_toggle_path = "/maestrano/#{tenant}/synchronizations/toggle_sync"
|
37
|
-
config.app.synchronization_start_path = "/maestrano/#{tenant}/synchronizations"
|
38
|
-
|
39
|
-
# ==> Single Sign-On activation
|
40
|
-
# Enable/Disable single sign-on. When troubleshooting authentication issues
|
41
|
-
# you might want to disable SSO temporarily
|
42
|
-
#
|
43
|
-
# config.sso.enabled = true
|
44
|
-
|
45
|
-
# ==> Single Sign-On Identity Manager
|
46
|
-
# By default we consider that the domain managing user identification
|
47
|
-
# is the same as your application host (see above config.app.host parameter)
|
48
|
-
# If you have a dedicated domain managing user identification and therefore
|
49
|
-
# responsible for the single sign-on handshake (e.g: https://idp.my-app.com)
|
50
|
-
# then you can specify it below
|
51
|
-
#
|
52
|
-
# config.sso.idm = (config.environment == 'production' ? 'https://idp.my-app.com' : 'http://localhost:3000')
|
53
|
-
|
54
|
-
# ==> SSO Initialization endpoint
|
55
|
-
# This is your application path to the SAML endpoint that allows users to
|
56
|
-
# initialize SSO authentication. Upon reaching this endpoint users your
|
57
|
-
# application will automatically create a SAML request and redirect the user
|
58
|
-
# to Maestrano. Maestrano will then authenticate and authorize the user. Upon
|
59
|
-
# authorization the user gets redirected to your application consumer endpoint
|
60
|
-
# (see below) for initial setup and/or login.
|
61
|
-
#
|
62
|
-
# The controller for this path is automatically
|
63
|
-
# generated when you run 'rake maestrano:install' and is available at
|
64
|
-
# <rails_root>/app/controllers/maestrano/auth/saml.rb
|
65
|
-
#
|
66
|
-
config.sso.init_path = Settings[tenant][:sso_init_path]
|
67
|
-
|
68
|
-
# ==> SSO Consumer endpoint
|
69
|
-
# This is your application path to the SAML endpoint that allows users to
|
70
|
-
# finalize SSO authentication. During the 'consume' action your application
|
71
|
-
# sets users (and associated group) up and/or log them in.
|
72
|
-
#
|
73
|
-
# The controller for this path is automatically
|
74
|
-
# generated when you run 'rake maestrano:install' and is available at
|
75
|
-
# <rails_root>/app/controllers/maestrano/auth/saml.rb
|
76
|
-
#
|
77
|
-
config.sso.consume_path = Settings[tenant][:sso_consume_path]
|
78
|
-
|
79
|
-
# ==> Single Logout activation
|
80
|
-
# Enable/Disable single logout. When troubleshooting authentication issues
|
81
|
-
# you might want to disable SLO temporarily.
|
82
|
-
# If set to false then Maestrano::SSO::Session#valid? - which should be
|
83
|
-
# used in a controller before filter to check user session - always return true
|
84
|
-
#
|
85
|
-
# config.sso.slo_enabled = true
|
86
|
-
|
87
|
-
# ==> SSO User creation mode
|
88
|
-
# !IMPORTANT
|
89
|
-
# On Maestrano users can take several "instances" of your service. You can consider
|
90
|
-
# each "instance" as 1) a billing entity and 2) a collaboration group (this is
|
91
|
-
# equivalent to a 'customer account' in a commercial world). When users login to
|
92
|
-
# your application via single sign-on they actually login via a specific group which
|
93
|
-
# is then supposed to determine which data they have access to inside your application.
|
94
|
-
#
|
95
|
-
# E.g: John and Jack are part of group 1. They should see the same data when they login to
|
96
|
-
# your application (employee info, analytics, sales etc..). John is also part of group 2
|
97
|
-
# but not Jack. Therefore only John should be able to see the data belonging to group 2.
|
98
|
-
#
|
99
|
-
# In most application this is done via collaboration/sharing/permission groups which is
|
100
|
-
# why a group is required to be created when a new user logs in via a new group (and
|
101
|
-
# also for billing purpose - you charge a group, not a user directly).
|
102
|
-
#
|
103
|
-
# == mode: 'real'
|
104
|
-
# In an ideal world a user should be able to belong to several groups in your application.
|
105
|
-
# In this case you would set the 'sso.creation_mode' to 'real' which means that the uid
|
106
|
-
# and email we pass to you are the actual user email and maestrano universal id.
|
107
|
-
#
|
108
|
-
# == mode: 'virtual'
|
109
|
-
# Now let's say that due to technical constraints your application cannot authorize a user
|
110
|
-
# to belong to several groups. Well next time John logs in via a different group there will
|
111
|
-
# be a problem: the user already exists (based on uid or email) and cannot be assigned
|
112
|
-
# to a second group. To fix this you can set the 'sso.creation_mode' to 'virtual'. In this
|
113
|
-
# mode users get assigned a truly unique uid and email across groups. So next time John logs
|
114
|
-
# in a whole new user account can be created for him without any validation problem. In this
|
115
|
-
# mode the email we assign to him looks like "usr-sdf54.cld-45aa2@mail.maestrano.com". But don't
|
116
|
-
# worry we take care of forwarding any email you would send to this address
|
117
|
-
#
|
118
|
-
# config.sso.creation_mode = 'real' # or 'virtual'
|
119
|
-
|
120
|
-
# ==> Account Webhooks
|
121
|
-
# Single sign on has been setup into your app and Maestrano users are now able
|
122
|
-
# to use your service. Great! Wait what happens when a business (group) decides to
|
123
|
-
# stop using your service? Also what happens when a user gets removed from a business?
|
124
|
-
# Well the endpoints below are for Maestrano to be able to notify you of such
|
125
|
-
# events.
|
126
|
-
#
|
127
|
-
# Even if the routes look restful we issue only issue DELETE requests for the moment
|
128
|
-
# to notify you of any service cancellation (group deletion) or any user being
|
129
|
-
# removed from a group.
|
130
|
-
#
|
131
|
-
# The controllers for these hooks path are automatically generated when
|
132
|
-
# you run 'rake maestrano:install' and is available under
|
133
|
-
# <rails_root>/app/controllers/maestrano/account/
|
134
|
-
#
|
135
|
-
config.webhook.account.groups_path = Settings[tenant][:webhook][:account][:groups_path]
|
136
|
-
config.webhook.account.group_users_path = Settings[tenant][:webhook][:account][:group_users_path]
|
137
|
-
|
138
|
-
config.webhook.connec.notifications_path = Settings[tenant][:webhook][:connec][:notifications_path]
|
139
|
-
config.webhook.connec.external_ids = true
|
140
|
-
#
|
141
|
-
# == Subscriptions
|
142
|
-
# This is the list of entities (organizations,people,invoices etc.) for which you want to be
|
143
|
-
# notified upon creation/update in Connec!
|
144
|
-
config.webhook.connec.subscriptions = {
|
145
|
-
accounts: false,
|
146
|
-
company: false,
|
147
|
-
employees: false,
|
148
|
-
events: false,
|
149
|
-
event_orders: false,
|
150
|
-
invoices: false,
|
151
|
-
items: false,
|
152
|
-
journals: false,
|
153
|
-
opportunities: false,
|
154
|
-
organizations: false,
|
155
|
-
payments: false,
|
156
|
-
pay_items: false,
|
157
|
-
pay_schedules: false,
|
158
|
-
pay_stubs: false,
|
159
|
-
pay_runs: false,
|
160
|
-
people: false,
|
161
|
-
projects: false,
|
162
|
-
purchase_orders: false,
|
163
|
-
quotes: false,
|
164
|
-
sales_orders: false,
|
165
|
-
tax_codes: false,
|
166
|
-
tax_rates: false,
|
167
|
-
time_activities: false,
|
168
|
-
time_sheets: false,
|
169
|
-
venues: false,
|
170
|
-
warehouses: false,
|
171
|
-
work_locations: false
|
172
|
-
}
|
173
|
-
end
|
174
|
-
end
|
1
|
+
Maestrano.auto_configure unless Rails.env.test?
|
2
|
+
Maestrano.configure { |config| config.environment = 'test' } if Rails.env.test?
|
@@ -33,22 +33,22 @@ if yes?('Use JRuby? [y/n]')
|
|
33
33
|
run 'echo "ruby \'2.2.3\', :engine => \'jruby\', :engine_version => \'9.0.5.0\'" | cat - Gemfile > temp && mv temp Gemfile'
|
34
34
|
end
|
35
35
|
|
36
|
-
gem 'rails', '~> 4.2
|
36
|
+
gem 'rails', '~> 4.2'
|
37
37
|
gem 'turbolinks', '~> 2.5'
|
38
38
|
gem 'jquery-rails'
|
39
|
-
gem 'puma'
|
39
|
+
gem 'puma', require: false
|
40
40
|
gem 'tzinfo-data', platforms: [:mingw, :mswin, :jruby]
|
41
41
|
gem 'uglifier', '>= 1.3.0'
|
42
42
|
|
43
43
|
gem 'maestrano-connector-rails'
|
44
44
|
|
45
|
-
|
46
|
-
gem 'activerecord-
|
47
|
-
gem '
|
45
|
+
group :production, :uat do
|
46
|
+
gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
|
47
|
+
gem 'mysql2', platforms: :ruby
|
48
48
|
gem 'rails_12factor'
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
group :test, :develpment do
|
52
52
|
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
53
53
|
gem 'sqlite3', platforms: :ruby
|
54
54
|
gem 'rubocop'
|
@@ -101,6 +101,7 @@ after_bundle do
|
|
101
101
|
copy_file 'settings/settings.yml', 'config/settings.yml'
|
102
102
|
|
103
103
|
copy_file 'application-sample.yml', 'config/application-sample.yml'
|
104
|
+
copy_file 'application-sample.yml', 'config/application.yml'
|
104
105
|
|
105
106
|
application do
|
106
107
|
<<-RUBY
|
@@ -117,6 +118,10 @@ after_bundle do
|
|
117
118
|
run 'bundle exec rake railties:install:migrations'
|
118
119
|
run 'bundle exec rake db:migrate'
|
119
120
|
|
121
|
+
run 'bundler binstubs puma --force'
|
122
|
+
run 'bundler binstubs sidekiq --force'
|
123
|
+
run 'bundler binstubs rake --force'
|
124
|
+
|
120
125
|
remove_file 'config/initializers/maestrano.rb'
|
121
126
|
copy_file 'maestrano.rb', 'config/initializers/maestrano.rb'
|
122
127
|
|
data/template/routes.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
mount Maestrano::Connector::Rails::Engine, at: '/'
|
3
|
-
mount Sidekiq::Web => '/sidekiq'
|
4
3
|
|
4
|
+
# Default Connector pages
|
5
5
|
root 'home#index'
|
6
6
|
get 'home/index' => 'home#index'
|
7
7
|
get 'home/redirect_to_external' => 'home#redirect_to_external'
|
8
8
|
get 'home/index' => 'home#index'
|
9
9
|
put 'home/update' => 'home#update'
|
10
10
|
post 'home/synchronize' => 'home#synchronize'
|
11
|
-
|
12
11
|
get 'synchronizations/index' => 'synchronizations#index'
|
13
12
|
get 'shared_entities/index' => 'shared_entities#index'
|
13
|
+
|
14
|
+
# OAuth workflow pages
|
15
|
+
match 'auth/:provider/request', to: 'oauth#create_omniauth', via: [:get, :post]
|
16
|
+
match 'signout_omniauth', to: 'oauth#destroy_omniauth', as: 'signout_omniauth', via: [:get, :post]
|
17
|
+
post 'auth/auth', to: 'auth#auth'
|
18
|
+
|
19
|
+
# Sidekiq Admin
|
20
|
+
require 'sidekiq/web'
|
21
|
+
Sidekiq::Web.use Rack::Auth::Basic do |username, password|
|
22
|
+
username == ENV['SIDEKIQ_USERNAME'] && password == ENV['SIDEKIQ_PASSWORD']
|
23
|
+
end
|
24
|
+
mount Sidekiq::Web => '/sidekiq'
|
14
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maestrano-connector-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.pre.
|
4
|
+
version: 2.0.0.pre.RC12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maestrano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -350,16 +350,16 @@ dependencies:
|
|
350
350
|
name: rubocop
|
351
351
|
requirement: !ruby/object:Gem::Requirement
|
352
352
|
requirements:
|
353
|
-
- - "
|
353
|
+
- - "~>"
|
354
354
|
- !ruby/object:Gem::Version
|
355
|
-
version: '0'
|
355
|
+
version: '0.43'
|
356
356
|
type: :development
|
357
357
|
prerelease: false
|
358
358
|
version_requirements: !ruby/object:Gem::Requirement
|
359
359
|
requirements:
|
360
|
-
- - "
|
360
|
+
- - "~>"
|
361
361
|
- !ruby/object:Gem::Version
|
362
|
-
version: '0'
|
362
|
+
version: '0.43'
|
363
363
|
- !ruby/object:Gem::Dependency
|
364
364
|
name: timecop
|
365
365
|
requirement: !ruby/object:Gem::Requirement
|
@@ -457,6 +457,7 @@ files:
|
|
457
457
|
- db/migrate/20160614114401_add_date_filtering_limit_to_organization.rb
|
458
458
|
- db/migrate/20160614160654_add_encryption_on_oauth_keys.rb
|
459
459
|
- db/migrate/20161011005751_add_unique_index_on_organization_oauth_uid.rb
|
460
|
+
- db/migrate/20161018155513_add_org_uid_to_organization.rb
|
460
461
|
- lib/generators/connector/USAGE
|
461
462
|
- lib/generators/connector/complex_entity_generator.rb
|
462
463
|
- lib/generators/connector/install_generator.rb
|
@@ -578,7 +579,6 @@ files:
|
|
578
579
|
- template/Procfile
|
579
580
|
- template/application-sample.yml
|
580
581
|
- template/database.yml
|
581
|
-
- template/factories.rb
|
582
582
|
- template/gitignore
|
583
583
|
- template/maestrano.rb
|
584
584
|
- template/maestrano_connector_template.rb
|
data/template/factories.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
FactoryGirl.define do
|
2
|
-
factory :organization, class: Maestrano::Connector::Rails::Organization do
|
3
|
-
name 'My company'
|
4
|
-
tenant 'default'
|
5
|
-
sequence(:uid) { |n| "cld-11#{n}" }
|
6
|
-
oauth_uid 'sfuiy765'
|
7
|
-
oauth_provider 'this_app'
|
8
|
-
end
|
9
|
-
|
10
|
-
factory :idmap, class: Maestrano::Connector::Rails::IdMap do
|
11
|
-
connec_entity 'person'
|
12
|
-
external_id '4567ada66'
|
13
|
-
external_entity 'contact'
|
14
|
-
last_push_to_external 2.days.ago
|
15
|
-
last_push_to_connec 1.day.ago
|
16
|
-
association :organization
|
17
|
-
end
|
18
|
-
|
19
|
-
factory :synchronization, class: Maestrano::Connector::Rails::Synchronization do
|
20
|
-
association :organization
|
21
|
-
status 'SUCCESS'
|
22
|
-
partial false
|
23
|
-
end
|
24
|
-
end
|