canvas_sync 0.3.12 → 0.3.13

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
2
  SHA256:
3
- metadata.gz: 6c6eec06420fbb476e980bf7c1aae7d9f8679eb6b98558de1cb7765f5df13a12
4
- data.tar.gz: 60963185f828d72df3e2a24d3bb3d1d4cf4dde73c0e2a9ce38f0c2147c178d70
3
+ metadata.gz: 0e20004cc4e924da4afb400f82f223abcf3b384afda17db07e66923528586f35
4
+ data.tar.gz: d0b270232aa379fc899a19b20c659f71b6bbf211e2c0dea70f010f3b02a59678
5
5
  SHA512:
6
- metadata.gz: 45c726b97e96b370c84fa2393d4d4378a22f145bf3b7f4544c4f78f1aff2a0a0b40b76e3b9d5c5e920e3ff423f6da0e5b8893f6744f05de69dcbfdabe5ea42d4
7
- data.tar.gz: 02d4f57c81e21724da088b3bf877b88a507895da1fd595335a0f42581d82e3875646084ce229f0d58d6c5ad72b4e13e68712e1befab589bea2673193b3e7c9de
6
+ metadata.gz: cbe225d20cc4f43382d70c3594798f4cf69013ca3b9094a6180e0be0f71db98c97d924792bb9711fd4868f6b0afbf9a17ebed8e2c569c23fcf94a2d88a3caf7b
7
+ data.tar.gz: f3d814550bbeac5deb732ca77f49942f703a6cd3ddca1351d53b794181c33527f6604007fed4dd3619c9af851cc0590f50a42d0c32f9872360c44868c686e72a
data/README.md CHANGED
@@ -26,7 +26,7 @@ bundle exec rake db:migrate
26
26
 
27
27
  For a list of currently supported models, see `CanvasSync::SUPPORTED_MODELS`.
28
28
 
29
- Additionally, your Canvas instance must have the "Proserv Provisioning Report" enabled.
29
+ Additionally, your Canvas instance must have the "Proserv Provisioning Report" enabled. If you are syncing assignments the "Assignment Report" report must be enabled.
30
30
 
31
31
  ## Prerequisites
32
32
 
@@ -1,7 +1,9 @@
1
- class Api::V1::HealthCheckController < ActionController::Base
2
-
3
- def ping
4
- head :ok
1
+ module Api
2
+ module V1
3
+ class HealthCheckController < ActionController::Base
4
+ def ping
5
+ head :ok
6
+ end
7
+ end
5
8
  end
6
-
7
- end
9
+ end
@@ -1,16 +1,18 @@
1
- class Api::V1::LiveEventsController < ActionController::Base
2
-
3
- def process_event
4
- payload = SymmetricEncryption.decrypt(params[:payload])
5
- payload = JSON.parse(payload)
6
- Rails.logger.debug("Processing event type: #{payload['attributes']['event_name']}")
7
- Rails.logger.debug("Payload: #{payload}")
8
- event = "LiveEvents::#{payload['attributes']['event_name'].camelcase}Event".constantize
9
- event.perform_later(payload)
10
- head :ok
11
- rescue => e
12
- Rails.logger.error("Live Events Error: #{e.message} - #{e.backtrace}")
13
- render json: {error: "Live Events Error: #{e.message}"}, status: 422
1
+ module Api
2
+ module V1
3
+ class LiveEventsController < ActionController::Base
4
+ def process_event # rubocop:disable Metrics/AbcSize
5
+ payload = SymmetricEncryption.decrypt(params[:payload])
6
+ payload = JSON.parse(payload)
7
+ Rails.logger.debug("Processing event type: #{payload['attributes']['event_name']}")
8
+ Rails.logger.debug("Payload: #{payload}")
9
+ event = "LiveEvents::#{payload['attributes']['event_name'].camelcase}Event".constantize
10
+ event.perform_later(payload)
11
+ head :ok
12
+ rescue => e # rubocop:disable Style/RescueStandardError
13
+ Rails.logger.error("Live Events Error: #{e.message} - #{e.backtrace}")
14
+ render json: { error: "Live Events Error: #{e.message}" }, status: 422
15
+ end
16
+ end
14
17
  end
15
-
16
18
  end
@@ -5,7 +5,7 @@ module CanvasSync
5
5
  class JobLog < ApplicationRecord
6
6
  serialize :job_arguments, Array
7
7
 
8
- ERROR_STATUS = 'error'
9
- SUCCESS_STATUS = 'success'
8
+ ERROR_STATUS = "error".freeze
9
+ SUCCESS_STATUS = "success".freeze
10
10
  end
11
11
  end
@@ -1,7 +1,6 @@
1
1
  require "bearcat"
2
2
  require "canvas_sync/version"
3
3
  require "canvas_sync/engine"
4
-
5
4
  require "canvas_sync/job"
6
5
  require "canvas_sync/jobs/report_starter"
7
6
  require "canvas_sync/jobs/report_checker"
@@ -12,7 +11,6 @@ require "canvas_sync/jobs/sync_terms_job"
12
11
  require "canvas_sync/jobs/sync_users_job"
13
12
  require "canvas_sync/jobs/sync_roles_job"
14
13
  require "canvas_sync/jobs/sync_admins_job"
15
-
16
14
  Dir[File.dirname(__FILE__) + "/canvas_sync/processors/*.rb"].each { |file| require file }
17
15
  Dir[File.dirname(__FILE__) + "/canvas_sync/importers/*.rb"].each { |file| require file }
18
16
  Dir[File.dirname(__FILE__) + "/canvas_sync/generators/*.rb"].each { |file| require file }
@@ -77,36 +75,34 @@ module CanvasSync
77
75
  # @param account_id [Integer, nil] This optional parameter can be used if your Term creation and
78
76
  # canvas_sync_client methods require an account ID.
79
77
  # @return [Hash]
80
- def self.default_provisioning_report_chain(models, term_scope=nil, legacy_support=false, account_id=nil)
78
+ def self.default_provisioning_report_chain(models, term_scope=nil, legacy_support=false, account_id=nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/LineLength
81
79
  term_scope = term_scope.to_s if term_scope
82
80
 
83
-
84
81
  # Always sync Terms first
85
82
  jobs = [{ job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} }]
86
83
 
87
- if models.include?('users') && term_scope.present?
88
- # Sync all users first when scoping by term, because users cannot be scoped to term
89
- jobs.push({ job: CanvasSync::Jobs::SyncUsersJob.to_s, options: {} })
90
- models = models - ['users']
84
+ # Users, roles, and admins are synced before provisioning because they cannot be scoped to term
85
+ if models.include?("users") && term_scope.present?
86
+ jobs.push(job: CanvasSync::Jobs::SyncUsersJob.to_s, options: {})
87
+ models -= ["users"]
91
88
  end
92
89
 
93
- if models.include?('roles')
94
- # Sync all roles first when scoping by term, because roles cannot be scoped to term
95
- jobs.push({ job: CanvasSync::Jobs::SyncRolesJob.to_s, options: {} })
96
- models = models - ['roles']
90
+ if models.include?("roles")
91
+ jobs.push(job: CanvasSync::Jobs::SyncRolesJob.to_s, options: {})
92
+ models -= ["roles"]
97
93
  end
98
94
 
99
- if models.include?('admins')
100
- # Sync all admins first when scoping by term, because admins cannot be scoped to term
101
- jobs.push({ job: CanvasSync::Jobs::SyncAdminsJob.to_s, options: {} })
102
- models = models - ['admins']
95
+ if models.include?("admins")
96
+ jobs.push(job: CanvasSync::Jobs::SyncAdminsJob.to_s, options: {})
97
+ models -= ["admins"]
103
98
  end
104
99
 
105
- jobs.push(job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: term_scope, models: models })
100
+ jobs.push(
101
+ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s,
102
+ options: { term_scope: term_scope, models: models },
103
+ )
106
104
 
107
- if models.include?("assignments")
108
- jobs.push(job: CanvasSync::Jobs::SyncAssignmentsJob.to_s, options: {})
109
- end
105
+ jobs.push(job: CanvasSync::Jobs::SyncAssignmentsJob.to_s, options: {}) if models.include?("assignments")
110
106
 
111
107
  global_options = { legacy_support: legacy_support }
112
108
  global_options[:account_id] = account_id if account_id.present?
@@ -126,19 +122,15 @@ module CanvasSync
126
122
  end
127
123
  end
128
124
 
129
- private
130
-
131
125
  def self.validate_models!(models)
132
126
  invalid = models - SUPPORTED_MODELS
133
- if invalid.length > 0
134
- raise "Invalid model(s) specified: #{invalid.join(', ')}. Only #{SUPPORTED_MODELS.join(', ')} are supported."
135
- end
127
+ return if invalid.empty?
128
+ raise "Invalid model(s) specified: #{invalid.join(', ')}. Only #{SUPPORTED_MODELS.join(', ')} are supported."
136
129
  end
137
130
 
138
131
  def self.validate_live_events!(events)
139
132
  invalid = events - SUPPORTED_LIVE_EVENTS
140
- if invalid.length > 0
141
- raise "Invalid live event(s) specified: #{invalid.join(', ')}. Only #{SUPPORTED_LIVE_EVENTS.join(', ')} are supported."
142
- end
133
+ return if invalid.empty?
134
+ raise "Invalid live event(s) specified: #{invalid.join(', ')}. Only #{SUPPORTED_LIVE_EVENTS.join(', ')} are supported."
143
135
  end
144
136
  end
@@ -1,4 +1,4 @@
1
- require 'rails'
1
+ require "rails"
2
2
 
3
3
  module CanvasSync
4
4
  class Engine < ::Rails::Engine
@@ -9,7 +9,7 @@ module CanvasSync
9
9
  app.config.paths["db/migrate"] << expanded_path
10
10
  end
11
11
  # Apartment will modify this, but it doesn't fully support engine migrations, so we'll reset it here
12
- ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
12
+ ActiveRecord::Migrator.migrations_paths = Rails.application.paths["db/migrate"].to_a
13
13
  end
14
14
  end
15
15
  end
@@ -4,7 +4,7 @@ require "rails/generators/migration"
4
4
  module CanvasSync
5
5
  class InstallGenerator < Rails::Generators::Base
6
6
  include Rails::Generators::Migration
7
- source_root File.expand_path('../templates/models', __FILE__)
7
+ source_root File.expand_path("../templates/models", __FILE__)
8
8
  class_option :models, type: :string, required: true
9
9
 
10
10
  def self.next_migration_number(path)
@@ -42,7 +42,7 @@ module CanvasSync
42
42
  #
43
43
  # bin/rails generate canvas_sync:install --models all
44
44
  def generate_migrations_and_models
45
- models = options['models'] == 'all' ? CanvasSync::SUPPORTED_MODELS : options['models'].split(',')
45
+ models = options["models"] == "all" ? CanvasSync::SUPPORTED_MODELS : options["models"].split(",")
46
46
  CanvasSync.validate_models!(models)
47
47
 
48
48
  models.each do |model|
@@ -2,7 +2,7 @@ require "rails/generators"
2
2
 
3
3
  module CanvasSync
4
4
  class InstallLiveEventsGenerator < Rails::Generators::Base
5
- source_root File.expand_path('../templates/services/live_events', __FILE__)
5
+ source_root File.expand_path("../templates/services/live_events", __FILE__)
6
6
  class_option :events, type: :string, required: true
7
7
 
8
8
  def autogenerated_event_warning
@@ -24,15 +24,15 @@ module CanvasSync
24
24
  #
25
25
  # bin/rails generate canvas_sync:install_live_events --events all
26
26
  def generate_live_events
27
- events = options['events'] == 'all' ? CanvasSync::SUPPORTED_LIVE_EVENTS : options['events'].split(',')
27
+ events = options["events"] == "all" ? CanvasSync::SUPPORTED_LIVE_EVENTS : options["events"].split(",")
28
28
  CanvasSync.validate_live_events!(events)
29
29
 
30
30
  events.each do |event|
31
31
  Dir.glob("#{File.dirname(__FILE__)}/templates/services/live_events/#{event}/*.rb") do |rb_file|
32
- template "#{rb_file}", "app/services/live_events/#{File.basename(rb_file)}"
32
+ template rb_file.to_s, "app/services/live_events/#{File.basename(rb_file)}"
33
33
  end
34
34
  end
35
- template 'base_event.rb', 'app/services/live_events/base_event.rb'
35
+ template "base_event.rb", "app/services/live_events/base_event.rb"
36
36
  end
37
37
  end
38
38
  end
@@ -1,2 +1,4 @@
1
+ <%= autogenerated_event_warning %>
2
+
1
3
  class LiveEvents::SyllabusUpdatedEvent < LiveEvents::SyllabusEvent
2
- end
4
+ end
@@ -17,9 +17,9 @@ module CanvasSync
17
17
  # Note: passing the key [:on_duplicate_key_ignore] will override the default behavior of [:on_duplicate_key_update]
18
18
  # @yieldparam [Array] row if a block is passed in it will yield the current row from the CSV.
19
19
  # This can be used if you need to filter or massage the data in any way.
20
- def self.import(report_file_path, mapping, klass, conflict_target, import_args: {})
20
+ def self.import(report_file_path, mapping, klass, conflict_target, import_args: {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/LineLength
21
21
  csv_column_names = mapping.keys
22
- database_column_names = mapping.values.map {|value| value[:database_column_name]}
22
+ database_column_names = mapping.values.map { |value| value[:database_column_name] }
23
23
  rows = []
24
24
  row_ids = {}
25
25
 
@@ -32,9 +32,9 @@ module CanvasSync
32
32
 
33
33
  rows << csv_column_names.map do |column|
34
34
  if mapping[column][:type].to_sym == :datetime
35
- # todo - add some timezone config to the mapping.
35
+ # TODO: add some timezone config to the mapping.
36
36
  # In cases where the timestamp or date doesn't include a timezone, you should be able to specify one
37
- DateTime.parse(row[column]).utc rescue nil
37
+ DateTime.parse(row[column]).utc rescue nil # rubocop:disable Style/RescueModifier
38
38
  else
39
39
  row[column]
40
40
  end
@@ -50,17 +50,17 @@ module CanvasSync
50
50
  perform_import(klass, database_column_names, rows, mapping[conflict_target][:database_column_name], import_args)
51
51
  end
52
52
 
53
- private
54
-
55
53
  def self.perform_import(klass, columns, rows, conflict_target, import_args={})
56
- return if rows.length == 0
54
+ return if rows.length.zero?
57
55
  columns = columns.dup
58
- options = {validate: false, on_duplicate_key_update: {
59
- conflict_target: conflict_target,
60
- condition: condition_sql(klass, columns),
61
- columns: columns
62
- }}.merge(import_args)
63
- options.delete(:on_duplicate_key_update) if options.has_key?(:on_duplicate_key_ignore)
56
+
57
+ options = { validate: false, on_duplicate_key_update: {
58
+ conflict_target: conflict_target,
59
+ condition: condition_sql(klass, columns),
60
+ columns: columns
61
+ } }.merge(import_args)
62
+
63
+ options.delete(:on_duplicate_key_update) if options.key?(:on_duplicate_key_ignore)
64
64
  klass.import(columns, rows, options)
65
65
  end
66
66
 
@@ -75,13 +75,13 @@ module CanvasSync
75
75
  # run_the_users_sync!
76
76
  # changed = User.where("updated_at >= ?", started_at)
77
77
  def self.condition_sql(klass, columns)
78
- columns_str = columns.map {|c| "#{klass.quoted_table_name}.#{c}"}.join(", ")
79
- excluded_str = columns.map {|c| "EXCLUDED.#{c}"}.join(", ")
78
+ columns_str = columns.map { |c| "#{klass.quoted_table_name}.#{c}" }.join(", ")
79
+ excluded_str = columns.map { |c| "EXCLUDED.#{c}" }.join(", ")
80
80
  "(#{columns_str}) IS DISTINCT FROM (#{excluded_str})"
81
81
  end
82
82
 
83
83
  def self.batch_size
84
- batch_size = ENV['BULK_IMPORTER_BATCH_SIZE'].to_i
84
+ batch_size = ENV["BULK_IMPORTER_BATCH_SIZE"].to_i
85
85
  batch_size > 0 ? batch_size : DEFAULT_BATCH_SIZE
86
86
  end
87
87
  end
@@ -5,20 +5,20 @@ module CanvasSync
5
5
  class Job < ActiveJob::Base
6
6
  around_perform do |job, block|
7
7
  @job_log = CanvasSync::JobLog.create(
8
- started_at: Time.now,
9
- job_class: self.class.name,
10
- job_arguments: job.arguments
8
+ started_at: Time.now,
9
+ job_class: self.class.name,
10
+ job_arguments: job.arguments,
11
11
  )
12
12
 
13
13
  begin
14
14
  block.call
15
- rescue => e
15
+ rescue => e # rubocop:disable Style/RescueStandardError
16
16
  @job_log.exception = "#{e.class}: #{e.message}"
17
17
  @job_log.backtrace = e.backtrace
18
18
  @job_log.status = JobLog::ERROR_STATUS
19
19
  raise e
20
20
  ensure
21
- if @job_log.job_class == 'CanvasSync::Jobs::ReportChecker' && @job_log.status != JobLog::ERROR_STATUS
21
+ if @job_log.job_class == "CanvasSync::Jobs::ReportChecker" && @job_log.status != JobLog::ERROR_STATUS
22
22
  @job_log.destroy
23
23
  else
24
24
  @job_log.completed_at = Time.now
@@ -10,32 +10,34 @@ module CanvasSync
10
10
  # @param processor [String] a stringified report processor class name
11
11
  # @param options [Hash] hash of options that will be passed to the job processor
12
12
  # @return [nil]
13
- def perform(job_chain, report_name, report_id, processor, options)
14
- account_id = options[:account_id] || job_chain[:global_options][:account_id] || 'self'
15
- report_status = CanvasSync.get_canvas_sync_client(job_chain[:global_options]).report_status(account_id, report_name, report_id)
13
+ def perform(job_chain, report_name, report_id, processor, options) # rubocop:disable Metrics/AbcSize
14
+ account_id = options[:account_id] || job_chain[:global_options][:account_id] || "self"
15
+ report_status = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
16
+ .report_status(account_id, report_name, report_id)
16
17
 
17
- case report_status['status'].downcase
18
- when 'complete'
18
+ case report_status["status"].downcase
19
+ when "complete"
19
20
  CanvasSync::Jobs::ReportProcessorJob.perform_later(
20
- job_chain,
21
- report_name,
22
- report_status['attachment']['url'],
23
- processor,
24
- options
21
+ job_chain,
22
+ report_name,
23
+ report_status["attachment"]["url"],
24
+ processor,
25
+ options,
25
26
  )
26
- when 'error', 'deleted'
27
- message = "Report failed to process; status was #{report_status} for report_name: #{report_name}, report_id: #{report_id}"
27
+ when "error", "deleted"
28
+ message = "Report failed to process; status was #{report_status} for report_name: #{report_name}, report_id: #{report_id}" # rubocop:disable Metrics/LineLength
28
29
  Rails.logger.error(message)
29
30
  raise message
30
31
  else
31
- CanvasSync::Jobs::ReportChecker.set(wait: report_checker_wait_time)
32
- .perform_later(
33
- job_chain,
34
- report_name,
35
- report_id,
36
- processor,
37
- options
38
- )
32
+ CanvasSync::Jobs::ReportChecker
33
+ .set(wait: report_checker_wait_time)
34
+ .perform_later(
35
+ job_chain,
36
+ report_name,
37
+ report_id,
38
+ processor,
39
+ options,
40
+ )
39
41
  end
40
42
  end
41
43
  end
@@ -1,4 +1,4 @@
1
- require 'open-uri'
1
+ require "open-uri"
2
2
 
3
3
  module CanvasSync
4
4
  module Jobs
@@ -11,7 +11,7 @@ module CanvasSync
11
11
  # so that any later jobs in the chain will use the same generated report
12
12
  # @return [nil]
13
13
  def perform(job_chain, report_name, report_params, processor, options, allow_redownloads: false)
14
- account_id = options[:account_id] || job_chain[:global_options][:account_id] || 'self'
14
+ account_id = options[:account_id] || job_chain[:global_options][:account_id] || "self"
15
15
 
16
16
  report_id = if allow_redownloads
17
17
  get_cached_report(job_chain, account_id, report_name, report_params)
@@ -20,11 +20,11 @@ module CanvasSync
20
20
  end
21
21
 
22
22
  CanvasSync::Jobs::ReportChecker.set(wait: report_checker_wait_time).perform_later(
23
- job_chain,
24
- report_name,
25
- report_id,
26
- processor,
27
- options
23
+ job_chain,
24
+ report_name,
25
+ report_id,
26
+ processor,
27
+ options,
28
28
  )
29
29
  end
30
30
 
@@ -41,8 +41,9 @@ module CanvasSync
41
41
  end
42
42
 
43
43
  def start_report(job_chain, account_id, report_name, report_params)
44
- report = CanvasSync.get_canvas_sync_client(job_chain[:global_options]).start_report(account_id, report_name, report_params)
45
- report['id']
44
+ report = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
45
+ .start_report(account_id, report_name, report_params)
46
+ report["id"]
46
47
  end
47
48
  end
48
49
  end
@@ -6,9 +6,9 @@ module CanvasSync
6
6
  #
7
7
  # @param job_chain [Hash]
8
8
  # @param options [Hash]
9
- def perform(job_chain, options)
9
+ def perform(job_chain, _options)
10
10
  updated_admins = []
11
- CanvasSync.get_canvas_sync_client(job_chain[:global_options]).account_admins('self').all_pages!.each do |admin_params|
11
+ CanvasSync.get_canvas_sync_client(job_chain[:global_options]).account_admins("self").all_pages!.each do |admin_params|
12
12
  admin = Admin.create_or_update(admin_params)
13
13
  updated_admins.push(admin.id)
14
14
  end