maestrano-connector-rails 0.2.16 → 0.2.17
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 +3 -0
- data/Gemfile.lock +27 -0
- data/VERSION +1 -1
- data/app/helpers/maestrano/connector/rails/session_helper.rb +5 -1
- data/app/models/maestrano/connector/rails/complex_entity.rb +14 -33
- data/app/models/maestrano/connector/rails/concerns/entity.rb +161 -73
- data/app/models/maestrano/connector/rails/sub_entity_base.rb +44 -4
- data/lib/generators/connector/install_generator.rb +20 -24
- data/lib/generators/connector/templates/home_controller.rb +33 -10
- data/lib/generators/connector/templates/home_controller_spec.rb +141 -0
- data/lib/generators/connector/templates/home_index.haml +103 -0
- data/lib/generators/connector/templates/layouts.haml +45 -0
- data/lib/generators/connector/templates/oauth_controller.rb +3 -6
- data/lib/generators/connector/templates/shared_entities_controller.rb +7 -0
- data/lib/generators/connector/templates/shared_entities_controller_spec.rb +23 -0
- data/lib/generators/connector/templates/shared_entities_index.haml +41 -0
- data/lib/generators/connector/templates/stylesheets/application.sass +24 -0
- data/lib/generators/connector/templates/stylesheets/banners.sass +59 -0
- data/lib/generators/connector/templates/stylesheets/home.sass +25 -0
- data/lib/generators/connector/templates/stylesheets/layout.sass +125 -0
- data/lib/generators/connector/templates/stylesheets/spacers.sass +46 -0
- data/lib/generators/connector/templates/stylesheets/variables.sass +57 -0
- data/lib/generators/connector/templates/sychronizations_controller_spec.rb +22 -0
- data/lib/generators/connector/templates/synchronizations_controller.rb +7 -0
- data/lib/generators/connector/templates/synchronizations_index.haml +42 -0
- data/maestrano-connector-rails.gemspec +29 -6
- data/pkg/maestrano-connector-rails-0.2.16.gem +0 -0
- data/spec/models/complex_entity_spec.rb +46 -12
- data/spec/models/entity_spec.rb +212 -113
- data/spec/models/sub_entity_base_spec.rb +59 -0
- data/template/maestrano-connector-template.rb +4 -3
- data/template/routes.rb +14 -0
- metadata +61 -5
- data/lib/generators/connector/templates/admin_controller.rb +0 -58
- data/lib/generators/connector/templates/admin_index.html.erb +0 -55
- data/lib/generators/connector/templates/home_index.html.erb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb5c07cb2cd6e41eed0cf6d969bccfaca04bbfd7
|
4
|
+
data.tar.gz: 597eff9e10f8091d32df3efa8fe3d401686471b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8255bd1676f26950267b98125e88679f3d91d5d127e650fbcfe4bc7d72c55b4d3d5ef3742022b6e2cdd267d5cab9d0fa449ed4197817f94c8ee43400320c4a55
|
7
|
+
data.tar.gz: 897a96ac9045cb71828ade21e216586f34db7af9bbec6ea7d6c1dca7cdbcbf9666e44a4a5dcb8f1fdb74fcd2fa194fa6f8386125f49b8cc21c73fc4dc372a65c
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -38,6 +38,11 @@ GEM
|
|
38
38
|
tzinfo (~> 1.1)
|
39
39
|
addressable (2.4.0)
|
40
40
|
arel (6.0.3)
|
41
|
+
autoprefixer-rails (6.3.3.1)
|
42
|
+
execjs
|
43
|
+
bootstrap-sass (3.3.6)
|
44
|
+
autoprefixer-rails (>= 5.2.1)
|
45
|
+
sass (>= 3.3.4)
|
41
46
|
builder (3.2.2)
|
42
47
|
concurrent-ruby (1.0.0)
|
43
48
|
connection_pool (2.2.0)
|
@@ -48,6 +53,7 @@ GEM
|
|
48
53
|
domain_name (0.5.20160128)
|
49
54
|
unf (>= 0.0.5, < 1.0.0)
|
50
55
|
erubis (2.7.0)
|
56
|
+
execjs (2.6.0)
|
51
57
|
factory_girl (4.5.0)
|
52
58
|
activesupport (>= 3.0.0)
|
53
59
|
factory_girl_rails (4.6.0)
|
@@ -65,10 +71,23 @@ GEM
|
|
65
71
|
oauth2
|
66
72
|
globalid (0.3.6)
|
67
73
|
activesupport (>= 4.1.0)
|
74
|
+
haml (4.0.7)
|
75
|
+
tilt
|
76
|
+
haml-rails (0.9.0)
|
77
|
+
actionpack (>= 4.0.1)
|
78
|
+
activesupport (>= 4.0.1)
|
79
|
+
haml (>= 4.0.6, < 5.0)
|
80
|
+
html2haml (>= 1.0.1)
|
81
|
+
railties (>= 4.0.1)
|
68
82
|
hash_mapper (0.2.1)
|
69
83
|
activesupport (~> 4)
|
70
84
|
hashie (3.4.3)
|
71
85
|
highline (1.7.8)
|
86
|
+
html2haml (2.0.0)
|
87
|
+
erubis (~> 2.7.0)
|
88
|
+
haml (~> 4.0.0)
|
89
|
+
nokogiri (~> 1.6.0)
|
90
|
+
ruby_parser (~> 3.5)
|
72
91
|
http-cookie (1.0.2)
|
73
92
|
domain_name (~> 0.5)
|
74
93
|
httparty (0.13.7)
|
@@ -174,6 +193,10 @@ GEM
|
|
174
193
|
rspec-mocks (~> 3.4.0)
|
175
194
|
rspec-support (~> 3.4.0)
|
176
195
|
rspec-support (3.4.1)
|
196
|
+
ruby_parser (3.8.1)
|
197
|
+
sexp_processor (~> 4.1)
|
198
|
+
sass (3.4.21)
|
199
|
+
sexp_processor (4.7.0)
|
177
200
|
shoulda (3.5.0)
|
178
201
|
shoulda-context (~> 1.0, >= 1.0.1)
|
179
202
|
shoulda-matchers (>= 1.4.1, < 3.0)
|
@@ -200,6 +223,7 @@ GEM
|
|
200
223
|
systemu (2.6.5)
|
201
224
|
thor (0.19.1)
|
202
225
|
thread_safe (0.3.5)
|
226
|
+
tilt (2.0.2)
|
203
227
|
tzinfo (1.2.2)
|
204
228
|
thread_safe (~> 0.1)
|
205
229
|
unf (0.1.4)
|
@@ -212,8 +236,11 @@ PLATFORMS
|
|
212
236
|
ruby
|
213
237
|
|
214
238
|
DEPENDENCIES
|
239
|
+
autoprefixer-rails
|
240
|
+
bootstrap-sass
|
215
241
|
bundler (~> 1.0)
|
216
242
|
factory_girl_rails
|
243
|
+
haml-rails
|
217
244
|
hash_mapper
|
218
245
|
jeweler (~> 2.0.1)
|
219
246
|
maestrano-rails
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.17
|
@@ -6,12 +6,16 @@ module Maestrano::Connector::Rails
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def current_organization
|
9
|
-
Organization.find_by(uid: session[:org_uid], tenant: session[:tenant])
|
9
|
+
@current_organization ||= Organization.find_by(uid: session[:org_uid], tenant: session[:tenant])
|
10
10
|
end
|
11
11
|
|
12
12
|
def current_user
|
13
13
|
@current_user ||= User.find_by(uid: session[:uid], tenant: session[:tenant])
|
14
14
|
end
|
15
15
|
|
16
|
+
def is_admin
|
17
|
+
@is_admin ||= current_user && current_organization && is_admin?(current_user, current_organization)
|
18
|
+
end
|
19
|
+
|
16
20
|
end
|
17
21
|
end
|
@@ -52,14 +52,14 @@ module Maestrano::Connector::Rails
|
|
52
52
|
# -------------------------------------------------------------
|
53
53
|
# General methods
|
54
54
|
# -------------------------------------------------------------
|
55
|
-
def map_to_external_with_idmap(entity, organization,
|
56
|
-
idmap =
|
55
|
+
def map_to_external_with_idmap(entity, organization, external_entity_name, sub_entity_instance)
|
56
|
+
idmap = sub_entity_instance.find_idmap({connec_id: entity['id'], external_entity: external_entity_name, organization_id: organization.id})
|
57
57
|
|
58
|
-
if idmap && idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at']
|
59
|
-
ConnectorLogger.log('info', organization, "Discard Connec! #{
|
58
|
+
if idmap && ((!idmap.to_external) || idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at'])
|
59
|
+
ConnectorLogger.log('info', organization, "Discard Connec! #{sub_entity_instance.entity_name} : #{entity}")
|
60
60
|
nil
|
61
61
|
else
|
62
|
-
{entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: idmap ||
|
62
|
+
{entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: idmap || sub_entity_instance.create_idmap_from_connec_entity(entity, external_entity_name, organization)}
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -95,41 +95,22 @@ module Maestrano::Connector::Rails
|
|
95
95
|
sub_entity_instance = "Entities::SubEntities::#{external_entity_name.titleize.split.join}".constantize.new
|
96
96
|
|
97
97
|
entities.map!{|entity|
|
98
|
-
idmap =
|
98
|
+
idmap = sub_entity_instance.find_idmap(external_id: sub_entity_instance.get_id_from_external_entity_hash(entity), connec_entity: connec_entity_name, organization_id: organization.id)
|
99
99
|
|
100
100
|
# No idmap: creating one, nothing else to do
|
101
101
|
unless idmap
|
102
|
-
next {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap:
|
102
|
+
next {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: sub_entity_instance.create_idmap_from_external_entity(entity, connec_entity_name, organization)}
|
103
103
|
end
|
104
104
|
|
105
|
+
# Not pushing entity to Connec!
|
106
|
+
next nil unless idmap.to_connec
|
107
|
+
|
105
108
|
# Entity has not been modified since its last push to connec!
|
106
|
-
if
|
107
|
-
ConnectorLogger.log('info', organization, "Discard #{@@external_name} #{external_entity_name} : #{entity}")
|
108
|
-
next nil
|
109
|
-
end
|
109
|
+
next nil if Maestrano::Connector::Rails::Entity.not_modified_since_last_push_to_connec(idmap, entity, sub_entity_instance, organization)
|
110
110
|
|
111
|
-
equivalent_connec_entities = connec_entities[connec_entity_name][external_entity_name] || []
|
112
111
|
# Check for conflict with entities from connec!
|
113
|
-
|
114
|
-
|
115
|
-
if !opts[:connec_preemption].nil?
|
116
|
-
keep_external = !opts[:connec_preemption]
|
117
|
-
else
|
118
|
-
keep_external = connec_entity['updated_at'] < sub_entity_instance.get_last_update_date_from_external_entity_hash(entity)
|
119
|
-
end
|
120
|
-
|
121
|
-
if keep_external
|
122
|
-
ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{external_entity_name} #{entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from #{@@external_name} kept")
|
123
|
-
equivalent_connec_entities.delete(connec_entity)
|
124
|
-
{entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: idmap}
|
125
|
-
else
|
126
|
-
ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{external_entity_name} #{entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
127
|
-
nil
|
128
|
-
end
|
129
|
-
|
130
|
-
else
|
131
|
-
{entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: idmap}
|
132
|
-
end
|
112
|
+
equivalent_connec_entities = modeled_connec_entities[connec_entity_name][external_entity_name] || []
|
113
|
+
Maestrano::Connector::Rails::Entity.solve_conflict(entity, sub_entity_instance, equivalent_connec_entities, connec_entity_name, idmap, organization, opts)
|
133
114
|
}.compact!
|
134
115
|
end
|
135
116
|
end
|
@@ -138,7 +119,7 @@ module Maestrano::Connector::Rails
|
|
138
119
|
entities_in_external_model.each do |external_entity_name, entities|
|
139
120
|
sub_entity_instance = "Entities::SubEntities::#{connec_entity_name.titleize.split.join}".constantize.new
|
140
121
|
entities.map!{|entity|
|
141
|
-
self.map_to_external_with_idmap(entity, organization,
|
122
|
+
self.map_to_external_with_idmap(entity, organization, external_entity_name, sub_entity_instance)
|
142
123
|
}.compact!
|
143
124
|
end
|
144
125
|
end
|
@@ -17,116 +17,159 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
17
17
|
# ----------------------------------------------
|
18
18
|
# Map a Connec! entity to the external format
|
19
19
|
def map_to_external(entity, organization)
|
20
|
-
|
20
|
+
mapper_class.normalize(entity)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Map an external entity to Connec! format
|
24
24
|
def map_to_connec(entity, organization)
|
25
|
-
|
25
|
+
mapper_class.denormalize(entity)
|
26
26
|
end
|
27
27
|
|
28
|
+
# ----------------------------------------------
|
29
|
+
# IdMap methods
|
30
|
+
# ----------------------------------------------
|
31
|
+
def names_hash
|
32
|
+
{
|
33
|
+
connec_entity: connec_entity_name.downcase,
|
34
|
+
external_entity: external_entity_name.downcase
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_or_create_idmap(organization_and_id)
|
39
|
+
Maestrano::Connector::Rails::IdMap.find_or_create_by(names_hash.merge(organization_and_id))
|
40
|
+
end
|
41
|
+
|
42
|
+
# organization_and_id can be either:
|
43
|
+
# * {connec_id: 'id', organization_id: 'id'}
|
44
|
+
# * {external_id: 'id', organization_id: 'id'}
|
45
|
+
# Needs to include either connec_entity or external_entity for complex entities
|
46
|
+
def find_idmap(organization_and_id)
|
47
|
+
Maestrano::Connector::Rails::IdMap.find_by(names_hash.merge(organization_and_id))
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_idmap_from_external_entity(entity, organization)
|
51
|
+
h = names_hash.merge({
|
52
|
+
external_id: get_id_from_external_entity_hash(entity),
|
53
|
+
name: object_name_from_external_entity_hash(entity),
|
54
|
+
organization_id: organization.id
|
55
|
+
})
|
56
|
+
Maestrano::Connector::Rails::IdMap.create(h)
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_idmap_from_connec_entity(entity, organization)
|
60
|
+
h = names_hash.merge({
|
61
|
+
connec_id: entity['id'],
|
62
|
+
name: object_name_from_connec_entity_hash(entity),
|
63
|
+
organization_id: organization.id
|
64
|
+
})
|
65
|
+
Maestrano::Connector::Rails::IdMap.create(h)
|
66
|
+
end
|
28
67
|
# ----------------------------------------------
|
29
68
|
# Connec! methods
|
30
69
|
# ----------------------------------------------
|
31
70
|
def normalized_connec_entity_name
|
32
|
-
if
|
33
|
-
|
71
|
+
if singleton?
|
72
|
+
connec_entity_name.downcase
|
34
73
|
else
|
35
|
-
|
74
|
+
connec_entity_name.downcase.pluralize
|
36
75
|
end
|
37
76
|
end
|
38
77
|
|
39
78
|
def get_connec_entities(client, last_synchronization, organization, opts={})
|
40
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching Connec! #{
|
79
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching Connec! #{connec_entity_name}")
|
41
80
|
|
42
81
|
entities = []
|
43
82
|
|
44
83
|
# Fetch first page
|
45
84
|
if last_synchronization.blank? || opts[:full_sync]
|
46
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{
|
47
|
-
response = client.get("/#{
|
85
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{connec_entity_name}, fetching all data")
|
86
|
+
response = client.get("/#{normalized_connec_entity_name}")
|
48
87
|
else
|
49
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{
|
88
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{connec_entity_name}, fetching data since #{last_synchronization.updated_at.iso8601}")
|
50
89
|
query_param = URI.encode("$filter=updated_at gt '#{last_synchronization.updated_at.iso8601}'")
|
51
|
-
response = client.get("/#{
|
90
|
+
response = client.get("/#{normalized_connec_entity_name}?#{query_param}")
|
52
91
|
end
|
53
|
-
raise "No data received from Connec! when trying to fetch #{
|
92
|
+
raise "No data received from Connec! when trying to fetch #{connec_entity_name.pluralize}" unless response
|
54
93
|
|
55
94
|
response_hash = JSON.parse(response.body)
|
56
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received first page entity=#{
|
57
|
-
if response_hash["#{
|
58
|
-
entities << response_hash["#{
|
95
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received first page entity=#{connec_entity_name}, response=#{response.body}")
|
96
|
+
if response_hash["#{normalized_connec_entity_name}"]
|
97
|
+
entities << response_hash["#{normalized_connec_entity_name}"]
|
59
98
|
else
|
60
|
-
raise "Received unrecognized Connec! data when trying to fetch #{
|
99
|
+
raise "Received unrecognized Connec! data when trying to fetch #{connec_entity_name.pluralize}"
|
61
100
|
end
|
62
101
|
|
63
102
|
# Fetch subsequent pages
|
64
103
|
while response_hash['pagination'] && response_hash['pagination']['next']
|
65
104
|
# ugly way to convert https://api-connec/api/v2/group_id/organizations?next_page_params to /organizations?next_page_params
|
66
|
-
next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{
|
105
|
+
next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{normalized_connec_entity_name}/, normalized_connec_entity_name)
|
67
106
|
response = client.get(next_page)
|
68
107
|
|
69
|
-
raise "No data received from Connec! when trying to fetch subsequent page of #{
|
70
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received next page entity=#{
|
108
|
+
raise "No data received from Connec! when trying to fetch subsequent page of #{connec_entity_name.pluralize}" unless response
|
109
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received next page entity=#{connec_entity_name}, response=#{response.body}")
|
71
110
|
|
72
111
|
response_hash = JSON.parse(response.body)
|
73
|
-
if response_hash["#{
|
74
|
-
entities << response_hash["#{
|
112
|
+
if response_hash["#{normalized_connec_entity_name}"]
|
113
|
+
entities << response_hash["#{normalized_connec_entity_name}"]
|
75
114
|
else
|
76
|
-
raise "Received unrecognized Connec! data when trying to fetch subsequent page of #{
|
115
|
+
raise "Received unrecognized Connec! data when trying to fetch subsequent page of #{connec_entity_name.pluralize}"
|
77
116
|
end
|
78
117
|
end
|
79
118
|
|
80
119
|
entities = entities.flatten
|
81
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received data: Source=Connec!, Entity=#{
|
120
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received data: Source=Connec!, Entity=#{connec_entity_name}, Data=#{entities}")
|
82
121
|
entities
|
83
122
|
end
|
84
123
|
|
85
124
|
def push_entities_to_connec(connec_client, mapped_external_entities_with_idmaps, organization)
|
86
|
-
|
125
|
+
push_entities_to_connec_to(connec_client, mapped_external_entities_with_idmaps, connec_entity_name, organization)
|
87
126
|
end
|
88
127
|
|
89
128
|
def push_entities_to_connec_to(connec_client, mapped_external_entities_with_idmaps, connec_entity_name, organization)
|
90
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{@@external_name} #{
|
129
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{@@external_name} #{external_entity_name.pluralize} to Connec! #{connec_entity_name.pluralize}")
|
91
130
|
mapped_external_entities_with_idmaps.each do |mapped_external_entity_with_idmap|
|
92
131
|
external_entity = mapped_external_entity_with_idmap[:entity]
|
93
132
|
idmap = mapped_external_entity_with_idmap[:idmap]
|
94
133
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
134
|
+
begin
|
135
|
+
if idmap.connec_id.blank?
|
136
|
+
connec_entity = create_connec_entity(connec_client, external_entity, connec_entity_name, organization)
|
137
|
+
idmap.update_attributes(connec_id: connec_entity['id'], connec_entity: connec_entity_name.downcase, last_push_to_connec: Time.now, message: nil)
|
138
|
+
else
|
139
|
+
connec_entity = update_connec_entity(connec_client, external_entity, idmap.connec_id, connec_entity_name, organization)
|
140
|
+
idmap.update_attributes(last_push_to_connec: Time.now, message: nil)
|
141
|
+
end
|
142
|
+
rescue => e
|
143
|
+
# Store Connec! error if any
|
144
|
+
idmap.update_attributes(message: e.message)
|
101
145
|
end
|
102
|
-
|
103
|
-
# Store Connec! error if any
|
104
|
-
idmap.update_attributes(message: connec_entity['errors'].first['title']) unless connec_entity.blank? || connec_entity['errors'].blank?
|
105
146
|
end
|
106
147
|
end
|
107
148
|
|
108
149
|
def create_connec_entity(connec_client, mapped_external_entity, connec_entity_name, organization)
|
109
150
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending create #{connec_entity_name}: #{mapped_external_entity} to Connec!")
|
110
151
|
response = connec_client.post("/#{normalized_connec_entity_name}", { "#{normalized_connec_entity_name}".to_sym => mapped_external_entity })
|
111
|
-
|
112
|
-
|
152
|
+
response = JSON.parse(response.body)
|
153
|
+
raise "Connec!: #{response['errors']['title']}" if response['errors'] && response['errors']['title']
|
154
|
+
response["#{normalized_connec_entity_name}"]
|
113
155
|
end
|
114
156
|
|
115
157
|
def update_connec_entity(connec_client, mapped_external_entity, connec_id, connec_entity_name, organization)
|
116
158
|
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending update #{connec_entity_name}: #{mapped_external_entity} to Connec!")
|
117
159
|
response = connec_client.put("/#{normalized_connec_entity_name}/#{connec_id}", { "#{normalized_connec_entity_name}".to_sym => mapped_external_entity })
|
118
|
-
|
119
|
-
|
160
|
+
response = JSON.parse(response.body)
|
161
|
+
raise "Connec!: #{response['errors']['title']}" if response['errors'] && response['errors']['title']
|
162
|
+
response["#{normalized_connec_entity_name}"]
|
120
163
|
end
|
121
164
|
|
122
165
|
def map_to_external_with_idmap(entity, organization)
|
123
|
-
idmap =
|
166
|
+
idmap = find_idmap({connec_id: entity['id'], organization_id: organization.id})
|
124
167
|
|
125
168
|
if idmap && ((!idmap.to_external) || (idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at']))
|
126
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{
|
169
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{connec_entity_name} : #{entity}")
|
127
170
|
nil
|
128
171
|
else
|
129
|
-
{entity:
|
172
|
+
{entity: map_to_external(entity, organization), idmap: idmap || create_idmap_from_connec_entity(entity, organization)}
|
130
173
|
end
|
131
174
|
end
|
132
175
|
|
@@ -134,18 +177,18 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
134
177
|
# External methods
|
135
178
|
# ----------------------------------------------
|
136
179
|
def get_external_entities(client, last_synchronization, organization, opts={})
|
137
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching #{@@external_name} #{
|
180
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching #{@@external_name} #{external_entity_name.pluralize}")
|
138
181
|
raise "Not implemented"
|
139
182
|
end
|
140
183
|
|
141
184
|
def push_entities_to_external(external_client, mapped_connec_entities_with_idmaps, organization)
|
142
|
-
push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps,
|
185
|
+
push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps, external_entity_name, organization)
|
143
186
|
end
|
144
187
|
|
145
188
|
def push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps, external_entity_name, organization)
|
146
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending Connec! #{
|
189
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending Connec! #{connec_entity_name.pluralize} to #{@@external_name} #{external_entity_name.pluralize}")
|
147
190
|
mapped_connec_entities_with_idmaps.each do |mapped_connec_entity_with_idmap|
|
148
|
-
|
191
|
+
push_entity_to_external(external_client, mapped_connec_entity_with_idmap, external_entity_name, organization)
|
149
192
|
end
|
150
193
|
end
|
151
194
|
|
@@ -155,10 +198,10 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
155
198
|
|
156
199
|
begin
|
157
200
|
if idmap.external_id.blank?
|
158
|
-
external_id =
|
201
|
+
external_id = create_external_entity(external_client, connec_entity, external_entity_name, organization)
|
159
202
|
idmap.update_attributes(external_id: external_id, external_entity: external_entity_name.downcase, last_push_to_external: Time.now, message: nil)
|
160
203
|
else
|
161
|
-
|
204
|
+
update_external_entity(external_client, connec_entity, idmap.external_id, external_entity_name, organization)
|
162
205
|
idmap.update_attributes(last_push_to_external: Time.now, message: nil)
|
163
206
|
end
|
164
207
|
rescue => e
|
@@ -193,54 +236,56 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
193
236
|
# * Maps not discarded entities and associates them with their idmap, or create one if there isn't any
|
194
237
|
# * Return a hash {connec_entities: [], external_entities: []}
|
195
238
|
def consolidate_and_map_data(connec_entities, external_entities, organization, opts={})
|
239
|
+
return consolidate_and_map_singleton(connec_entities, external_entities, organization, opts) if singleton?
|
240
|
+
|
196
241
|
mapped_external_entities = external_entities.map{|entity|
|
197
|
-
idmap =
|
242
|
+
idmap = find_idmap({external_id: get_id_from_external_entity_hash(entity), organization_id: organization.id})
|
198
243
|
# No idmap: creating one, nothing else to do
|
199
244
|
unless idmap
|
200
|
-
next {entity:
|
245
|
+
next {entity: map_to_connec(entity, organization), idmap: create_idmap_from_external_entity(entity, organization)}
|
201
246
|
end
|
202
247
|
|
203
248
|
# Not pushing entity to Connec!
|
204
249
|
next nil unless idmap.to_connec
|
205
250
|
|
206
251
|
# Entity has not been modified since its last push to connec!
|
207
|
-
if
|
208
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard #{@@external_name} #{self.external_entity_name} : #{entity}")
|
209
|
-
next nil
|
210
|
-
end
|
252
|
+
next nil if self.class.not_modified_since_last_push_to_connec(idmap, entity, self, organization)
|
211
253
|
|
212
254
|
# Check for conflict with entities from connec!
|
213
|
-
|
214
|
-
# We keep the most recently updated entity
|
215
|
-
if !opts[:connec_preemption].nil?
|
216
|
-
keep_external = !opts[:connec_preemption]
|
217
|
-
else
|
218
|
-
keep_external = connec_entity['updated_at'] < self.get_last_update_date_from_external_entity_hash(entity)
|
219
|
-
end
|
220
|
-
|
221
|
-
if keep_external
|
222
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{self.external_entity_name} #{entity} and Connec! #{self.connec_entity_name} #{connec_entity}. Entity from #{@@external_name} kept")
|
223
|
-
connec_entities.delete(connec_entity)
|
224
|
-
{entity: self.map_to_connec(entity, organization), idmap: idmap}
|
225
|
-
else
|
226
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{self.external_entity_name} #{entity} and Connec! #{self.connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
227
|
-
nil
|
228
|
-
end
|
229
|
-
|
230
|
-
else
|
231
|
-
{entity: self.map_to_connec(entity, organization), idmap: idmap}
|
232
|
-
end
|
255
|
+
self.class.solve_conflict(entity, self, connec_entities, connec_entity_name, idmap, organization, opts)
|
233
256
|
}
|
234
257
|
mapped_external_entities.compact!
|
235
258
|
|
236
259
|
mapped_connec_entities = connec_entities.map{|entity|
|
237
|
-
|
260
|
+
map_to_external_with_idmap(entity, organization)
|
238
261
|
}
|
239
262
|
mapped_connec_entities.compact!
|
240
263
|
|
241
264
|
return {connec_entities: mapped_connec_entities, external_entities: mapped_external_entities}
|
242
265
|
end
|
243
266
|
|
267
|
+
def consolidate_and_map_singleton(connec_entities, external_entities, organization, opts={})
|
268
|
+
return {connec_entities: [], external_entities: []} if external_entities.empty? && connec_entities.empty?
|
269
|
+
|
270
|
+
idmap = find_or_create_idmap({organization_id: organization.id})
|
271
|
+
|
272
|
+
if external_entities.empty?
|
273
|
+
keep_external = false
|
274
|
+
elsif connec_entities.empty?
|
275
|
+
keep_external = true
|
276
|
+
elsif !opts[:connec_preemption].nil?
|
277
|
+
keep_external = !opts[:connec_preemption]
|
278
|
+
else
|
279
|
+
keep_external = self.class.is_external_more_recent?(connec_entities.first, external_entities.first, self)
|
280
|
+
end
|
281
|
+
if keep_external
|
282
|
+
idmap.update(external_id: get_id_from_external_entity_hash(external_entities.first))
|
283
|
+
return {connec_entities: [], external_entities: [{entity: map_to_connec(external_entities.first, organization), idmap: idmap}]}
|
284
|
+
else
|
285
|
+
idmap.update(connec_id: connec_entities.first['id'])
|
286
|
+
return {connec_entities: [{entity: map_to_external(connec_entities.first, organization), idmap: idmap}], external_entities: []}
|
287
|
+
end
|
288
|
+
end
|
244
289
|
|
245
290
|
# ----------------------------------------------
|
246
291
|
# Entity specific methods
|
@@ -275,4 +320,47 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
275
320
|
def object_name_from_external_entity_hash(entity)
|
276
321
|
raise "Not implemented"
|
277
322
|
end
|
323
|
+
|
324
|
+
|
325
|
+
# ----------------------------------------------
|
326
|
+
# Internal helper methods
|
327
|
+
# ----------------------------------------------
|
328
|
+
module ClassMethods
|
329
|
+
def not_modified_since_last_push_to_connec(idmap, entity, entity_instance, organization)
|
330
|
+
result = idmap.last_push_to_connec && idmap.last_push_to_connec > entity_instance.get_last_update_date_from_external_entity_hash(entity)
|
331
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard #{entity_instance.external_entity_name} : #{entity}") unless result
|
332
|
+
result
|
333
|
+
end
|
334
|
+
|
335
|
+
def is_external_more_recent?(connec_entity, external_entity, entity_instance)
|
336
|
+
connec_entity['updated_at'] < entity_instance.get_last_update_date_from_external_entity_hash(external_entity)
|
337
|
+
end
|
338
|
+
|
339
|
+
def solve_conflict(external_entity, entity_instance, connec_entities, connec_entity_name, idmap, organization, opts)
|
340
|
+
if idmap.connec_id && connec_entity = connec_entities.detect{|connec_entity| connec_entity['id'] == idmap.connec_id}
|
341
|
+
# We keep the most recently updated entity
|
342
|
+
if !opts[:connec_preemption].nil?
|
343
|
+
keep_external = !opts[:connec_preemption]
|
344
|
+
else
|
345
|
+
keep_external = is_external_more_recent?(connec_entity, external_entity, entity_instance)
|
346
|
+
end
|
347
|
+
|
348
|
+
if keep_external
|
349
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{entity_instance.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from external kept")
|
350
|
+
connec_entities.delete(connec_entity)
|
351
|
+
entity_instance.map_external_entity_with_idmap(external_entity, connec_entity_name, idmap, organization)
|
352
|
+
else
|
353
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{entity_instance.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
354
|
+
nil
|
355
|
+
end
|
356
|
+
|
357
|
+
else
|
358
|
+
entity_instance.map_external_entity_with_idmap(external_entity, connec_entity_name, idmap, organization)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
def map_external_entity_with_idmap(external_entity, connec_entity_name, idmap, organization)
|
364
|
+
{entity: map_to_connec(external_entity, organization), idmap: idmap}
|
365
|
+
end
|
278
366
|
end
|