oneroster 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ PAGE_LIMIT = 5_000
5
+
6
+ class Paginator
7
+ def initialize(connection, path, method, type, offset = 0, limit = PAGE_LIMIT, client: nil)
8
+ @connection = connection
9
+ @path = path
10
+ @method = method
11
+ @type = type
12
+ @offset = offset
13
+ @limit = limit
14
+ @client = client
15
+ end
16
+
17
+ def fetch
18
+ Enumerator.new do |yielder|
19
+ loop do
20
+ response = request(@path, @offset)
21
+ body = response.body
22
+
23
+ fail "Failed to fetch #{@path}" unless response.success?
24
+ fail StopIteration if body.empty?
25
+
26
+ if body.any?
27
+ body.each do |item|
28
+ yielder << @type.new(item, client: @client) unless item['status'] == 'tobedeleted'
29
+ end
30
+ end
31
+
32
+ @offset = next_offset
33
+ end
34
+ end.lazy
35
+ end
36
+
37
+ def self.fetch(*params)
38
+ new(*params).fetch
39
+ end
40
+
41
+ private
42
+
43
+ def next_offset
44
+ @offset + @limit
45
+ end
46
+
47
+ def request(path, offset)
48
+ @connection.execute(path, @method, limit: @limit, offset: offset)
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,31 @@
1
+ module OneRoster
2
+ class Response
3
+ attr_reader :status, :raw_body, :headers
4
+
5
+ attr_accessor :body
6
+
7
+ def initialize(faraday_response)
8
+ @status = faraday_response.status
9
+ @raw_body = faraday_response.body
10
+ @type = resource_type(faraday_response)
11
+
12
+ return unless faraday_response.body
13
+
14
+ @body = faraday_response.body[@type]
15
+
16
+ return unless faraday_response.headers
17
+
18
+ @headers = faraday_response.headers
19
+ end
20
+
21
+ def success?
22
+ @status == 200
23
+ end
24
+
25
+ private
26
+
27
+ def resource_type(faraday_response)
28
+ RESPONSE_TYPE_MAP[faraday_response.env.url.path.split('/').last]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ VERSION = '1.3.6'
5
+ end
@@ -0,0 +1,19 @@
1
+ module OneRoster
2
+ module Types
3
+ class Application < Base
4
+ attr_reader :uid,
5
+ :bearer,
6
+ :name,
7
+ :tenant_name,
8
+ :app_id
9
+
10
+ def initialize(attributes = {}, *)
11
+ @uid = attributes['id']
12
+ @bearer = attributes['bearer']
13
+ @name = attributes['name']
14
+ @tenant_name = attributes['tenant_name']
15
+ @app_id = attributes['oneroster_application_id']
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Base
6
+ def to_h
7
+ instance_variables.each_with_object({}) do |instance_var, variables|
8
+ key = instance_var.to_s.tr('@', '').to_sym
9
+ value = instance_variable_get(instance_var)
10
+ variables[key] = value
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Class < Base
6
+ attr_reader :uid,
7
+ :title,
8
+ :course_uid,
9
+ :provider,
10
+ :period,
11
+ :grades
12
+
13
+ def initialize(attributes = {}, *)
14
+ @uid = attributes['sourcedId']
15
+ @title = capitalize(attributes['title'])
16
+ @course_uid = attributes['course']['sourcedId']
17
+ @status = attributes['status']
18
+ @period = first_period(attributes) || period_from_code(attributes)
19
+ @grades = attributes['grades']
20
+ @provider = 'oneroster'
21
+ end
22
+
23
+ private
24
+
25
+ def capitalize(string)
26
+ string.split(' ').map(&:capitalize).join(' ')
27
+ end
28
+
29
+ def first_period(attributes)
30
+ attributes['periods']&.first
31
+ end
32
+
33
+ def period_from_code(attributes)
34
+ attributes['classCode']&.match(/- Period (\d+) -/) { |m| m[1] }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Classroom < Base
6
+ attr_reader :uid,
7
+ :name,
8
+ :course_number,
9
+ :period,
10
+ :grades,
11
+ :provider
12
+
13
+ def initialize(attributes = {})
14
+ @uid = attributes['id']
15
+ @name = attributes['name']
16
+ @course_number = attributes['course_number']
17
+ @period = attributes['period']
18
+ @grades = attributes['grades']
19
+ @provider = 'oneroster'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Course < Base
6
+ attr_reader :uid,
7
+ :course_code,
8
+ :provider
9
+
10
+ def initialize(attributes = {}, *)
11
+ @uid = attributes['sourcedId']
12
+ @course_code = attributes['courseCode']
13
+ @provider = 'oneroster'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Enrollment < Base
6
+ attr_reader :uid,
7
+ :classroom_uid,
8
+ :user_uid,
9
+ :role,
10
+ :provider
11
+
12
+ def initialize(attributes = {}, *)
13
+ @uid = attributes['sourcedId']
14
+ # allow instantiation with classroom_uid and user_uid attrs for consistency with clever
15
+ @classroom_uid = attributes['classroom_uid'] || attributes.dig('class', 'sourcedId')
16
+ @user_uid = attributes['user_uid'] || attributes.dig('user', 'sourcedId')
17
+ @role = attributes['role']
18
+ @primary = attributes['primary']
19
+ @provider = 'oneroster'
20
+ end
21
+
22
+ def valid?
23
+ return true if student?
24
+
25
+ teacher?
26
+ end
27
+
28
+ def primary_teacher?
29
+ teacher? && @primary.to_s == 'true'
30
+ end
31
+
32
+ def teacher?
33
+ @role == 'teacher'
34
+ end
35
+
36
+ def student?
37
+ @role == 'student'
38
+ end
39
+
40
+ def to_h
41
+ {
42
+ classroom_uid: @classroom_uid,
43
+ user_uid: @user_uid,
44
+ provider: @provider
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Student < Base
6
+ attr_reader :uid,
7
+ :first_name,
8
+ :last_name,
9
+ :provider
10
+
11
+ def initialize(attributes = {}, client: nil)
12
+ @uid = attributes['sourcedId']
13
+ @first_name = attributes['givenName']
14
+ @last_name = attributes['familyName']
15
+ @api_username = attributes['username']
16
+ @status = attributes['status']
17
+ @email = attributes['email']
18
+ @username = username(client)
19
+ @provider = 'oneroster'
20
+ end
21
+
22
+ def username(client = nil)
23
+ username_source = client&.username_source
24
+
25
+ @username ||= presence(username_from(username_source)) || default_username
26
+ end
27
+
28
+ def to_h
29
+ {
30
+ uid: @uid,
31
+ first_name: @first_name,
32
+ last_name: @last_name,
33
+ username: @username,
34
+ provider: @provider
35
+ }
36
+ end
37
+
38
+ private
39
+
40
+ def presence(field)
41
+ field unless blank?(field)
42
+ end
43
+
44
+ def blank?(field)
45
+ field.nil? || field == ''
46
+ end
47
+
48
+ def username_from(username_source)
49
+ return unless presence(username_source)
50
+
51
+ source = username_source(username_source)
52
+
53
+ presence(instance_variable_get("@#{source}"))
54
+ end
55
+
56
+ # if the username_source is `sourcedId`, we want to return `uid`
57
+ # so we can grab the right instance variable
58
+ def username_source(source)
59
+ case source
60
+ when 'sourcedId' then 'uid'
61
+ when 'username' then 'api_username'
62
+ else
63
+ source
64
+ end
65
+ end
66
+
67
+ def default_username
68
+ presence(@api_username) || presence(@email) || @uid
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneRoster
4
+ module Types
5
+ class Teacher < Base
6
+ attr_reader :uid,
7
+ :email,
8
+ :first_name,
9
+ :last_name,
10
+ :provider
11
+
12
+ def initialize(attributes = {}, *)
13
+ @uid = attributes['sourcedId']
14
+ @email = attributes['email']
15
+ @first_name = attributes['givenName']
16
+ @last_name = attributes['familyName']
17
+ @provider = 'oneroster'
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'one_roster/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'oneroster'
8
+ spec.version = OneRoster::VERSION
9
+ spec.authors = ['Robert Julius']
10
+ spec.email = ['robertmjulius@gmail.com']
11
+
12
+ spec.summary = 'Wrapper for the OneRoster API.'
13
+ spec.description = 'Wrapper for the OneRoster API.'
14
+ spec.homepage = "https://github.com/TCI/oneroster"
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
23
+ 'public gem pushes.'
24
+ end
25
+
26
+ # Specify which files should be added to the gem when it is released.
27
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
29
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
+ end
31
+ spec.bindir = 'exe'
32
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ['lib']
34
+
35
+ spec.add_runtime_dependency 'faraday'
36
+ spec.add_runtime_dependency 'faraday_middleware'
37
+ spec.add_runtime_dependency 'dry-inflector'
38
+ spec.add_runtime_dependency 'simple_oauth'
39
+ spec.add_runtime_dependency 'oauth'
40
+
41
+ spec.add_development_dependency 'bundler', '~> 2.1.4'
42
+ spec.add_development_dependency 'mocha'
43
+ spec.add_development_dependency 'pry'
44
+ spec.add_development_dependency 'pry-nav'
45
+ spec.add_development_dependency 'rake', '~> 10.0'
46
+ spec.add_development_dependency 'rspec', '~> 3.0'
47
+ spec.add_development_dependency 'rspec_junit_formatter'
48
+ spec.add_development_dependency 'rubocop'
49
+ spec.add_development_dependency 'simplecov'
50
+ end
metadata ADDED
@@ -0,0 +1,272 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oneroster
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.6
5
+ platform: ruby
6
+ authors:
7
+ - Robert Julius
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-05-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dry-inflector
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: simple_oauth
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: oauth
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.1.4
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.1.4
97
+ - !ruby/object:Gem::Dependency
98
+ name: mocha
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
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-nav
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '10.0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '10.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '3.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '3.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rspec_junit_formatter
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: simplecov
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: Wrapper for the OneRoster API.
210
+ email:
211
+ - robertmjulius@gmail.com
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - ".circleci/config.yml"
217
+ - ".codeclimate.yml"
218
+ - ".gitignore"
219
+ - ".rspec"
220
+ - ".rubocop.yml"
221
+ - ".ruby-style.yml"
222
+ - ".ruby-version"
223
+ - ".travis.yml"
224
+ - Gemfile
225
+ - Gemfile.lock
226
+ - LICENSE.txt
227
+ - README.md
228
+ - Rakefile
229
+ - bin/console
230
+ - bin/rspec
231
+ - bin/setup
232
+ - lib/one_roster.rb
233
+ - lib/one_roster/client.rb
234
+ - lib/one_roster/connection.rb
235
+ - lib/one_roster/paginator.rb
236
+ - lib/one_roster/response.rb
237
+ - lib/one_roster/version.rb
238
+ - lib/types/application.rb
239
+ - lib/types/base.rb
240
+ - lib/types/class.rb
241
+ - lib/types/classroom.rb
242
+ - lib/types/course.rb
243
+ - lib/types/enrollment.rb
244
+ - lib/types/student.rb
245
+ - lib/types/teacher.rb
246
+ - one_roster.gemspec
247
+ homepage: https://github.com/TCI/oneroster
248
+ licenses:
249
+ - MIT
250
+ metadata:
251
+ allowed_push_host: https://rubygems.org
252
+ post_install_message:
253
+ rdoc_options: []
254
+ require_paths:
255
+ - lib
256
+ required_ruby_version: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ required_rubygems_version: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - ">="
264
+ - !ruby/object:Gem::Version
265
+ version: '0'
266
+ requirements: []
267
+ rubyforge_project:
268
+ rubygems_version: 2.6.11
269
+ signing_key:
270
+ specification_version: 4
271
+ summary: Wrapper for the OneRoster API.
272
+ test_files: []