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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9793ce7b94518bfd9fda69a602b792cedbf30a69
4
- data.tar.gz: 94d5059ebbeccd918ef66108273dbe31f853aa27
3
+ metadata.gz: e4034931c4f557a653f429fe27c03144246429d3
4
+ data.tar.gz: 8ac0745b563b712d1858bc4a0ea952d033a08a09
5
5
  SHA512:
6
- metadata.gz: 36716f4680c9fa4b6f1d81d578aa4122baa0fc27c342d9c38f02f1904af50853e2199be6727242531f0f07e28c1a15eec3f98225b79c9bded68353f77b60a71d
7
- data.tar.gz: 6d78274a939867b4dd196d264101a97d22678d3983d4882ddcd73a59236907ad50da0a766472fe83a5c5e6ad7d91bd7a2ef3afd71de9e4669c96123eb30f8a38
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', 'Pierre Berard', 'Marco Bagnasco']
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.RC8
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.logger.info "Received notification from Connec! for unknow entity: #{entity_name}" unless entity_class_hash
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
- entity_instance.after_sync(last_synchronization_date)
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.logger.warn("error processing notification #{e.message} - #{e.backtrace.join("\n")}")
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.logger.warn "Called push to connec job with unknow entity: #{external_entity_name}"
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("org: #{organization.uid} (#{organization.tenant}). Msg: #{msg}")
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 << response_hash[self.class.normalized_connec_entity_name]
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.logger.info "The #{idmap.external_entity} - #{idmap.external_id} record has been deleted. It is now set to inactive."
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('error', @organization, "Error while pushing to Connec!: #{result['body']}")
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
- def check_historical_data(checkbox_ticked)
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
- # checkbox_ticked is a boolean
92
- if checkbox_ticked
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?
@@ -0,0 +1,5 @@
1
+ class AddUniqueIndexOnOrganizationOauthUid < ActiveRecord::Migration
2
+ def change
3
+ add_index :organizations, :oauth_uid, unique: true
4
+ end
5
+ end
@@ -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
- old_sync_state = organization.sync_enabled
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.check_historical_data(params['historical-data'].present?)
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
- start_synchronization(old_sync_state, organization) unless !old_sync_state && organization.sync_enabled
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(old_sync_state, organization)
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) { |n| "cld-11#{n}" }
11
- oauth_uid 'sfuiy765'
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) { |n| "#{n}6798-ada6-te43#{n}" }
21
+ sequence(:connec_id) { SecureRandom.uuid }
22
22
  connec_entity 'person'
23
- sequence(:external_id) { |n| "#{n}4567ada66#{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.RC8 ruby lib
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.RC8"
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", "Pierre Berard", "Marco Bagnasco"]
14
- s.date = "2016-10-05"
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 'logs a warning' do
37
- allow(controller).to receive(:find_entity_class).and_raise('Bruno c\'est peter')
38
- expect(Rails.logger).to receive(:warn)
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 'logs a warning' do
50
- expect(Rails.logger).to receive(:info).with('Received notification from Connec! for unknow entity: people')
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 'logs a warning' do
116
- expect(Rails.logger).to receive(:warn).with("Received notification from Connec! for unknown group or group without oauth: #{group_id} (tenant: default)")
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 'logs a warning' do
125
- expect(Rails.logger).to receive(:warn).with("Received notification from Connec! for unknown group or group without oauth: #{group_id} (tenant: default)")
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
@@ -6,6 +6,7 @@ require 'factory_girl_rails'
6
6
  require 'shoulda/matchers'
7
7
  require 'simplecov'
8
8
  require 'timecop'
9
+ require 'maestrano_connector_rails/factories.rb'
9
10
  SimpleCov.start
10
11
 
11
12
  Rails.backtrace_cleaner.remove_silencers!
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.RC8
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-05 00:00:00.000000000 Z
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