maestrano-connector-rails 2.3.2 → 2.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: fe03ff785065c1f8cadca66eb2e2b82ed5fc84f5323c4869b48336d12972c85b
4
- data.tar.gz: b498996b210d55d76a64ddee0e3172b98ec59a2414865c6cc78b29cecd926057
2
+ SHA1:
3
+ metadata.gz: d68e736e0130292d4985536e944a42f6b373dad1
4
+ data.tar.gz: 47dc6757656ad1363103a289191ab8c3bb52e48a
5
5
  SHA512:
6
- metadata.gz: e4bcd12d815b164b47bcea4882499ddecfacb4ed5eb86aa140ef89aa086f98df44dd250b5cc9f32f87ac05974038c026aef2917c1294178ff75141ede6c76d1b
7
- data.tar.gz: 7118fddc3d02a5681232eeec359c16f2c500aac7456a621577d8443420d1785cd19a87c954bff5d011aa3a78ea864cd66af2b55d50a6851f830192ddf4c51ea7
6
+ metadata.gz: c267435b208139421e3022f830805875fa57bdd4017e836d5dde57c58c90d4813e34948d3382e3eb06d7d831359ab7e52b2e42223aabc4a5c882a330f2c7e38b
7
+ data.tar.gz: 24d85d8957e387213429130c571ee0f60d7697be355d6cbfba573ab9f449862ffa7ed88a57229f34b2b83368ee169729dbc3c180dded7056731fc6911b2e365c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 2.3.3
2
+
3
+ * [MARLIN-244] Decorate SynchronizationController [\#176](https://github.com/maestrano/maestrano-connector-rails/pull/176)
4
+ * Rubofix [\#177](https://github.com/maestrano/maestrano-connector-rails/pull/177)
5
+ * [MNO-816] Fix regex pattern [\#175](https://github.com/maestrano/maestrano-connector-rails/pull/175)
6
+ * Spread out sync jobs [\#173](https://github.com/maestrano/maestrano-connector-rails/pull/173)
7
+
8
+ ## 2.3.2
9
+
10
+ * Update framework generators and template [\#171](https://github.com/maestrano/maestrano-connector-rails/pull/171)
11
+
12
+ ## 2.3.1
13
+
14
+ * Do not skip Connec! webhook on push_disabled (transac! compatibility) [\#170](https://github.com/maestrano/maestrano-connector-rails/pull/170)
15
+
1
16
  ## 2.3.0
2
17
 
3
18
  * Send data to Connec! even if the push/pull parameters are disabled (Transac! integration)
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source 'http://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  gemspec
4
6
 
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maestrano
4
+ module Concerns
5
+ module SynchronizationsController
6
+ extend ActiveSupport::Concern
7
+
8
+ #==================================================================
9
+ # Included methods
10
+ #==================================================================
11
+ # 'included do' causes the included code to be evaluated in the
12
+ # context where it is included rather than being executed in the
13
+ # module's context
14
+ included do
15
+ end
16
+
17
+ #==================================================================
18
+ # Class methods
19
+ #==================================================================
20
+ module ClassMethods
21
+ end
22
+
23
+ #==================================================================
24
+ # Instance methods
25
+ #==================================================================
26
+ def show
27
+ tenant = params[:tenant]
28
+ uid = params[:id]
29
+ organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
30
+ return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
31
+
32
+ status = organization_status organization
33
+
34
+ render_organization_sync(organization, status, 200)
35
+ end
36
+
37
+ def create
38
+ tenant = params[:tenant]
39
+ uid = params[:group_id]
40
+ opts = params[:opts] || {}
41
+ organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
42
+ return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
43
+
44
+ organization.sync_enabled = organization.synchronized_entities.values.any? { |settings| settings.values.any? { |v| v } }
45
+ organization.save if organization.sync_enabled_changed?
46
+
47
+ status = organization_status(organization)
48
+
49
+ unless %w[RUNNING ENQUEUED].include?(status)
50
+ Maestrano::Connector::Rails::SynchronizationJob.perform_later(organization.id, opts.with_indifferent_access)
51
+ status = 'ENQUEUED'
52
+ end
53
+
54
+ render_organization_sync(organization, status, 201)
55
+ end
56
+
57
+ def update_metadata
58
+ tenant = params[:tenant]
59
+ uid = params[:group_id]
60
+ organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
61
+ return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
62
+
63
+ organization.set_instance_metadata
64
+ organization.reset_synchronized_entities
65
+ render_organization_sync(organization, status, 200)
66
+ end
67
+
68
+ def toggle_sync
69
+ tenant = params[:tenant]
70
+ uid = params[:group_id]
71
+ organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
72
+ return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
73
+
74
+ organization.toggle(:sync_enabled)
75
+ organization.save
76
+ status = organization_status organization
77
+ render_organization_sync(organization, status, 200)
78
+ end
79
+
80
+ private
81
+
82
+ def render_organization_sync(organization, status, code)
83
+ h = {
84
+ group_id: organization.uid,
85
+ sync_enabled: organization.sync_enabled,
86
+ status: status
87
+ }
88
+ last_sync = organization.synchronizations.last
89
+ if last_sync
90
+ h[:message] = last_sync.message
91
+ h[:updated_at] = last_sync.updated_at
92
+ end
93
+
94
+ render json: h, status: code
95
+ end
96
+
97
+ def organization_status(organization)
98
+ if Maestrano::Connector::Rails::SynchronizationJob.find_running_job(organization.id)
99
+ 'RUNNING'
100
+ elsif Maestrano::Connector::Rails::SynchronizationJob.find_job(organization.id)
101
+ 'ENQUEUED'
102
+ else
103
+ organization.synchronizations.last&.status || 'DISABLED'
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -9,6 +9,7 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
9
9
  begin
10
10
  organization = find_valid_organization(entity[:group_id], params[:tenant], entity_class_hash)
11
11
  next if organization.blank?
12
+
12
13
  Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Processing entity from Connec! webhook, entity_name=\"#{entity_name}\", data=\"#{entity}\"")
13
14
 
14
15
  connec_client = Maestrano::Connector::Rails::ConnecHelper.get_client(organization)
@@ -1,82 +1,7 @@
1
- class Maestrano::SynchronizationsController < Maestrano::Rails::WebHookController
2
- def show
3
- tenant = params[:tenant]
4
- uid = params[:id]
5
- organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
6
- return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
1
+ # frozen_string_literal: true
7
2
 
8
- status = organization_status organization
9
-
10
- render_organization_sync(organization, status, 200)
3
+ module Maestrano
4
+ class SynchronizationsController < Maestrano::Rails::WebHookController
5
+ include Maestrano::Concerns::SynchronizationsController
11
6
  end
12
-
13
- def create
14
- tenant = params[:tenant]
15
- uid = params[:group_id]
16
- opts = params[:opts] || {}
17
- organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
18
- return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
19
-
20
- organization.sync_enabled = organization.synchronized_entities.values.any? { |settings| settings.values.any? { |v| v } }
21
- organization.save if organization.sync_enabled_changed?
22
-
23
- status = organization_status(organization)
24
-
25
- unless %w[RUNNING ENQUEUED].include?(status)
26
- Maestrano::Connector::Rails::SynchronizationJob.perform_later(organization.id, opts.with_indifferent_access)
27
- status = 'ENQUEUED'
28
- end
29
-
30
- render_organization_sync(organization, status, 201)
31
- end
32
-
33
- def update_metadata
34
- tenant = params[:tenant]
35
- uid = params[:group_id]
36
- organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
37
- return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
38
-
39
- organization.set_instance_metadata
40
- organization.reset_synchronized_entities
41
- render_organization_sync(organization, status, 200)
42
- end
43
-
44
- def toggle_sync
45
- tenant = params[:tenant]
46
- uid = params[:group_id]
47
- organization = Maestrano::Connector::Rails::Organization.find_by(uid: uid, tenant: tenant)
48
- return render json: {errors: [{message: 'Organization not found', code: 404}]}, status: :not_found unless organization
49
-
50
- organization.toggle(:sync_enabled)
51
- organization.save
52
- status = organization_status organization
53
- render_organization_sync(organization, status, 200)
54
- end
55
-
56
- private
57
-
58
- def render_organization_sync(organization, status, code)
59
- h = {
60
- group_id: organization.uid,
61
- sync_enabled: organization.sync_enabled,
62
- status: status
63
- }
64
- last_sync = organization.synchronizations.last
65
- if last_sync
66
- h[:message] = last_sync.message
67
- h[:updated_at] = last_sync.updated_at
68
- end
69
-
70
- render json: h, status: code
71
- end
72
-
73
- def organization_status(organization)
74
- if Maestrano::Connector::Rails::SynchronizationJob.find_running_job(organization.id)
75
- 'RUNNING'
76
- elsif Maestrano::Connector::Rails::SynchronizationJob.find_job(organization.id)
77
- 'ENQUEUED'
78
- else
79
- organization.synchronizations.last&.status || 'DISABLED'
80
- end
81
- end
82
7
  end
@@ -4,9 +4,15 @@ module Maestrano::Connector::Rails
4
4
 
5
5
  # Trigger synchronization of all active organizations
6
6
  def perform(name = nil, count = nil)
7
- Maestrano::Connector::Rails::Organization.where.not(oauth_provider: nil, encrypted_oauth_token: nil).each do |o|
8
- next unless [true, 1].include?(o.sync_enabled)
9
- Maestrano::Connector::Rails::SynchronizationJob.perform_later(o.id, {})
7
+ active_organizations = Maestrano::Connector::Rails::Organization
8
+ .where.not(oauth_provider: nil, encrypted_oauth_token: nil)
9
+ .select { |o| [true, 1].include?(o.sync_enabled) }
10
+
11
+ return true if active_organizations.count.zero?
12
+
13
+ time_span_seconds = (3600 / active_organizations.count).to_i
14
+ active_organizations.each_with_index do |organization, i|
15
+ Maestrano::Connector::Rails::SynchronizationJob.set(wait: time_span_seconds * i).perform_later(organization.id, {})
10
16
  end
11
17
  end
12
18
  end
@@ -14,10 +14,10 @@ module Maestrano::Connector::Rails::Concerns::SynchronizationJob
14
14
  queue = Sidekiq::Queue.new(:default)
15
15
  queue.find do |job|
16
16
  job_organization_id = begin
17
- job.item['args'][0]['arguments'].first
18
- rescue
19
- false
20
- end
17
+ job.item['args'][0]['arguments'].first
18
+ rescue
19
+ false
20
+ end
21
21
  organization_id == job_organization_id
22
22
  end
23
23
  end
@@ -25,10 +25,10 @@ module Maestrano::Connector::Rails::Concerns::SynchronizationJob
25
25
  def find_running_job(organization_id)
26
26
  Sidekiq::Workers.new.find do |_, _, work|
27
27
  job_organization_id = begin
28
- work['payload']['args'][0]['arguments'].first
29
- rescue
30
- false
31
- end
28
+ work['payload']['args'][0]['arguments'].first
29
+ rescue
30
+ false
31
+ end
32
32
  work['queue'] == 'default' && organization_id == job_organization_id
33
33
  end
34
34
  rescue
@@ -75,6 +75,7 @@ module Maestrano::Connector::Rails::Concerns::SynchronizationJob
75
75
  Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, 'First synchronization ever. Doing two half syncs to allow smart merging to work its magic.')
76
76
  organization.synchronized_entities.each do |entity, settings|
77
77
  next unless settings[:can_push_to_connec] || settings[:can_push_to_external]
78
+
78
79
  Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "First synchronization ever. Doing half sync from external for #{entity}.")
79
80
  first_sync_entity(entity.to_s, organization, connec_client, external_client, last_synchronization_date, opts, true)
80
81
  Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "First synchronization ever. Doing half sync from Connec! for #{entity}.")
@@ -90,6 +91,7 @@ module Maestrano::Connector::Rails::Concerns::SynchronizationJob
90
91
  else
91
92
  organization.synchronized_entities.each do |entity, settings|
92
93
  next unless settings[:can_push_to_connec] || settings[:can_push_to_external]
94
+
93
95
  sync_entity(entity.to_s, organization, connec_client, external_client, last_synchronization_date, opts)
94
96
  end
95
97
  end
@@ -136,6 +138,7 @@ module Maestrano::Connector::Rails::Concerns::SynchronizationJob
136
138
  # We're comparing the first record to check that it is different
137
139
  first_record = Digest::MD5.hexdigest(perform_hash[:first].to_s)
138
140
  break if last_first_record && first_record == last_first_record
141
+
139
142
  last_first_record = first_record
140
143
 
141
144
  skip += limit
@@ -8,6 +8,7 @@ module Maestrano::Connector::Rails::Concerns::UpdateConfigurationJob
8
8
 
9
9
  def perform
10
10
  return if ENV['SKIP_CONFIGURATION']
11
+
11
12
  Maestrano.reset!
12
13
  Maestrano.auto_configure
13
14
  rescue StandardError => e
@@ -24,6 +24,7 @@ module Maestrano::Connector::Rails::Concerns::ComplexEntity
24
24
 
25
25
  def formatted_entities_names(names)
26
26
  return names.with_indifferent_access if names.is_a?(Hash)
27
+
27
28
  names.index_by { |name| name }.with_indifferent_access
28
29
  end
29
30
 
@@ -44,6 +45,7 @@ module Maestrano::Connector::Rails::Concerns::ComplexEntity
44
45
  def public_name(formatted_names)
45
46
  names = formatted_names.keys.map(&:pluralize)
46
47
  return names.first.humanize if names.size == 1
48
+
47
49
  (names[0..-2].join(', ') + " and #{names.last}").humanize
48
50
  end
49
51
  end
@@ -119,6 +119,7 @@ module Maestrano::Connector::Rails::Concerns::ConnecHelper
119
119
  # Unfold the id
120
120
  if array_of_refs.empty? && field
121
121
  return entity.delete(ref) if field.is_a?(String) # ~retro-compatibility to ease transition aroud Connec! idmaps rework. Should be removed eventually.
122
+
122
123
  id_hash = field.find { |id| id[:provider] == organization.oauth_provider && id[:realm] == organization.oauth_uid }
123
124
  if id_hash
124
125
  entity[ref] = id_hash['id']
@@ -134,6 +135,7 @@ module Maestrano::Connector::Rails::Concerns::ConnecHelper
134
135
  # Follow embedment path
135
136
  else
136
137
  return true if field.blank?
138
+
137
139
  case field
138
140
  when Array
139
141
  bool = true
@@ -151,6 +153,7 @@ module Maestrano::Connector::Rails::Concerns::ConnecHelper
151
153
  # References can either be an array (only record references), or a hash
152
154
  def format_references(references)
153
155
  return {record_references: references, id_references: []} if references.is_a?(Array)
156
+
154
157
  references[:record_references] ||= []
155
158
  references[:id_references] ||= []
156
159
  references
@@ -173,6 +176,7 @@ module Maestrano::Connector::Rails::Concerns::ConnecHelper
173
176
  # Recursive method for filtering connec entities
174
177
  def filter_connec_entity_for_id_refs_helper(entity_hash, tree)
175
178
  return if tree.empty?
179
+
176
180
  entity_hash.slice!(*tree.keys)
177
181
 
178
182
  tree.each do |key, children|
@@ -234,7 +234,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
234
234
  # Fetch subsequent pages
235
235
  while response_hash['pagination'] && response_hash['pagination']['next']
236
236
  # ugly way to convert https://api-connec/api/v2/group_id/organizations?next_page_params to /organizations?next_page_params
237
- next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{self.class.normalized_connec_entity_name}/, self.class.normalized_connec_entity_name)
237
+ next_page = response_hash['pagination']['next'].gsub(/\A(.*)\/#{self.class.normalized_connec_entity_name}/, self.class.normalized_connec_entity_name)
238
238
 
239
239
  response_hash = fetch_connec(next_page)
240
240
  entities.concat response_hash[self.class.normalized_connec_entity_name]
@@ -273,6 +273,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
273
273
  mapped_external_entities_with_idmaps.each do |mapped_external_entity_with_idmap|
274
274
  id_map = mapped_external_entity_with_idmap[:idmap]
275
275
  next unless id_map&.metadata&.dig(:ignore_currency_update)
276
+
276
277
  self.class.currency_check_fields.each do |field|
277
278
  mapped_external_entity_with_idmap[:entity].delete(field)
278
279
  end
@@ -302,6 +303,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
302
303
  # Wrapper to process options and limitations
303
304
  def get_external_entities_wrapper(last_synchronization_date = nil, entity_name = self.class.external_entity_name)
304
305
  return [] if @opts[:__skip_external] || !self.class.can_read_external?
306
+
305
307
  get_external_entities(entity_name, last_synchronization_date)
306
308
  end
307
309
 
@@ -367,6 +369,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
367
369
  # Update
368
370
  else
369
371
  return nil unless self.class.can_update_external?
372
+
370
373
  external_hash = update_external_entity(mapped_connec_entity, idmap.external_id, external_entity_name)
371
374
 
372
375
  completed_hash = map_and_complete_hash_with_connec_ids(external_hash, external_entity_name, id_refs_only_connec_entity)
@@ -479,6 +482,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
479
482
  response = @connec_client.batch(batch_request)
480
483
  Maestrano::Connector::Rails::ConnectorLogger.log('debug', @organization, "Received batch response from Connec! for #{self.class.normalize_connec_entity_name(connec_entity_name)}: #{response}")
481
484
  raise "No data received from Connec! when trying to send batch request #{log_info} for #{self.class.connec_entity_name.pluralize}" unless response && response.body.present?
485
+
482
486
  response = JSON.parse(response.body)
483
487
 
484
488
  # Parse batch response
@@ -114,6 +114,7 @@ module Maestrano::Connector::Rails::Concerns::Organization
114
114
  def enable_historical_data(enabled)
115
115
  # Historical data sharing cannot be unset
116
116
  return if historical_data
117
+
117
118
  if enabled
118
119
  self.date_filtering_limit = nil
119
120
  self.historical_data = true
@@ -12,11 +12,13 @@ module Maestrano::Connector::Rails::Concerns::SubEntityBase
12
12
 
13
13
  def external_entity_name
14
14
  return entity_name if external?
15
+
15
16
  raise 'Forbidden call: cannot call external_entity_name for a connec entity'
16
17
  end
17
18
 
18
19
  def connec_entity_name
19
20
  return entity_name unless external?
21
+
20
22
  raise 'Forbidden call: cannot call connec_entity_name for an external entity'
21
23
  end
22
24
 
@@ -16,6 +16,7 @@ class Maestrano::Connector::Rails::ApplicationPolicy
16
16
  def initialize(user, record)
17
17
  # Closed system: must be logged in to do anything
18
18
  raise Pundit::NotAuthorizedError, 'must be logged in' unless user
19
+
19
20
  @user = user
20
21
  @record = record
21
22
  end
@@ -16,6 +16,7 @@ module Maestrano
16
16
  def self.all_filters
17
17
  # Skipping if there is no tables as calling columns_hash in attribute_type is causing issue
18
18
  return unless tables_exists?
19
+
19
20
  _attributes.keys.each do |attribute|
20
21
  type = attribute_type(attribute)
21
22
  if type == :boolean
@@ -34,6 +35,7 @@ module Maestrano
34
35
  # iterating through all the api operator and adding them as custom filter
35
36
  # name.gt, name.like etc...
36
37
  next unless _model_class
38
+
37
39
  field = "#{_model_class.table_name}.#{key}"
38
40
 
39
41
  API_SQL_OPERATOR_MAPPING.each do |api_operator, sql_operator|
@@ -15,6 +15,7 @@ module Maestrano
15
15
  @model.tenant = context[:client]
16
16
  super
17
17
  return unless org_uid == context.dig(:params, :org_uid)
18
+
18
19
  org = Maestrano::Connector::Rails::Organization.find_by(org_uid: org_uid)
19
20
  org.add_member(@model) unless !org || org.member?(@model)
20
21
  end
@@ -1,7 +1,7 @@
1
1
  module Maestrano
2
2
  module Connector
3
3
  module Rails
4
- VERSION = '2.3.2'.freeze
4
+ VERSION = '2.3.3'.freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maestrano-connector-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maestrano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-26 00:00:00.000000000 Z
11
+ date: 2018-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -435,6 +435,7 @@ files:
435
435
  - app/controllers/maestrano/api/users_controller.rb
436
436
  - app/controllers/maestrano/application_controller.rb
437
437
  - app/controllers/maestrano/auth/saml_controller.rb
438
+ - app/controllers/maestrano/concerns/synchronizations_controller.rb
438
439
  - app/controllers/maestrano/connec_controller.rb
439
440
  - app/controllers/maestrano/dependancies_controller.rb
440
441
  - app/controllers/maestrano/sessions_controller.rb
@@ -563,7 +564,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
563
564
  version: '0'
564
565
  requirements: []
565
566
  rubyforge_project:
566
- rubygems_version: 2.7.6
567
+ rubygems_version: 2.6.14
567
568
  signing_key:
568
569
  specification_version: 4
569
570
  summary: Rails framework to build connector with Maestrano