canvas_sync 0.3.12 → 0.3.13

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
  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