canvas_sync 0.22.18 → 0.23.1.beta1
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/concerns/ability_helper.rb +18 -5
- data/lib/canvas_sync/concerns/deleted_scoping.rb +24 -0
- data/lib/canvas_sync/generators/templates/models/account.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/admin.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/assignment.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/assignment_group.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/context_module.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/context_module_item.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/course.rb +11 -0
- data/lib/canvas_sync/generators/templates/models/enrollment.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/grading_period.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/grading_period_group.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/group.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/group_membership.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/pseudonym.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/role.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/section.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/submission.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/term.rb +10 -6
- data/lib/canvas_sync/generators/templates/models/user.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/user_observer.rb +1 -0
- data/lib/canvas_sync/jobs/term_batches_job.rb +10 -2
- data/lib/canvas_sync/record.rb +15 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +15 -3
- data/spec/canvas_sync/canvas_sync_spec.rb +8 -4
- data/spec/dummy/app/models/account.rb +1 -0
- data/spec/dummy/app/models/admin.rb +1 -0
- data/spec/dummy/app/models/assignment.rb +1 -0
- data/spec/dummy/app/models/assignment_group.rb +1 -0
- data/spec/dummy/app/models/context_module.rb +1 -0
- data/spec/dummy/app/models/context_module_item.rb +1 -0
- data/spec/dummy/app/models/course.rb +11 -0
- data/spec/dummy/app/models/enrollment.rb +3 -0
- data/spec/dummy/app/models/grading_period.rb +1 -0
- data/spec/dummy/app/models/grading_period_group.rb +1 -0
- data/spec/dummy/app/models/group.rb +1 -0
- data/spec/dummy/app/models/group_membership.rb +1 -0
- data/spec/dummy/app/models/pseudonym.rb +1 -0
- data/spec/dummy/app/models/role.rb +1 -0
- data/spec/dummy/app/models/section.rb +1 -0
- data/spec/dummy/app/models/submission.rb +1 -0
- data/spec/dummy/app/models/term.rb +10 -6
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/app/models/user_observer.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48b7c1dac720b5d18b462414ffc84645e604912089fdacbd2ca9223ae98e2609
|
4
|
+
data.tar.gz: 74d978170f2f4e755fa77b11e47a791e6f4a3cb2fc426e25ffa82d87fd86655d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc8c695d1314127dc7edb3ff514340ac4bb22be59898b52930c15deeb2768e3c8b56a17c1aee9fd194e6b88c663027754299d617af687ab39355a29a9426faaa
|
7
|
+
data.tar.gz: 4ce862f92be4ced93947d665dec9eec1e98ff4b81dcb5fde03b8cbb0070edb668121bfe27b441b822d734976b5e4f8404069c356aed157e7aaf931bc3b39c8d5
|
@@ -23,21 +23,34 @@ module CanvasSync::Concerns
|
|
23
23
|
if panda_pal_session.lti_launch_placement == "global_navigation"
|
24
24
|
:global
|
25
25
|
elsif panda_pal_session.get_lti_cust_param('custom_canvas_course_id').present?
|
26
|
-
::Course
|
26
|
+
load_canvas_model(::Course, panda_pal_session.get_lti_cust_param('custom_canvas_course_id'))
|
27
27
|
else
|
28
|
-
::Account
|
28
|
+
load_canvas_model(::Account, panda_pal_session.get_lti_cust_param('custom_canvas_account_id'))
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
def launch_account
|
34
|
-
@launch_account
|
35
|
-
|
36
|
-
|
34
|
+
return @launch_account if defined?(@launch_account)
|
35
|
+
|
36
|
+
if launch_context.respond_to?(:account)
|
37
|
+
@launch_account = launch_context.account
|
38
|
+
@launch_account ||= load_canvas_model(::Account, launch_context.canvas_account_id) if launch_context.respond_to?(:canvas_account_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
@launch_account ||= load_canvas_model(::Account, panda_pal_session.get_lti_cust_param('custom_canvas_account_id'))
|
42
|
+
|
43
|
+
@launch_account
|
37
44
|
end
|
38
45
|
|
39
46
|
# CanvasSync Domain
|
40
47
|
|
48
|
+
def load_canvas_model(model, canvas_id)
|
49
|
+
record = model.find_or_fetch(canvas_id) if model.respond_to?(:find_or_fetch)
|
50
|
+
record ||= model.find_by(canvas_id: canvas_id)
|
51
|
+
record
|
52
|
+
end
|
53
|
+
|
41
54
|
def canvas_permissions
|
42
55
|
panda_pal_session[:canvas_permissions] ||= ::Role.joined_permissions(canvas_roles)
|
43
56
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This concern sets the default_scope of the model to exclude items with workflow_state: 'deleted'
|
2
|
+
module CanvasSync::Concerns
|
3
|
+
module DeletedScoping
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
class_methods do
|
7
|
+
def with_deleted
|
8
|
+
unscope(where: :workflow_state)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
included do
|
13
|
+
default_scope do
|
14
|
+
model = scope.try(:model) || scope
|
15
|
+
|
16
|
+
if model.try(:column_names)&.include?(:workflow_state)
|
17
|
+
scope.where.not(workflow_state: %w[deleted])
|
18
|
+
else
|
19
|
+
all
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -5,6 +5,7 @@ class Account < ApplicationRecord
|
|
5
5
|
include CanvasSync::Concerns::ApiSyncable
|
6
6
|
# include CanvasSync::Concerns::Account::Ancestry # Add support for the ancestry Gem
|
7
7
|
# include CanvasSync::Concerns::LiveEventSync
|
8
|
+
# include CanvasSync::Concerns::DeletedScoping
|
8
9
|
|
9
10
|
canvas_sync_features :defaults
|
10
11
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
class Course < ApplicationRecord
|
4
4
|
include CanvasSync::Record
|
5
5
|
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
# include CanvasSync::Concerns::DeletedScoping
|
6
7
|
|
7
8
|
canvas_sync_features :defaults
|
8
9
|
|
@@ -34,4 +35,14 @@ class Course < ApplicationRecord
|
|
34
35
|
start_at: :start_at,
|
35
36
|
end_at: :end_at,
|
36
37
|
}, -> (api) { api.course(canvas_id) })
|
38
|
+
|
39
|
+
scope :active, -> { where(workflow_state: 'active') }
|
40
|
+
|
41
|
+
scope :current, -> {
|
42
|
+
base_query = all.joins(:term)
|
43
|
+
base_query
|
44
|
+
.where("#{current_table_name}.start_at <= ? OR #{current_table_name}.start_at IS NULL", DateTime.now)
|
45
|
+
.where("#{current_table_name}.end_at >= ? OR #{current_table_name}.end_at IS NULL", DateTime.now)
|
46
|
+
.or(base_query.merge(Term.current))
|
47
|
+
}
|
37
48
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
class Enrollment < ApplicationRecord
|
4
4
|
include CanvasSync::Record
|
5
5
|
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
# include CanvasSync::Concerns::DeletedScoping
|
6
7
|
|
7
8
|
canvas_sync_features :defaults
|
8
9
|
|
@@ -36,4 +37,6 @@ class Enrollment < ApplicationRecord
|
|
36
37
|
base_role_type: :type,
|
37
38
|
workflow_state: :enrollment_state,
|
38
39
|
}, -> (api) { api.enrollment("self", canvas_id) })
|
40
|
+
|
41
|
+
scope :active, -> { where(workflow_state: 'active') }
|
39
42
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
class Term < ApplicationRecord
|
4
4
|
include CanvasSync::Record
|
5
5
|
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
# include CanvasSync::Concerns::DeletedScoping
|
6
7
|
|
7
8
|
canvas_sync_features :defaults
|
8
9
|
|
@@ -25,12 +26,15 @@ class Term < ApplicationRecord
|
|
25
26
|
term_data
|
26
27
|
})
|
27
28
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
scope :active, -> {
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
# Our pattern has usually had `Term.active` include date scoping.
|
30
|
+
# `active` here is then a bit of a misnomer, but the template is written to follow our previous patterns.
|
31
|
+
scope :active, -> { where(workflow_state: 'active').current }
|
32
|
+
|
33
|
+
scope :current, ->(grace_time: 0.seconds) {
|
34
|
+
all
|
35
|
+
.where("#{current_table_name}.start_at <= ? OR #{current_table_name}.start_at IS NULL", grace_time.from_now)
|
36
|
+
.where("#{current_table_name}.end_at >= ? OR #{current_table_name}.end_at IS NULL", grace_time.ago)
|
34
37
|
}
|
35
38
|
|
39
|
+
scope :should_canvas_sync, -> { where(workflow_state: 'active').current(grace_time: 15.days) }
|
36
40
|
end
|
@@ -4,8 +4,16 @@ module CanvasSync
|
|
4
4
|
def perform(options)
|
5
5
|
if (jobs = options[:sub_jobs]).present?
|
6
6
|
context = options[:context] || {}
|
7
|
-
if options[:term_scope]
|
8
|
-
|
7
|
+
if options[:term_scope] != false
|
8
|
+
terms = Term
|
9
|
+
|
10
|
+
if !options[:term_scope].present? || options[:term_scope] == true
|
11
|
+
terms = CanvasSync.sync_scope(terms)
|
12
|
+
else
|
13
|
+
terms = terms.send(options[:term_scope])
|
14
|
+
end
|
15
|
+
|
16
|
+
terms.find_each.map do |term|
|
9
17
|
term_id = get_term_id(term)
|
10
18
|
local_context = context.merge(canvas_term_id: term_id)
|
11
19
|
|
data/lib/canvas_sync/record.rb
CHANGED
@@ -108,5 +108,20 @@ module CanvasSync
|
|
108
108
|
belongs_to :canvas_sync_batch, foreign_key: :canvas_sync_batch_id, class_name: "CanvasSync::SyncBatch", optional: true
|
109
109
|
end
|
110
110
|
end
|
111
|
+
|
112
|
+
class_methods do
|
113
|
+
def current_table_name
|
114
|
+
current_table = current_scope.arel.source.left
|
115
|
+
|
116
|
+
case current_table
|
117
|
+
when Arel::Table
|
118
|
+
current_table.name
|
119
|
+
when Arel::Nodes::TableAlias
|
120
|
+
current_table.right
|
121
|
+
else
|
122
|
+
fail
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
111
126
|
end
|
112
127
|
end
|
data/lib/canvas_sync/version.rb
CHANGED
data/lib/canvas_sync.rb
CHANGED
@@ -128,11 +128,23 @@ module CanvasSync
|
|
128
128
|
end
|
129
129
|
|
130
130
|
# Given a Model or Relation, scope it down to items that should be synced
|
131
|
-
def sync_scope(scope)
|
132
|
-
terms =
|
131
|
+
def sync_scope(scope, fallback_scopes: [])
|
132
|
+
terms = [
|
133
|
+
:should_canvas_sync,
|
134
|
+
:active_for_canvas_sync,
|
135
|
+
:should_sync,
|
136
|
+
:active_for_sync,
|
137
|
+
*fallback_scopes,
|
138
|
+
:active,
|
139
|
+
]
|
133
140
|
terms.each do |t|
|
134
141
|
return scope.send(t) if scope.respond_to?(t)
|
135
142
|
end
|
143
|
+
|
144
|
+
if block_given? && !(block_result = yield).nil?
|
145
|
+
return block_result
|
146
|
+
end
|
147
|
+
|
136
148
|
model = scope.try(:model) || scope
|
137
149
|
if model.try(:column_names)&.include?(:workflow_state)
|
138
150
|
return scope.where.not(workflow_state: %w[deleted])
|
@@ -203,7 +215,7 @@ module CanvasSync
|
|
203
215
|
|
204
216
|
# These Models use the provisioning report, but are not term-scoped,
|
205
217
|
# so we sync them outside of the term scoping to ensure work is not duplicated
|
206
|
-
|
218
|
+
unless term_scope == false
|
207
219
|
models -= (first_provisioning_models = models & ['users', 'pseudonyms', 'user_observers', 'grading_periods', 'grading_period_groups'])
|
208
220
|
current_chain.insert(generate_provisioning_jobs(first_provisioning_models, options))
|
209
221
|
end
|
@@ -99,11 +99,12 @@ RSpec.describe CanvasSync do
|
|
99
99
|
{
|
100
100
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
101
101
|
:args=>[[
|
102
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
|
102
103
|
{
|
103
104
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
104
105
|
:args=>[],
|
105
106
|
:kwargs=>{
|
106
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["
|
107
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
|
107
108
|
:term_scope=>nil,
|
108
109
|
}
|
109
110
|
}
|
@@ -260,13 +261,14 @@ RSpec.describe CanvasSync do
|
|
260
261
|
{
|
261
262
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
262
263
|
:args=>[[
|
264
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
|
263
265
|
{
|
264
266
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
265
267
|
:args=>[],
|
266
268
|
:kwargs=>{
|
267
269
|
:sub_jobs=>[
|
268
270
|
{:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :options=>{}},
|
269
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["
|
271
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["enrollments"]}}
|
270
272
|
],
|
271
273
|
:term_scope=>nil
|
272
274
|
}
|
@@ -290,13 +292,14 @@ RSpec.describe CanvasSync do
|
|
290
292
|
{
|
291
293
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
292
294
|
:args=>[[
|
295
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
|
293
296
|
{
|
294
297
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
295
298
|
:args=>[],
|
296
299
|
:kwargs=>{
|
297
300
|
:sub_jobs=>[
|
298
301
|
{:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :options=>{}},
|
299
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["
|
302
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["enrollments"]}}
|
300
303
|
],
|
301
304
|
:term_scope=>nil
|
302
305
|
}
|
@@ -320,13 +323,14 @@ RSpec.describe CanvasSync do
|
|
320
323
|
{
|
321
324
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
322
325
|
:args=>[[
|
326
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
|
323
327
|
{
|
324
328
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
325
329
|
:args=>[],
|
326
330
|
:kwargs=>{
|
327
331
|
:sub_jobs=>[
|
328
332
|
{:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :options=>{}},
|
329
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["
|
333
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["enrollments"]}}
|
330
334
|
],
|
331
335
|
:term_scope=>nil
|
332
336
|
}
|
@@ -11,6 +11,7 @@ class Account < ApplicationRecord
|
|
11
11
|
include CanvasSync::Concerns::ApiSyncable
|
12
12
|
# include CanvasSync::Concerns::Account::Ancestry # Add support for the ancestry Gem
|
13
13
|
# include CanvasSync::Concerns::LiveEventSync
|
14
|
+
# include CanvasSync::Concerns::DeletedScoping
|
14
15
|
|
15
16
|
canvas_sync_features :defaults
|
16
17
|
|
@@ -12,6 +12,7 @@
|
|
12
12
|
class ContextModule < ApplicationRecord
|
13
13
|
include CanvasSync::Record
|
14
14
|
include CanvasSync::Concerns::ApiSyncable
|
15
|
+
# include CanvasSync::Concerns::DeletedScoping
|
15
16
|
|
16
17
|
# include CanvasSync::Concerns::LiveEventSync
|
17
18
|
# live_events_config event_prefix: :module
|
@@ -9,6 +9,7 @@
|
|
9
9
|
class Course < ApplicationRecord
|
10
10
|
include CanvasSync::Record
|
11
11
|
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
# include CanvasSync::Concerns::DeletedScoping
|
12
13
|
|
13
14
|
canvas_sync_features :defaults
|
14
15
|
|
@@ -40,4 +41,14 @@ class Course < ApplicationRecord
|
|
40
41
|
start_at: :start_at,
|
41
42
|
end_at: :end_at,
|
42
43
|
}, -> (api) { api.course(canvas_id) })
|
44
|
+
|
45
|
+
scope :active, -> { where(workflow_state: 'active') }
|
46
|
+
|
47
|
+
scope :current, -> {
|
48
|
+
base_query = all.joins(:term)
|
49
|
+
base_query
|
50
|
+
.where("#{current_table_name}.start_at <= ? OR #{current_table_name}.start_at IS NULL", DateTime.now)
|
51
|
+
.where("#{current_table_name}.end_at >= ? OR #{current_table_name}.end_at IS NULL", DateTime.now)
|
52
|
+
.or(base_query.merge(Term.current))
|
53
|
+
}
|
43
54
|
end
|
@@ -9,6 +9,7 @@
|
|
9
9
|
class Enrollment < ApplicationRecord
|
10
10
|
include CanvasSync::Record
|
11
11
|
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
# include CanvasSync::Concerns::DeletedScoping
|
12
13
|
|
13
14
|
canvas_sync_features :defaults
|
14
15
|
|
@@ -42,4 +43,6 @@ class Enrollment < ApplicationRecord
|
|
42
43
|
base_role_type: :type,
|
43
44
|
workflow_state: :enrollment_state,
|
44
45
|
}, -> (api) { api.enrollment("self", canvas_id) })
|
46
|
+
|
47
|
+
scope :active, -> { where(workflow_state: 'active') }
|
45
48
|
end
|
@@ -9,6 +9,7 @@
|
|
9
9
|
class Term < ApplicationRecord
|
10
10
|
include CanvasSync::Record
|
11
11
|
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
# include CanvasSync::Concerns::DeletedScoping
|
12
13
|
|
13
14
|
canvas_sync_features :defaults
|
14
15
|
|
@@ -31,12 +32,15 @@ class Term < ApplicationRecord
|
|
31
32
|
term_data
|
32
33
|
})
|
33
34
|
|
34
|
-
#
|
35
|
-
#
|
36
|
-
scope :active, -> {
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
# Our pattern has usually had `Term.active` include date scoping.
|
36
|
+
# `active` here is then a bit of a misnomer, but the template is written to follow our previous patterns.
|
37
|
+
scope :active, -> { where(workflow_state: 'active').current }
|
38
|
+
|
39
|
+
scope :current, ->(grace_time: 0.seconds) {
|
40
|
+
all
|
41
|
+
.where("#{current_table_name}.start_at <= ? OR #{current_table_name}.start_at IS NULL", grace_time.from_now)
|
42
|
+
.where("#{current_table_name}.end_at >= ? OR #{current_table_name}.end_at IS NULL", grace_time.ago)
|
40
43
|
}
|
41
44
|
|
45
|
+
scope :should_canvas_sync, -> { where(workflow_state: 'active').current(grace_time: 15.days) }
|
42
46
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.23.1.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Instructure CustomDev
|
@@ -442,6 +442,7 @@ files:
|
|
442
442
|
- lib/canvas_sync/concerns/account/ancestry.rb
|
443
443
|
- lib/canvas_sync/concerns/account/base.rb
|
444
444
|
- lib/canvas_sync/concerns/api_syncable.rb
|
445
|
+
- lib/canvas_sync/concerns/deleted_scoping.rb
|
445
446
|
- lib/canvas_sync/concerns/legacy_columns.rb
|
446
447
|
- lib/canvas_sync/concerns/live_event_sync.rb
|
447
448
|
- lib/canvas_sync/concerns/role/base.rb
|