mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-09 16:18:30 +08:00
Since the session is backed by a cookie, storing too much data will lead to a cookie overflow error. A return path can be quite large sometimes, so intead of storing it in the session, this patch stores it in our server session.
76 lines
2.3 KiB
Ruby
76 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# name: discourse-lti
|
|
# about: Allows login integration with a number of learning management systems via the LTI 1.3 standard.
|
|
# meta_topic_id: 196174
|
|
# version: 1.0
|
|
# authors: David Taylor
|
|
# url: https://github.com/discourse/discourse/tree/main/plugins/discourse-lti
|
|
|
|
enabled_site_setting :lti_enabled
|
|
|
|
module ::DiscourseLti
|
|
PLUGIN_NAME = "discourse-lti"
|
|
CUSTOM_DATA_CLAIM = "https://purl.imsglobal.org/spec/lti/claim/custom"
|
|
DISCOURSE_INVITE_KEYS = %w[discourse_invite_link custom_discourse_invite_link] # Coursera prefixes keys with `custom_`
|
|
|
|
class ShouldReconnect < StandardError
|
|
end
|
|
end
|
|
|
|
after_initialize do
|
|
# Check for invite URL in LTI custom fields
|
|
# If present, and this is a new user, redirect the user to the invite url.
|
|
# Otherwise, continue as normal
|
|
on(:after_auth) do |authenticator, auth_result, session, cookies, request|
|
|
next if !(authenticator.name.to_sym == :lti)
|
|
next if auth_result.user # Only redirect new users to invite
|
|
|
|
uaa =
|
|
UserAssociatedAccount.find_by(
|
|
provider_name: "lti",
|
|
provider_uid: auth_result.extra_data[:uid],
|
|
)
|
|
next if uaa.nil?
|
|
|
|
custom_data = uaa.extra.dig("raw_info", ::DiscourseLti::CUSTOM_DATA_CLAIM)
|
|
next if custom_data.nil?
|
|
|
|
invite = nil
|
|
::DiscourseLti::DISCOURSE_INVITE_KEYS.each { |k| break if invite = custom_data[k] }
|
|
next if invite.nil?
|
|
|
|
parsed =
|
|
begin
|
|
URI.parse(invite)
|
|
rescue URI::Error
|
|
next
|
|
end
|
|
next if parsed.nil?
|
|
next if parsed.host && parsed.host != Discourse.current_hostname
|
|
|
|
route = Discourse.route_for(parsed.path)
|
|
next if !(route[:controller] == "invites" && route[:action] == "show")
|
|
|
|
request.server_session[:destination_url] = parsed.to_s
|
|
end
|
|
|
|
on(:after_auth) do |authenticator, auth_result, session, cookies|
|
|
next if !(authenticator.name.to_sym == :lti)
|
|
if !auth_result.user && cookies["_t"] # User (probably) already logged in
|
|
raise ::DiscourseLti::ShouldReconnect.new
|
|
end
|
|
end
|
|
|
|
reloadable_patch do
|
|
::Users::OmniauthCallbacksController.rescue_from(::DiscourseLti::ShouldReconnect) do
|
|
session[:auth_reconnect] = true
|
|
complete
|
|
end
|
|
end
|
|
end
|
|
|
|
require_relative "lib/discourse_lti/lti_omniauth_strategy"
|
|
require_relative "lib/discourse_lti/lti_authenticator"
|
|
|
|
auth_provider authenticator: ::DiscourseLti::LtiAuthenticator.new
|