From 6868167c329881319f9a2912465609ae16ab64fe Mon Sep 17 00:00:00 2001 From: Justin Ball Date: Tue, 21 May 2019 22:58:15 -0700 Subject: [PATCH] Adding Caliper support --- Gemfile | 7 ++++ Gemfile.lock | 29 ++++++++++++- app/controllers/lti_launches_controller.rb | 16 +++++++ app/lib/kaliper/events.rb | 48 +++++++++++++++++++++ app/lib/kaliper/lti_utils.rb | 49 ++++++++++++++++++++++ db/seeds.rb | 3 ++ 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 app/lib/kaliper/events.rb create mode 100644 app/lib/kaliper/lti_utils.rb diff --git a/Gemfile b/Gemfile index a2c13f35c..2bd7ff74a 100644 --- a/Gemfile +++ b/Gemfile @@ -54,6 +54,13 @@ gem "will_paginate" # Application secrets checker gem "nuclear_secrets" +# Caliper +gem "rest-client" +gem "uuid" +git "https://github.com/IMSGlobal/caliper-ruby.git", branch: "develop" do + gem "ims_caliper" +end + group :development do # UI gem "autoprefixer-rails" diff --git a/Gemfile.lock b/Gemfile.lock index a86804077..e4564acc7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,10 @@ +GIT + remote: https://github.com/IMSGlobal/caliper-ruby.git + revision: 16256300ecdf13bd2438ffc166b1a93f240b9839 + branch: develop + specs: + ims_caliper (1.1) + GIT remote: https://github.com/alexpeattie/heroku_secrets.git revision: 717af8e0acf399bc88d2c8c1a7e230023942af0f @@ -96,6 +103,8 @@ GEM responders warden (~> 1.2.3) diff-lcs (1.3) + domain_name (0.5.20180417) + unf (>= 0.0.5, < 1.0.0) dotenv (2.7.2) dotenv-rails (2.7.2) dotenv (= 2.7.2) @@ -134,6 +143,8 @@ GEM rspec (>= 2.99.0, < 4.0) hashdiff (0.3.8) hashie (3.6.0) + http-cookie (1.0.3) + domain_name (~> 0.5) httparty (0.16.4) mime-types (~> 3.0) multi_xml (>= 0.5.2) @@ -167,6 +178,8 @@ GEM crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.0.13) + macaddr (1.7.1) + systemu (~> 2.6.2) mail (2.7.1) mini_mime (>= 0.1.1) mail_view (2.0.4) @@ -182,6 +195,7 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) nenv (0.3.0) + netrc (0.11.0) nio4r (2.3.1) nokogiri (1.10.2) mini_portile2 (~> 2.4.0) @@ -268,6 +282,10 @@ GEM responders (2.4.1) actionpack (>= 4.2.0, < 6.0) railties (>= 4.2.0, < 6.0) + rest-client (2.0.2) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) rolify (5.2.0) rollbar (2.19.3) multi_json @@ -338,6 +356,7 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) + systemu (2.6.5) thor (0.20.3) thread_safe (0.3.6) tilt (2.0.9) @@ -345,7 +364,12 @@ GEM thread_safe (~> 0.1) uglifier (4.1.20) execjs (>= 0.3.0, < 3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.6) unicode-display_width (1.5.0) + uuid (2.3.9) + macaddr (~> 1.0) warden (1.2.8) rack (>= 2.0.6) web-console (3.7.0) @@ -388,6 +412,7 @@ DEPENDENCIES httparty hub ims-lti (~> 2.1.5) + ims_caliper! jwt (~> 1.5.0) launchy listen @@ -409,6 +434,7 @@ DEPENDENCIES rb-fchange rb-fsevent rb-inotify + rest-client rolify rollbar rspec-rails @@ -422,10 +448,11 @@ DEPENDENCIES spring-watcher-listen tzinfo-data uglifier + uuid web-console webmock will_paginate yajl-ruby BUNDLED WITH - 1.17.3 + 2.0.1 diff --git a/app/controllers/lti_launches_controller.rb b/app/controllers/lti_launches_controller.rb index 8dadda4bd..3491a1617 100644 --- a/app/controllers/lti_launches_controller.rb +++ b/app/controllers/lti_launches_controller.rb @@ -6,6 +6,7 @@ class LtiLaunchesController < ApplicationController skip_before_action :verify_authenticity_token before_action :do_lti, except: [:launch] + after_action :do_caliper def index if current_application_instance.disabled_at @@ -43,4 +44,19 @@ def setup_lti_response set_lti_launch_values end + def do_caliper + events = Kaliper::LtiUtils.from_lti_1_2( + application_instance: current_application_instance, + user: current_user, + params: params, + ) + options = Caliper::Options.new + sensor = Caliper::Sensor.new('https://www.atomicjolt.com/sensors/1', options) + requestor = Caliper::Request::HttpRequestor.new({ + 'host' => "http://learncaliper.herokuapp.com/api/consumer/events/1ebb1f70-5e82-0137-e4ac-4a8f9eeae0c8", + 'auth_token' => "1ebb1f70-5e82-0137-e4ac-4a8f9eeae0c8", + }) + requestor.send(sensor, events.tool_use_event) + end + end diff --git a/app/lib/kaliper/events.rb b/app/lib/kaliper/events.rb new file mode 100644 index 000000000..d2c541db3 --- /dev/null +++ b/app/lib/kaliper/events.rb @@ -0,0 +1,48 @@ +require "caliper" + +module Kaliper + class Events + + attr_accessor :actor + attr_accessor :ed_app + attr_accessor :group + attr_accessor :membership + attr_accessor :session + + def initialize(application_instance:, user:) + @application_instance = application_instance + @user = user + + @actor = Caliper::Entities::Agent::Person.new( + id: "#{@application_instance.domain}/users/#{@user.id}", + name: @user.display_name, + ) + + @ed_app = Caliper::Entities::Agent::SoftwareApplication.new( + id: @application_instance.domain, + name: @application_instance.application.name, + description: @application_instance.application.description, + ) + end + + # tool use Event docs: https://www.imsglobal.org/sites/default/files/caliper/v1p1/caliper-spec-v1p1/caliper-spec-v1p1.html#toolUseEvent + def tool_use_event(event_time: Time.now.utc.iso8601) + event = Caliper::Events::ToolUseEvent.new( + id: "urn:uuid:#{SecureRandom.uuid}", + object: @ed_app, + actor: @actor, + action: Caliper::Actions::USED, + edApp: @ed_app, + eventTime: event_time + ) + + event.group = @group if @group + event.membership = @membership if @membership + event.session = @session if @session + event.federated_session = @federated_session if @federated_session + + event + end + + end +end diff --git a/app/lib/kaliper/lti_utils.rb b/app/lib/kaliper/lti_utils.rb new file mode 100644 index 000000000..32d836c52 --- /dev/null +++ b/app/lib/kaliper/lti_utils.rb @@ -0,0 +1,49 @@ +require "caliper" + +module Kaliper + class LtiUtils + + def self.from_lti_1_2(application_instance:, user:, params:) + event = Kaliper::Events.new(application_instance: application_instance, user: user) + + if params[:customer_caliper_federated_session_id].present? + # https://www.imsglobal.org/sites/default/files/caliper/v1p1/caliper-spec-v1p1/caliper-spec-v1p1.html#ltiSession + event.federatedSession = Caliper::Entities::Session::LtiSession.new( + id: params[:customer_caliper_federated_session_id], + user: event.actor, + ) + end + + #return from_canvas_lti(event, params) if params[:custom_canvas_api_domain].present? + event + end + + # TODO + # def self.from_canvas_lti(event, params) + + # event.group = Caliper::Entities::LIS::CourseSection.new( + # id: "https://#{params[:custom_canvas_api_domain]}/courses/#{params[:custom_canvas_course_id]}/sections/#{params[:custom_canvas_section_id]}", + # courseNumber: params[:context_title], + # academicSession: params[:canvas_term_start_at], + # ) + + # event.membership = Caliper::Entities::LIS::Membership.new( + # id: membership_id, + # member: event.actor, + # organization: event.group, + # roles: caliper_role_from(params), + # status: Caliper::Entities::LIS::Status::ACTIVE, + # ) + + # event.session = Caliper::Entities::Session::Session.new( + # id: id, + # startedAtTime: started_at.utc.iso8601, + # ) + # end + + # def self.caliper_role_from(params) + # roles = [ Caliper::Entities::LIS::Role::LEARNER ] + # end + + end +end diff --git a/db/seeds.rb b/db/seeds.rb index 3835885f8..065379808 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -101,6 +101,9 @@ custom_fields: { canvas_course_id: "$Canvas.course.id", canvas_api_domain: "$Canvas.api.domain", + customer_caliper_endpoint_url: "$Caliper.url", + canvas_course_section_ids: "$Canvas.course.sectionIds", + canvas_term_start_at: "$Canvas.term.startAt",, }, course_navigation: { text: "LTI Starter App",