canvas_shim 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +21 -0
  5. data/app/assets/config/canvas_shim_manifest.js +2 -0
  6. data/app/assets/javascripts/canvas_shim/application.js +13 -0
  7. data/app/assets/stylesheets/canvas_shim/application.css +15 -0
  8. data/app/controllers/canvas_shim/application_controller.rb +12 -0
  9. data/app/controllers/canvas_shim/settings_api/swagger_controller.rb +11 -0
  10. data/app/controllers/canvas_shim/settings_api/v1/users_controller.rb +27 -0
  11. data/app/deploy/canvas_shim_asset_uploader.rb +19 -0
  12. data/app/helpers/canvas_shim/application_helper.rb +4 -0
  13. data/app/jobs/canvas_shim/application_job.rb +4 -0
  14. data/app/mailers/canvas_shim/application_mailer.rb +6 -0
  15. data/app/models/canvas_shim/application_record.rb +5 -0
  16. data/app/services/courses_service.rb +5 -0
  17. data/app/services/courses_service/commands/distribute_due_dates.rb +50 -0
  18. data/app/services/courses_service/commands/distribute_due_dates/scheduler.rb +70 -0
  19. data/app/services/grades_service.rb +33 -0
  20. data/app/services/grades_service/account.rb +13 -0
  21. data/app/services/grades_service/commands/zero_out_assignment_grades.rb +73 -0
  22. data/app/services/grades_service/commands/zero_out_assignment_grades_rollback.rb +38 -0
  23. data/app/services/pipeline_service.rb +27 -0
  24. data/app/services/pipeline_service/account.rb +9 -0
  25. data/app/services/pipeline_service/api/publish.rb +53 -0
  26. data/app/services/pipeline_service/commands/publish.rb +44 -0
  27. data/app/services/pipeline_service/commands/publish_events.rb +17 -0
  28. data/app/services/pipeline_service/endpoints/pipeline.rb +62 -0
  29. data/app/services/pipeline_service/endpoints/pipeline/message_builder.rb +75 -0
  30. data/app/services/pipeline_service/events/emitter.rb +56 -0
  31. data/app/services/pipeline_service/events/graded_out_event.rb +31 -0
  32. data/app/services/pipeline_service/events/http_client.rb +14 -0
  33. data/app/services/pipeline_service/events/responders/sis.rb +66 -0
  34. data/app/services/pipeline_service/events/subscription.rb +11 -0
  35. data/app/services/pipeline_service/http_client.rb +21 -0
  36. data/app/services/pipeline_service/logger.rb +39 -0
  37. data/app/services/pipeline_service/pipeline_client.rb +41 -0
  38. data/app/services/pipeline_service/serializers/assignment.rb +55 -0
  39. data/app/services/pipeline_service/serializers/base_methods.rb +33 -0
  40. data/app/services/pipeline_service/serializers/canvas_api_enrollment.rb +55 -0
  41. data/app/services/pipeline_service/serializers/enrollment.rb +31 -0
  42. data/app/services/pipeline_service/serializers/fetcher.rb +17 -0
  43. data/app/services/pipeline_service/serializers/submission.rb +30 -0
  44. data/app/services/pipeline_service/serializers/user.rb +31 -0
  45. data/app/services/settings_service.rb +51 -0
  46. data/app/services/settings_service/api_docs.yml +68 -0
  47. data/app/services/settings_service/assignment.rb +24 -0
  48. data/app/services/settings_service/assignment_repository.rb +89 -0
  49. data/app/services/settings_service/auth_middleware.rb +19 -0
  50. data/app/services/settings_service/auth_token.rb +21 -0
  51. data/app/services/settings_service/authenticator_stub.rb +9 -0
  52. data/app/services/settings_service/commands/get_enrollment_settings.rb +17 -0
  53. data/app/services/settings_service/commands/get_settings.rb +34 -0
  54. data/app/services/settings_service/commands/get_user_settings.rb +18 -0
  55. data/app/services/settings_service/commands/update_enrollment_setting.rb +22 -0
  56. data/app/services/settings_service/commands/update_settings.rb +38 -0
  57. data/app/services/settings_service/commands/update_user_setting.rb +21 -0
  58. data/app/services/settings_service/enrollment.rb +28 -0
  59. data/app/services/settings_service/queries/zero_grader_audit.rb +6 -0
  60. data/app/services/settings_service/repository.rb +93 -0
  61. data/app/services/settings_service/school.rb +26 -0
  62. data/app/services/settings_service/student_assignment.rb +24 -0
  63. data/app/services/settings_service/student_assignment_repository.rb +116 -0
  64. data/app/services/settings_service/submission.rb +24 -0
  65. data/app/services/settings_service/user.rb +28 -0
  66. data/app/views/layouts/canvas_shim/application.html.erb +14 -0
  67. data/config/initializers/hash.rb +17 -0
  68. data/config/initializers/string.rb +9 -0
  69. data/config/routes.rb +9 -0
  70. data/lib/canvas_shim.rb +5 -0
  71. data/lib/canvas_shim/engine.rb +12 -0
  72. data/lib/canvas_shim/version.rb +3 -0
  73. data/lib/tasks/canvas_shim_tasks.rake +7 -0
  74. metadata +214 -0
@@ -0,0 +1,26 @@
1
+ module SettingsService
2
+ class School
3
+ OBJECT_NAME = 'school_settings'
4
+
5
+ def self.create_table
6
+ Repository.create_table(name: table_name)
7
+ end
8
+
9
+ def self.get(id:)
10
+ Repository.get(table_name: table_name, id: id)
11
+ end
12
+
13
+ def self.put(id:, setting: , value:)
14
+ Repository.put(
15
+ table_name: table_name,
16
+ id: id,
17
+ setting: setting,
18
+ value: value
19
+ )
20
+ end
21
+
22
+ def self.table_name
23
+ [SettingsService.canvas_domain, '-', OBJECT_NAME].join('')
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module SettingsService
2
+ class StudentAssignment
3
+ def self.table_name
4
+ [SettingsService.canvas_domain, '-', 'student_assignment_settings'].join('')
5
+ end
6
+ def self.put(id:, setting: , value:)
7
+ StudentAssignmentRepository.put(
8
+ table_name: table_name,
9
+ id: id,
10
+ setting: setting,
11
+ value: value
12
+ )
13
+ end
14
+ def table_name
15
+ self.class.table_name
16
+ end
17
+ def self.create_table
18
+ StudentAssignmentRepository.create_table(name: table_name)
19
+ end
20
+ def self.get(id:)
21
+ StudentAssignmentRepository.get(table_name: table_name, id: id)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,116 @@
1
+ require 'forwardable'
2
+ module SettingsService
3
+ class StudentAssignmentRepository
4
+ include Singleton
5
+
6
+ class << self
7
+ extend Forwardable
8
+ def_delegators :instance, :create_table, :get, :put
9
+ end
10
+
11
+ def initialize
12
+ raise "missing canvas domain!" if SettingsService.canvas_domain.nil?
13
+ @secret_key = ENV['S3_ACCESS_KEY']
14
+ @id_key = ENV['S3_ACCESS_KEY_ID']
15
+ Aws.config.update(
16
+ region: 'us-west-2',
17
+ credentials: creds
18
+ )
19
+ end
20
+
21
+ def create_table(name:)
22
+ begin
23
+ self.class.dynamodb.create_table(table_params(name)).successful?
24
+ rescue
25
+ end
26
+ end
27
+
28
+ def get(table_name:, id:)
29
+ assignment = ::Assignment.find(id[:assignment_id])
30
+ migration_id = assignment.migration_id
31
+ student_assignment_id = "#{migration_id}:#{id[:student_id]}"
32
+
33
+ self.class.dynamodb.query(
34
+ table_name: table_name,
35
+ key_condition_expression: "#id = :id",
36
+ expression_attribute_names: { "#id" => "id" },
37
+ expression_attribute_values: { ":id" => student_assignment_id }
38
+ ).items.inject({}) do |newhash, setting|
39
+ newhash[setting['setting']] = setting['value']
40
+ newhash
41
+ end
42
+ end
43
+
44
+ def put(table_name:, id:, setting:, value:)
45
+ return unless value == 'increment'
46
+
47
+
48
+ assignment = ::Assignment.find(id[:assignment_id])
49
+ return unless assignment.migration_id
50
+ migration_id = assignment.migration_id
51
+ student_assignment_id = "#{migration_id}:#{id[:student_id]}"
52
+
53
+
54
+ value = SettingsService.get_settings(
55
+ object: 'assignment',
56
+ id: migration_id
57
+ )["max_attempts"]
58
+
59
+ return unless value
60
+
61
+ student_attempts = SettingsService.get_settings(
62
+ object: 'student_assignment',
63
+ id: id
64
+ )['max_attempts']
65
+
66
+ value = student_attempts if student_attempts
67
+
68
+ self.class.dynamodb.put_item(
69
+ table_name: table_name,
70
+ item: {
71
+ id: student_assignment_id,
72
+ setting: setting,
73
+ value: value.to_i + 1
74
+ }
75
+ )
76
+ end
77
+
78
+ def self.use_test_client!
79
+ instance.use_test_client!
80
+ end
81
+
82
+ def use_test_client!
83
+ Aws.config = {}
84
+ @dynamodb = Aws::DynamoDB::Client.new(endpoint: 'http://localhost:8000')
85
+ end
86
+
87
+ def self.dynamodb
88
+ @dynamodb || Aws::DynamoDB::Client.new
89
+ end
90
+
91
+ private
92
+
93
+ def creds
94
+ Aws::Credentials.new(@id_key, @secret_key)
95
+ end
96
+
97
+ def table_params(name)
98
+ {
99
+ table_name: name,
100
+ key_schema: [
101
+ { attribute_name: 'id', key_type: 'HASH' },
102
+ { attribute_name: 'setting', key_type: 'RANGE'},
103
+ ],
104
+ attribute_definitions: [
105
+ { attribute_name: 'id', attribute_type: 'S' },
106
+ { attribute_name: 'setting', attribute_type: 'S' },
107
+ ],
108
+ provisioned_throughput: {
109
+ read_capacity_units: 10,
110
+ write_capacity_units: 10
111
+ }
112
+ }
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,24 @@
1
+ module SettingsService
2
+ class Submission
3
+ def self.table_name
4
+ [SettingsService.canvas_domain, '-', 'submission_settings'].join('')
5
+ end
6
+ def self.put(id:, setting: , value:)
7
+ Repository.put(
8
+ table_name: table_name,
9
+ id: id,
10
+ setting: setting,
11
+ value: value
12
+ )
13
+ end
14
+ def table_name
15
+ self.class.table_name
16
+ end
17
+ def self.create_table
18
+ Repository.create_table(name: table_name)
19
+ end
20
+ def self.get(id:)
21
+ Repository.get(table_name: table_name, id: id)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ module SettingsService
2
+ class User
3
+ def self.create_table
4
+ Repository.create_table(name: table_name)
5
+ end
6
+
7
+ def self.put(id:, setting: , value:)
8
+ Repository.put(
9
+ table_name: table_name,
10
+ id: id,
11
+ setting: setting,
12
+ value: value
13
+ )
14
+ end
15
+
16
+ def self.get(id:)
17
+ Repository.get(table_name: table_name, id: id)
18
+ end
19
+
20
+ def self.table_name
21
+ [SettingsService.canvas_domain, '-', 'user_settings'].join('')
22
+ end
23
+
24
+ def table_name
25
+ self.class.table_name
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Canvas shim</title>
5
+ <%= stylesheet_link_tag "canvas_shim/application", media: "all" %>
6
+ <%= javascript_include_tag "canvas_shim/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,17 @@
1
+ module ActiveSupport
2
+ class HashWithIndifferentAccess
3
+ def delete_blank
4
+ delete_if do |k, v|
5
+ (v.respond_to?(:empty?) ? v.empty? : !v) or v.instance_of?(HashWithIndifferentAccess || Hash) && v.delete_blank.empty?
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ class Hash
12
+ def delete_blank
13
+ delete_if do |k, v|
14
+ (v.respond_to?(:empty?) ? v.empty? : !v) or v.instance_of?(HashWithIndifferentAccess || Hash) && v.delete_blank.empty?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def underscore
3
+ gsub(/::/, '/')
4
+ .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
5
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
6
+ .tr("-", "_")
7
+ .downcase
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ CanvasShim::Engine.routes.draw do
2
+ namespace "settings_api" do
3
+ resource :swagger, controller: 'swagger'
4
+ get '/docs' => redirect('/swagger/dist/index.html?url=/canvas_shim/settings_api/swagger')
5
+ namespace 'v1' do
6
+ resources :users, only: ['update']
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require "canvas_shim/engine"
2
+
3
+ module CanvasShim
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,12 @@
1
+ module CanvasShim
2
+ class Engine < ::Rails::Engine
3
+ config.autoload_paths << File.expand_path("app/services", __dir__)
4
+ config.autoload_paths << File.expand_path("app/deploy", __dir__)
5
+
6
+ isolate_namespace CanvasShim
7
+
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module CanvasShim
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ namespace :canvas_shim do
2
+ namespace :deploy do
3
+ task :assets => :environment do
4
+ CanvasShimAssetUploader.new.upload!
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,214 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: canvas_shim
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ''
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: grape
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grape-swagger
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: grape-swagger-ui
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-dynamodb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pipeline_publisher_ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pipeline_publisher_ruby
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A rails engine to be integrated with Canvas
112
+ email:
113
+ - ''
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - MIT-LICENSE
119
+ - README.md
120
+ - Rakefile
121
+ - app/assets/config/canvas_shim_manifest.js
122
+ - app/assets/javascripts/canvas_shim/application.js
123
+ - app/assets/stylesheets/canvas_shim/application.css
124
+ - app/controllers/canvas_shim/application_controller.rb
125
+ - app/controllers/canvas_shim/settings_api/swagger_controller.rb
126
+ - app/controllers/canvas_shim/settings_api/v1/users_controller.rb
127
+ - app/deploy/canvas_shim_asset_uploader.rb
128
+ - app/helpers/canvas_shim/application_helper.rb
129
+ - app/jobs/canvas_shim/application_job.rb
130
+ - app/mailers/canvas_shim/application_mailer.rb
131
+ - app/models/canvas_shim/application_record.rb
132
+ - app/services/courses_service.rb
133
+ - app/services/courses_service/commands/distribute_due_dates.rb
134
+ - app/services/courses_service/commands/distribute_due_dates/scheduler.rb
135
+ - app/services/grades_service.rb
136
+ - app/services/grades_service/account.rb
137
+ - app/services/grades_service/commands/zero_out_assignment_grades.rb
138
+ - app/services/grades_service/commands/zero_out_assignment_grades_rollback.rb
139
+ - app/services/pipeline_service.rb
140
+ - app/services/pipeline_service/account.rb
141
+ - app/services/pipeline_service/api/publish.rb
142
+ - app/services/pipeline_service/commands/publish.rb
143
+ - app/services/pipeline_service/commands/publish_events.rb
144
+ - app/services/pipeline_service/endpoints/pipeline.rb
145
+ - app/services/pipeline_service/endpoints/pipeline/message_builder.rb
146
+ - app/services/pipeline_service/events/emitter.rb
147
+ - app/services/pipeline_service/events/graded_out_event.rb
148
+ - app/services/pipeline_service/events/http_client.rb
149
+ - app/services/pipeline_service/events/responders/sis.rb
150
+ - app/services/pipeline_service/events/subscription.rb
151
+ - app/services/pipeline_service/http_client.rb
152
+ - app/services/pipeline_service/logger.rb
153
+ - app/services/pipeline_service/pipeline_client.rb
154
+ - app/services/pipeline_service/serializers/assignment.rb
155
+ - app/services/pipeline_service/serializers/base_methods.rb
156
+ - app/services/pipeline_service/serializers/canvas_api_enrollment.rb
157
+ - app/services/pipeline_service/serializers/enrollment.rb
158
+ - app/services/pipeline_service/serializers/fetcher.rb
159
+ - app/services/pipeline_service/serializers/submission.rb
160
+ - app/services/pipeline_service/serializers/user.rb
161
+ - app/services/settings_service.rb
162
+ - app/services/settings_service/api_docs.yml
163
+ - app/services/settings_service/assignment.rb
164
+ - app/services/settings_service/assignment_repository.rb
165
+ - app/services/settings_service/auth_middleware.rb
166
+ - app/services/settings_service/auth_token.rb
167
+ - app/services/settings_service/authenticator_stub.rb
168
+ - app/services/settings_service/commands/get_enrollment_settings.rb
169
+ - app/services/settings_service/commands/get_settings.rb
170
+ - app/services/settings_service/commands/get_user_settings.rb
171
+ - app/services/settings_service/commands/update_enrollment_setting.rb
172
+ - app/services/settings_service/commands/update_settings.rb
173
+ - app/services/settings_service/commands/update_user_setting.rb
174
+ - app/services/settings_service/enrollment.rb
175
+ - app/services/settings_service/queries/zero_grader_audit.rb
176
+ - app/services/settings_service/repository.rb
177
+ - app/services/settings_service/school.rb
178
+ - app/services/settings_service/student_assignment.rb
179
+ - app/services/settings_service/student_assignment_repository.rb
180
+ - app/services/settings_service/submission.rb
181
+ - app/services/settings_service/user.rb
182
+ - app/views/layouts/canvas_shim/application.html.erb
183
+ - config/initializers/hash.rb
184
+ - config/initializers/string.rb
185
+ - config/routes.rb
186
+ - lib/canvas_shim.rb
187
+ - lib/canvas_shim/engine.rb
188
+ - lib/canvas_shim/version.rb
189
+ - lib/tasks/canvas_shim_tasks.rake
190
+ homepage: http://www.strongmind.com
191
+ licenses:
192
+ - MIT
193
+ metadata: {}
194
+ post_install_message:
195
+ rdoc_options: []
196
+ require_paths:
197
+ - lib
198
+ required_ruby_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ required_rubygems_version: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ requirements: []
209
+ rubyforge_project:
210
+ rubygems_version: 2.6.14
211
+ signing_key:
212
+ specification_version: 4
213
+ summary: A tool to make it easy to write code that plugs into canvas
214
+ test_files: []