Module: CoalescingPanda::ControllerHelpers

Defined in:
lib/coalescing_panda/controller_helpers.rb

Instance Method Summary collapse

Instance Method Details

#canvas_environmentObject



161
162
163
164
165
166
167
168
# File 'lib/coalescing_panda/controller_helpers.rb', line 161

def canvas_environment
  case params['custom_test_environment']
    when 'true'
      :test
    else
      :production
  end
end

#canvas_oauth2(*roles) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/coalescing_panda/controller_helpers.rb', line 6

def canvas_oauth2(*roles)
  return if have_session?
  if lti_authorize!(*roles)
    user_id = params['user_id']
    launch_presentation_return_url = .settings[:launch_presentation_return_url] || params['launch_presentation_return_url']
    launch_presentation_return_url = [BearcatUri.new(request.env["HTTP_REFERER"]).prefix, launch_presentation_return_url].join unless launch_presentation_return_url.include?('http')
    uri = BearcatUri.new(launch_presentation_return_url)
    set_session(launch_presentation_return_url)

    api_auth = CanvasApiAuth.find_by('user_id = ? and api_domain = ?', user_id, uri.api_domain)
    if api_auth
      begin
        refresh_token(uri, api_auth) if api_auth.expired?
        @client = Bearcat::Client.new(token: api_auth.api_token, prefix: uri.prefix)
        @client. 'self'
      rescue Footrest::HttpError::BadRequest, Footrest::HttpError::Unauthorized
        # If we can't retrieve our own user profile, or the token refresh fails, something is awry on the canvas end
        # and we'll need to go through the oauth flow again
        render_oauth2_page uri, user_id
      end
    else
      render_oauth2_page uri, user_id
    end
  end
end

#check_for_iframes_problemObject



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/coalescing_panda/controller_helpers.rb', line 174

def check_for_iframes_problem
  if cookies_need_iframe_fix?
    fix_iframe_cookies
    return false
  end

  # For safari we may have been launched temporarily full-screen by canvas.  This allows us to set the session cookie.
  # In this case, we should make sure the session cookie is fixed and redirect back to canvas to properly launch the embedded LTI.
  if params[:platform_redirect_url]
    session[:safari_cookie_fixed] = true
    redirect_to params[:platform_redirect_url]
    return false
  end
  true
end

#check_refresh_tokenObject



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/coalescing_panda/controller_helpers.rb', line 58

def check_refresh_token
  return unless session['uri'] && session['user_id'] && session['oauth_consumer_key']
  uri = BearcatUri.new(session['uri'])
  api_auth = CanvasApiAuth.find_by(user_id: session['user_id'], api_domain: uri.api_domain)
   = LtiAccount.find_by(key: session['oauth_consumer_key'])
  return if .nil? || api_auth.nil? # Not all tools use oauth

  refresh_token(uri, api_auth) if api_auth.expired?
rescue Footrest::HttpError::BadRequest
  render_oauth2_page uri, session['user_id']
end

#cookies_need_iframe_fix?Boolean

Returns:

  • (Boolean)


190
191
192
193
# File 'lib/coalescing_panda/controller_helpers.rb', line 190

def cookies_need_iframe_fix?
  @browser ||= Browser.new(request.user_agent)
  @browser.safari? && !request.referrer&.include?('sessionless_launch') && !session[:safari_cookie_fixed]  && !params[:platform_redirect_url]
end

#fix_iframe_cookiesObject



195
196
197
198
199
200
201
202
# File 'lib/coalescing_panda/controller_helpers.rb', line 195

def fix_iframe_cookies
  if params[:safari_cookie_fix].present?
    session[:safari_cookie_fixed] = true
    redirect_to params[:return_to]
  else
    render 'coalescing_panda/lti/iframe_cookie_fix', layout: false
  end
end

#have_session?Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/coalescing_panda/controller_helpers.rb', line 78

def have_session?
  if params['tool_consumer_instance_guid'] && session['user_id'] != params['user_id']
    reset_session
    logger.info("resetting session params")
    session['user_id'] = params['user_id']
  end

  if (session['user_id'] && session['uri'])
    uri = BearcatUri.new(session['uri'])
    api_auth = CanvasApiAuth.find_by('user_id = ? and api_domain = ?', session['user_id'], uri.api_domain)
    if api_auth && !api_auth.expired?
      @client = Bearcat::Client.new(token: api_auth.api_token, prefix: uri.prefix)
      @client. 'self'
    end
  end

   = LtiAccount.find_by_key(session['oauth_consumer_key']) if session['oauth_consumer_key']

  !!@client
rescue Footrest::HttpError::Unauthorized
  false
end

#lti_authorize!(*roles) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/coalescing_panda/controller_helpers.rb', line 101

def lti_authorize!(*roles)
  authorized = false
  if  = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key'])
    sanitized_params = sanitize_params
    authenticator = IMS::LTI::Services::MessageAuthenticator.new(request.original_url, sanitized_params, .secret)
    authorized = authenticator.valid_signature?
  end
  logger.info 'not authorized on tp valid request' if !authorized
  authorized = authorized && (roles.count == 0 || (roles & lti_roles).count > 0)
  logger.info 'not authorized on roles' if !authorized
  authorized = authorized && .validate_nonce(params['oauth_nonce'], DateTime.strptime(params['oauth_timestamp'], '%s'))
  logger.info 'not authorized on nonce' if !authorized
  render :text => 'Invalid Credentials, please contact your Administrator.', :status => :unauthorized unless authorized
  authorized = authorized && check_for_iframes_problem if authorized
  authorized
end

#lti_editor_button_response(return_type, return_params) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/coalescing_panda/controller_helpers.rb', line 130

def lti_editor_button_response(return_type, return_params)
  valid_return_types = [:image_url, :iframe, :url, :lti_launch_url]
  raise "invalid editor button return type #{return_type}" unless valid_return_types.include?(return_type)
  return_params[:return_type] = return_type.to_s
  return_url = "#{params['launch_presentation_return_url']}?#{return_params.to_query}"
  redirect_to return_url
end

#lti_rolesObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/coalescing_panda/controller_helpers.rb', line 138

def lti_roles
  @lti_roles ||= params['roles'].split(',').map { |role|
    case role.downcase.strip
      when 'admin'
        :admin
      when 'urn:lti:instrole:ims/lis/administrator'
        :admin
      when 'learner'
        :student
      when 'instructor'
        :teacher
      when 'urn:lti:role:ims/lis/teachingassistant'
        :ta
      when 'contentdeveloper'
        :designer
      when 'urn:lti:instrole:ims/lis/observer'
        :observer
      else
        :none
    end
  }.uniq
end

#refresh_token(uri, api_auth) ⇒ Object



51
52
53
54
55
56
# File 'lib/coalescing_panda/controller_helpers.rb', line 51

def refresh_token(uri, api_auth)
  refresh_client = Bearcat::Client.new(prefix: uri.prefix)
  refresh_body = refresh_client.retrieve_token(.oauth2_client_id, coalescing_panda.oauth2_redirect_url,
    .oauth2_client_key, api_auth.refresh_token, 'refresh_token')
  api_auth.update({ api_token: refresh_body['access_token'], expires_at: (Time.now + refresh_body['expires_in']) })
end

#render_oauth2_page(uri, user_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/coalescing_panda/controller_helpers.rb', line 32

def render_oauth2_page(uri, user_id)
   = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key'])
  return unless 

  client_id = .oauth2_client_id
  client = Bearcat::Client.new(prefix: uri.prefix)
  state = SecureRandom.hex(32)
  OauthState.create! state_key: state, data: { key: params['oauth_consumer_key'], user_id: user_id, api_domain: uri.api_domain }
  redirect_path = coalescing_panda.oauth2_redirect_path
  redirect_url = [coalescing_panda_url, redirect_path.sub(/^\/lti/, '')].join
  @canvas_url = client.auth_redirect_url(client_id, redirect_url, { state: state })

  #delete the added params so the original oauth sig still works
  @lti_params = params.to_hash
  @lti_params.delete('action')
  @lti_params.delete('controller')
  render 'coalescing_panda/oauth2/oauth2', layout: 'coalescing_panda/application'
end

#sanitize_paramsObject

code for method taken from panda_pal v 4.0.8 used for safari workaround



120
121
122
123
124
125
126
127
128
# File 'lib/coalescing_panda/controller_helpers.rb', line 120

def sanitize_params
  sanitized_params = request.request_parameters
  # These params come over with a safari-workaround launch.  The authenticator doesn't like them, so clean them out.
  safe_unexpected_params = ["full_win_launch_requested", "platform_redirect_url"]
  safe_unexpected_params.each do |p|
    sanitized_params.delete(p)
  end
  sanitized_params
end

#session_checkObject



170
171
172
# File 'lib/coalescing_panda/controller_helpers.rb', line 170

def session_check
  logger.warn 'session_check is deprecated. Functionality moved to canvas_oauth2.'
end

#set_session(launch_presentation_return_url) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/coalescing_panda/controller_helpers.rb', line 70

def set_session(launch_presentation_return_url)
  session['user_id'] = params['user_id']
  session['uri'] = launch_presentation_return_url
  session['lis_person_sourcedid'] = params['lis_person_sourcedid']
  session['oauth_consumer_key'] = params['oauth_consumer_key']
  session['custom_canvas_account_id'] = params['custom_canvas_account_id']
end