canvas_sync 0.27.11 → 0.27.15

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.
Files changed (243) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/canvas_sync/api/v1/health_check_controller.rb +0 -0
  3. data/app/models/canvas_sync/job_log.rb +0 -0
  4. data/app/models/canvas_sync/sync_batch.rb +0 -0
  5. data/config/initializers/apartment.rb +0 -0
  6. data/config/routes.rb +0 -0
  7. data/db/migrate/20170915210836_create_canvas_sync_job_log.rb +0 -0
  8. data/db/migrate/20180725155729_add_job_id_to_canvas_sync_job_logs.rb +0 -0
  9. data/db/migrate/20190916154829_add_fork_count_to_canvas_sync_job_logs.rb +0 -0
  10. data/db/migrate/20201018210836_create_canvas_sync_sync_batches.rb +0 -0
  11. data/db/migrate/20201030210836_add_full_sync_to_canvas_sync_sync_batch.rb +0 -0
  12. data/lib/canvas_sync/api_syncable.rb +0 -0
  13. data/lib/canvas_sync/batch_processor.rb +0 -0
  14. data/lib/canvas_sync/class_callback_executor.rb +0 -0
  15. data/lib/canvas_sync/concerns/ability_helper.rb +43 -2
  16. data/lib/canvas_sync/concerns/account/ancestry.rb +0 -0
  17. data/lib/canvas_sync/concerns/account/base.rb +0 -0
  18. data/lib/canvas_sync/concerns/api_syncable.rb +0 -0
  19. data/lib/canvas_sync/concerns/canvas_id_as_primary.rb +0 -0
  20. data/lib/canvas_sync/concerns/jit_syncing.rb +0 -0
  21. data/lib/canvas_sync/concerns/legacy_columns.rb +0 -0
  22. data/lib/canvas_sync/concerns/role/base.rb +0 -0
  23. data/lib/canvas_sync/generators/install_generator.rb +0 -0
  24. data/lib/canvas_sync/generators/install_live_events_generator.rb +0 -0
  25. data/lib/canvas_sync/generators/templates/migrations/create_accounts.rb +0 -0
  26. data/lib/canvas_sync/generators/templates/migrations/create_admins.rb +0 -0
  27. data/lib/canvas_sync/generators/templates/migrations/create_assignment_groups.rb +0 -0
  28. data/lib/canvas_sync/generators/templates/migrations/create_assignments.rb +0 -0
  29. data/lib/canvas_sync/generators/templates/migrations/create_content_migrations.rb +0 -0
  30. data/lib/canvas_sync/generators/templates/migrations/create_context_module_items.rb +0 -0
  31. data/lib/canvas_sync/generators/templates/migrations/create_context_modules.rb +0 -0
  32. data/lib/canvas_sync/generators/templates/migrations/create_course_nicknames.rb +0 -0
  33. data/lib/canvas_sync/generators/templates/migrations/create_course_progresses.rb +0 -0
  34. data/lib/canvas_sync/generators/templates/migrations/create_grading_period_groups.rb +0 -0
  35. data/lib/canvas_sync/generators/templates/migrations/create_grading_periods.rb +0 -0
  36. data/lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb +0 -0
  37. data/lib/canvas_sync/generators/templates/migrations/create_groups.rb +0 -0
  38. data/lib/canvas_sync/generators/templates/migrations/create_learning_outcome_results.rb +0 -0
  39. data/lib/canvas_sync/generators/templates/migrations/create_learning_outcomes.rb +0 -0
  40. data/lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb +0 -0
  41. data/lib/canvas_sync/generators/templates/migrations/create_rubric_assessments.rb +0 -0
  42. data/lib/canvas_sync/generators/templates/migrations/create_rubric_associations.rb +0 -0
  43. data/lib/canvas_sync/generators/templates/migrations/create_rubrics.rb +0 -0
  44. data/lib/canvas_sync/generators/templates/migrations/create_sections.rb +0 -0
  45. data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +0 -0
  46. data/lib/canvas_sync/generators/templates/migrations/create_terms.rb +0 -0
  47. data/lib/canvas_sync/generators/templates/migrations/create_user_observers.rb +0 -0
  48. data/lib/canvas_sync/generators/templates/migrations/create_users.rb +0 -0
  49. data/lib/canvas_sync/generators/templates/models/content_migration.rb +0 -0
  50. data/lib/canvas_sync/generators/templates/models/course_nickname.rb +0 -0
  51. data/lib/canvas_sync/generators/templates/models/rubric.rb +0 -0
  52. data/lib/canvas_sync/generators/templates/models/rubric_assessment.rb +0 -0
  53. data/lib/canvas_sync/generators/templates/models/rubric_association.rb +0 -0
  54. data/lib/canvas_sync/generators/templates/services/live_events/assignment_event.rb +0 -0
  55. data/lib/canvas_sync/generators/templates/services/live_events/assignment_group_event.rb +0 -0
  56. data/lib/canvas_sync/generators/templates/services/live_events/course_event.rb +0 -0
  57. data/lib/canvas_sync/generators/templates/services/live_events/course_section_event.rb +0 -0
  58. data/lib/canvas_sync/generators/templates/services/live_events/enrollment_event.rb +0 -0
  59. data/lib/canvas_sync/generators/templates/services/live_events/grade_event.rb +0 -0
  60. data/lib/canvas_sync/generators/templates/services/live_events/module_event.rb +0 -0
  61. data/lib/canvas_sync/generators/templates/services/live_events/module_item_event.rb +0 -0
  62. data/lib/canvas_sync/generators/templates/services/live_events/submission_event.rb +0 -0
  63. data/lib/canvas_sync/generators/templates/services/live_events/syllabus_event.rb +0 -0
  64. data/lib/canvas_sync/generators/templates/services/live_events/user_event.rb +0 -0
  65. data/lib/canvas_sync/importers/legacy_importer.rb +0 -0
  66. data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +0 -0
  67. data/lib/canvas_sync/jobs/canvas_process_waiter.rb +0 -0
  68. data/lib/canvas_sync/jobs/report_starter.rb +5 -1
  69. data/lib/canvas_sync/jobs/report_sync_task.rb +12 -4
  70. data/lib/canvas_sync/jobs/sync_accounts_job.rb +2 -1
  71. data/lib/canvas_sync/jobs/sync_admins_job.rb +0 -0
  72. data/lib/canvas_sync/jobs/sync_assignment_groups_job.rb +0 -0
  73. data/lib/canvas_sync/jobs/sync_assignments_job.rb +0 -0
  74. data/lib/canvas_sync/jobs/sync_content_migrations_job.rb +0 -0
  75. data/lib/canvas_sync/jobs/sync_context_module_items_job.rb +0 -0
  76. data/lib/canvas_sync/jobs/sync_context_modules_job.rb +0 -0
  77. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +1 -1
  78. data/lib/canvas_sync/jobs/sync_rubrics_job.rb +0 -0
  79. data/lib/canvas_sync/jobs/sync_simple_table_job.rb +0 -0
  80. data/lib/canvas_sync/live_events/base_handler.rb +0 -0
  81. data/lib/canvas_sync/live_events.rb +0 -0
  82. data/lib/canvas_sync/misc_helper.rb +0 -0
  83. data/lib/canvas_sync/processors/normal_processor.rb +0 -0
  84. data/lib/canvas_sync/sidekiq_job.rb +0 -0
  85. data/lib/canvas_sync/version.rb +1 -1
  86. data/lib/canvas_sync.rb +66 -86
  87. data/spec/canvas_sync/concerns/ability_helper_spec.rb +165 -0
  88. data/spec/canvas_sync/jobs/begin_sync_chain_job_spec.rb +9 -3
  89. data/spec/canvas_sync/jobs/canvas_process_waiter_spec.rb +0 -0
  90. data/spec/canvas_sync/jobs/report_starter_spec.rb +0 -0
  91. data/spec/canvas_sync/jobs/report_sync_task_spec.rb +56 -0
  92. data/spec/canvas_sync/jobs/sync_accounts_job_spec.rb +41 -0
  93. data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +0 -0
  94. data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +2 -2
  95. data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +0 -0
  96. data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +0 -0
  97. data/spec/canvas_sync/jobs/sync_terms_job_spec.rb +0 -0
  98. data/spec/canvas_sync/live_events/live_event_sync_spec.rb +0 -0
  99. data/spec/canvas_sync/live_events/live_events_controller_spec.rb +0 -0
  100. data/spec/canvas_sync/misc_helper_spec.rb +0 -0
  101. data/spec/canvas_sync/models/accounts_spec.rb +0 -0
  102. data/spec/canvas_sync/models/admins_spec.rb +0 -0
  103. data/spec/canvas_sync/models/assignment_group_spec.rb +0 -0
  104. data/spec/canvas_sync/models/assignment_spec.rb +0 -0
  105. data/spec/canvas_sync/models/context_module_item_spec.rb +0 -0
  106. data/spec/canvas_sync/models/context_module_spec.rb +0 -0
  107. data/spec/canvas_sync/models/course_spec.rb +0 -0
  108. data/spec/canvas_sync/models/enrollment_spec.rb +0 -0
  109. data/spec/canvas_sync/models/group_membership_spec.rb +0 -0
  110. data/spec/canvas_sync/models/group_spec.rb +0 -0
  111. data/spec/canvas_sync/models/roles_spec.rb +0 -0
  112. data/spec/canvas_sync/models/section_spec.rb +0 -0
  113. data/spec/canvas_sync/models/submission_spec.rb +0 -0
  114. data/spec/canvas_sync/models/term_spec.rb +0 -0
  115. data/spec/canvas_sync/models/user_spec.rb +0 -0
  116. data/spec/canvas_sync/processors/assignment_groups_processor_spec.rb +0 -0
  117. data/spec/canvas_sync/processors/assignments_processor_spec.rb +0 -0
  118. data/spec/canvas_sync/processors/content_migrations_processor_spec.rb +0 -0
  119. data/spec/canvas_sync/processors/context_module_items_processor_spec.rb +0 -0
  120. data/spec/canvas_sync/processors/context_modules_processor_spec.rb +0 -0
  121. data/spec/canvas_sync/processors/course_completion_report_processor_spec.rb +0 -0
  122. data/spec/canvas_sync/processors/rubric_assessments_spec.rb +0 -0
  123. data/spec/canvas_sync/processors/rubric_associations_spec.rb +0 -0
  124. data/spec/canvas_sync/processors/rubrics_processor_spec.rb +0 -0
  125. data/spec/canvas_sync/processors/submissions_processor_spec.rb +0 -0
  126. data/spec/canvas_sync/services/module_event_spec.rb +0 -0
  127. data/spec/canvas_sync/services/module_item_event_spec.rb +0 -0
  128. data/spec/factories/admin_factory.rb +0 -0
  129. data/spec/factories/assignment_factory.rb +0 -0
  130. data/spec/factories/assignment_group_factory.rb +0 -0
  131. data/spec/factories/context_module_factory.rb +0 -0
  132. data/spec/factories/context_module_item_factory.rb +0 -0
  133. data/spec/factories/course_factory.rb +0 -0
  134. data/spec/factories/enrollment_factory.rb +0 -0
  135. data/spec/factories/group_factory.rb +0 -0
  136. data/spec/factories/group_membership_factory.rb +0 -0
  137. data/spec/factories/role_factory.rb +0 -0
  138. data/spec/factories/section_factory.rb +0 -0
  139. data/spec/factories/submission_factory.rb +0 -0
  140. data/spec/factories/term_factory.rb +0 -0
  141. data/spec/factories/user_factory.rb +0 -0
  142. data/spec/spec_helper.rb +3 -1
  143. data/spec/support/fake_canvas.rb +4 -0
  144. data/spec/support/fixtures/canvas_responses/account.json +12 -0
  145. data/spec/support/fixtures/canvas_responses/admins.json +0 -0
  146. data/spec/support/fixtures/canvas_responses/module.json +0 -0
  147. data/spec/support/fixtures/canvas_responses/module_item.json +0 -0
  148. data/spec/support/fixtures/canvas_responses/roles.json +0 -0
  149. data/spec/support/fixtures/canvas_responses/terms.json +0 -0
  150. data/spec/support/fixtures/reports/assignment_groups.csv +0 -0
  151. data/spec/support/fixtures/reports/assignments.csv +0 -0
  152. data/spec/support/fixtures/reports/content_migrations.csv +0 -0
  153. data/spec/support/fixtures/reports/context_module_items.csv +0 -0
  154. data/spec/support/fixtures/reports/context_modules.csv +0 -0
  155. data/spec/support/fixtures/reports/course_nicknames.csv +0 -0
  156. data/spec/support/fixtures/reports/course_progresses.csv +0 -0
  157. data/spec/support/fixtures/reports/course_progresses_conflict.csv +0 -0
  158. data/spec/support/fixtures/reports/grading_period_groups.csv +0 -0
  159. data/spec/support/fixtures/reports/grading_periods.csv +0 -0
  160. data/spec/support/fixtures/reports/group_memberships.csv +0 -0
  161. data/spec/support/fixtures/reports/groups.csv +0 -0
  162. data/spec/support/fixtures/reports/learning_outcome_results.csv +0 -0
  163. data/spec/support/fixtures/reports/learning_outcomes.csv +0 -0
  164. data/spec/support/fixtures/reports/provisioning_csv +0 -0
  165. data/spec/support/fixtures/reports/rubric_assessments.csv +0 -0
  166. data/spec/support/fixtures/reports/rubric_associations.csv +0 -0
  167. data/spec/support/fixtures/reports/rubrics.csv +0 -0
  168. data/spec/support/fixtures/reports/sections.csv +0 -0
  169. data/spec/support/fixtures/reports/submissions.csv +0 -0
  170. data/spec/support/fixtures/reports/user_observers.csv +0 -0
  171. data/spec/support/fixtures/reports/users.csv +0 -0
  172. data/spec/support/fixtures/reports/xlist.csv +0 -0
  173. metadata +9 -143
  174. data/spec/internal/app/models/account.rb +0 -35
  175. data/spec/internal/app/models/admin.rb +0 -35
  176. data/spec/internal/app/models/assignment.rb +0 -39
  177. data/spec/internal/app/models/assignment_group.rb +0 -31
  178. data/spec/internal/app/models/assignment_override.rb +0 -34
  179. data/spec/internal/app/models/content_migration.rb +0 -18
  180. data/spec/internal/app/models/context_module.rb +0 -69
  181. data/spec/internal/app/models/context_module_item.rb +0 -33
  182. data/spec/internal/app/models/course.rb +0 -57
  183. data/spec/internal/app/models/course_nickname.rb +0 -20
  184. data/spec/internal/app/models/course_progress.rb +0 -29
  185. data/spec/internal/app/models/enrollment.rb +0 -48
  186. data/spec/internal/app/models/grading_period.rb +0 -17
  187. data/spec/internal/app/models/grading_period_group.rb +0 -16
  188. data/spec/internal/app/models/group.rb +0 -28
  189. data/spec/internal/app/models/group_membership.rb +0 -26
  190. data/spec/internal/app/models/learning_outcome.rb +0 -30
  191. data/spec/internal/app/models/learning_outcome_result.rb +0 -54
  192. data/spec/internal/app/models/pseudonym.rb +0 -19
  193. data/spec/internal/app/models/role.rb +0 -27
  194. data/spec/internal/app/models/rubric.rb +0 -36
  195. data/spec/internal/app/models/rubric_assessment.rb +0 -23
  196. data/spec/internal/app/models/rubric_association.rb +0 -20
  197. data/spec/internal/app/models/score.rb +0 -18
  198. data/spec/internal/app/models/section.rb +0 -36
  199. data/spec/internal/app/models/submission.rb +0 -32
  200. data/spec/internal/app/models/term.rb +0 -46
  201. data/spec/internal/app/models/user.rb +0 -43
  202. data/spec/internal/app/models/user_observer.rb +0 -22
  203. data/spec/internal/app/services/live_events/assignment_event.rb +0 -43
  204. data/spec/internal/app/services/live_events/course_event.rb +0 -28
  205. data/spec/internal/app/services/live_events/course_section_event.rb +0 -28
  206. data/spec/internal/app/services/live_events/enrollment_event.rb +0 -30
  207. data/spec/internal/app/services/live_events/grade_event.rb +0 -36
  208. data/spec/internal/app/services/live_events/module_event.rb +0 -26
  209. data/spec/internal/app/services/live_events/module_item_event.rb +0 -25
  210. data/spec/internal/app/services/live_events/submission_event.rb +0 -28
  211. data/spec/internal/app/services/live_events/syllabus_event.rb +0 -31
  212. data/spec/internal/app/services/live_events/user_event.rb +0 -27
  213. data/spec/internal/db/migrate/20251029222307_create_users.rb +0 -26
  214. data/spec/internal/db/migrate/20251029222308_create_pseudonyms.rb +0 -24
  215. data/spec/internal/db/migrate/20251029222309_create_courses.rb +0 -30
  216. data/spec/internal/db/migrate/20251029222310_create_groups.rb +0 -29
  217. data/spec/internal/db/migrate/20251029222311_create_group_memberships.rb +0 -24
  218. data/spec/internal/db/migrate/20251029222312_create_accounts.rb +0 -23
  219. data/spec/internal/db/migrate/20251029222313_create_terms.rb +0 -24
  220. data/spec/internal/db/migrate/20251029222314_create_enrollments.rb +0 -31
  221. data/spec/internal/db/migrate/20251029222315_create_sections.rb +0 -27
  222. data/spec/internal/db/migrate/20251029222316_create_assignments.rb +0 -37
  223. data/spec/internal/db/migrate/20251029222317_create_submissions.rb +0 -32
  224. data/spec/internal/db/migrate/20251029222318_create_roles.rb +0 -24
  225. data/spec/internal/db/migrate/20251029222319_create_admins.rb +0 -26
  226. data/spec/internal/db/migrate/20251029222320_create_assignment_groups.rb +0 -28
  227. data/spec/internal/db/migrate/20251029222321_create_context_modules.rb +0 -28
  228. data/spec/internal/db/migrate/20251029222322_create_context_module_items.rb +0 -26
  229. data/spec/internal/db/migrate/20251029222324_create_grading_periods.rb +0 -28
  230. data/spec/internal/db/migrate/20251029222325_create_grading_period_groups.rb +0 -24
  231. data/spec/internal/db/migrate/20251029222326_create_content_migrations.rb +0 -30
  232. data/spec/internal/db/migrate/20251029222327_create_learning_outcomes.rb +0 -36
  233. data/spec/internal/db/migrate/20251029222328_create_learning_outcome_results.rb +0 -52
  234. data/spec/internal/db/migrate/20251029222330_create_rubrics.rb +0 -44
  235. data/spec/internal/db/migrate/20251029222331_create_rubric_associations.rb +0 -42
  236. data/spec/internal/db/migrate/20251029222332_create_rubric_assessments.rb +0 -37
  237. data/spec/internal/db/migrate/20251029222334_create_assignment_overrides.rb +0 -25
  238. data/spec/internal/db/migrate/20251029222335_create_scores.rb +0 -42
  239. data/spec/internal/db/migrate/20251029223411_create_user_observers.rb +0 -23
  240. data/spec/internal/db/migrate/20251029224009_create_course_nicknames.rb +0 -23
  241. data/spec/internal/db/migrate/20251029224010_create_course_progresses.rb +0 -26
  242. data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +0 -3
  243. data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83ea16b4fb4ba5a744d39a92d8145e5ebf1123355e5c6562094f91fe5d523176
4
- data.tar.gz: 7505711d374c3f86648ce435234668df10a6c032dc6546cdf144c4b6d9d944f9
3
+ metadata.gz: 5b9df64b18232b05db0d002ff124845da7e8b5b04e712024047122e5ee3d228d
4
+ data.tar.gz: 9537a34a09178f945eca6342159b005491c38fb52848ebd1c095358a57718354
5
5
  SHA512:
6
- metadata.gz: 9906d9f164b5cdae293e6ca6e249a7793988c951ea7f3d84500364e8e88f2184e8f1fc58d54e762f4854d4fa5f755115a99759fdeea1f3b5d56bde94181aca1a
7
- data.tar.gz: a0b592ee83e841af466cd06d66f564d9e731f7398a9f400fa96da4807a0027dd5575163b60cc10351730b017bc15ff18fbbc8f2073ef48a2724d5529d70bbfd4
6
+ metadata.gz: '0647553723168ca27615daff30aa6a3ed746e68c11d559e51db31e6710a665572668765431ffcfe01f3db7807d2dd938be80f33987c47cd852477435264519a0'
7
+ data.tar.gz: 57031d7dd3884bbdf2f8c8af966e9ccdeb257011537aee39ba23ab261c3dee38b2dc32f69957b1d3d4d2b294d1fa0da88ff6736118091917b7b017830c9dfb1d
File without changes
File without changes
File without changes
data/config/routes.rb CHANGED
File without changes
File without changes
File without changes
File without changes
@@ -98,18 +98,59 @@ module CanvasSync::Concerns
98
98
  canvas_roles.where.not(base_role_type: 'AccountMembership')
99
99
  end
100
100
 
101
+ ACCOUNT_ADMIN_ROLE_LABELS = ["AccountAdmin", "Account Admin"].freeze
102
+
103
+ # True for an Admin of the Account this Tool is installed on. Note that
104
+ # `:root` is PandaPal's install-Account sense of "root" — the top of what
105
+ # this Tool can see — and not necessarily Canvas's own root Account.
101
106
  def canvas_super_user?
102
107
  canvas_account_admin?(:root)
103
108
  end
104
109
 
110
+ # True when the User administers +account+, INCLUDING by way of an Admin
111
+ # role held on an Account above it: in Canvas an Account Admin administers
112
+ # their Account and everything beneath it, so checking only the exact
113
+ # Account under-reports. Where a Tool is installed on a sub-account, that
114
+ # under-reporting inverted this check both ways — a genuine higher-level
115
+ # admin was rejected while a lower-scoped one was accepted.
105
116
  def canvas_account_admin?(account = launch_account)
106
- panda_pal_session.cache([:canvas_account_admin?, account]) do
107
- panda_pal_session.canvas_site_admin? || (panda_pal_session.canvas_account_role_labels(account) & ["AccountAdmin", "Account Admin"]).present?
117
+ # The `:inherited` cache-key segment is load-bearing, not decoration:
118
+ # #cache persists into the Session row, so sessions created before the
119
+ # traversal existed hold a cached `false` under the old key. Keying the
120
+ # new semantics separately retires those answers instead of serving
121
+ # stale denials to already-launched sessions.
122
+ panda_pal_session.cache([:canvas_account_admin?, account, :inherited]) do
123
+ panda_pal_session.canvas_site_admin? ||
124
+ (account_role_labels(account) & ACCOUNT_ADMIN_ROLE_LABELS).present?
108
125
  end
109
126
  end
110
127
 
111
128
  def canvas_user_id
112
129
  user&.canvas_id || panda_pal_session.get_lti_cust_param('canvas_user_id')
113
130
  end
131
+
132
+ private
133
+
134
+ # Feature-detected rather than version-pinned: CanvasSync deliberately
135
+ # declares no dependency on PandaPal (only this concern assumes one), so it
136
+ # cannot require >= 5.17 where `inherited:` was introduced. Detecting the
137
+ # keyword makes the upgrade order between the two gems irrelevant, instead
138
+ # of failing an authorization check with ArgumentError.
139
+ def account_role_labels(account)
140
+ if accepts_inherited_kwarg?
141
+ panda_pal_session.canvas_account_role_labels(account, inherited: true)
142
+ else
143
+ panda_pal_session.canvas_account_role_labels(account)
144
+ end
145
+ end
146
+
147
+ # `**opts` counts as support: a host app that wraps or decorates the Session
148
+ # commonly forwards keywords that way, and treating it as "too old" would
149
+ # silently drop the traversal for exactly the apps most likely to subclass.
150
+ def accepts_inherited_kwarg?
151
+ panda_pal_session.method(:canvas_account_role_labels).parameters.any? do |type, name|
152
+ type == :keyrest || ((type == :key || type == :keyreq) && name == :inherited)
153
+ end
154
+ end
114
155
  end
115
156
  end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -53,9 +53,13 @@ module CanvasSync
53
53
  processor_class = processor_class_name.constantize
54
54
  account_id = options[:account_id] || context[:account_id] || "self"
55
55
 
56
+ # The old ReportProcessorJob passed `batch_context.merge(options)` (e.g. sync_start_time)
57
+ # through to the processor; preserve that here for old custom Processor subclasses.
58
+ merged_options = state.merge(options)
59
+
56
60
  # The old processor signature: process(file_path, options, report_id)
57
61
  # Note: The third param was report_id in ReportProcessorJob but was account_id in practice
58
- processor_class.process(file, options, account_id)
62
+ processor_class.process(file, merged_options, account_id)
59
63
  end
60
64
  end
61
65
  end
@@ -27,10 +27,15 @@ module CanvasSync
27
27
  class << self
28
28
  def from_context
29
29
  report_batch = JobBatches::Batch.current
30
- base_context = report_batch.parent.context
31
- state = report_batch.context
30
+ state = report_batch&.context
31
+
32
+ # Only a report Batch carries :report_class. Any other Batch in the chain inherits a
33
+ # context from its parents, so check for the key itself rather than asking whether the
34
+ # context is present.
35
+ return nil if state.nil? || state[:report_class].blank?
36
+
32
37
  cls = state[:report_class].constantize
33
- cls.new(state[:report_options], base_context, state)
38
+ cls.new(state[:report_options], report_batch.parent&.context, state)
34
39
  end
35
40
 
36
41
  def perform_later(options)
@@ -141,10 +146,13 @@ module CanvasSync
141
146
  end
142
147
 
143
148
  def do_bulk_import(report_file_path, model, options: {}, mapping_key: nil, &blk)
144
- Processors::ReportProcessor.new().do_bulk_import(report_file_path, model, options: options, mapping_key: mapping_key, &blk)
149
+ import_options = { sync_start_time: state[:sync_start_time] }.merge(options)
150
+ Processors::ReportProcessor.new().do_bulk_import(report_file_path, model, options: import_options, mapping_key: mapping_key, &blk)
145
151
  end
146
152
 
147
153
  class ReportTaskJob < CanvasSync::Job
154
+ discard_on FatalReportError
155
+
148
156
  protected
149
157
 
150
158
  def canvas_account_id
@@ -10,7 +10,8 @@ module CanvasSync
10
10
  # @param options [Hash]
11
11
  def perform(options)
12
12
  unless options[:root_account] == false
13
- accid = report_task.options[:account_id] || batch_context[:account_id] || "self"
13
+ task = ReportSyncTask.from_context || nil
14
+ accid = options[:account_id] || task&.options&.dig(:account_id) || batch_context[:account_id] || "self"
14
15
  acc_params = CanvasSync.get_canvas_sync_client(batch_context).account(accid)
15
16
  update_or_create_model(Account, acc_params)
16
17
  end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -16,7 +16,7 @@ module CanvasSync
16
16
  params[model] = true
17
17
  end
18
18
 
19
- merged_params = merge_report_params(options, params)
19
+ merged_params = merge_report_params(options, params).with_indifferent_access
20
20
 
21
21
  # Make sure the report also checks last_activity_at when checking updated_at
22
22
  if options[:models].include?("enrollments")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.27.11".freeze
2
+ VERSION = "0.27.15".freeze
3
3
  end
data/lib/canvas_sync.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "active_support"
1
2
  require "bearcat"
2
3
 
3
4
  require "canvas_sync/version"
@@ -26,66 +27,53 @@ module CanvasSync
26
27
  JobBatches = Joblin::Batching
27
28
  JobUniqueness = Joblin::Uniqueness
28
29
 
29
- SUPPORTED_MODELS = %w[
30
- users
31
- pseudonyms
32
- courses
33
- groups
34
- group_memberships
35
- accounts
36
- terms
37
- enrollments
38
- sections
39
- assignments
40
- submissions
41
- roles
42
- admins
43
- assignment_groups
44
- context_modules
45
- context_module_items
46
- xlist
47
- user_observers
48
- grading_periods
49
- grading_period_groups
50
- content_migrations
51
- learning_outcomes
52
- learning_outcome_results
53
- course_nicknames
54
- rubrics
55
- rubric_associations
56
- rubric_assessments
57
- course_progresses
58
- assignment_overrides
59
- scores
60
- ].freeze
30
+ KNOWN_MODELS = {
31
+ users: { job: :provisioning, term_scoped: false },
32
+ pseudonyms: { job: :provisioning, term_scoped: false },
33
+ user_observers: { job: :provisioning, term_scoped: false },
34
+ grading_periods: { job: :provisioning, term_scoped: false },
35
+ grading_period_groups: { job: :provisioning, term_scoped: false },
36
+ learning_outcomes: { job: :provisioning, term_scoped: false },
37
+ learning_outcome_results: { job: :provisioning, term_scoped: false },
61
38
 
62
- SUPPORTED_TERM_SCOPE_MODELS = %w[
63
- assignments
64
- submissions
65
- assignment_groups
66
- context_modules
67
- context_module_items
68
- rubrics
69
- rubric_associations
70
- rubric_assessments
71
- course_progresses
72
- assignment_overrides
73
- scores
74
- ].freeze
39
+ terms: { job: CanvasSync::Jobs::SyncTermsJob, term_scoped: false },
40
+ accounts: { job: CanvasSync::Jobs::SyncAccountsJob, term_scoped: false },
41
+ roles: { job: CanvasSync::Jobs::SyncRolesJob, term_scoped: false },
42
+ admins: { job: CanvasSync::Jobs::SyncAdminsJob, term_scoped: false },
75
43
 
76
- DEFAULT_TERM_SCOPE_MODELS = %w[
77
- assignments
78
- submissions
79
- assignment_groups
80
- context_modules
81
- context_module_items
82
- rubrics
83
- rubric_associations
84
- rubric_assessments
85
- course_progresses
86
- assignment_overrides
87
- scores
88
- ].freeze
44
+ groups: { job: :provisioning, term_scoped: false },
45
+ group_memberships: { job: :provisioning, term_scoped: false },
46
+
47
+ courses: { job: :provisioning, term_scoped: true },
48
+ course_nicknames: { job: :provisioning, term_scoped: true },
49
+ sections: { job: :provisioning, term_scoped: true },
50
+ xlist: { job: :provisioning, term_scoped: true },
51
+
52
+ context_modules: { job: CanvasSync::Jobs::SyncContextModulesJob, term_scoped: true },
53
+ context_module_items: { job: CanvasSync::Jobs::SyncContextModuleItemsJob, term_scoped: true },
54
+ content_migrations: { job: CanvasSync::Jobs::SyncContentMigrationsJob, term_scoped: true },
55
+
56
+ enrollments: { job: :provisioning, term_scoped: true },
57
+ course_progresses: { job: CanvasSync::Jobs::SyncCourseProgressesJob, term_scoped: true },
58
+
59
+ assignments: { job: CanvasSync::Jobs::SyncAssignmentsJob, term_scoped: true },
60
+ assignment_groups: { job: CanvasSync::Jobs::SyncAssignmentGroupsJob, term_scoped: true },
61
+ assignment_overrides: { job: CanvasSync::Jobs::SyncAssignmentOverridesJob, term_scoped: true },
62
+ submissions: { job: CanvasSync::Jobs::SyncSubmissionsJob, term_scoped: true },
63
+ scores: { job: CanvasSync::Jobs::SyncScoresJob, term_scoped: true },
64
+
65
+ rubrics: { job: CanvasSync::Jobs::SyncRubricsJob, term_scoped: false },
66
+ rubric_associations: { job: CanvasSync::Jobs::SyncRubricAssociationsJob, term_scoped: false },
67
+ rubric_assessments: { job: CanvasSync::Jobs::SyncRubricAssessmentsJob, term_scoped: false },
68
+ }.with_indifferent_access.freeze
69
+
70
+ SUPPORTED_MODELS = KNOWN_MODELS.keys.map(&:to_s).freeze
71
+
72
+ SUPPORTED_TERM_SCOPE_MODELS = KNOWN_MODELS.select { |_, v| v[:term_scoped] }.keys.map(&:to_s).freeze
73
+
74
+ DEFAULT_TERM_SCOPE_MODELS = SUPPORTED_TERM_SCOPE_MODELS
75
+
76
+ PROVISIONING_REPORT_MODELS = KNOWN_MODELS.select { |_, v| v[:job] == :provisioning }.keys.map(&:to_s).freeze
89
77
 
90
78
  SUPPORTED_LIVE_EVENTS = %w[
91
79
  course
@@ -181,26 +169,7 @@ module CanvasSync
181
169
  options = options.deep_symbolize_keys!
182
170
 
183
171
  given_models = models.dup
184
-
185
- model_job_map = {
186
- terms: CanvasSync::Jobs::SyncTermsJob,
187
- accounts: CanvasSync::Jobs::SyncAccountsJob,
188
- roles: CanvasSync::Jobs::SyncRolesJob,
189
- admins: CanvasSync::Jobs::SyncAdminsJob,
190
-
191
- assignments: CanvasSync::Jobs::SyncAssignmentsJob,
192
- submissions: CanvasSync::Jobs::SyncSubmissionsJob,
193
- assignment_groups: CanvasSync::Jobs::SyncAssignmentGroupsJob,
194
- assignment_overrides: CanvasSync::Jobs::SyncAssignmentOverridesJob,
195
- context_modules: CanvasSync::Jobs::SyncContextModulesJob,
196
- context_module_items: CanvasSync::Jobs::SyncContextModuleItemsJob,
197
- content_migrations: CanvasSync::Jobs::SyncContentMigrationsJob,
198
- course_progresses: CanvasSync::Jobs::SyncCourseProgressesJob,
199
- rubrics: CanvasSync::Jobs::SyncRubricsJob,
200
- rubric_associations: CanvasSync::Jobs::SyncRubricAssociationsJob,
201
- rubric_assessments: CanvasSync::Jobs::SyncRubricAssessmentsJob,
202
- scores: CanvasSync::Jobs::SyncScoresJob,
203
- }.with_indifferent_access
172
+ term_scoped_models = term_scoped_models & SUPPORTED_TERM_SCOPE_MODELS
204
173
 
205
174
  root_chain = base_canvas_sync_chain(**kwargs, globals: options[:global] || kwargs[:globals])
206
175
  concurrent_root_chain = JobBatches::ChainBuilder.new(JobBatches::ConcurrentBatchJob)
@@ -210,7 +179,8 @@ module CanvasSync
210
179
 
211
180
  try_add_model_job = ->(model) {
212
181
  return unless models.include?(model)
213
- current_chain << { job: model_job_map[model].to_s, options: options[model.to_sym] || {} }
182
+ return if KNOWN_MODELS[model][:job] == :provisioning
183
+ current_chain << { job: KNOWN_MODELS[model][:job].to_s, options: options[model.to_sym] || {} }
214
184
  models -= [model]
215
185
  }
216
186
 
@@ -218,20 +188,26 @@ module CanvasSync
218
188
  # General provisioning jobs (not term-scoped)
219
189
  ##############################
220
190
 
191
+ models -= ['terms']
192
+
221
193
  # Accounts, users, roles, and admins cannot be scoped to term
222
194
  try_add_model_job.call('accounts')
223
195
 
224
- # These Models use the provisioning report, but are not term-scoped,
225
- # so we sync them outside of the term scoping to ensure work is not duplicated
196
+ # We could safely remove the unless wrapping, but it allows us to just merge these models into
197
+ # the later provisioning report so we do it w/ one report instead of two.
226
198
  unless term_scope == false
227
- models -= (first_provisioning_models = models & ['users', 'pseudonyms', 'user_observers', 'grading_periods', 'grading_period_groups'])
199
+ # These Models use the provisioning report, but are not term-scoped,
200
+ # so we sync them outside of the term scoping to ensure work is not duplicated
201
+ first_provisioning_models = (models - term_scoped_models) & PROVISIONING_REPORT_MODELS
202
+ models -= first_provisioning_models
228
203
  current_chain.insert(generate_provisioning_jobs(first_provisioning_models, options))
229
204
  end
230
205
 
231
206
  try_add_model_job.call('roles')
232
207
  try_add_model_job.call('admins')
233
208
 
234
- (SUPPORTED_TERM_SCOPE_MODELS - term_scoped_models).each do |mdl|
209
+ # (SUPPORTED_TERM_SCOPE_MODELS - term_scoped_models).each do |mdl|
210
+ (models - term_scoped_models).each do |mdl|
235
211
  try_add_model_job.call(mdl)
236
212
  end
237
213
 
@@ -241,22 +217,26 @@ module CanvasSync
241
217
 
242
218
  term_parent_chain = current_chain
243
219
 
244
- per_term_chain = JobBatches::ChainBuilder.build(model_job_map[:terms], term_scope: term_scope)
220
+ per_term_chain = JobBatches::ChainBuilder.build(KNOWN_MODELS['terms'][:job].to_s, term_scope: term_scope)
245
221
  current_chain = per_term_chain
246
222
 
247
223
  term_scoped_models.each do |mdl|
248
224
  try_add_model_job.call(mdl)
249
225
  end
250
226
 
227
+ prov_rep_models = models & PROVISIONING_REPORT_MODELS
228
+ models -= prov_rep_models
251
229
  current_chain.insert(
252
- generate_provisioning_jobs(models - ['terms'], options)
230
+ generate_provisioning_jobs(prov_rep_models, options)
253
231
  )
254
232
 
255
233
  # Skip syncing terms if not required
256
- if !current_chain.empty? || (models & ['terms']).present?
234
+ if !current_chain.empty? || (given_models & ['terms']).present?
257
235
  term_parent_chain << per_term_chain
258
236
  end
259
237
 
238
+ raise ArgumentError, "Some models were not processed: #{models.join(', ')}" if models.present?
239
+
260
240
  ###############################
261
241
  # Wrap it all up
262
242
  ###############################