maestrano-connector-rails 2.0.0.pre.RC8 → 2.0.0.pre.RC9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +209 -0
- data/Rakefile +7 -3
- data/VERSION +1 -1
- data/app/controllers/maestrano/account/group_users_controller.rb +2 -0
- data/app/controllers/maestrano/account/groups_controller.rb +2 -0
- data/app/controllers/maestrano/auth/saml_controller.rb +3 -0
- data/app/controllers/maestrano/connec_controller.rb +41 -28
- data/app/controllers/version_controller.rb +1 -1
- data/app/jobs/maestrano/connector/rails/push_to_connec_job.rb +1 -1
- data/app/models/maestrano/connector/rails/concerns/connector_logger.rb +1 -1
- data/app/models/maestrano/connector/rails/concerns/entity.rb +4 -4
- data/app/models/maestrano/connector/rails/organization.rb +7 -5
- data/db/migrate/20161011005751_add_unique_index_on_organization_oauth_uid.rb +5 -0
- data/lib/generators/connector/templates/home_controller.rb +9 -5
- data/{spec → lib/maestrano_connector_rails}/factories.rb +4 -4
- data/maestrano-connector-rails.gemspec +8 -6
- data/spec/controllers/connec_controller_spec.rb +9 -10
- data/spec/controllers/version_controller_spec.rb +2 -2
- data/spec/models/organization_spec.rb +9 -3
- data/spec/spec_helper.rb +1 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4034931c4f557a653f429fe27c03144246429d3
|
4
|
+
data.tar.gz: 8ac0745b563b712d1858bc4a0ea952d033a08a09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c2c00231f6c47fd978dce08bb9750118314497f386d5c9c99b5d34c4e927bd92bf66e6416fbcbb2e8a41d7425a2d599e7aafdb4e095c48280438552c7ed0e2a
|
7
|
+
data.tar.gz: f3cfec868108174a4de89d53803987d1e8058f8561c4eb0bff59cb46685e36dfa852ae0def32e58fbedbcc334e72ed4c20a2acedf34ca1464c769bbfa9433681
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
## 1.5.0
|
2
|
+
|
3
|
+
### Breaking changes
|
4
|
+
* `Maestrano::Connector::Rails::SynchronizationJob.perform` now takes an `organization.id` as parameter.
|
5
|
+
|
6
|
+
## 1.4.0
|
7
|
+
|
8
|
+
### Breaking changes
|
9
|
+
* `map_to`, `map_to_connec` and `map_to_external` method have changed and now take two arguments.
|
10
|
+
Additionally you should be able to remove all overloading to those methods using the new argument in hash mapper. See [documentation](https://maestrano.atlassian.net/wiki/display/DEV/Mapping+and+synchronization#Mappingandsynchronization-FAQ) for more details
|
11
|
+
|
12
|
+
### Features
|
13
|
+
* Possibility to use an extended mapper for creation only
|
14
|
+
* Possibility to pass additional arguments to hash mapper to use in the after/before hooks
|
15
|
+
|
16
|
+
## 1.3.5
|
17
|
+
|
18
|
+
### Features
|
19
|
+
* Improve generated files
|
20
|
+
* Adds a built-in way to handle error when updating a deleted record
|
21
|
+
|
22
|
+
### Fixes
|
23
|
+
* Adds safety against potential infinite loop
|
24
|
+
|
25
|
+
## 1.3.4
|
26
|
+
`maestrano.rb` file should be updated with new synchronization paths.
|
27
|
+
|
28
|
+
### Features
|
29
|
+
* `connec_version_lt?` method
|
30
|
+
|
31
|
+
### Fixes
|
32
|
+
* Fixes multi-tenancy of synchronization endpoints
|
33
|
+
* Fixes display of singleton entity
|
34
|
+
|
35
|
+
## 1.3.3
|
36
|
+
|
37
|
+
### Fixes
|
38
|
+
* Fixes `connec_version` method
|
39
|
+
|
40
|
+
## 1.3.2
|
41
|
+
|
42
|
+
### Features
|
43
|
+
* Improve display of entity names on the home page. You'll need to change your home view and controller as well as add some things in the layout and javascript files
|
44
|
+
|
45
|
+
## 1.3.1
|
46
|
+
|
47
|
+
### Fixes
|
48
|
+
* Fix method in organization class that caused issue with authentication
|
49
|
+
|
50
|
+
## 1.3.0
|
51
|
+
* Methods `create_external_entity` and `update_external_entity` should now returns the created/updated entity
|
52
|
+
* Home page should now include a link populated from `external.rb` to create an account
|
53
|
+
|
54
|
+
### Features
|
55
|
+
* Add support for references to Connec! sub entities' ids
|
56
|
+
* Add support for support for sub_entities having the same name
|
57
|
+
* Re-introduct `can_update_connec?` method
|
58
|
+
* Add method for a `create an account` link
|
59
|
+
|
60
|
+
### Fixes
|
61
|
+
* Fix error format on the synchronizations endpoint
|
62
|
+
|
63
|
+
## 1.2.3
|
64
|
+
|
65
|
+
### Fixes
|
66
|
+
* Fix Connec! version that was not cached scoped by tenant
|
67
|
+
|
68
|
+
## 1.2.2
|
69
|
+
|
70
|
+
### Fixes
|
71
|
+
* Fix PushToConnecWork to take an organization_id insteand of an organization object
|
72
|
+
|
73
|
+
### Features
|
74
|
+
* Add a version endpoint with the framework version
|
75
|
+
|
76
|
+
### Improvments
|
77
|
+
* Add rubocop in the framework for better code quality
|
78
|
+
* Improve framework dependancies handling and update template accordingly
|
79
|
+
|
80
|
+
## 1.2.1
|
81
|
+
|
82
|
+
### Features
|
83
|
+
* Add PushToConnecWorker that give the possibilty to do jobs sequentially for a given organization and entity
|
84
|
+
|
85
|
+
## 1.2.0
|
86
|
+
/!\ For this version to work, you'll need to add `< Maestrano::Connector::Rails::EntityBase` to your `entity.rb` class
|
87
|
+
|
88
|
+
### Features
|
89
|
+
* Custom synchronization process for first sync. (For this feature to work, you'll need to implement handling of additionnal options in your `get_external_entities` method. The connector will still work as before if you don't).
|
90
|
+
* Administrations endpoints to get the synchronizations status, start a synchronization, toggle `sync_enabled` and get the connector dependancies (depenancies are declared in ConnecHelper. You'll need to overload the dependancies method if you have specific dependancies)
|
91
|
+
|
92
|
+
### Improvments
|
93
|
+
* Entity and ComplexEntity now inherits from EntityBase
|
94
|
+
|
95
|
+
## 1.1.2
|
96
|
+
/!\ This version need a migration (`bundle exec rake railties:install:migrations; bundle exec rake db:migrate`). It also requires the running of a manual script to encrypt existing oauth_keys
|
97
|
+
You'll also need to change some methods as the framework is not sending the `last_synchronization` anymore but directly the `last_synchronization_date` (`get_external_entities`, `before_sync`, `after_sync`)
|
98
|
+
|
99
|
+
### Features
|
100
|
+
* Encryption of oauth keys (you'll need to add `gem 'attr_encrypted', '~> 1.4.0'` to your Gemfile)
|
101
|
+
* No historical data option: only data created after the link to the connector will be sync. For this option to be available, you'll need to implement a `creation_date_from_external_entity_hash` method. It also requires a front end update (view, controller, js)
|
102
|
+
|
103
|
+
### Fixes
|
104
|
+
* Fix synchronization cleaning
|
105
|
+
* Minor fixes
|
106
|
+
|
107
|
+
## 1.0.4
|
108
|
+
|
109
|
+
### Fixes
|
110
|
+
* Fix uneeded creation of idmap for Connec! entities following a failure
|
111
|
+
* Fix Connec! pagination
|
112
|
+
|
113
|
+
## 1.0.3
|
114
|
+
|
115
|
+
### Fixes
|
116
|
+
* Fix an issue with options that were involuntarily shared across entities
|
117
|
+
|
118
|
+
## 1.0.2
|
119
|
+
|
120
|
+
### Fixes
|
121
|
+
* Fix an issue with integer ids
|
122
|
+
|
123
|
+
## 1.0.1
|
124
|
+
|
125
|
+
### Fixes
|
126
|
+
* Fix an issue with singleton entities
|
127
|
+
|
128
|
+
## 1.0.0
|
129
|
+
|
130
|
+
### Features
|
131
|
+
* Reference in mapping greatly simplified. See the documentation for an explanation and example: [here](https://maestrano.atlassian.net/wiki/display/DEV/Mapping+and+synchronization#Mappingandsynchronization-References).
|
132
|
+
* Smart merging available. You can specifiy field on which Connec! will attempt to merge the record with an existing one. See the framework [documentation](https://maestrano.atlassian.net/wiki/display/DEV/Examples#Examples-Smartmerging) for an example, as well as the Connec! [documentation](http://maestrano.github.io/connec/#api-|-save-data-resource-creation-post)
|
133
|
+
|
134
|
+
### Breaking changes
|
135
|
+
A major refactoring as lead to some breaking changes:
|
136
|
+
* `Entity` and `ComplexEntity` `initialize` method now take 3-4 argument instead of 0: `organization`, `connec_client`, `external_client` and `opts`
|
137
|
+
* All the **instance** methods of those classes that previously took one of these arguments have been change to not include them anymore. Full list:
|
138
|
+
|
139
|
+
**ComplexEntity & Entity:**
|
140
|
+
**`connec_model_to_external_model`**
|
141
|
+
**`external_model_to_connec_model`**
|
142
|
+
`get_connec_entities`
|
143
|
+
**`get_external_entities`**
|
144
|
+
`consolidate_and_map_data`
|
145
|
+
`push_entities_to_connec`
|
146
|
+
`push_entities_to_external`
|
147
|
+
**`before_sync`**
|
148
|
+
**`after_sync`**
|
149
|
+
**`filter_connec_entities`**
|
150
|
+
|
151
|
+
|
152
|
+
**Entity:**
|
153
|
+
**`map_to_external`**
|
154
|
+
**`map_to_connec`**
|
155
|
+
`push_entities_to_connec_to`
|
156
|
+
`batch_op`
|
157
|
+
`push_entities_to_external_to`
|
158
|
+
`push_entity_to_external`
|
159
|
+
**`create_external_entity`**
|
160
|
+
**`update_external_entity`**
|
161
|
+
`consolidate_and_map_singleton`
|
162
|
+
`map_external_entity_with_idmap`
|
163
|
+
|
164
|
+
**SubEntityBase:**
|
165
|
+
**`map_to`**
|
166
|
+
|
167
|
+
* The class method `entities_list` has been moved from `Entity` to `External`
|
168
|
+
* The `references` method has been changed with the new reference system. The framework now expect it to be an array os strings instead of an array of hashes. Furthermore, it now supports reference fields embedded in hashes and arrays.
|
169
|
+
* The following method from `Entity` as been changed from class methods to instance methods (and their arguments have been changed):
|
170
|
+
`not_modified_since_last_push_to_connec?`
|
171
|
+
`is_external_more_recent?`
|
172
|
+
`solve_conflict`
|
173
|
+
* Organization.uid is now enforced as an uniq attributes
|
174
|
+
|
175
|
+
* The following methods have been removed
|
176
|
+
`map_to_external_with_idmap`
|
177
|
+
`create_idmap_from_external_entity`
|
178
|
+
`create_idmap_from_connec_entity`
|
179
|
+
`can_update_connec?`
|
180
|
+
`id_from_ref`
|
181
|
+
|
182
|
+
|
183
|
+
- - - -
|
184
|
+
- - - -
|
185
|
+
|
186
|
+
## 0.4.4
|
187
|
+
|
188
|
+
### Features
|
189
|
+
* Add filter_connec_entities method to allow filtering in webhook workflow
|
190
|
+
|
191
|
+
### Fixes
|
192
|
+
* Truncate idmap message to avoid database errors
|
193
|
+
|
194
|
+
## 0.4.3
|
195
|
+
|
196
|
+
### Fixes
|
197
|
+
* Add `forced` option in home_controller when requesting a manual synchronization.
|
198
|
+
|
199
|
+
|
200
|
+
## 0.4.2
|
201
|
+
/!\ This release contains a new migration that you'll need to fetch and run
|
202
|
+
|
203
|
+
### Features
|
204
|
+
* Add call to before and after_sync methods during synchronization workflows
|
205
|
+
* Add logic for record flagged as inactive in the external application
|
206
|
+
|
207
|
+
### Fixes
|
208
|
+
* Fix recovery mode: recovery mode was previously on as soon as the organization had three failed synchronizations, even if a synchronization had succeed afterward. Moreover, recovery mode doesn't prevent manual synchronization anymore.
|
209
|
+
* Fix a typo in saml controller that prevented deletion of a session param.
|
data/Rakefile
CHANGED
@@ -18,13 +18,17 @@ Jeweler::Tasks.new do |gem|
|
|
18
18
|
gem.homepage = 'http://github.com/maestrano/maestrano-connector-rails'
|
19
19
|
gem.license = 'MIT'
|
20
20
|
gem.summary = 'Rails framework to build connector with Maestrano'
|
21
|
-
gem.description = 'Maestrano is the next generation marketplace for SME applications. See https://maestrano.com for details.'
|
21
|
+
gem.description = 'Maestrano is the next generation marketplace for SME applications. See https://sme.maestrano.com for details.'
|
22
22
|
gem.email = 'developers@maestrano.com'
|
23
|
-
gem.authors = ['Maestrano'
|
23
|
+
gem.authors = ['Maestrano']
|
24
24
|
# dependencies defined in Gemfile
|
25
25
|
end
|
26
26
|
Jeweler::RubygemsDotOrgTasks.new
|
27
27
|
|
28
|
+
# Rubocop
|
29
|
+
require 'rubocop/rake_task'
|
30
|
+
RuboCop::RakeTask.new
|
31
|
+
|
28
32
|
APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
|
29
33
|
load 'rails/tasks/engine.rake'
|
30
34
|
|
@@ -34,4 +38,4 @@ require 'rspec/core/rake_task'
|
|
34
38
|
desc 'Run all specs in spec directory (excluding plugin specs)'
|
35
39
|
RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
|
36
40
|
|
37
|
-
task default: :spec
|
41
|
+
task default: [:spec, :rubocop]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.0.pre.
|
1
|
+
2.0.0.pre.RC9
|
@@ -10,6 +10,8 @@ class Maestrano::Account::GroupUsersController < Maestrano::Rails::WebHookContro
|
|
10
10
|
user = Maestrano::Connector::Rails::User.find_by_uid_and_tenant(user_uid, params[:tenant] || 'default')
|
11
11
|
organization = Maestrano::Connector::Rails::Organization.find_by_uid_and_tenant(group_uid, params[:tenant] || 'default')
|
12
12
|
|
13
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "remove user from group, user_uid=\"#{user_uid}\", group_uid=\"#{group_uid}\"")
|
14
|
+
|
13
15
|
# Remove the user from the organization
|
14
16
|
organization.remove_member(user)
|
15
17
|
|
@@ -8,6 +8,8 @@ class Maestrano::Account::GroupsController < Maestrano::Rails::WebHookController
|
|
8
8
|
# Get entity
|
9
9
|
organization = Maestrano::Connector::Rails::Organization.find_by_uid_and_tenant(org_uid, params[:tenant] || 'default')
|
10
10
|
|
11
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, 'delete organization')
|
12
|
+
|
11
13
|
# Delete all relations
|
12
14
|
organization.user_organization_rels.delete_all
|
13
15
|
|
@@ -12,6 +12,9 @@ class Maestrano::Auth::SamlController < Maestrano::Rails::SamlBaseController
|
|
12
12
|
params[:tenant] ||= 'default'
|
13
13
|
user = Maestrano::Connector::Rails::User.find_or_create_for_maestrano(user_auth_hash, params[:tenant])
|
14
14
|
organization = Maestrano::Connector::Rails::Organization.find_or_create_for_maestrano(group_auth_hash, params[:tenant])
|
15
|
+
|
16
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "user authentication, user_uid=\"#{user.uid}\"")
|
17
|
+
|
15
18
|
if user && organization
|
16
19
|
organization.add_member(user) unless organization.member?(user)
|
17
20
|
|
@@ -1,43 +1,56 @@
|
|
1
1
|
class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
2
2
|
def notifications
|
3
|
-
Rails.logger.debug "Received notification from Connec!: #{params}"
|
4
|
-
|
5
3
|
begin
|
6
4
|
params.except(:tenant, :controller, :action, :connec).each do |entity_name, entities|
|
7
5
|
entity_class_hash = find_entity_class(entity_name)
|
8
|
-
next Rails.
|
6
|
+
next Maestrano::Connector::Rails::ConnectorLogger.log('info', nil, "Received notification from Connec! for unknow entity: #{entity_name}") unless entity_class_hash
|
9
7
|
|
10
8
|
entities.each do |entity|
|
11
9
|
organization = Maestrano::Connector::Rails::Organization.find_by_uid_and_tenant(entity[:group_id], params[:tenant])
|
12
|
-
next Rails.logger.warn "Received notification from Connec! for unknown group or group without oauth: #{entity['group_id']} (tenant: #{params[:tenant]})" unless organization&.oauth_uid
|
13
|
-
next unless organization.sync_enabled && organization.synchronized_entities[entity_class_hash[:name].to_sym]
|
14
|
-
|
15
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received entity from Connec! webhook: Entity=#{entity_name}, Data=#{entity}")
|
16
|
-
connec_client = Maestrano::Connector::Rails::ConnecHelper.get_client(organization)
|
17
|
-
external_client = Maestrano::Connector::Rails::External.get_client(organization)
|
18
|
-
last_synchronization_date = organization.last_synchronization_date
|
19
|
-
|
20
|
-
entity_instance = entity_class_hash[:class].new(organization, connec_client, external_client, {})
|
21
|
-
entity_instance.before_sync(last_synchronization_date)
|
22
|
-
|
23
|
-
# Build expected input for consolidate_and_map_data
|
24
|
-
if entity_class_hash[:is_complex]
|
25
|
-
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])
|
26
|
-
filtered_entities = entity_instance.filter_connec_entities(connec_hash_of_entities)
|
27
|
-
|
28
|
-
empty_external_hash = Maestrano::Connector::Rails::ComplexEntity.build_empty_hash(entity_instance.class.external_entities_names)
|
29
|
-
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, empty_external_hash)
|
30
|
-
else
|
31
|
-
filtered_entities = entity_instance.filter_connec_entities([entity])
|
32
|
-
mapped_entity = entity_instance.consolidate_and_map_data(filtered_entities, [])
|
33
|
-
end
|
34
|
-
entity_instance.push_entities_to_external(mapped_entity[:connec_entities])
|
35
10
|
|
36
|
-
|
11
|
+
begin
|
12
|
+
if organization.nil?
|
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
|
+
|
24
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Processing entity from Connec! webhook, entity_name=\"#{entity_name}\", data=\"#{entity}\"")
|
25
|
+
|
26
|
+
connec_client = Maestrano::Connector::Rails::ConnecHelper.get_client(organization)
|
27
|
+
external_client = Maestrano::Connector::Rails::External.get_client(organization)
|
28
|
+
last_synchronization_date = organization.last_synchronization_date
|
29
|
+
|
30
|
+
entity_instance = entity_class_hash[:class].new(organization, connec_client, external_client, {})
|
31
|
+
entity_instance.before_sync(last_synchronization_date)
|
32
|
+
|
33
|
+
# Build expected input for consolidate_and_map_data
|
34
|
+
if entity_class_hash[:is_complex]
|
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])
|
45
|
+
|
46
|
+
entity_instance.after_sync(last_synchronization_date)
|
47
|
+
rescue => e
|
48
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('warn', organization, "error processing notification entity_name=\"#{entity_name}\", message=\"#{e.message}\", #{e.backtrace.join("\n")}")
|
49
|
+
end
|
37
50
|
end
|
38
51
|
end
|
39
52
|
rescue => e
|
40
|
-
Rails.
|
53
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('warn', nil, "error processing notification #{e.message} - #{e.backtrace.join("\n")}")
|
41
54
|
end
|
42
55
|
|
43
56
|
head 200, content_type: 'application/json'
|
@@ -3,7 +3,7 @@ class VersionController < ApplicationController
|
|
3
3
|
framework_version = Gem.loaded_specs['maestrano-connector-rails'].version.version
|
4
4
|
respond_to do |format|
|
5
5
|
format.html { render text: "framework_version=#{framework_version}\n" }
|
6
|
-
format.json { render json: {framework_version: framework_version} }
|
6
|
+
format.json { render json: {framework_version: framework_version, env: Rails.env} }
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -27,7 +27,7 @@ module Maestrano::Connector::Rails
|
|
27
27
|
|
28
28
|
entity_instance.after_sync(last_synchronization_date)
|
29
29
|
else
|
30
|
-
Rails.
|
30
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('warn', organization, "Called push to connec job with unknow entity: #{external_entity_name}")
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -3,7 +3,7 @@ module Maestrano::Connector::Rails::Concerns::ConnectorLogger
|
|
3
3
|
|
4
4
|
module ClassMethods
|
5
5
|
def log(level, organization, msg)
|
6
|
-
Rails.logger.method(level).call("
|
6
|
+
Rails.logger.method(level).call("organization_uid=\"#{organization&.uid}\", tenant=\"#{organization&.tenant}\"), message=\"#{msg}\"")
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -237,7 +237,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
237
237
|
next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{self.class.normalized_connec_entity_name}/, self.class.normalized_connec_entity_name)
|
238
238
|
|
239
239
|
response_hash = fetch_connec(next_page, page_number)
|
240
|
-
entities
|
240
|
+
entities.concat response_hash[self.class.normalized_connec_entity_name]
|
241
241
|
end
|
242
242
|
end
|
243
243
|
|
@@ -367,7 +367,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
367
367
|
# TODO: improve the flexibility by adding the option for the developer to pass a custom/gem-dependent error
|
368
368
|
if e.class == Maestrano::Connector::Rails::Exceptions::EntityNotFoundError
|
369
369
|
idmap.update!(message: "The #{external_entity_name} record has been deleted in #{Maestrano::Connector::Rails::External.external_name}. Last attempt to sync on #{Time.now}", external_inactive: true)
|
370
|
-
Rails.
|
370
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', @organization, "The #{idmap.external_entity} - #{idmap.external_id} record has been deleted. It is now set to inactive.")
|
371
371
|
else
|
372
372
|
# Store External error
|
373
373
|
Maestrano::Connector::Rails::ConnectorLogger.log('error', @organization, "Error while pushing to #{Maestrano::Connector::Rails::External.external_name}: #{e}")
|
@@ -541,7 +541,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
541
541
|
elsif result['status'] == 201
|
542
542
|
batch_entities[index][:idmap].update(connec_id: result['body'][self.class.normalize_connec_entity_name(connec_entity_name)]['id'].find { |id| id['provider'] == 'connec' }['id'], last_push_to_connec: Time.now, message: nil)
|
543
543
|
else
|
544
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('
|
544
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('warn', @organization, "Error while pushing to Connec!: #{result['body']}")
|
545
545
|
# TODO, better error message
|
546
546
|
batch_entities[index][:idmap].update(message: result['body'].to_s.truncate(255))
|
547
547
|
end
|
@@ -571,7 +571,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
571
571
|
connec_entity['updated_at'] > self.class.last_update_date_from_external_entity_hash(external_entity)
|
572
572
|
end
|
573
573
|
|
574
|
-
# This methods try to find a external entity among all the external entities matching the connec one (same id)
|
574
|
+
# This methods try to find a external entity among all the external entities matching the connec (mapped) one (same id)
|
575
575
|
# If it does not find any, there is no conflict, and it returns the mapped connec entity
|
576
576
|
# If it finds one, the conflict is solved either with options or using the entities timestamps
|
577
577
|
# If the connec entity is kept, it is returned mapped and the matching external entity is discarded (deleted from the array)
|
@@ -38,6 +38,7 @@ module Maestrano::Connector::Rails
|
|
38
38
|
validates :name, presence: true
|
39
39
|
validates :tenant, presence: true
|
40
40
|
validates :uid, uniqueness: {scope: :tenant}
|
41
|
+
validates :oauth_uid, uniqueness: {message: 'This account has already been linked'}
|
41
42
|
|
42
43
|
#===================================
|
43
44
|
# Serialized field
|
@@ -75,7 +76,7 @@ module Maestrano::Connector::Rails
|
|
75
76
|
self.oauth_token = auth.credentials.token
|
76
77
|
self.refresh_token = auth.credentials.refresh_token
|
77
78
|
self.instance_url = auth.credentials.instance_url
|
78
|
-
save
|
79
|
+
self.save
|
79
80
|
end
|
80
81
|
|
81
82
|
def clear_omniauth
|
@@ -86,16 +87,17 @@ module Maestrano::Connector::Rails
|
|
86
87
|
self.save
|
87
88
|
end
|
88
89
|
|
89
|
-
|
90
|
+
# Enable historical data sharing (prior to account linking)
|
91
|
+
def enable_historical_data(enabled)
|
92
|
+
# Historical data sharing cannot be unset
|
90
93
|
return if self.historical_data
|
91
|
-
|
92
|
-
if
|
94
|
+
|
95
|
+
if enabled
|
93
96
|
self.date_filtering_limit = nil
|
94
97
|
self.historical_data = true
|
95
98
|
else
|
96
99
|
self.date_filtering_limit ||= Time.now.getlocal
|
97
100
|
end
|
98
|
-
self.save
|
99
101
|
end
|
100
102
|
|
101
103
|
def last_three_synchronizations_failed?
|
@@ -7,16 +7,19 @@ class HomeController < ApplicationController
|
|
7
7
|
|
8
8
|
def update
|
9
9
|
organization = Maestrano::Connector::Rails::Organization.find_by_id(params[:id])
|
10
|
-
|
11
10
|
return redirect_to(:back) unless organization && is_admin?(current_user, organization)
|
12
|
-
|
11
|
+
|
12
|
+
# Update list of entities to synchronize
|
13
13
|
organization.synchronized_entities.keys.each do |entity|
|
14
14
|
organization.synchronized_entities[entity] = params[entity.to_s].present?
|
15
15
|
end
|
16
16
|
organization.sync_enabled = organization.synchronized_entities.values.any?
|
17
|
-
organization.
|
17
|
+
organization.enable_historical_data(params['historical-data'].present?)
|
18
|
+
trigger_sync = organization.sync_enabled && organization.sync_enabled_changed?
|
19
|
+
organization.save
|
18
20
|
|
19
|
-
|
21
|
+
# Trigger sync only if the sync has been enabled
|
22
|
+
start_synchronization(organization) if trigger_sync
|
20
23
|
|
21
24
|
redirect_to(:back)
|
22
25
|
end
|
@@ -28,13 +31,14 @@ class HomeController < ApplicationController
|
|
28
31
|
redirect_to(:back)
|
29
32
|
end
|
30
33
|
|
34
|
+
# Implement the redirection to the external application
|
31
35
|
def redirect_to_external
|
32
36
|
redirect_to 'https://path/to/external/app'
|
33
37
|
end
|
34
38
|
|
35
39
|
private
|
36
40
|
|
37
|
-
def start_synchronization(
|
41
|
+
def start_synchronization(organization)
|
38
42
|
Maestrano::Connector::Rails::SynchronizationJob.perform_later(organization.id, {})
|
39
43
|
flash[:info] = 'Congrats, you\'re all set up! Your data are now being synced'
|
40
44
|
end
|
@@ -7,8 +7,8 @@ FactoryGirl.define do
|
|
7
7
|
factory :organization, class: Maestrano::Connector::Rails::Organization do
|
8
8
|
name 'My company'
|
9
9
|
tenant 'default'
|
10
|
-
sequence(:uid) {
|
11
|
-
oauth_uid
|
10
|
+
sequence(:uid) { SecureRandom.uuid }
|
11
|
+
sequence(:oauth_uid) { |n| "realm_#{n}" }
|
12
12
|
oauth_provider 'this_app'
|
13
13
|
end
|
14
14
|
|
@@ -18,9 +18,9 @@ FactoryGirl.define do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
factory :idmap, class: Maestrano::Connector::Rails::IdMap do
|
21
|
-
sequence(:connec_id) {
|
21
|
+
sequence(:connec_id) { SecureRandom.uuid }
|
22
22
|
connec_entity 'person'
|
23
|
-
sequence(:external_id) { |n| "#{n}
|
23
|
+
sequence(:external_id) { |n| "external_#{n}" }
|
24
24
|
external_entity 'contact'
|
25
25
|
last_push_to_external 2.days.ago
|
26
26
|
last_push_to_connec 1.day.ago
|
@@ -2,17 +2,17 @@
|
|
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.RC9 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.RC9"
|
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
|
-
s.authors = ["Maestrano"
|
14
|
-
s.date = "2016-10-
|
15
|
-
s.description = "Maestrano is the next generation marketplace for SME applications. See https://maestrano.com for details."
|
13
|
+
s.authors = ["Maestrano"]
|
14
|
+
s.date = "2016-10-12"
|
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"]
|
18
18
|
s.extra_rdoc_files = [
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
".rubocop.yml",
|
25
25
|
".rubocop_todo.yml",
|
26
26
|
".ruby-version",
|
27
|
+
"CHANGELOG.md",
|
27
28
|
"CODESHIP.md",
|
28
29
|
"DEVELOPER.md",
|
29
30
|
"Gemfile",
|
@@ -77,6 +78,7 @@ Gem::Specification.new do |s|
|
|
77
78
|
"db/migrate/20160427112250_add_inactive_to_idmaps.rb",
|
78
79
|
"db/migrate/20160614114401_add_date_filtering_limit_to_organization.rb",
|
79
80
|
"db/migrate/20160614160654_add_encryption_on_oauth_keys.rb",
|
81
|
+
"db/migrate/20161011005751_add_unique_index_on_organization_oauth_uid.rb",
|
80
82
|
"lib/generators/connector/USAGE",
|
81
83
|
"lib/generators/connector/complex_entity_generator.rb",
|
82
84
|
"lib/generators/connector/install_generator.rb",
|
@@ -109,6 +111,7 @@ Gem::Specification.new do |s|
|
|
109
111
|
"lib/generators/connector/templates/synchronizations_index.haml",
|
110
112
|
"lib/maestrano/connector/rails.rb",
|
111
113
|
"lib/maestrano_connector_rails.rb",
|
114
|
+
"lib/maestrano_connector_rails/factories.rb",
|
112
115
|
"maestrano-connector-rails.gemspec",
|
113
116
|
"maestrano.png",
|
114
117
|
"release_notes.md",
|
@@ -169,7 +172,6 @@ Gem::Specification.new do |s|
|
|
169
172
|
"spec/dummy/public/500.html",
|
170
173
|
"spec/dummy/public/favicon.ico",
|
171
174
|
"spec/dummy/tmp/cache/.gitkeep",
|
172
|
-
"spec/factories.rb",
|
173
175
|
"spec/integration/complex_id_references_spec.rb",
|
174
176
|
"spec/integration/complex_naming_spec.rb",
|
175
177
|
"spec/integration/complex_spec.rb",
|
@@ -33,9 +33,9 @@ describe Maestrano::ConnecController, type: :controller do
|
|
33
33
|
|
34
34
|
context 'with an unexpected error' do
|
35
35
|
let(:notifications) { {'people' => [entity]} }
|
36
|
-
it '
|
37
|
-
allow(controller).to receive(:find_entity_class).and_raise('
|
38
|
-
expect(Rails
|
36
|
+
it 'does nothing' do
|
37
|
+
allow(controller).to receive(:find_entity_class).and_raise('Unexpected error')
|
38
|
+
expect(Maestrano::Connector::Rails::External).to_not receive(:get_client)
|
39
39
|
subject
|
40
40
|
end
|
41
41
|
end
|
@@ -46,8 +46,8 @@ describe Maestrano::ConnecController, type: :controller do
|
|
46
46
|
allow(Maestrano::Connector::Rails::External).to receive(:entities_list).and_return(%w())
|
47
47
|
}
|
48
48
|
|
49
|
-
it '
|
50
|
-
expect(Rails
|
49
|
+
it 'does nothing' do
|
50
|
+
expect(Maestrano::Connector::Rails::External).to_not receive(:get_client)
|
51
51
|
subject
|
52
52
|
end
|
53
53
|
end
|
@@ -112,8 +112,8 @@ describe Maestrano::ConnecController, type: :controller do
|
|
112
112
|
|
113
113
|
context 'with an invalid organization' do
|
114
114
|
context 'with no organization' do
|
115
|
-
it '
|
116
|
-
expect(Rails
|
115
|
+
it 'does nothing' do
|
116
|
+
expect(Maestrano::Connector::Rails::External).to_not receive(:get_client)
|
117
117
|
subject
|
118
118
|
end
|
119
119
|
end
|
@@ -121,8 +121,8 @@ describe Maestrano::ConnecController, type: :controller do
|
|
121
121
|
context 'with an organization with no oauth' do
|
122
122
|
let!(:organization) { create(:organization, uid: group_id, oauth_uid: nil) }
|
123
123
|
|
124
|
-
it '
|
125
|
-
expect(Rails
|
124
|
+
it 'does nothing' do
|
125
|
+
expect(Maestrano::Connector::Rails::External).to_not receive(:get_client).with(organization)
|
126
126
|
subject
|
127
127
|
end
|
128
128
|
end
|
@@ -160,7 +160,6 @@ describe Maestrano::ConnecController, type: :controller do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
164
163
|
end
|
165
164
|
end
|
166
165
|
end
|
@@ -11,7 +11,7 @@ describe VersionController, type: :controller do
|
|
11
11
|
|
12
12
|
it 'returns a version hash' do
|
13
13
|
subject
|
14
|
-
expect(JSON.parse(response.body)).to eql({"framework_version"=>"1.2"})
|
14
|
+
expect(JSON.parse(response.body)).to eql({"framework_version"=>"1.2", "env" => "test"})
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
@@ -25,6 +25,12 @@ describe Maestrano::Connector::Rails::Organization do
|
|
25
25
|
expect(subject.synchronized_entities).to include(entities_list.first.to_sym)
|
26
26
|
expect(subject.synchronized_entities).to include(entities_list.last.to_sym)
|
27
27
|
end
|
28
|
+
|
29
|
+
it 'does not allow organizations with the same oauth UID' do
|
30
|
+
organization1 = create(:organization, oauth_provider: 'myapp', oauth_uid: 'ABC')
|
31
|
+
organization2 = build(:organization, oauth_provider: 'myapp', oauth_uid: 'ABC')
|
32
|
+
expect(organization2).not_to be_valid
|
33
|
+
end
|
28
34
|
end
|
29
35
|
|
30
36
|
describe "instance methods" do
|
@@ -129,7 +135,7 @@ describe Maestrano::Connector::Rails::Organization do
|
|
129
135
|
2.times do
|
130
136
|
subject.synchronizations.create(status: 'ERROR')
|
131
137
|
end
|
132
|
-
|
138
|
+
|
133
139
|
expect(subject.last_three_synchronizations_failed?).to be false
|
134
140
|
end
|
135
141
|
end
|
@@ -146,7 +152,7 @@ describe Maestrano::Connector::Rails::Organization do
|
|
146
152
|
|
147
153
|
describe 'last_synchronization_date' do
|
148
154
|
let(:date) { 2.days.ago }
|
149
|
-
|
155
|
+
|
150
156
|
context 'with date_filtering_limit' do
|
151
157
|
before {
|
152
158
|
subject.date_filtering_limit = date
|
@@ -179,4 +185,4 @@ describe Maestrano::Connector::Rails::Organization do
|
|
179
185
|
end
|
180
186
|
|
181
187
|
|
182
|
-
end
|
188
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,16 +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.RC9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maestrano
|
8
|
-
- Pierre Berard
|
9
|
-
- Marco Bagnasco
|
10
8
|
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-12 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
14
|
name: rails
|
@@ -391,7 +389,7 @@ dependencies:
|
|
391
389
|
- !ruby/object:Gem::Version
|
392
390
|
version: '0'
|
393
391
|
description: Maestrano is the next generation marketplace for SME applications. See
|
394
|
-
https://maestrano.com for details.
|
392
|
+
https://sme.maestrano.com for details.
|
395
393
|
email: developers@maestrano.com
|
396
394
|
executables:
|
397
395
|
- rails
|
@@ -404,6 +402,7 @@ files:
|
|
404
402
|
- ".rubocop.yml"
|
405
403
|
- ".rubocop_todo.yml"
|
406
404
|
- ".ruby-version"
|
405
|
+
- CHANGELOG.md
|
407
406
|
- CODESHIP.md
|
408
407
|
- DEVELOPER.md
|
409
408
|
- Gemfile
|
@@ -457,6 +456,7 @@ files:
|
|
457
456
|
- db/migrate/20160427112250_add_inactive_to_idmaps.rb
|
458
457
|
- db/migrate/20160614114401_add_date_filtering_limit_to_organization.rb
|
459
458
|
- db/migrate/20160614160654_add_encryption_on_oauth_keys.rb
|
459
|
+
- db/migrate/20161011005751_add_unique_index_on_organization_oauth_uid.rb
|
460
460
|
- lib/generators/connector/USAGE
|
461
461
|
- lib/generators/connector/complex_entity_generator.rb
|
462
462
|
- lib/generators/connector/install_generator.rb
|
@@ -489,6 +489,7 @@ files:
|
|
489
489
|
- lib/generators/connector/templates/synchronizations_index.haml
|
490
490
|
- lib/maestrano/connector/rails.rb
|
491
491
|
- lib/maestrano_connector_rails.rb
|
492
|
+
- lib/maestrano_connector_rails/factories.rb
|
492
493
|
- maestrano-connector-rails.gemspec
|
493
494
|
- maestrano.png
|
494
495
|
- release_notes.md
|
@@ -549,7 +550,6 @@ files:
|
|
549
550
|
- spec/dummy/public/500.html
|
550
551
|
- spec/dummy/public/favicon.ico
|
551
552
|
- spec/dummy/tmp/cache/.gitkeep
|
552
|
-
- spec/factories.rb
|
553
553
|
- spec/integration/complex_id_references_spec.rb
|
554
554
|
- spec/integration/complex_naming_spec.rb
|
555
555
|
- spec/integration/complex_spec.rb
|