bright 1.3 → 2.1

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.
@@ -1,22 +1,21 @@
1
- require 'oauth'
1
+ require "oauth"
2
2
 
3
3
  module Bright
4
4
  module SisApi
5
- class InfiniteCampus < Base
6
-
7
- @@description = "Connects to the Infinite Campus OneRoster API for accessing student information"
8
- @@doc_url = "https://content.infinitecampus.com/sis/latest/documentation/oneroster-api"
9
- @@api_version = "1.1"
5
+ class OneRoster < Base
6
+ @@description = "Connects to the OneRoster API for accessing student information"
7
+ @@doc_url = "https://www.imsglobal.org/sites/default/files/spec/oneroster/v1p2/rostering-informationmodel/OneRosterv1p2RosteringService_InfoModelv1p0.html"
8
+ @@api_version = "1.2"
10
9
 
11
10
  attr_accessor :connection_options, :schools_cache, :school_years_cache
12
11
 
13
12
  DEMOGRAPHICS_CONVERSION = {
14
- "americanIndianOrAlaskaNative"=>"American Indian Or Alaska Native",
15
- "asian"=>"Asian",
16
- "blackOrAfricanAmerican"=>"Black Or African American",
17
- "nativeHawaiianOrOtherPacificIslander"=>"Native Hawaiian Or Other Pacific Islander",
18
- "white"=>"White",
19
- "hispanicOrLatinoEthnicity"=>"Hispanic Or Latino"
13
+ "americanIndianOrAlaskaNative" => "American Indian Or Alaska Native",
14
+ "asian" => "Asian",
15
+ "blackOrAfricanAmerican" => "Black Or African American",
16
+ "nativeHawaiianOrOtherPacificIslander" => "Native Hawaiian Or Other Pacific Islander",
17
+ "white" => "White",
18
+ "hispanicOrLatinoEthnicity" => "Hispanic Or Latino"
20
19
  }
21
20
 
22
21
  def initialize(options = {})
@@ -31,36 +30,36 @@ module Bright
31
30
  end
32
31
 
33
32
  def api_version
34
- Gem::Version.new(self.connection_options.dig(:api_version) || @@api_version)
33
+ Gem::Version.new(connection_options.dig(:api_version) || @@api_version)
35
34
  end
36
35
 
37
36
  def get_student_by_api_id(api_id, params = {})
38
- if api_version <= Gem::Version.new("1.1")
39
- params = {:role => "student"}.merge(params)
37
+ params = if api_version <= Gem::Version.new("1.1")
38
+ {role: "student"}.merge(params)
40
39
  else
41
- params = {:roles => "student"}.merge(params)
40
+ {roles: "student"}.merge(params)
42
41
  end
43
- st_hsh = self.request(:get, "users/#{api_id}", params)
44
- Student.new(convert_to_user_data(st_hsh["user"])) if st_hsh and st_hsh["user"]
42
+ st_hsh = request(:get, "users/#{api_id}", params)
43
+ Student.new(convert_to_user_data(st_hsh["user"])) if st_hsh && st_hsh["user"]
45
44
  end
46
45
 
47
46
  def get_student(params = {}, options = {})
48
- self.get_students(params, options.merge(:limit => 1, :wrap_in_collection => false)).first
47
+ get_students(params, options.merge(limit: 1, wrap_in_collection: false)).first
49
48
  end
50
49
 
51
50
  def get_students(params = {}, options = {})
52
- if api_version <= Gem::Version.new("1.1")
53
- params = {:role => "student"}.merge(params)
51
+ params = if api_version <= Gem::Version.new("1.1")
52
+ {role: "student"}.merge(params)
54
53
  else
55
- params = {:roles => "student"}.merge(params)
54
+ {roles: "student"}.merge(params)
56
55
  end
57
56
  params[:limit] = params[:limit] || options[:limit] || 100
58
- students_response_hash = self.request(:get, 'users', self.map_search_params(params))
57
+ students_response_hash = request(:get, "users", map_search_params(params))
59
58
  total_results = students_response_hash[:response_headers]["x-total-count"].to_i
60
- if students_response_hash and students_response_hash["users"]
59
+ if students_response_hash && students_response_hash["users"]
61
60
  students_hash = [students_response_hash["users"]].flatten
62
61
 
63
- students = students_hash.compact.collect {|st_hsh|
62
+ students = students_hash.compact.collect { |st_hsh|
64
63
  Student.new(convert_to_user_data(st_hsh))
65
64
  }
66
65
  end
@@ -69,14 +68,14 @@ module Bright
69
68
  load_more_call = proc { |page|
70
69
  # pages start at one, so add a page here
71
70
  params[:offset] = (params[:limit].to_i * page)
72
- api.get_students(params, {:wrap_in_collection => false})
71
+ api.get_students(params, {wrap_in_collection: false})
73
72
  }
74
73
  ResponseCollection.new({
75
- :seed_page => students,
76
- :total => total_results,
77
- :per_page => params[:limit],
78
- :load_more_call => load_more_call,
79
- :no_threads => options[:no_threads]
74
+ seed_page: students,
75
+ total: total_results,
76
+ per_page: params[:limit],
77
+ load_more_call: load_more_call,
78
+ no_threads: options[:no_threads]
80
79
  })
81
80
  else
82
81
  students
@@ -92,22 +91,22 @@ module Bright
92
91
  end
93
92
 
94
93
  def get_school_by_api_id(api_id, params = {})
95
- sc_hsh = self.request(:get, "schools/#{api_id}", params)
96
- School.new(convert_to_school_data(sc_hsh["org"])) if sc_hsh and sc_hsh["org"]
94
+ sc_hsh = request(:get, "schools/#{api_id}", params)
95
+ School.new(convert_to_school_data(sc_hsh["org"])) if sc_hsh && sc_hsh["org"]
97
96
  end
98
97
 
99
98
  def get_school(params = {}, options = {})
100
- self.get_schools(params, options.merge(:limit => 1, :wrap_in_collection => false)).first
99
+ get_schools(params, options.merge(limit: 1, wrap_in_collection: false)).first
101
100
  end
102
101
 
103
102
  def get_schools(params = {}, options = {})
104
103
  params[:limit] = params[:limit] || options[:limit] || 100
105
- schools_response_hash = self.request(:get, 'schools', self.map_school_search_params(params))
104
+ schools_response_hash = request(:get, "schools", map_school_search_params(params))
106
105
  total_results = schools_response_hash[:response_headers]["x-total-count"].to_i
107
- if schools_response_hash and schools_response_hash["orgs"]
106
+ if schools_response_hash && schools_response_hash["orgs"]
108
107
  schools_hash = [schools_response_hash["orgs"]].flatten
109
108
 
110
- schools = schools_hash.compact.collect {|sc_hsh|
109
+ schools = schools_hash.compact.collect { |sc_hsh|
111
110
  School.new(convert_to_school_data(sc_hsh))
112
111
  }
113
112
  end
@@ -116,27 +115,27 @@ module Bright
116
115
  load_more_call = proc { |page|
117
116
  # pages start at one, so add a page here
118
117
  params[:offset] = (params[:limit].to_i * page)
119
- api.get_schools(params, {:wrap_in_collection => false})
118
+ api.get_schools(params, {wrap_in_collection: false})
120
119
  }
121
120
  ResponseCollection.new({
122
- :seed_page => schools,
123
- :total => total_results,
124
- :per_page => params[:limit],
125
- :load_more_call => load_more_call,
126
- :no_threads => options[:no_threads]
121
+ seed_page: schools,
122
+ total: total_results,
123
+ per_page: params[:limit],
124
+ load_more_call: load_more_call,
125
+ no_threads: options[:no_threads]
127
126
  })
128
127
  else
129
128
  schools
130
129
  end
131
130
  end
132
131
 
133
- def get_contact_by_api_id(api_id, params ={})
134
- contact_hsh = self.request(:get, "users/#{api_id}", params)
135
- Contact.new(convert_to_user_data(contact_hsh["user"], bright_type: "Contact")) if contact_hsh and contact_hsh["user"]
132
+ def get_contact_by_api_id(api_id, params = {})
133
+ contact_hsh = request(:get, "users/#{api_id}", params)
134
+ Contact.new(convert_to_user_data(contact_hsh["user"], bright_type: "Contact")) if contact_hsh && contact_hsh["user"]
136
135
  end
137
136
 
138
137
  def request(method, path, params = {})
139
- uri = "#{self.connection_options[:uri]}/#{path}"
138
+ uri = "#{connection_options[:uri]}/#{path}"
140
139
  body = nil
141
140
  if method == :get
142
141
  query = URI.encode_www_form(params)
@@ -147,7 +146,7 @@ module Bright
147
146
 
148
147
  response = connection_retry_wrapper {
149
148
  connection = Bright::Connection.new(uri)
150
- headers = self.headers_for_auth(uri)
149
+ headers = headers_for_auth(uri)
151
150
  connection.request(method, body, headers)
152
151
  }
153
152
 
@@ -155,8 +154,8 @@ module Bright
155
154
  response_hash = JSON.parse(response.body)
156
155
  response_hash[:response_headers] = response.headers
157
156
  else
158
- puts "#{response.inspect}"
159
- puts "#{response.body}"
157
+ puts response.inspect
158
+ puts response.body
160
159
  end
161
160
  response_hash
162
161
  end
@@ -164,48 +163,46 @@ module Bright
164
163
  protected
165
164
 
166
165
  def headers_for_auth(uri)
167
- case api_version
168
- when Gem::Version.new("1.1")
169
- site = URI.parse(self.connection_options[:uri])
170
- site = "#{site.scheme}://#{site.host}"
171
- consumer = OAuth::Consumer.new(self.connection_options[:client_id], self.connection_options[:client_secret], { :site => site, :scheme => :header })
172
- options = {:timestamp => Time.now.to_i, :nonce => SecureRandom.uuid}
173
- {"Authorization" => consumer.create_signed_request(:get, uri, nil, options)["Authorization"]}
174
- when Gem::Version.new("1.2")
175
- if self.connection_options[:access_token].nil? or self.connection_options[:access_token_expires] < Time.now
176
- self.retrieve_access_token
166
+ if api_version >= Gem::Version.new("1.2") || connection_options[:token_uri].present?
167
+ if connection_options[:access_token].nil? || (connection_options[:access_token_expires] < Time.now)
168
+ retrieve_access_token
177
169
  end
178
170
  {
179
- "Authorization" => "Bearer #{self.connection_options[:access_token]}",
180
- "Accept" => "application/json;charset=UTF-8",
181
- "Content-Type" =>"application/json;charset=UTF-8"
171
+ "Authorization" => "Bearer #{connection_options[:access_token]}",
172
+ "Accept" => "application/json",
173
+ "Content-Type" => "application/json"
182
174
  }
175
+ else
176
+ site = URI.parse(connection_options[:uri])
177
+ site = "#{site.scheme}://#{site.host}"
178
+ consumer = OAuth::Consumer.new(connection_options[:client_id], connection_options[:client_secret], {site: site, scheme: :header})
179
+ options = {timestamp: Time.now.to_i, nonce: SecureRandom.uuid}
180
+ {"Authorization" => consumer.create_signed_request(:get, uri, nil, options)["Authorization"]}
183
181
  end
184
182
  end
185
183
 
186
184
  def retrieve_access_token
187
- connection = Bright::Connection.new(self.connection_options[:token_uri])
185
+ connection = Bright::Connection.new(connection_options[:token_uri])
188
186
  response = connection.request(:post,
189
187
  {
190
188
  "grant_type" => "client_credentials",
191
- "username" => self.connection_options[:client_id],
192
- "password" => self.connection_options[:client_secret]
189
+ "username" => connection_options[:client_id],
190
+ "password" => connection_options[:client_secret]
193
191
  },
194
- self.headers_for_access_token
195
- )
192
+ headers_for_access_token)
196
193
  if !response.error?
197
194
  response_hash = JSON.parse(response.body)
198
195
  end
199
196
  if response_hash["access_token"]
200
- self.connection_options[:access_token] = response_hash["access_token"]
201
- self.connection_options[:access_token_expires] = (Time.now - 10) + response_hash["expires_in"]
197
+ connection_options[:access_token] = response_hash["access_token"]
198
+ connection_options[:access_token_expires] = (Time.now - 10) + response_hash["expires_in"]
202
199
  end
203
200
  response_hash
204
201
  end
205
202
 
206
203
  def headers_for_access_token
207
204
  {
208
- "Authorization" => "Basic #{Base64.strict_encode64("#{self.connection_options[:client_id]}:#{self.connection_options[:client_secret]}")}",
205
+ "Authorization" => "Basic #{Base64.strict_encode64("#{connection_options[:client_id]}:#{connection_options[:client_secret]}")}",
209
206
  "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
210
207
  }
211
208
  end
@@ -215,7 +212,7 @@ module Bright
215
212
  default_params = {}
216
213
 
217
214
  filter = []
218
- params.each do |k,v|
215
+ params.each do |k, v|
219
216
  case k.to_s
220
217
  when "first_name"
221
218
  filter << "givenName='#{v}'"
@@ -236,14 +233,14 @@ module Bright
236
233
  unless filter.empty?
237
234
  params = {"filter" => filter.join(" AND ")}
238
235
  end
239
- default_params.merge(params).reject{|k,v| v.respond_to?(:empty?) ? v.empty? : v.nil?}
236
+ default_params.merge(params).reject { |k, v| v.respond_to?(:empty?) ? v.empty? : v.nil? }
240
237
  end
241
238
 
242
239
  def map_school_search_params(params)
243
240
  params = params.dup
244
241
  default_params = {}
245
242
  filter = []
246
- params.each do |k,v|
243
+ params.each do |k, v|
247
244
  case k.to_s
248
245
  when "number"
249
246
  filter << "identifier='#{v}'"
@@ -256,50 +253,46 @@ module Bright
256
253
  unless filter.empty?
257
254
  params = {"filter" => filter.join(" AND ")}
258
255
  end
259
- default_params.merge(params).reject{|k,v| v.respond_to?(:empty?) ? v.empty? : v.nil?}
256
+ default_params.merge(params).reject { |k, v| v.respond_to?(:empty?) ? v.empty? : v.nil? }
260
257
  end
261
258
 
262
259
  def convert_to_school_data(school_params)
263
260
  return {} if school_params.blank?
264
- school_data_hsh = {
265
- :api_id => school_params["sourcedId"],
266
- :name => school_params["name"],
267
- :number => school_params["identifier"],
268
- :last_modified => school_params["dateLastModified"]
261
+ {
262
+ api_id: school_params["sourcedId"],
263
+ name: school_params["name"],
264
+ number: school_params["identifier"],
265
+ last_modified: school_params["dateLastModified"]
269
266
  }
270
- return school_data_hsh
271
267
  end
272
268
 
273
269
  def convert_to_user_data(user_params, bright_type: "Student")
274
270
  return {} if user_params.blank?
275
271
  user_data_hsh = {
276
- :api_id => user_params["sourcedId"],
277
- :first_name => user_params["givenName"],
278
- :middle_name => user_params["middleName"],
279
- :last_name => user_params["familyName"],
280
- :last_modified => user_params["dateLastModified"]
281
- }.reject{|k,v| v.blank?}
272
+ api_id: user_params["sourcedId"],
273
+ first_name: user_params["givenName"],
274
+ middle_name: user_params["middleName"],
275
+ last_name: user_params["familyName"],
276
+ last_modified: user_params["dateLastModified"]
277
+ }.reject { |k, v| v.blank? }
282
278
  unless user_params["identifier"].blank?
283
279
  user_data_hsh[:sis_student_id] = user_params["identifier"]
284
280
  end
285
- unless user_params["userMasterIdentifier"].blank?
286
- user_data_hsh[:state_student_id] = user_params["userMasterIdentifier"]
287
- end
288
281
  unless user_params["userIds"].blank?
289
- if (state_id_hsh = user_params["userIds"].detect{|user_id_hsh| user_id_hsh["type"] == "stateID"})
282
+ if (state_id_hsh = user_params["userIds"].detect { |user_id_hsh| user_id_hsh["type"] == "stateID" })
290
283
  user_data_hsh[:state_student_id] = state_id_hsh["identifier"]
291
284
  end
292
285
  end
293
286
  unless user_params["email"].blank?
294
287
  user_data_hsh[:email_address] = {
295
- :email_address => user_params["email"]
288
+ email_address: user_params["email"]
296
289
  }
297
290
  end
298
291
  unless user_params["orgs"].blank?
299
- if (s = user_params["orgs"].detect{|org| org["href"] =~ /\/schools\//})
292
+ if (s = user_params["orgs"].detect { |org| org["href"] =~ /\/schools\// })
300
293
  self.schools_cache ||= {}
301
294
  if (attending_school = self.schools_cache[s["sourcedId"]]).nil?
302
- attending_school = self.get_school_by_api_id(s["sourcedId"])
295
+ attending_school = get_school_by_api_id(s["sourcedId"])
303
296
  self.schools_cache[attending_school.api_id] = attending_school
304
297
  end
305
298
  end
@@ -308,26 +301,24 @@ module Bright
308
301
  end
309
302
  end
310
303
  unless user_params["phone"].blank?
311
- user_data_hsh[:phone_numbers] = [{:phone_number => user_params["phone"]}]
304
+ user_data_hsh[:phone_numbers] = [{phone_number: user_params["phone"]}]
312
305
  end
313
306
  unless user_params["sms"].blank?
314
307
  user_data_hsh[:phone_numbers] ||= []
315
- user_data_hsh[:phone_numbers] << {:phone_number => user_params["sms"]}
308
+ user_data_hsh[:phone_numbers] << {phone_number: user_params["sms"]}
316
309
  end
317
310
 
318
- #add the demographic information
311
+ # add the demographic information
319
312
  demographics_hash = get_demographic_information(user_data_hsh[:api_id])
320
313
  user_data_hsh.merge!(demographics_hash) unless demographics_hash.blank?
321
314
 
322
- #if you're a student, build the contacts too
323
- if bright_type == "Student" and !user_params["agents"].blank?
315
+ # if you're a student, build the contacts too
316
+ if (bright_type == "Student") && !user_params["agents"].blank?
324
317
  user_data_hsh[:contacts] = user_params["agents"].collect do |agent_hsh|
325
- begin
326
- self.get_contact_by_api_id(agent_hsh["sourcedId"])
327
- rescue Bright::ResponseError => e
328
- if !e.message.to_s.include?("404")
329
- raise e
330
- end
318
+ get_contact_by_api_id(agent_hsh["sourcedId"])
319
+ rescue Bright::ResponseError => e
320
+ if !e.message.to_s.include?("404")
321
+ raise e
331
322
  end
332
323
  end.compact
333
324
  user_data_hsh[:grade] = (user_params["grades"] || []).first
@@ -336,7 +327,7 @@ module Bright
336
327
  end
337
328
  end
338
329
 
339
- return user_data_hsh
330
+ user_data_hsh
340
331
  end
341
332
 
342
333
  def get_demographic_information(api_id)
@@ -345,7 +336,7 @@ module Bright
345
336
  begin
346
337
  demographics_params = request(:get, "demographics/#{api_id}")["demographics"]
347
338
  rescue Bright::ResponseError => e
348
- if e.message.to_s.include?('404')
339
+ if e.message.to_s.include?("404")
349
340
  return demographic_hsh
350
341
  else
351
342
  raise e
@@ -368,22 +359,21 @@ module Bright
368
359
  end
369
360
  end
370
361
  end
371
- return demographic_hsh
362
+ demographic_hsh
372
363
  end
373
364
 
374
365
  def get_grade_school_year(date = Date.today)
375
- #return the school year of a specific date
366
+ # return the school year of a specific date
376
367
  self.school_years_cache ||= {}
377
368
  if self.school_years_cache[date].nil?
378
- academic_periods_params = self.request(:get, "academicSessions", {"filter" => "startDate<='#{date.to_s}' AND endDate>='#{date.to_s}' AND status='active'"})["academicSessions"]
379
- school_years = academic_periods_params.map{|ap| ap["schoolYear"]}.uniq
369
+ academic_periods_params = request(:get, "academicSessions", {"filter" => "startDate<='#{date}' AND endDate>='#{date}' AND status='active'"})["academicSessions"]
370
+ school_years = academic_periods_params.map { |ap| ap["schoolYear"] }.uniq
380
371
  if school_years.size == 1
381
372
  self.school_years_cache[date] = school_years.first
382
373
  end
383
374
  end
384
- return self.school_years_cache[date]
375
+ self.school_years_cache[date]
385
376
  end
386
-
387
377
  end
388
378
  end
389
379
  end