mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-27 11:53:31 +08:00
When an "anon" user visits a topic that is "private", they will get a page that is server-rendered and doesn't load the client-side app. When they click the "login" button, it will redirect to the /login route which loads the app. The only way we can know where the user landed initially is via the "document.referrer". The issue was that the code that checked the referrer was **after** the code that is doing the redirection to discourse connect. By putting the code before doing the redirection to discourse connect, we are successfully redirected to the landing url after doing the discourse connect auth. I've also added a system spec that test the happy path by starting the most basic discourse connect compliant sso server in the background.
84 lines
2.1 KiB
Ruby
Vendored
84 lines
2.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
require "webrick"
|
|
|
|
describe "Discourse Connect", type: :system do
|
|
let(:sso_secret) { SecureRandom.alphanumeric(32) }
|
|
let(:sso_port) { 9876 }
|
|
let(:sso_url) { "http://localhost:#{sso_port}/sso" }
|
|
|
|
fab!(:user)
|
|
fab!(:private_group) { Fabricate(:group, users: [user]) }
|
|
fab!(:private_category) { Fabricate(:private_category, group: private_group) }
|
|
fab!(:private_topic) { Fabricate(:topic, category: private_category) }
|
|
fab!(:private_post) { Fabricate(:post, topic: private_topic) }
|
|
|
|
before do
|
|
setup_test_sso_server
|
|
configure_discourse_connect
|
|
end
|
|
|
|
after { shutdown_test_sso_server }
|
|
|
|
context "when auth_immediately is enabled" do
|
|
before { SiteSetting.auth_immediately = true }
|
|
|
|
it "redirects the user back to the landing URL" do
|
|
visit private_topic.url
|
|
|
|
find(".login-button").click
|
|
|
|
wait_for { has_css?("#current-user") }
|
|
|
|
expect(page).to have_current_path(private_topic.relative_url)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def setup_test_sso_server
|
|
@server =
|
|
WEBrick::HTTPServer.new(
|
|
Port: sso_port,
|
|
Logger: WEBrick::Log.new(File.open(File::NULL, "w")),
|
|
AccessLog: [],
|
|
)
|
|
|
|
@server.mount_proc "/sso" do |req, res|
|
|
decoded = Base64.decode64(req.query["sso"])
|
|
params = Rack::Utils.parse_query(decoded)
|
|
|
|
response_sso = DiscourseConnectBase.new
|
|
response_sso.nonce = params["nonce"]
|
|
response_sso.sso_secret = sso_secret
|
|
response_sso.external_id = "foo-bar"
|
|
response_sso.email = user.email
|
|
response_sso.username = user.username
|
|
|
|
res.status = 302
|
|
res["Location"] = "#{params["return_sso_url"]}?#{response_sso.payload}"
|
|
end
|
|
|
|
@server_thread = Thread.new { @server.start }
|
|
|
|
sleep 0.1 until server_responding?
|
|
end
|
|
|
|
def shutdown_test_sso_server
|
|
@server&.shutdown
|
|
@server_thread&.kill
|
|
end
|
|
|
|
def server_responding?
|
|
Net::HTTP.get_response(URI(sso_url))
|
|
true
|
|
rescue StandardError
|
|
false
|
|
end
|
|
|
|
def configure_discourse_connect
|
|
SiteSetting.discourse_connect_url = sso_url
|
|
SiteSetting.discourse_connect_secret = sso_secret
|
|
SiteSetting.enable_discourse_connect = true
|
|
end
|
|
end
|