canvas_sync 0.13.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/canvas_sync.rb +69 -15
- data/lib/canvas_sync/concerns/api_syncable.rb +1 -1
- data/lib/canvas_sync/concerns/legacy_columns.rb +5 -4
- data/lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb +18 -0
- data/lib/canvas_sync/generators/templates/migrations/create_groups.rb +23 -0
- data/lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb +18 -0
- data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/account.rb +4 -0
- data/lib/canvas_sync/generators/templates/models/course.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/group.rb +19 -0
- data/lib/canvas_sync/generators/templates/models/group_membership.rb +17 -0
- data/lib/canvas_sync/generators/templates/models/pseudonym.rb +8 -0
- data/lib/canvas_sync/generators/templates/models/submission.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/user.rb +2 -0
- data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +2 -0
- data/lib/canvas_sync/processors/model_mappings.yml +81 -0
- data/lib/canvas_sync/processors/provisioning_report_processor.rb +28 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/canvas_sync/canvas_sync_spec.rb +5 -2
- data/spec/canvas_sync/models/accounts_spec.rb +3 -0
- data/spec/canvas_sync/models/course_spec.rb +4 -0
- data/spec/canvas_sync/models/group_membership_spec.rb +26 -0
- data/spec/canvas_sync/models/group_spec.rb +26 -0
- data/spec/canvas_sync/models/user_spec.rb +2 -0
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +20 -0
- data/spec/dummy/app/models/account.rb +1 -0
- data/spec/dummy/app/models/course.rb +1 -0
- data/spec/dummy/app/models/group.rb +25 -0
- data/spec/dummy/app/models/group_membership.rb +23 -0
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/db/migrate/20190702203627_create_submissions.rb +1 -0
- data/spec/dummy/db/migrate/20200415171620_create_groups.rb +29 -0
- data/spec/dummy/db/migrate/20200416214248_create_group_memberships.rb +24 -0
- data/spec/dummy/db/schema.rb +31 -1
- data/spec/factories/group_factory.rb +8 -0
- data/spec/factories/group_membership_factory.rb +6 -0
- data/spec/support/fixtures/reports/group_memberships.csv +3 -0
- data/spec/support/fixtures/reports/groups.csv +3 -0
- data/spec/support/fixtures/reports/submissions.csv +3 -3
- metadata +33 -10
- data/lib/canvas_sync/jobs/sync_users_job.rb +0 -26
- data/spec/canvas_sync/jobs/sync_users_job_spec.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c6655d28b3ac244a94cd59da9f76f6878658bff43d1ca071dd7718b82a505ad
|
4
|
+
data.tar.gz: e8ee3801761dd8a84d80ea162ff11e079b219e1d1992788aecd49451c59efaf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47a9f7e858cb510f191d1c62f99f112384dc62d3d9d62365369bad5b275d0168d1d5ace94a32b7f76921ee072ae49d3b940e6d56c2aeb51601e9daf52c86b36e
|
7
|
+
data.tar.gz: 84c5b5c9816a2ff8578bb32892739a8737fb6049526f24ef1416d7a5f404fc385f808ca9a7739b1d971baf06f81fe172351015332fe56a67a2e64417158e60d3
|
data/lib/canvas_sync.rb
CHANGED
@@ -22,7 +22,10 @@ Dir[File.dirname(__FILE__) + "/canvas_sync/concerns/**/*.rb"].each { |file| req
|
|
22
22
|
module CanvasSync
|
23
23
|
SUPPORTED_MODELS = %w[
|
24
24
|
users
|
25
|
+
pseudonyms
|
25
26
|
courses
|
27
|
+
groups
|
28
|
+
group_memberships
|
26
29
|
accounts
|
27
30
|
terms
|
28
31
|
enrollments
|
@@ -143,6 +146,10 @@ module CanvasSync
|
|
143
146
|
terms.each do |t|
|
144
147
|
return scope.send(t) if scope.respond_to?(t)
|
145
148
|
end
|
149
|
+
model = scope.try(:model) || scope
|
150
|
+
if model.try(:column_names)&.include?(:workflow_state)
|
151
|
+
return scope.where.not(workflow_state: %w[deleted])
|
152
|
+
end
|
146
153
|
Rails.logger.warn("Could not filter Syncable Scope for model '#{scope.try(:model)&.name || scope.name}'")
|
147
154
|
scope
|
148
155
|
end
|
@@ -193,7 +200,6 @@ module CanvasSync
|
|
193
200
|
model_job_map = {
|
194
201
|
terms: CanvasSync::Jobs::SyncTermsJob,
|
195
202
|
accounts: CanvasSync::Jobs::SyncAccountsJob,
|
196
|
-
users: CanvasSync::Jobs::SyncUsersJob,
|
197
203
|
roles: CanvasSync::Jobs::SyncRolesJob,
|
198
204
|
admins: CanvasSync::Jobs::SyncAdminsJob,
|
199
205
|
|
@@ -221,35 +227,41 @@ module CanvasSync
|
|
221
227
|
|
222
228
|
# Accounts, users, roles, and admins are synced before provisioning because they cannot be scoped to term
|
223
229
|
try_add_model_job.call('accounts')
|
224
|
-
|
230
|
+
|
231
|
+
# These Models use the provisioning report, but are not term-scoped,
|
232
|
+
# so we sync them before to ensure work is not duplicated
|
233
|
+
if term_scope.present?
|
234
|
+
models -= (first_provisioning_models = models & ['users', 'pseudonyms'])
|
235
|
+
jobs.concat(
|
236
|
+
generate_provisioning_jobs(first_provisioning_models, options)
|
237
|
+
)
|
238
|
+
end
|
239
|
+
|
225
240
|
try_add_model_job.call('roles')
|
226
241
|
try_add_model_job.call('admins')
|
227
|
-
|
228
242
|
pre_provisioning_jobs = jobs
|
229
|
-
jobs = []
|
230
243
|
|
231
244
|
###############################
|
232
245
|
# Post provisioning report jobs
|
233
246
|
###############################
|
234
247
|
|
248
|
+
jobs = []
|
235
249
|
try_add_model_job.call('assignments')
|
236
250
|
try_add_model_job.call('submissions')
|
237
251
|
try_add_model_job.call('assignment_groups')
|
238
252
|
try_add_model_job.call('context_modules')
|
239
253
|
try_add_model_job.call('context_module_items')
|
240
|
-
|
241
254
|
post_provisioning_jobs = jobs
|
242
255
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
jobs += post_provisioning_jobs
|
256
|
+
###############################
|
257
|
+
# Main provisioning job and queueing
|
258
|
+
###############################
|
259
|
+
|
260
|
+
jobs = [
|
261
|
+
*pre_provisioning_jobs,
|
262
|
+
*generate_provisioning_jobs(models, options, job_options: { term_scope: term_scope }, only_split: ['users']),
|
263
|
+
*post_provisioning_jobs,
|
264
|
+
]
|
253
265
|
|
254
266
|
global_options = { legacy_support: legacy_support }
|
255
267
|
global_options[:account_id] = account_id if account_id.present?
|
@@ -258,6 +270,48 @@ module CanvasSync
|
|
258
270
|
JobChain.new(jobs: jobs, global_options: global_options)
|
259
271
|
end
|
260
272
|
|
273
|
+
def group_by_job_options(model_list, options_hash, only_split: nil, default_key: :provisioning)
|
274
|
+
dup_models = [ *model_list ]
|
275
|
+
unique_option_models = {}
|
276
|
+
|
277
|
+
filtered_models = only_split ? (only_split & model_list) : model_list
|
278
|
+
filtered_models.each do |m|
|
279
|
+
mopts = options_hash[m.to_sym] || options_hash[default_key]
|
280
|
+
unique_option_models[mopts] ||= []
|
281
|
+
unique_option_models[mopts] << m
|
282
|
+
dup_models.delete(m)
|
283
|
+
end
|
284
|
+
|
285
|
+
if dup_models.present?
|
286
|
+
mopts = options_hash[default_key]
|
287
|
+
unique_option_models[mopts] ||= []
|
288
|
+
unique_option_models[mopts].concat(dup_models)
|
289
|
+
end
|
290
|
+
|
291
|
+
unique_option_models
|
292
|
+
end
|
293
|
+
|
294
|
+
def generate_provisioning_jobs(model_list, options_hash, job_options: {}, only_split: nil, default_key: :provisioning)
|
295
|
+
# Group the model options as best we can.
|
296
|
+
# This is mainly for backwards compatibility, since 'users' was previously it's own job
|
297
|
+
unique_option_models = group_by_job_options(
|
298
|
+
model_list,
|
299
|
+
options_hash,
|
300
|
+
only_split: only_split,
|
301
|
+
default_key: default_key,
|
302
|
+
)
|
303
|
+
|
304
|
+
unique_option_models.map do |mopts, models|
|
305
|
+
opts = { models: models }
|
306
|
+
opts.merge!(job_options)
|
307
|
+
opts.merge!(mopts) if mopts.present?
|
308
|
+
{
|
309
|
+
job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s,
|
310
|
+
options: opts,
|
311
|
+
}
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
261
315
|
# Calls the canvas_sync_client in your app. If you have specified an account
|
262
316
|
# ID when starting the job it will pass the account ID to your canvas_sync_client method.
|
263
317
|
#
|
@@ -146,7 +146,7 @@ module CanvasSync::Concerns
|
|
146
146
|
# Apply a response Hash from the API to this model's attributes and save if changed?
|
147
147
|
# @param [Hash] api_params API-format Hash
|
148
148
|
# @return [self] self
|
149
|
-
def update_from_api_params(
|
149
|
+
def update_from_api_params(*args)
|
150
150
|
assign_from_api_params(*args)
|
151
151
|
save if changed?
|
152
152
|
end
|
@@ -15,13 +15,14 @@ module CanvasSync::Concerns
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def legacy_column_apply(cls)
|
18
|
-
|
19
|
-
|
18
|
+
return if cls.abstract_class
|
19
|
+
cid_column = "canvas_#{cls.name.downcase}_id"
|
20
|
+
column_names = cls.columns.map(&:name)
|
20
21
|
return if column_names.include?('canvas_id') && column_names.include?(cid_column)
|
21
22
|
if column_names.include?('canvas_id')
|
22
|
-
|
23
|
+
cls.alias_attribute(cid_column.to_sym, :canvas_id)
|
23
24
|
elsif column_names.include?(cid_column)
|
24
|
-
|
25
|
+
cls.alias_attribute(:canvas_id, cid_column.to_sym)
|
25
26
|
end
|
26
27
|
rescue ActiveRecord::StatementInvalid
|
27
28
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# <%= autogenerated_migration_warning %>
|
2
|
+
|
3
|
+
class CreateGroupMemberships < ActiveRecord::Migration[5.1]
|
4
|
+
def change
|
5
|
+
create_table :group_memberships do |t|
|
6
|
+
t.bigint :canvas_id, null: false
|
7
|
+
t.bigint :canvas_user_id, null: false
|
8
|
+
t.bigint :canvas_group_id, null: false
|
9
|
+
t.string :group_sis_id
|
10
|
+
t.string :user_sis_id
|
11
|
+
t.string :workflow_state
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :group_memberships, :canvas_id, unique: true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# <%= autogenerated_migration_warning %>
|
2
|
+
|
3
|
+
class CreateGroups < ActiveRecord::Migration[5.1]
|
4
|
+
def change
|
5
|
+
create_table :groups do |t|
|
6
|
+
t.bigint :canvas_id, null: false
|
7
|
+
t.string :sis_id
|
8
|
+
t.bigint :canvas_group_category_id
|
9
|
+
t.string :group_category_sis_id
|
10
|
+
t.bigint :canvas_account_id
|
11
|
+
t.bigint :canvas_course_id
|
12
|
+
t.string :name
|
13
|
+
t.string :workflow_state
|
14
|
+
t.bigint :context_id
|
15
|
+
t.string :context_type
|
16
|
+
t.integer :max_membership
|
17
|
+
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
|
21
|
+
add_index :groups, :canvas_id, unique: true
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# <%= autogenerated_migration_warning %>
|
2
|
+
|
3
|
+
class CreatePseudonyms < ActiveRecord::Migration[5.1]
|
4
|
+
def change
|
5
|
+
create_table :pseudonyms do |t|
|
6
|
+
t.bigint :canvas_id, null: false
|
7
|
+
t.bigint :canvas_user_id
|
8
|
+
t.string :sis_id
|
9
|
+
t.string :unique_id
|
10
|
+
t.string :workflow_state
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :pseudonyms, :canvas_id, unique: true
|
16
|
+
add_index :pseudonyms, :canvas_user_id
|
17
|
+
end
|
18
|
+
end
|
@@ -12,6 +12,10 @@ class Account < ApplicationRecord
|
|
12
12
|
primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
|
13
13
|
has_many :sub_accounts, class_name: 'Account',
|
14
14
|
primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
|
15
|
+
has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
|
16
|
+
|
17
|
+
scope :active, -> { where.not(workflow_state: 'deleted') }
|
18
|
+
# scope :should_canvas_sync, -> { active } # Optional - uses .active if not given
|
15
19
|
|
16
20
|
api_syncable({
|
17
21
|
name: :name,
|
@@ -11,6 +11,7 @@ class Course < ApplicationRecord
|
|
11
11
|
has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
|
12
12
|
has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
13
13
|
has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
14
|
+
has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
14
15
|
|
15
16
|
api_syncable({
|
16
17
|
sis_id: :sis_course_id,
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# <%= autogenerated_model_warning %>
|
2
|
+
|
3
|
+
class Group < ApplicationRecord
|
4
|
+
include CanvasSync::Record
|
5
|
+
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
|
7
|
+
validates :canvas_id, uniqueness: true, presence: true
|
8
|
+
belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
|
9
|
+
belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
|
10
|
+
has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
|
11
|
+
|
12
|
+
api_syncable({
|
13
|
+
canvas_id: :id,
|
14
|
+
name: :name,
|
15
|
+
canvas_course_id: :course_id,
|
16
|
+
sis_id: :sis_group_id,
|
17
|
+
workflow_state: ->(r){ 'available' },
|
18
|
+
}, -> (api) { api.group(canvas_id) })
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# <%= autogenerated_model_warning %>
|
2
|
+
|
3
|
+
class GroupMembership < ApplicationRecord
|
4
|
+
include CanvasSync::Record
|
5
|
+
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
|
7
|
+
validates :canvas_id, uniqueness: true, presence: true
|
8
|
+
belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
|
9
|
+
belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
10
|
+
|
11
|
+
api_syncable({
|
12
|
+
canvas_id: :id,
|
13
|
+
canvas_group_id: :group_id,
|
14
|
+
canvas_user_id: :user_id,
|
15
|
+
workflow_state: :workflow_state,
|
16
|
+
}, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
|
17
|
+
end
|
@@ -5,10 +5,12 @@ class User < ApplicationRecord
|
|
5
5
|
include CanvasSync::Concerns::ApiSyncable
|
6
6
|
|
7
7
|
validates :canvas_id, uniqueness: true, presence: true
|
8
|
+
has_many :pseudonyms, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
8
9
|
has_many :enrollments, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
9
10
|
has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
10
11
|
has_many :admin_roles, through: :admins, source: :role
|
11
12
|
has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
13
|
+
has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
12
14
|
|
13
15
|
api_syncable({
|
14
16
|
sis_id: :sis_user_id,
|
@@ -29,6 +29,25 @@ users:
|
|
29
29
|
database_column_name: login_id
|
30
30
|
type: string
|
31
31
|
|
32
|
+
pseudonyms:
|
33
|
+
conflict_target: pseudonym_id
|
34
|
+
report_columns:
|
35
|
+
pseudonym_id:
|
36
|
+
database_column_name: canvas_id
|
37
|
+
type: integer
|
38
|
+
canvas_user_id:
|
39
|
+
database_column_name: canvas_user_id
|
40
|
+
type: integer
|
41
|
+
sis_user_id:
|
42
|
+
database_column_name: sis_id
|
43
|
+
type: string
|
44
|
+
unique_id:
|
45
|
+
database_column_name: unique_id
|
46
|
+
type: string
|
47
|
+
status:
|
48
|
+
database_column_name: workflow_state
|
49
|
+
type: string
|
50
|
+
|
32
51
|
accounts:
|
33
52
|
conflict_target: canvas_account_id
|
34
53
|
report_columns:
|
@@ -230,6 +249,9 @@ submissions:
|
|
230
249
|
submission_date:
|
231
250
|
database_column_name: submitted_at
|
232
251
|
type: datetime
|
252
|
+
due_at:
|
253
|
+
database_column_name: due_at
|
254
|
+
type: datetime
|
233
255
|
graded_date:
|
234
256
|
database_column_name: graded_at
|
235
257
|
type: datetime
|
@@ -326,3 +348,62 @@ context_module_items:
|
|
326
348
|
assignment_id:
|
327
349
|
database_column_name: canvas_assignment_id
|
328
350
|
type: integer
|
351
|
+
|
352
|
+
groups:
|
353
|
+
conflict_target: canvas_group_id
|
354
|
+
report_columns:
|
355
|
+
canvas_group_id:
|
356
|
+
database_column_name: canvas_id
|
357
|
+
type: integer
|
358
|
+
group_id:
|
359
|
+
database_column_name: sis_id
|
360
|
+
type: string
|
361
|
+
canvas_group_category_id:
|
362
|
+
database_column_name: canvas_group_category_id
|
363
|
+
type: integer
|
364
|
+
group_category_id:
|
365
|
+
database_column_name: group_category_sis_id
|
366
|
+
type: integer
|
367
|
+
canvas_account_id:
|
368
|
+
database_column_name: canvas_account_id
|
369
|
+
type: integer
|
370
|
+
canvas_course_id:
|
371
|
+
database_column_name: canvas_course_id
|
372
|
+
type: integer
|
373
|
+
name:
|
374
|
+
database_column_name: name
|
375
|
+
type: string
|
376
|
+
status:
|
377
|
+
database_column_name: workflow_state
|
378
|
+
type: string
|
379
|
+
context_id:
|
380
|
+
database_column_name: context_id
|
381
|
+
type: integer
|
382
|
+
context_type:
|
383
|
+
database_column_name: context_type
|
384
|
+
type: string
|
385
|
+
max_membership:
|
386
|
+
database_column_name: max_membership
|
387
|
+
type: integer
|
388
|
+
|
389
|
+
group_memberships:
|
390
|
+
conflict_target: canvas_group_membership_id
|
391
|
+
report_columns:
|
392
|
+
canvas_group_membership_id:
|
393
|
+
database_column_name: canvas_id
|
394
|
+
type: integer
|
395
|
+
canvas_group_id:
|
396
|
+
database_column_name: canvas_group_id
|
397
|
+
type: integer
|
398
|
+
group_id:
|
399
|
+
database_column_name: group_sis_id
|
400
|
+
type: string
|
401
|
+
canvas_user_id:
|
402
|
+
database_column_name: canvas_user_id
|
403
|
+
type: integer
|
404
|
+
user_id:
|
405
|
+
database_column_name: user_sis_id
|
406
|
+
type: string
|
407
|
+
status:
|
408
|
+
database_column_name: workflow_state
|
409
|
+
type: string
|
@@ -78,6 +78,15 @@ module CanvasSync
|
|
78
78
|
)
|
79
79
|
end
|
80
80
|
|
81
|
+
def bulk_process_pseudonyms(report_file_path)
|
82
|
+
CanvasSync::Importers::BulkImporter.import(
|
83
|
+
report_file_path,
|
84
|
+
mapping[:pseudonyms][:report_columns],
|
85
|
+
Pseudonym,
|
86
|
+
mapping[:pseudonyms][:conflict_target].to_sym,
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
81
90
|
def bulk_process_accounts(report_file_path)
|
82
91
|
CanvasSync::Importers::BulkImporter.import(
|
83
92
|
report_file_path,
|
@@ -122,6 +131,25 @@ module CanvasSync
|
|
122
131
|
mapping[:xlist][:conflict_target].to_sym,
|
123
132
|
)
|
124
133
|
end
|
134
|
+
|
135
|
+
def bulk_process_groups(report_file_path)
|
136
|
+
CanvasSync::Importers::BulkImporter.import(
|
137
|
+
report_file_path,
|
138
|
+
mapping[:groups][:report_columns],
|
139
|
+
Group,
|
140
|
+
mapping[:groups][:conflict_target].to_sym,
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Note that group membership is singular because we override the model name param in sync_provisioning_report_job
|
145
|
+
def bulk_process_group_membership(report_file_path)
|
146
|
+
CanvasSync::Importers::BulkImporter.import(
|
147
|
+
report_file_path,
|
148
|
+
mapping[:group_memberships][:report_columns],
|
149
|
+
GroupMembership,
|
150
|
+
mapping[:group_memberships][:conflict_target].to_sym,
|
151
|
+
)
|
152
|
+
end
|
125
153
|
end
|
126
154
|
end
|
127
155
|
end
|
data/lib/canvas_sync/version.rb
CHANGED
@@ -34,7 +34,7 @@ RSpec.describe CanvasSync do
|
|
34
34
|
expect(chain.chain_data).to eq({
|
35
35
|
jobs: [
|
36
36
|
{ job: CanvasSync::Jobs::SyncTermsJob.to_s, options: { a: 1 } },
|
37
|
-
{ job: CanvasSync::Jobs::
|
37
|
+
{ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'], b: 2 } },
|
38
38
|
{ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'], c: 3 } }
|
39
39
|
],
|
40
40
|
global_options: { legacy_support: false, d: 4 }
|
@@ -47,7 +47,7 @@ RSpec.describe CanvasSync do
|
|
47
47
|
expect(chain.chain_data).to eq({
|
48
48
|
jobs: [
|
49
49
|
{ job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
|
50
|
-
{ job: CanvasSync::Jobs::
|
50
|
+
{ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'] } },
|
51
51
|
{ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'] } }
|
52
52
|
],
|
53
53
|
global_options: { legacy_support: false }
|
@@ -247,4 +247,7 @@ RSpec.describe CanvasSync do
|
|
247
247
|
end
|
248
248
|
end
|
249
249
|
|
250
|
+
describe ".sync_scope" do
|
251
|
+
|
252
|
+
end
|
250
253
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe GroupMembership, type: :model do
|
4
|
+
let(:subject) {
|
5
|
+
FactoryGirl.create(:group_membership, group: FactoryGirl.create(:group), user: FactoryGirl.create(:user))
|
6
|
+
}
|
7
|
+
|
8
|
+
describe 'validations' do
|
9
|
+
it { should validate_presence_of(:canvas_id) }
|
10
|
+
it { should validate_uniqueness_of(:canvas_id) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'associations' do
|
14
|
+
it do
|
15
|
+
should belong_to(:group)
|
16
|
+
.with_primary_key(:canvas_id)
|
17
|
+
.with_foreign_key(:canvas_group_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
it do
|
21
|
+
should belong_to(:user)
|
22
|
+
.with_primary_key(:canvas_id)
|
23
|
+
.with_foreign_key(:canvas_user_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Group, type: :model do
|
4
|
+
let(:subject) { FactoryGirl.create(:group) }
|
5
|
+
|
6
|
+
describe 'validations' do
|
7
|
+
it { should validate_presence_of(:canvas_id) }
|
8
|
+
it { should validate_uniqueness_of(:canvas_id) }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'associations' do
|
12
|
+
it { should have_many(:group_memberships) }
|
13
|
+
|
14
|
+
it do
|
15
|
+
should belong_to(:course)
|
16
|
+
.with_primary_key(:canvas_id)
|
17
|
+
.with_foreign_key(:canvas_course_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
it do
|
21
|
+
should belong_to(:account)
|
22
|
+
.with_primary_key(:canvas_id)
|
23
|
+
.with_foreign_key(:canvas_account_id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -42,6 +42,26 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
|
|
42
42
|
expect(cross_listed_section.canvas_nonxlist_course_id).to eq 2
|
43
43
|
end
|
44
44
|
|
45
|
+
it 'processes groups' do
|
46
|
+
expect {
|
47
|
+
subject.process('spec/support/fixtures/reports/groups.csv', { models: ['groups'] }, 1)
|
48
|
+
}.to change { Group.count }.by(2)
|
49
|
+
group = Group.find_by_name('Group1')
|
50
|
+
expect(group.workflow_state).to eq 'available'
|
51
|
+
expect(group.canvas_account_id).to eq 1
|
52
|
+
expect(group.canvas_id).to eq 50
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'processes group memberships' do
|
56
|
+
expect {
|
57
|
+
subject.process('spec/support/fixtures/reports/group_memberships.csv', { models: ['group_membership'] }, 1)
|
58
|
+
}.to change { GroupMembership.count }.by(2)
|
59
|
+
group = GroupMembership.find_by_canvas_id(50)
|
60
|
+
expect(group.workflow_state).to eq 'accepted'
|
61
|
+
expect(group.canvas_group_id).to eq 1
|
62
|
+
expect(group.canvas_user_id).to eq 10
|
63
|
+
end
|
64
|
+
|
45
65
|
context 'options[:models] is multiple models' do
|
46
66
|
it 'extracts the ZIP and processes each model' do
|
47
67
|
user_count = User.count
|
@@ -18,6 +18,7 @@ class Account < ApplicationRecord
|
|
18
18
|
primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
|
19
19
|
has_many :sub_accounts, class_name: 'Account',
|
20
20
|
primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
|
21
|
+
has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
|
21
22
|
|
22
23
|
api_syncable({
|
23
24
|
name: :name,
|
@@ -17,6 +17,7 @@ class Course < ApplicationRecord
|
|
17
17
|
has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
|
18
18
|
has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
19
19
|
has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
20
|
+
has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
|
20
21
|
|
21
22
|
api_syncable({
|
22
23
|
sis_id: :sis_course_id,
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# #
|
2
|
+
# AUTO GENERATED MODEL
|
3
|
+
# This model was auto generated by the CanvasSync Gem.
|
4
|
+
# You can customize it as needed, but make sure you test
|
5
|
+
# any changes you make to the auto generated methods.
|
6
|
+
#
|
7
|
+
|
8
|
+
|
9
|
+
class Group < ApplicationRecord
|
10
|
+
include CanvasSync::Record
|
11
|
+
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
|
13
|
+
validates :canvas_id, uniqueness: true, presence: true
|
14
|
+
belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
|
15
|
+
belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
|
16
|
+
has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
|
17
|
+
|
18
|
+
api_syncable({
|
19
|
+
canvas_id: :id,
|
20
|
+
name: :name,
|
21
|
+
canvas_course_id: :course_id,
|
22
|
+
sis_id: :sis_group_id,
|
23
|
+
workflow_state: ->(r){ 'available' },
|
24
|
+
}, -> (api) { api.group(canvas_id) })
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# #
|
2
|
+
# AUTO GENERATED MODEL
|
3
|
+
# This model was auto generated by the CanvasSync Gem.
|
4
|
+
# You can customize it as needed, but make sure you test
|
5
|
+
# any changes you make to the auto generated methods.
|
6
|
+
#
|
7
|
+
|
8
|
+
|
9
|
+
class GroupMembership < ApplicationRecord
|
10
|
+
include CanvasSync::Record
|
11
|
+
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
|
13
|
+
validates :canvas_id, uniqueness: true, presence: true
|
14
|
+
belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
|
15
|
+
belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
16
|
+
|
17
|
+
api_syncable({
|
18
|
+
canvas_id: :id,
|
19
|
+
canvas_group_id: :group_id,
|
20
|
+
canvas_user_id: :user_id,
|
21
|
+
workflow_state: :workflow_state,
|
22
|
+
}, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
|
23
|
+
end
|
@@ -15,6 +15,7 @@ class User < ApplicationRecord
|
|
15
15
|
has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
16
16
|
has_many :admin_roles, through: :admins, source: :role
|
17
17
|
has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
18
|
+
has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
18
19
|
|
19
20
|
api_syncable({
|
20
21
|
sis_id: :sis_user_id,
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# #
|
2
|
+
# AUTO GENERATED MIGRATION
|
3
|
+
# This migration was auto generated by the CanvasSync Gem.
|
4
|
+
# You can add new columns to this table, but removing or
|
5
|
+
# re-naming ones created here may break Canvas Syncing.
|
6
|
+
#
|
7
|
+
|
8
|
+
|
9
|
+
class CreateGroups < ActiveRecord::Migration[5.1]
|
10
|
+
def change
|
11
|
+
create_table :groups do |t|
|
12
|
+
t.bigint :canvas_id, null: false
|
13
|
+
t.string :sis_id
|
14
|
+
t.bigint :canvas_group_category_id
|
15
|
+
t.string :group_category_sis_id
|
16
|
+
t.bigint :canvas_account_id
|
17
|
+
t.bigint :canvas_course_id
|
18
|
+
t.string :name
|
19
|
+
t.string :workflow_state
|
20
|
+
t.bigint :context_id
|
21
|
+
t.string :context_type
|
22
|
+
t.integer :max_membership
|
23
|
+
|
24
|
+
t.timestamps
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index :groups, :canvas_id, unique: true
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# #
|
2
|
+
# AUTO GENERATED MIGRATION
|
3
|
+
# This migration was auto generated by the CanvasSync Gem.
|
4
|
+
# You can add new columns to this table, but removing or
|
5
|
+
# re-naming ones created here may break Canvas Syncing.
|
6
|
+
#
|
7
|
+
|
8
|
+
|
9
|
+
class CreateGroupMemberships < ActiveRecord::Migration[5.1]
|
10
|
+
def change
|
11
|
+
create_table :group_memberships do |t|
|
12
|
+
t.bigint :canvas_id, null: false
|
13
|
+
t.bigint :canvas_user_id, null: false
|
14
|
+
t.bigint :canvas_group_id, null: false
|
15
|
+
t.string :group_sis_id
|
16
|
+
t.string :user_sis_id
|
17
|
+
t.string :workflow_state
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :group_memberships, :canvas_id, unique: true
|
23
|
+
end
|
24
|
+
end
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 2020_04_16_214248) do
|
14
14
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
16
16
|
enable_extension "plpgsql"
|
@@ -162,6 +162,35 @@ ActiveRecord::Schema.define(version: 20190927204546) do
|
|
162
162
|
t.index ["canvas_user_id"], name: "index_enrollments_on_canvas_user_id"
|
163
163
|
end
|
164
164
|
|
165
|
+
create_table "group_memberships", force: :cascade do |t|
|
166
|
+
t.bigint "canvas_id", null: false
|
167
|
+
t.bigint "canvas_user_id", null: false
|
168
|
+
t.bigint "canvas_group_id", null: false
|
169
|
+
t.string "group_sis_id"
|
170
|
+
t.string "user_sis_id"
|
171
|
+
t.string "workflow_state"
|
172
|
+
t.datetime "created_at", null: false
|
173
|
+
t.datetime "updated_at", null: false
|
174
|
+
t.index ["canvas_id"], name: "index_group_memberships_on_canvas_id", unique: true
|
175
|
+
end
|
176
|
+
|
177
|
+
create_table "groups", force: :cascade do |t|
|
178
|
+
t.bigint "canvas_id", null: false
|
179
|
+
t.string "sis_id"
|
180
|
+
t.bigint "canvas_group_category_id"
|
181
|
+
t.string "group_category_sis_id"
|
182
|
+
t.bigint "canvas_account_id"
|
183
|
+
t.bigint "canvas_course_id"
|
184
|
+
t.string "name"
|
185
|
+
t.string "workflow_state"
|
186
|
+
t.bigint "context_id"
|
187
|
+
t.string "context_type"
|
188
|
+
t.integer "max_membership"
|
189
|
+
t.datetime "created_at", null: false
|
190
|
+
t.datetime "updated_at", null: false
|
191
|
+
t.index ["canvas_id"], name: "index_groups_on_canvas_id", unique: true
|
192
|
+
end
|
193
|
+
|
165
194
|
create_table "roles", force: :cascade do |t|
|
166
195
|
t.integer "canvas_id", null: false
|
167
196
|
t.string "label"
|
@@ -196,6 +225,7 @@ ActiveRecord::Schema.define(version: 20190927204546) do
|
|
196
225
|
t.bigint "canvas_assignment_id"
|
197
226
|
t.bigint "canvas_user_id"
|
198
227
|
t.datetime "submitted_at"
|
228
|
+
t.datetime "due_at"
|
199
229
|
t.datetime "graded_at"
|
200
230
|
t.float "score"
|
201
231
|
t.float "points_possible"
|
@@ -0,0 +1,3 @@
|
|
1
|
+
canvas_group_id,group_id,canvas_group_category_id,group_category_id,canvas_account_id,account_id,canvas_course_id,course_id,name,status,created_by_sis,context_id,context_type,max_membership
|
2
|
+
50,sis1,10,,1,,,,Group1,available,false,1,Account,
|
3
|
+
51,sis2,2,,,,1,coursesis,Group2,available,false,1,Course,1
|
@@ -1,3 +1,3 @@
|
|
1
|
-
"canvas user id","sis user id","user name","canvas course id","sis course id","course name","assignment id","assignment name","submission date","graded date","score","points possible","submission id","workflow state","excused"
|
2
|
-
1,1,userName,1,1,courseName,1,assignmentName,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,1,graded,true
|
3
|
-
1,1,userName,1,1,courseName,2,assignment2Name,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,2,submitted,false
|
1
|
+
"canvas user id","sis user id","user name","canvas course id","sis course id","course name","assignment id","assignment name","submission date","graded date","score","points possible","submission id","workflow state","excused","due at"
|
2
|
+
1,1,userName,1,1,courseName,1,assignmentName,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,1,graded,true,2017-09-27 18:28:15 UTC
|
3
|
+
1,1,userName,1,1,courseName,2,assignment2Name,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,2,submitted,false,2017-09-28 18:28:15 UTC
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Collings
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -304,7 +304,7 @@ dependencies:
|
|
304
304
|
- - ">="
|
305
305
|
- !ruby/object:Gem::Version
|
306
306
|
version: '0'
|
307
|
-
description:
|
307
|
+
description:
|
308
308
|
email:
|
309
309
|
- ncollings@instructure.com
|
310
310
|
executables: []
|
@@ -338,6 +338,9 @@ files:
|
|
338
338
|
- lib/canvas_sync/generators/templates/migrations/create_context_modules.rb
|
339
339
|
- lib/canvas_sync/generators/templates/migrations/create_courses.rb
|
340
340
|
- lib/canvas_sync/generators/templates/migrations/create_enrollments.rb
|
341
|
+
- lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb
|
342
|
+
- lib/canvas_sync/generators/templates/migrations/create_groups.rb
|
343
|
+
- lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb
|
341
344
|
- lib/canvas_sync/generators/templates/migrations/create_roles.rb
|
342
345
|
- lib/canvas_sync/generators/templates/migrations/create_sections.rb
|
343
346
|
- lib/canvas_sync/generators/templates/migrations/create_submissions.rb
|
@@ -351,6 +354,9 @@ files:
|
|
351
354
|
- lib/canvas_sync/generators/templates/models/context_module_item.rb
|
352
355
|
- lib/canvas_sync/generators/templates/models/course.rb
|
353
356
|
- lib/canvas_sync/generators/templates/models/enrollment.rb
|
357
|
+
- lib/canvas_sync/generators/templates/models/group.rb
|
358
|
+
- lib/canvas_sync/generators/templates/models/group_membership.rb
|
359
|
+
- lib/canvas_sync/generators/templates/models/pseudonym.rb
|
354
360
|
- lib/canvas_sync/generators/templates/models/role.rb
|
355
361
|
- lib/canvas_sync/generators/templates/models/section.rb
|
356
362
|
- lib/canvas_sync/generators/templates/models/submission.rb
|
@@ -387,7 +393,6 @@ files:
|
|
387
393
|
- lib/canvas_sync/jobs/sync_simple_table_job.rb
|
388
394
|
- lib/canvas_sync/jobs/sync_submissions_job.rb
|
389
395
|
- lib/canvas_sync/jobs/sync_terms_job.rb
|
390
|
-
- lib/canvas_sync/jobs/sync_users_job.rb
|
391
396
|
- lib/canvas_sync/processors/assignment_groups_processor.rb
|
392
397
|
- lib/canvas_sync/processors/assignments_processor.rb
|
393
398
|
- lib/canvas_sync/processors/context_module_items_processor.rb
|
@@ -416,7 +421,6 @@ files:
|
|
416
421
|
- spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
|
417
422
|
- spec/canvas_sync/jobs/sync_submissions_job_spec.rb
|
418
423
|
- spec/canvas_sync/jobs/sync_terms_job_spec.rb
|
419
|
-
- spec/canvas_sync/jobs/sync_users_job_spec.rb
|
420
424
|
- spec/canvas_sync/models/accounts_spec.rb
|
421
425
|
- spec/canvas_sync/models/admins_spec.rb
|
422
426
|
- spec/canvas_sync/models/assignment_group_spec.rb
|
@@ -425,6 +429,8 @@ files:
|
|
425
429
|
- spec/canvas_sync/models/context_module_spec.rb
|
426
430
|
- spec/canvas_sync/models/course_spec.rb
|
427
431
|
- spec/canvas_sync/models/enrollment_spec.rb
|
432
|
+
- spec/canvas_sync/models/group_membership_spec.rb
|
433
|
+
- spec/canvas_sync/models/group_spec.rb
|
428
434
|
- spec/canvas_sync/models/roles_spec.rb
|
429
435
|
- spec/canvas_sync/models/section_spec.rb
|
430
436
|
- spec/canvas_sync/models/submission_spec.rb
|
@@ -450,6 +456,8 @@ files:
|
|
450
456
|
- spec/dummy/app/models/context_module_item.rb
|
451
457
|
- spec/dummy/app/models/course.rb
|
452
458
|
- spec/dummy/app/models/enrollment.rb
|
459
|
+
- spec/dummy/app/models/group.rb
|
460
|
+
- spec/dummy/app/models/group_membership.rb
|
453
461
|
- spec/dummy/app/models/role.rb
|
454
462
|
- spec/dummy/app/models/section.rb
|
455
463
|
- spec/dummy/app/models/submission.rb
|
@@ -510,6 +518,8 @@ files:
|
|
510
518
|
- spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
|
511
519
|
- spec/dummy/db/migrate/20190927204545_create_roles.rb
|
512
520
|
- spec/dummy/db/migrate/20190927204546_create_admins.rb
|
521
|
+
- spec/dummy/db/migrate/20200415171620_create_groups.rb
|
522
|
+
- spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
|
513
523
|
- spec/dummy/db/schema.rb
|
514
524
|
- spec/dummy/db/test.sqlite3
|
515
525
|
- spec/dummy/log/development.log
|
@@ -522,6 +532,8 @@ files:
|
|
522
532
|
- spec/factories/context_module_item_factory.rb
|
523
533
|
- spec/factories/course_factory.rb
|
524
534
|
- spec/factories/enrollment_factory.rb
|
535
|
+
- spec/factories/group_factory.rb
|
536
|
+
- spec/factories/group_membership_factory.rb
|
525
537
|
- spec/factories/role_factory.rb
|
526
538
|
- spec/factories/section_factory.rb
|
527
539
|
- spec/factories/submission_factory.rb
|
@@ -540,6 +552,8 @@ files:
|
|
540
552
|
- spec/support/fixtures/reports/context_modules.csv
|
541
553
|
- spec/support/fixtures/reports/courses.csv
|
542
554
|
- spec/support/fixtures/reports/enrollments.csv
|
555
|
+
- spec/support/fixtures/reports/group_memberships.csv
|
556
|
+
- spec/support/fixtures/reports/groups.csv
|
543
557
|
- spec/support/fixtures/reports/provisioning_csv
|
544
558
|
- spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
|
545
559
|
- spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
|
@@ -550,7 +564,7 @@ files:
|
|
550
564
|
homepage: https://instructure.com
|
551
565
|
licenses: []
|
552
566
|
metadata: {}
|
553
|
-
post_install_message:
|
567
|
+
post_install_message:
|
554
568
|
rdoc_options: []
|
555
569
|
require_paths:
|
556
570
|
- lib
|
@@ -565,8 +579,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
565
579
|
- !ruby/object:Gem::Version
|
566
580
|
version: '0'
|
567
581
|
requirements: []
|
568
|
-
rubygems_version: 3.
|
569
|
-
signing_key:
|
582
|
+
rubygems_version: 3.1.2
|
583
|
+
signing_key:
|
570
584
|
specification_version: 4
|
571
585
|
summary: Gem for generating Canvas models and migrations and syncing data from Canvas
|
572
586
|
test_files:
|
@@ -586,7 +600,6 @@ test_files:
|
|
586
600
|
- spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
|
587
601
|
- spec/canvas_sync/jobs/sync_submissions_job_spec.rb
|
588
602
|
- spec/canvas_sync/jobs/sync_terms_job_spec.rb
|
589
|
-
- spec/canvas_sync/jobs/sync_users_job_spec.rb
|
590
603
|
- spec/canvas_sync/models/accounts_spec.rb
|
591
604
|
- spec/canvas_sync/models/admins_spec.rb
|
592
605
|
- spec/canvas_sync/models/assignment_group_spec.rb
|
@@ -595,6 +608,8 @@ test_files:
|
|
595
608
|
- spec/canvas_sync/models/context_module_spec.rb
|
596
609
|
- spec/canvas_sync/models/course_spec.rb
|
597
610
|
- spec/canvas_sync/models/enrollment_spec.rb
|
611
|
+
- spec/canvas_sync/models/group_membership_spec.rb
|
612
|
+
- spec/canvas_sync/models/group_spec.rb
|
598
613
|
- spec/canvas_sync/models/roles_spec.rb
|
599
614
|
- spec/canvas_sync/models/section_spec.rb
|
600
615
|
- spec/canvas_sync/models/submission_spec.rb
|
@@ -620,6 +635,8 @@ test_files:
|
|
620
635
|
- spec/dummy/app/models/context_module_item.rb
|
621
636
|
- spec/dummy/app/models/course.rb
|
622
637
|
- spec/dummy/app/models/enrollment.rb
|
638
|
+
- spec/dummy/app/models/group.rb
|
639
|
+
- spec/dummy/app/models/group_membership.rb
|
623
640
|
- spec/dummy/app/models/role.rb
|
624
641
|
- spec/dummy/app/models/section.rb
|
625
642
|
- spec/dummy/app/models/submission.rb
|
@@ -680,6 +697,8 @@ test_files:
|
|
680
697
|
- spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
|
681
698
|
- spec/dummy/db/migrate/20190927204545_create_roles.rb
|
682
699
|
- spec/dummy/db/migrate/20190927204546_create_admins.rb
|
700
|
+
- spec/dummy/db/migrate/20200415171620_create_groups.rb
|
701
|
+
- spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
|
683
702
|
- spec/dummy/db/schema.rb
|
684
703
|
- spec/dummy/db/test.sqlite3
|
685
704
|
- spec/dummy/log/development.log
|
@@ -692,6 +711,8 @@ test_files:
|
|
692
711
|
- spec/factories/context_module_item_factory.rb
|
693
712
|
- spec/factories/course_factory.rb
|
694
713
|
- spec/factories/enrollment_factory.rb
|
714
|
+
- spec/factories/group_factory.rb
|
715
|
+
- spec/factories/group_membership_factory.rb
|
695
716
|
- spec/factories/role_factory.rb
|
696
717
|
- spec/factories/section_factory.rb
|
697
718
|
- spec/factories/submission_factory.rb
|
@@ -710,6 +731,8 @@ test_files:
|
|
710
731
|
- spec/support/fixtures/reports/context_modules.csv
|
711
732
|
- spec/support/fixtures/reports/courses.csv
|
712
733
|
- spec/support/fixtures/reports/enrollments.csv
|
734
|
+
- spec/support/fixtures/reports/group_memberships.csv
|
735
|
+
- spec/support/fixtures/reports/groups.csv
|
713
736
|
- spec/support/fixtures/reports/provisioning_csv
|
714
737
|
- spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
|
715
738
|
- spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module CanvasSync
|
2
|
-
module Jobs
|
3
|
-
class SyncUsersJob < ReportStarter
|
4
|
-
# Starts a provisioning report for just users.
|
5
|
-
#
|
6
|
-
# Provisioning reports do not scope users by term, so when we are
|
7
|
-
# running provisioning by term we sync users first so we don't duplicate
|
8
|
-
# the work of syncing all users for each term.
|
9
|
-
#
|
10
|
-
# @param job_chain [Hash]
|
11
|
-
# @param options [Hash]
|
12
|
-
def perform(job_chain, options)
|
13
|
-
super(
|
14
|
-
job_chain,
|
15
|
-
"proservices_provisioning_csv",
|
16
|
-
merge_report_params(job_chain, options, {
|
17
|
-
users: true,
|
18
|
-
include_deleted: true,
|
19
|
-
}, term_scope: false),
|
20
|
-
CanvasSync::Processors::ProvisioningReportProcessor.to_s,
|
21
|
-
{ models: ["users"] },
|
22
|
-
)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe CanvasSync::Jobs::SyncUsersJob do
|
4
|
-
describe '#perform' do
|
5
|
-
it 'enqueues a ReportStarter for a provisioning report across all terms with just users' do
|
6
|
-
expect_any_instance_of(Bearcat::Client).to receive(:start_report)
|
7
|
-
.with('self', 'proservices_provisioning_csv', { parameters: { users: true, include_deleted: true } })
|
8
|
-
.and_return({ 'id' => 1 })
|
9
|
-
|
10
|
-
expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
|
11
|
-
|
12
|
-
CanvasSync::Jobs::SyncUsersJob.perform_now({ jobs: [], global_options: {}}, {})
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|