scorm_engine 0.7.0 → 0.8.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/scorm_engine/api/endpoints.rb +4 -0
  3. data/lib/scorm_engine/api/endpoints/configuration.rb +64 -0
  4. data/lib/scorm_engine/api/endpoints/courses/configuration.rb +1 -1
  5. data/lib/scorm_engine/api/endpoints/dispatches.rb +45 -2
  6. data/lib/scorm_engine/api/endpoints/registrations/configuration.rb +1 -1
  7. data/lib/scorm_engine/api/endpoints/tenants/configuration.rb +108 -0
  8. data/lib/scorm_engine/configuration.rb +4 -2
  9. data/lib/scorm_engine/faraday/connection.rb +10 -4
  10. data/lib/scorm_engine/faraday/request.rb +17 -4
  11. data/lib/scorm_engine/models.rb +2 -0
  12. data/lib/scorm_engine/models/dispatch_registration_count.rb +49 -0
  13. data/lib/scorm_engine/models/tenant_configuration.rb +34 -0
  14. data/lib/scorm_engine/version.rb +1 -1
  15. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Configuration/_get_app_configuration/is_successful.yml +64 -0
  16. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Configuration/_get_app_configuration/returns_settings_and_values.yml +64 -0
  17. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Configuration/_post_app_configuration/fails_when_settings_are_invalid.yml +48 -0
  18. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Configuration/_post_app_configuration/is_successful.yml +44 -0
  19. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Configuration/_post_app_configuration/persists_the_settings.yml +207 -0
  20. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/successful_imports/works.yml +6 -6
  21. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/unsuccessful_imports/fails_to_import_given_an_invalid_url.yml +7 -7
  22. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/unsuccessful_imports/fails_to_import_a_previously_existing_course.yml +2 -2
  23. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_delete_dispatch_registration_count/is_successful.yml +30 -0
  24. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_delete_dispatch_registration_count/succeeds_even_when_id_is_invalid.yml +30 -0
  25. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_get_dispatch_registration_count/fails_when_id_is_invalid.yml +63 -0
  26. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_get_dispatch_registration_count/is_successful.yml +63 -0
  27. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_get_dispatch_registration_count/results/sucessfully_creates_the_dispatch_attributes.yml +63 -0
  28. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Dispatches/_get_dispatch_registration_count/when_dispatch_has_registrations/knows_it_s_registration_count.yml +63 -0
  29. data/spec/scorm_engine/api/endpoints/configuration_spec.rb +51 -0
  30. data/spec/scorm_engine/api/endpoints/courses/import_spec.rb +1 -1
  31. data/spec/scorm_engine/api/endpoints/dispatches_spec.rb +47 -1
  32. data/spec/scorm_engine/api/endpoints/tenants/configuration_spec.rb +126 -0
  33. data/spec/scorm_engine/faraday/connection_spec.rb +23 -5
  34. data/spec/scorm_engine/models/dispatch_registration_count_spec.rb +42 -0
  35. data/spec/scorm_engine/models/tenant_configuration_spec.rb +16 -0
  36. data/spec/support/scorm_engine.rb +1 -1
  37. data/spec/support/vcr.rb +1 -0
  38. metadata +33 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96f9e3115cb5345e489c54e9d49ac10dd67b1b2bb7dbd30878a222c5eca3dde5
4
- data.tar.gz: a64f2c8ce1dcc564e71d06a020324e947406020e5930f24a5f59b91b377d47c5
3
+ metadata.gz: 125a0882006861786fcc335c3656cd75b69d832669ae34c9b7e6a93969137580
4
+ data.tar.gz: f33e66667a0866bf8bf133c6a0a9cddcca990a02e4737fc2c4f7f1ef53ecac6e
5
5
  SHA512:
6
- metadata.gz: 15dae198e937cfe18146767424e8361a7464372137dda3123a78cabcd87f3b9d0d2da92e566dfa82f942f3955caff1246160311ea403a2afb084fd95f5503ba9
7
- data.tar.gz: 189edb44a0f257a82336efdb39e4876b47c16a021cc49d81db2644aac2068167d7b06193e80e52dfc0fc4c1866d1ce635f5f8564c32958cbccab013bb8c46d1b
6
+ metadata.gz: 2b845922b85e20a822b7d519e1d919ce61333c89da2525a9eb3d37ace034b1e525a53a43a77229eb8804179f25ff541c4afcbd1ccff4851f140cbb48e301ceb6
7
+ data.tar.gz: d221c2aee2b0761b9ce568bf428c724ba7451224bf74e96a5ad6610ff89e8174fdcf2350b1089ba923f2d3576a9eb2e2aa99edfcf17e781fc709556b9ba37399
@@ -1,4 +1,5 @@
1
1
  require_relative "endpoints/about"
2
+ require_relative "endpoints/configuration"
2
3
  require_relative "endpoints/courses"
3
4
  require_relative "endpoints/courses/configuration"
4
5
  require_relative "endpoints/courses/import"
@@ -8,11 +9,13 @@ require_relative "endpoints/ping"
8
9
  require_relative "endpoints/registrations"
9
10
  require_relative "endpoints/registrations/configuration"
10
11
  require_relative "endpoints/registrations/launch_history"
12
+ require_relative "endpoints/tenants/configuration"
11
13
 
12
14
  module ScormEngine
13
15
  module Api
14
16
  module Endpoints
15
17
  include About
18
+ include Configuration
16
19
  include Courses
17
20
  include Courses::Configuration
18
21
  include Courses::Import
@@ -22,6 +25,7 @@ module ScormEngine
22
25
  include Registrations
23
26
  include Registrations::Configuration
24
27
  include Registrations::LaunchHistory
28
+ include Tenants::Configuration
25
29
 
26
30
  private
27
31
 
@@ -0,0 +1,64 @@
1
+ module ScormEngine
2
+ module Api
3
+ module Endpoints
4
+ module Configuration
5
+ #
6
+ # Get the application settings currently configured in Engine.
7
+ #
8
+ # @see http://rustici-docs.s3.amazonaws.com/engine/20.1.x/api/apiV2.html#/appManagement/GetApplicationConfiguration
9
+ #
10
+ # @param [Hash] options
11
+ #
12
+ # @option options [Boolean] :for_tenant
13
+ # Indicates whether the configuration effective for the current tenant should be fetched.
14
+ # If false or not specified, will return configuration settings for the application in general.
15
+ #
16
+ # @return [ScormEngine::Response]
17
+ #
18
+ def get_app_configuration(options = {})
19
+ api_v2(without_tenant: !options.fetch(:for_tenant, false)) do
20
+ response = get("appManagement/configuration")
21
+
22
+ result = OpenStruct.new
23
+
24
+ response.body["settingItems"].each do |setting|
25
+ result[setting["id"]] = setting["effectiveValue"]
26
+ end
27
+
28
+ Response.new(raw_response: response, result: result)
29
+ end
30
+ end
31
+
32
+ #
33
+ # Set one or more application settings in Engine.
34
+ #
35
+ # @see http://rustici-docs.s3.amazonaws.com/engine/20.1.x/api/apiV2.html#/appManagement/SetApplicationConfiguration
36
+ #
37
+ # @param [Hash] options
38
+ #
39
+ # @option [Hash] settings
40
+ # The configuration settings to be updated.
41
+ #
42
+ # @option options [Boolean] :for_tenant
43
+ # Indicates whether the configuration should be set for the current tenant.
44
+ # If false or not specified, will update configuration settings for the application in general.
45
+ #
46
+ # @return [ScormEngine::Response]
47
+ #
48
+ def post_app_configuration(options = {})
49
+ require_options(options, :settings)
50
+
51
+ api_v2(without_tenant: !options.fetch(:for_tenant, false)) do
52
+ settings = options.delete(:settings)
53
+
54
+ body = { settings: settings.map { |k, v| { "settingId" => k, "value" => v.to_s } } }
55
+
56
+ response = post("appManagement/configuration", {}, body)
57
+
58
+ Response.new(raw_response: response)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  #
2
- # TODO: Consider consolidating this and Registrations::Configuration, but only
2
+ # TODO: Consider consolidating this and [Registrations|Tenants]::Configuration, but only
3
3
  # after we're sure they are really 99.9% the same in terms of functionality.
4
4
  #
5
5
  module ScormEngine
@@ -272,8 +272,7 @@ module ScormEngine
272
272
 
273
273
  options = options.dup
274
274
  dispatch_id = options.delete(:dispatch_id)
275
- options[:type] ||= "SCORM12"
276
- options[:type]&.upcase!
275
+ options[:type] = options[:type]&.upcase || "SCORM12"
277
276
 
278
277
  response = get("dispatches/#{dispatch_id}/zip", options)
279
278
 
@@ -289,6 +288,49 @@ module ScormEngine
289
288
  Response.new(raw_response: response, result: result)
290
289
  end
291
290
 
291
+ #
292
+ # Get the registration count and last reset time of a dispatch.
293
+ #
294
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x.dispatch/api-dispatch.html#tenant__dispatches__dispatchId__registrationCount_get
295
+ #
296
+ # @param [Hash] options
297
+ #
298
+ # @option options [String] :dispatch_id
299
+ # The ID of the dispatch to get.
300
+ #
301
+ # @return [ScormEngine::Models::DispatchRegistrationCount]
302
+ #
303
+ def get_dispatch_registration_count(options = {})
304
+ require_options(options, :dispatch_id)
305
+
306
+ response = get("dispatches/#{options[:dispatch_id]}/registrationCount")
307
+
308
+ # merge options to pick up dispatch_id which isn't passed back in the response
309
+ result = response.success? ? ScormEngine::Models::DispatchRegistrationCount.new_from_api({ "id" => options[:dispatch_id] }.merge(response.body)) : nil
310
+
311
+ Response.new(raw_response: response, result: result)
312
+ end
313
+
314
+ #
315
+ # Reset the registration count and last reset time of a dispatch.
316
+ #
317
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x.dispatch/api-dispatch.html#tenant__dispatches__dispatchId__registrationCount_delete
318
+ #
319
+ # @param [Hash] options
320
+ #
321
+ # @option options [String] :dispatch_id
322
+ # The ID of the dispatch to get.
323
+ #
324
+ # @return [ScormEngine::Response]
325
+ #
326
+ def delete_dispatch_registration_count(options = {})
327
+ require_options(options, :dispatch_id)
328
+
329
+ response = delete("dispatches/#{options[:dispatch_id]}/registrationCount")
330
+
331
+ Response.new(raw_response: response)
332
+ end
333
+
292
334
  private
293
335
 
294
336
  def coerce_dispatch_options(options = {})
@@ -301,6 +343,7 @@ module ScormEngine
301
343
 
302
344
  def coerce_expiration_date(date)
303
345
  return date if date == "none"
346
+
304
347
  date = date.is_a?(String) ? Date.parse(date) : date
305
348
  date&.iso8601 # might be nil
306
349
  rescue ArgumentError # unparsable date string
@@ -1,5 +1,5 @@
1
1
  #
2
- # TODO: Consider consolidating this and Courses::Configuration, but only after we're
2
+ # TODO: Consider consolidating this and [Courses|Tenants]::Configuration, but only after we're
3
3
  # sure they are really 99.9% the same in terms of functionality.
4
4
  #
5
5
  module ScormEngine
@@ -0,0 +1,108 @@
1
+ #
2
+ # TODO: Consider consolidating this and [Courses|Registrations]::Configuration, but only
3
+ # after we're sure they are really 99.9% the same in terms of functionality.
4
+ #
5
+ module ScormEngine
6
+ module Api
7
+ module Endpoints
8
+ module Tenants
9
+ module Configuration
10
+
11
+ #
12
+ # Returns the effective value of every setting at this level, as well
13
+ # as the effective value of any setting at a more specific level.
14
+ #
15
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__configuration_get
16
+ #
17
+ # @return [ScormEngine::Models::TenantConfiguration]
18
+ #
19
+ def get_tenant_configuration
20
+ response = get("configuration")
21
+
22
+ result = response.success? ? ScormEngine::Models::TenantConfiguration.new_from_api(response.body) : nil
23
+
24
+ Response.new(raw_response: response, result: result)
25
+ end
26
+
27
+ #
28
+ # Bulk set configuration settings via POST request.
29
+ #
30
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__configuration_post
31
+ #
32
+ # @param [Hash] options
33
+ #
34
+ # @option options [Hash] :settings
35
+ # Key/value pairs of configuration options to set.
36
+ #
37
+ # @return [ScormEngine::Response]
38
+ #
39
+ def post_tenant_configuration(options = {})
40
+ require_options(options, :settings)
41
+
42
+ options = options.dup
43
+ settings = options.delete(:settings)
44
+
45
+ body = { settings: settings.map { |k, v| { "settingId" => k, "value" => v.to_s } } }
46
+
47
+ response = post("configuration", options, body)
48
+
49
+ Response.new(raw_response: response)
50
+ end
51
+
52
+ #
53
+ # Returns the effective value for this configuration setting for the resource being configured.
54
+ #
55
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__configuration__settingId__get
56
+ #
57
+ # @param [Hash] options
58
+ #
59
+ # @option options [String] :setting_id
60
+ # The ID of the setting to get.
61
+ #
62
+ # @return [String]
63
+ #
64
+ def get_tenant_configuration_setting(options = {})
65
+ require_options(options, :setting_id)
66
+
67
+ options = options.dup
68
+ setting_id = options.delete(:setting_id)
69
+
70
+ response = get("configuration/#{setting_id}", options)
71
+
72
+ result = response.success? ? response.body["value"] : nil
73
+
74
+ Response.new(raw_response: response, result: result)
75
+ end
76
+
77
+ #
78
+ # Sets the value for this configuration setting, for the resource being configured.
79
+ #
80
+ # @see http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html#tenant__configuration__settingId__put
81
+ #
82
+ # @param [Hash] options
83
+ #
84
+ # @option options [String] :setting_id
85
+ # The ID of the setting to set.
86
+ #
87
+ # @option options [String] :value ("")
88
+ # The value of the setting to set.
89
+ #
90
+ # @return [ScormEngine::Response]
91
+ #
92
+ def put_tenant_configuration_setting(options = {})
93
+ require_options(options, :setting_id)
94
+
95
+ options = options.dup
96
+ setting_id = options.delete(:setting_id)
97
+
98
+ body = { value: options.delete(:value).to_s }
99
+
100
+ response = put("configuration/#{setting_id}", options, body)
101
+
102
+ Response.new(raw_response: response)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -10,8 +10,9 @@ module ScormEngine
10
10
  end
11
11
 
12
12
  class Configuration
13
- # http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html
14
- attr_accessor :protocol, :host, :path_prefix
13
+ # Legacy v1 API: http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/api.html
14
+ # Latest v2 API: https://rustici-docs.s3.amazonaws.com/engine/20.1.x/api/apiV2.html
15
+ attr_accessor :protocol, :host, :path_prefix, :v2_path_prefix
15
16
 
16
17
  # http://rustici-docs.s3.amazonaws.com/engine/2017.1.x/Architecture-API.html#api-authentication
17
18
  attr_accessor :username, :password
@@ -28,6 +29,7 @@ module ScormEngine
28
29
  @protocol = ENV.fetch("SCORM_ENGINE_PROTOCOL", "https")
29
30
  @host = ENV["SCORM_ENGINE_HOST"]
30
31
  @path_prefix = ENV.fetch("SCORM_ENGINE_PATH_PREFIX", "/ScormEngineInterface/api/v1/")
32
+ @v2_path_prefix = ENV.fetch("SCORM_ENGINE_V2_PATH_PREFIX", "/ScormEngineInterface/api/v2/")
31
33
 
32
34
  @username = ENV["SCORM_ENGINE_USERNAME"]
33
35
  @password = ENV["SCORM_ENGINE_PASSWORD"]
@@ -5,18 +5,24 @@ module ScormEngine
5
5
  module Faraday
6
6
  module Connection
7
7
 
8
- def base_uri
8
+ def base_uri(version: 1)
9
9
  uri = URI("")
10
10
  uri.scheme = ScormEngine.configuration.protocol
11
11
  uri.host = ScormEngine.configuration.host
12
- uri.path = ScormEngine.configuration.path_prefix
12
+
13
+ uri.path = if version == 2
14
+ ScormEngine.configuration.v2_path_prefix
15
+ else
16
+ ScormEngine.configuration.path_prefix
17
+ end
18
+
13
19
  URI(uri.to_s) # convert URI::Generic to URI:HTTPS
14
20
  end
15
21
 
16
22
  private
17
23
 
18
- def connection
19
- @connection ||= ::Faraday.new(url: base_uri.to_s) do |faraday|
24
+ def connection(version: 1)
25
+ @connection ||= ::Faraday.new(url: base_uri(version: version).to_s) do |faraday|
20
26
  faraday.headers["User-Agent"] = "ScormEngine Ruby Gem #{ScormEngine::VERSION}"
21
27
 
22
28
  faraday.basic_auth(ScormEngine.configuration.username, ScormEngine.configuration.password)
@@ -17,15 +17,28 @@ module ScormEngine
17
17
  request(:delete, path, options)
18
18
  end
19
19
 
20
+ def api_v2(without_tenant: false)
21
+ @api_version = 2
22
+ @without_tenant = without_tenant
23
+
24
+ yield
25
+ ensure
26
+ @api_version = 1
27
+ end
28
+
20
29
  private
21
30
 
22
31
  def request(method, path, options, body = nil)
23
- # "more" pagination urls are fully qualified
24
- path = "#{tenant}/#{path}" unless path =~ %r{\Ahttps?://}
32
+ connection(version: @api_version).send(method) do |request|
33
+ if @api_version == 2
34
+ request.headers["engineTenantName"] = tenant unless @without_tenant
35
+ else
36
+ # "more" pagination urls are fully qualified
37
+ path = "#{tenant}/#{path}" unless path =~ %r{\Ahttps?://}
38
+ end
25
39
 
26
- options = coerce_options(options)
40
+ options = coerce_options(options)
27
41
 
28
- connection.send(method) do |request|
29
42
  case method
30
43
  when :get, :delete
31
44
  request.url(path, options)
@@ -4,6 +4,7 @@ require_relative "models/course_configuration"
4
4
  require_relative "models/course_import"
5
5
  require_relative "models/destination"
6
6
  require_relative "models/dispatch"
7
+ require_relative "models/dispatch_registration_count"
7
8
  require_relative "models/dispatch_zip"
8
9
  require_relative "models/learner"
9
10
  require_relative "models/registration"
@@ -11,3 +12,4 @@ require_relative "models/registration_activity_detail"
11
12
  require_relative "models/registration_configuration"
12
13
  require_relative "models/registration_launch_history"
13
14
  require_relative "models/registration_runtime_interaction"
15
+ require_relative "models/tenant_configuration"
@@ -0,0 +1,49 @@
1
+ require "date"
2
+
3
+ module ScormEngine
4
+ module Models
5
+ class DispatchRegistrationCount < Base
6
+ # @attr
7
+ # The external identification of this dispatch.
8
+ # @return [String]
9
+ attr_accessor :id
10
+
11
+ # @attr
12
+ # The registration count for this dispatch.
13
+ # @return [Integer]
14
+ attr_accessor :registration_count
15
+
16
+ # @attr
17
+ # The date and time of the last count reset, if any.
18
+ # @return [DateTime]
19
+ attr_accessor :last_reset_at
20
+
21
+ def self.new_from_api(options = {})
22
+ this = new
23
+
24
+ this.options = options.dup
25
+ this.id = options["id"]
26
+ this.registration_count = options["registrationCount"].to_i
27
+ this.last_reset_at = get_last_reset_time(options)
28
+
29
+ this
30
+ end
31
+
32
+ #
33
+ # Extract and normalize the last reset datetime from the API options.
34
+ #
35
+ # @param [Hash] options
36
+ # The API options hash
37
+ #
38
+ # @return [Time]
39
+ # a date/time or nil if undefined.
40
+ #
41
+ def self.get_last_reset_time(options = {})
42
+ time = options["lastResetTime"]
43
+ return if time.nil? || time == "none"
44
+
45
+ Time.parse(time)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ module ScormEngine
2
+ module Models
3
+ class TenantConfiguration < Base
4
+ # @attr
5
+ #
6
+ # @return [Hash]
7
+ attr_accessor :settings
8
+
9
+ def self.new_from_api(options = {})
10
+ this = new
11
+
12
+ this.options = options.dup
13
+ this.settings = get_settings_from_api(options)
14
+ this
15
+ end
16
+
17
+ #
18
+ # Extract and normalize the settings from the API options.
19
+ #
20
+ # @param [Hash] options
21
+ # The API options hash
22
+ #
23
+ # @return [Hash]
24
+ # A hash of key/value pairs.
25
+ #
26
+ def self.get_settings_from_api(options = {})
27
+ options["configurationItems"].reduce({}) do |m, o|
28
+ m[o["id"]] = o["value"]
29
+ m
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end