class IMS::LTI::Models::Messages::Message

Constants

CUSTOM_PREFIX
EXTENSION_PREFIX
LAUNCH_TARGET_IFRAME
LAUNCH_TARGET_WINDOW
MESSAGE_TYPE
OAUTH_KEYS

Attributes

custom_params[R]
ext_params[R]
jwt[RW]
launch_url[RW]
message_authenticator[R]
unknown_params[R]

Public Class Methods

add_deprecated_params(param, *params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 36
def add_deprecated_params(param, *params)
  add_params('@deprecated_params', param, *params)
end
add_optional_params(param, *params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 28
def add_optional_params(param, *params)
  add_params('@optional_params', param, *params)
end
add_required_params(param, *params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 12
def add_required_params(param, *params)
  add_params('@required_params', param, *params)
end
deprecated_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 32
def deprecated_params
  supers_params('@deprecated_params') | (@deprecated_params || [])
end
descendants() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 46
def descendants
  @descendants || Set.new
end
generate(launch_params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 89
def self.generate(launch_params)
  params = launch_params.key?('jwt') ? parse_jwt(jwt: launch_params['jwt']) : launch_params
  klass = self.descendants.select {|d| d::MESSAGE_TYPE == params['lti_message_type']}.first
  message = klass ? klass.new(params) : Message.new(params)
  message.jwt = launch_params['jwt'] if launch_params.key?('jwt')
  message
end
inherited(klass) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 40
def inherited(klass)
  @descendants ||= Set.new
  @descendants << klass
  superclass.inherited(klass) unless (self == Message)
end
new(attrs = {}, custom_params = {}, ext_params = {}) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 108
def initialize(attrs = {}, custom_params = {}, ext_params = {})

  @custom_params = custom_params
  @ext_params = ext_params
  @unknown_params = {}

  attrs.each do |k, v|
    str_key = k.to_s
    if str_key.start_with?(EXTENSION_PREFIX)
      @ext_params[str_key] = v
    elsif str_key.start_with?(CUSTOM_PREFIX)
      @custom_params[str_key] = v
    elsif !v.nil? && self.respond_to?(k.to_sym)
      send(("#{k}=").to_sym, v)

    else
      warn "Unknown parameter #{k}"
      @unknown_params[str_key] = v
    end
  end
end
optional_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 24
def optional_params
  supers_params('@optional_params') | (@optional_params || [])
end
parse_jwt(jwt:) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 97
def self.parse_jwt(jwt:)
  decoded_jwt = JSON::JWT.decode(jwt, :skip_verification)
  params = decoded_jwt['org.imsglobal.lti.message'] || {}
  custom = params.delete(:custom)
  custom.each {|k,v| params["custom_#{k}"] = v }
  params['consumer_key'] = decoded_jwt[:sub]
  ext = params.delete(:ext)
  ext.each {|k,v| params["ext_#{k}"] = v }
  params
end
required_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 8
def required_params
  supers_params('@required_params') | (@required_params || [])
end

Private Class Methods

add_params(instance_variable, param, *params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 52
def add_params(instance_variable, param, *params)
  instance_var = self.instance_variable_get(instance_variable) || []
  instance_var |= params.unshift(param)
  self.instance_variable_set(instance_variable, instance_var)
  attr_accessor(params.shift, *params)
end
parameters() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 59
def parameters
  required_params + recommended_params + optional_params + deprecated_params
end
supers_params(instance_variable) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 63
def supers_params(instance_variable)
  if name == "IMS::LTI::Models::Messages::Message"
    []
  else
    (superclass.instance_variable_get(instance_variable) || []) | superclass.send(:supers_params, instance_variable)
  end
end

Public Instance Methods

add_custom_params(params) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 130
def add_custom_params(params)
  params.each {|k, v| k.to_s.start_with?('custom_') ? @custom_params[k.to_s] = v : @custom_params["custom_#{k.to_s}"] = v}
end
deprecated_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 172
def deprecated_params
  collect_attributes(self.class.deprecated_params)
end
get_custom_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 134
def get_custom_params
  @custom_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Acustom_/, '')] = v; hash}
end
get_ext_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 138
def get_ext_params
  @ext_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Aext_/, '')] = v; hash}
end
jwt_params(private_key:, originating_domain:, algorithm: :HS256) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 146
def jwt_params(private_key:, originating_domain:, algorithm: :HS256)
  { 'jwt' => to_jwt(private_key: private_key, originating_domain: originating_domain, algorithm: algorithm) }
end
method_missing(meth, *args, &block) click to toggle source
Calls superclass method
# File lib/ims/lti/models/messages/message.rb, line 180
def method_missing(meth, *args, &block)
  if match = /^(custom|ext)_([^=$]*)/.match(meth)
    param_type, key = match.captures
    param_hash = instance_variable_get("@#{param_type}_params".to_sym)
    meth =~ /=$/ ? param_hash[match.to_s] = args[0] : param_hash[match.to_s]
  else
    super
  end
end
oauth_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 176
def oauth_params
  collect_attributes(OAUTH_KEYS)
end
optional_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 168
def optional_params
  collect_attributes(self.class.optional_params)
end
parameters() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 156
def parameters
  collect_attributes(self.class.send("parameters"))
end
post_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 142
def post_params
  unknown_params.merge(@custom_params).merge(@ext_params).merge(parameters)
end
required_params() click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 160
def required_params
  collect_attributes(self.class.required_params)
end
signed_post_params(secret) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 150
def signed_post_params(secret)
  message_params = oauth_params.merge(post_params)
  @message_authenticator = IMS::LTI::Services::MessageAuthenticator.new(launch_url, message_params, secret)
  @message_authenticator.signed_params
end
to_jwt(private_key:, originating_domain:, algorithm: :HS256) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 190
def to_jwt(private_key:, originating_domain:, algorithm: :HS256)
  now = Time.now
  exp = now + 60 * 5
  ims = unknown_params.merge(parameters)
  ims[:custom] = get_custom_params
  ims[:ext] = get_ext_params
  claim = {
    iss: originating_domain,
    sub: consumer_key,
    aud: launch_url,
    iat: now,
    exp: exp,
    jti: SecureRandom.uuid,
    "org.imsglobal.lti.message" => ims
  }
  jwt = JSON::JWT.new(claim).sign(private_key, algorithm)
  jwt.to_s
end

Private Instance Methods

collect_attributes(attributes) click to toggle source
# File lib/ims/lti/models/messages/message.rb, line 213
def collect_attributes(attributes)
  attributes.inject({}) do |h, param|
    value = instance_variable_get("@#{param}")
    h[param.to_s] = value if value
    h
  end
end