discourse/app/controllers/users/associate_accounts_controller.rb
Loïc Guitaut 8761d47e26
DEV: Allow ServerSession to store arbitrary data (#34919)
Currently, the server session can only store strings. As we want to move
more things into it (like with a proper session object), we need to be
able to store arbitrary data.

This PR serializes data using Message Pack, as it’s almost as flexible
as Marshal but without the potential security issues.
2025-09-26 10:35:28 +02:00

59 lines
1.8 KiB
Ruby

# frozen_string_literal: true
class Users::AssociateAccountsController < ApplicationController
SERVER_SESSION_PREFIX = "omniauth_reconnect"
before_action :ensure_logged_in
def connect_info
account_description = authenticator.description_for_auth_hash(auth_hash)
existing_account_description = authenticator.description_for_user(current_user).presence
render json: {
token: params[:token],
provider_name: auth_hash.provider,
account_description: account_description,
existing_account_description: existing_account_description,
}
end
def connect
if authenticator.description_for_user(current_user).present? && authenticator.can_revoke?
authenticator.revoke(current_user)
end
DiscourseEvent.trigger(:before_auth, authenticator, auth_hash, session, cookies, request)
auth_result = authenticator.after_authenticate(auth_hash, existing_account: current_user)
DiscourseEvent.trigger(:after_auth, authenticator, auth_result, session, cookies, request)
server_session.delete(self.class.key(params[:token]))
render json: success_json
end
private
def auth_hash
@auth_hash ||=
begin
token = params[:token]
json = server_session[self.class.key(token)]
raise Discourse::NotFound if json.nil?
OmniAuth::AuthHash.new(JSON.parse(json))
end
end
def authenticator
provider_name = auth_hash.provider
authenticator = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
raise Discourse::InvalidAccess.new(I18n.t("authenticator_not_found")) if authenticator.nil?
if !authenticator.can_connect_existing_user?
raise Discourse::InvalidAccess.new(I18n.t("authenticator_no_connect"))
end
authenticator
end
def self.key(token)
"#{SERVER_SESSION_PREFIX}_#{token}"
end
end