Class: IMS::LTI::Models::Messages::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/ims/lti/models/messages/message.rb

Direct Known Subclasses

ContentItemSelection, RequestMessage

Constant Summary collapse

MESSAGE_TYPE =
"".freeze
LAUNCH_TARGET_IFRAME =
'iframe'
LAUNCH_TARGET_WINDOW =
'window'
EXTENSION_PREFIX =
'ext_'
CUSTOM_PREFIX =
'custom_'
OAUTH_KEYS =
:oauth_callback, :oauth_consumer_key, :oauth_nonce, :oauth_signature, :oauth_signature_method,
:oauth_timestamp, :oauth_token, :oauth_verifier, :oauth_version

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}, custom_params = {}, ext_params = {}) ⇒ Message

Returns a new instance of Message.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object



180
181
182
183
184
185
186
187
188
# 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

Instance Attribute Details

#custom_paramsObject (readonly)

Returns the value of attribute custom_params.



85
86
87
# File 'lib/ims/lti/models/messages/message.rb', line 85

def custom_params
  @custom_params
end

#ext_paramsObject (readonly)

Returns the value of attribute ext_params.



85
86
87
# File 'lib/ims/lti/models/messages/message.rb', line 85

def ext_params
  @ext_params
end

#message_authenticatorObject (readonly)

Returns the value of attribute message_authenticator.



4
5
6
# File 'lib/ims/lti/models/messages/message.rb', line 4

def message_authenticator
  @message_authenticator
end

#unknown_paramsObject (readonly)

Returns the value of attribute unknown_params.



85
86
87
# File 'lib/ims/lti/models/messages/message.rb', line 85

def unknown_params
  @unknown_params
end

Class Method Details

.add_deprecated_params(param, *params) ⇒ Object



36
37
38
# 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) ⇒ Object



28
29
30
# File 'lib/ims/lti/models/messages/message.rb', line 28

def add_optional_params(param, *params)
  add_params('@optional_params', param, *params)
end


20
21
22
# File 'lib/ims/lti/models/messages/message.rb', line 20

def add_recommended_params(param, *params)
  add_params('@recommended_params', param, *params)
end

.add_required_params(param, *params) ⇒ Object



12
13
14
# File 'lib/ims/lti/models/messages/message.rb', line 12

def add_required_params(param, *params)
  add_params('@required_params', param, *params)
end

.deprecated_paramsObject



32
33
34
# File 'lib/ims/lti/models/messages/message.rb', line 32

def deprecated_params
  supers_params('@deprecated_params') | (@deprecated_params || [])
end

.descendantsObject



46
47
48
# File 'lib/ims/lti/models/messages/message.rb', line 46

def descendants
  @descendants || Set.new
end

.generate(launch_params) ⇒ Object



89
90
91
92
93
94
95
# 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) ⇒ Object



40
41
42
43
44
# 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

.optional_paramsObject



24
25
26
# File 'lib/ims/lti/models/messages/message.rb', line 24

def optional_params
  supers_params('@optional_params') | (@optional_params || [])
end

.parse_jwt(jwt:) ⇒ Object



97
98
99
100
101
102
103
104
105
106
# 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


16
17
18
# File 'lib/ims/lti/models/messages/message.rb', line 16

def recommended_params
  supers_params('@recommended_params') | (@recommended_params || [])
end

.required_paramsObject



8
9
10
# File 'lib/ims/lti/models/messages/message.rb', line 8

def required_params
  supers_params('@required_params') | (@required_params || [])
end

Instance Method Details

#add_custom_params(params) ⇒ Object



130
131
132
# 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_paramsObject



172
173
174
# File 'lib/ims/lti/models/messages/message.rb', line 172

def deprecated_params
  collect_attributes(self.class.deprecated_params)
end

#get_custom_paramsObject



134
135
136
# 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_paramsObject



138
139
140
# 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) ⇒ Object



146
147
148
# 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

#oauth_paramsObject



176
177
178
# File 'lib/ims/lti/models/messages/message.rb', line 176

def oauth_params
  collect_attributes(OAUTH_KEYS)
end

#optional_paramsObject



168
169
170
# File 'lib/ims/lti/models/messages/message.rb', line 168

def optional_params
  collect_attributes(self.class.optional_params)
end

#parametersObject



156
157
158
# File 'lib/ims/lti/models/messages/message.rb', line 156

def parameters
  collect_attributes(self.class.send("parameters"))
end

#post_paramsObject



142
143
144
# File 'lib/ims/lti/models/messages/message.rb', line 142

def post_params
  unknown_params.merge(@custom_params).merge(@ext_params).merge(parameters)
end


164
165
166
# File 'lib/ims/lti/models/messages/message.rb', line 164

def recommended_params
  collect_attributes(self.class.recommended_params)
end

#required_paramsObject



160
161
162
# File 'lib/ims/lti/models/messages/message.rb', line 160

def required_params
  collect_attributes(self.class.required_params)
end

#signed_post_params(secret) ⇒ Object



150
151
152
153
154
# File 'lib/ims/lti/models/messages/message.rb', line 150

def signed_post_params(secret)
  message_params = { oauth_consumer_key: oauth_consumer_key }.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) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# 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