Module: CoalescingPanda::ControllerHelpers

Extended by:
ActiveSupport::Concern
Includes:
SessionReplacement
Defined in:
lib/coalescing_panda/controller_helpers.rb

Instance Method Summary collapse

Methods included from SessionReplacement

#current_session, #current_session_data, #forbid_access_if_lacking_session, #link_nonce, #link_nonce_type, #link_with_session_to, #redirect_with_session_to, #save_session, #session_changed?, #session_expiration_period_minutes, #session_url_for, #url_with_session, #verify_authenticity_token

Instance Method Details

#canvas_environmentObject



151
152
153
154
155
156
157
158
# File 'lib/coalescing_panda/controller_helpers.rb', line 151

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

#canvas_oauth2(*roles) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/coalescing_panda/controller_helpers.rb', line 16

def canvas_oauth2(*roles)
  return if have_session?
  if lti_authorize!(*roles)
    user_id = params['user_id']
    launch_presentation_return_url = @lti_account.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_refresh_tokenObject



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

def check_refresh_token
  return unless current_session_data['uri'] && current_session_data['user_id'] && current_session_data['oauth_consumer_key']
  uri = BearcatUri.new(current_session_data['uri'])
  api_auth = CanvasApiAuth.find_by(user_id: current_session_data['user_id'], api_domain: uri.api_domain)
  @lti_account = LtiAccount.find_by(key: current_session_data['oauth_consumer_key'])
  return if @lti_account.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, current_session_data['user_id']
end

#current_lti_accountObject



9
10
11
12
13
# File 'lib/coalescing_panda/controller_helpers.rb', line 9

def 
  @account ||= (CoalescingPanda::LtiAccount.find_by!(key: organization_key) if organization_key)
  @account ||= (CoalescingPanda::LtiAccount.find_by(id: organization_id) if organization_id)
  @account
end

#current_organizationObject



14
# File 'lib/coalescing_panda/controller_helpers.rb', line 14

def current_organization; ; end

#have_session?Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/coalescing_panda/controller_helpers.rb', line 86

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

  if (current_session_data['user_id'] && current_session_data['uri'])
    uri = BearcatUri.new(current_session_data['uri'])
    api_auth = CanvasApiAuth.find_by('user_id = ? and api_domain = ?', current_session_data['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

  @lti_account = LtiAccount.find_by_key(current_session_data['oauth_consumer_key']) if current_session_data['oauth_consumer_key']

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

#lti_authorize!(*roles) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/coalescing_panda/controller_helpers.rb', line 109

def lti_authorize!(*roles)
  authorized = false
  if (@lti_account = params['oauth_consumer_key'] && LtiAccount.find_by_key(params['oauth_consumer_key']))
    sanitized_params = sanitize_params
    @tp = IMS::LTI::ToolProvider.new(@lti_account.key, @lti_account.secret, sanitized_params)
    authorized = @tp.valid_request?(request)
  end
  logger.info 'not authorized on tp valid request' unless authorized
  authorized = authorized && (roles.count == 0 || (roles & lti_roles).count > 0)
  logger.info 'not authorized on roles' unless authorized
  authorized = authorized && @lti_account.validate_nonce(params['oauth_nonce'], DateTime.strptime(params['oauth_timestamp'], '%s'))
  logger.info 'not authorized on nonce' unless authorized
  render :text => 'Invalid Credentials, please contact your Administrator.', :status => :unauthorized unless authorized
  # create session on first launch
  current_session
  authorized
end

#lti_editor_button_response(return_type, return_params) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/coalescing_panda/controller_helpers.rb', line 139

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



147
148
149
# File 'lib/coalescing_panda/controller_helpers.rb', line 147

def lti_roles
  @lti_roles ||= current_session_data[:roles]
end

#refresh_token(uri, api_auth) ⇒ Object



59
60
61
62
63
64
# File 'lib/coalescing_panda/controller_helpers.rb', line 59

def refresh_token(uri, api_auth)
  refresh_client = Bearcat::Client.new(prefix: uri.prefix)
  refresh_body = refresh_client.retrieve_token(@lti_account.oauth2_client_id, resolve_coalescing_panda_url(:oauth2_redirect_url),
    @lti_account.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



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/coalescing_panda/controller_helpers.rb', line 42

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

  client_id = @lti_account.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 }
  @canvas_url = client.auth_redirect_url(client_id, resolve_coalescing_panda_url(:oauth2_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



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

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

#set_session(launch_presentation_return_url) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/coalescing_panda/controller_helpers.rb', line 78

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

#valid_session?Boolean

Returns:

  • (Boolean)


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

def valid_session?
  return false unless current_session(create_missing: false)&.persisted?
  true
rescue SessionNonceMismatch
  false
end