discourse/spec/requests/embed_controller_spec.rb
Blake Erickson d04ba4b3b2
DEPRECATION: Remove support for api creds in query params (#9106)
* DEPRECATION: Remove support for api creds in query params

This commit removes support for api credentials in query params except
for a few whitelisted routes like rss/json feeds and the handle_mail
route.

Several tests were written to valid these changes, but the bulk of the
spec changes are just switching them over to use header based auth so
that they will pass without changing what they were actually testing.

Original commit that notified admins this change was coming was created
over 3 months ago: 2db2003187

* fix tests

* Also allow iCalendar feeds

Co-authored-by: Rafael dos Santos Silva <xfalcox@gmail.com>
2020-04-06 16:55:44 -06:00

254 lines
7.9 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
describe EmbedController do
let(:embed_url) { "http://eviltrout.com/2013/02/10/why-discourse-uses-emberjs.html" }
let(:embed_url_secure) { "https://eviltrout.com/2013/02/10/why-discourse-uses-emberjs.html" }
let(:discourse_username) { "eviltrout" }
it "is 404 without an embed_url" do
get '/embed/comments'
expect(response.body).to match(I18n.t('embed.error'))
end
it "raises an error with a missing host" do
get '/embed/comments', params: { embed_url: embed_url }
expect(response.body).to match(I18n.t('embed.error'))
end
context "by topic id" do
let(:headers) { { 'REFERER' => 'http://eviltrout.com/some-page' } }
before do
Fabricate(:embeddable_host)
end
it "allows a topic to be embedded by id" do
topic = Fabricate(:topic)
get '/embed/comments', params: { topic_id: topic.id }, headers: headers
expect(response.status).to eq(200)
end
end
context "#info" do
context "without api key" do
it "fails" do
get '/embed/info.json'
expect(response.body).to match(I18n.t('embed.error'))
end
end
context "with api key" do
let(:api_key) { Fabricate(:api_key) }
context "with valid embed url" do
let(:topic_embed) { Fabricate(:topic_embed, embed_url: embed_url) }
it "returns information about the topic" do
get '/embed/info.json',
params: { embed_url: topic_embed.embed_url },
headers: { HTTP_API_KEY: api_key.key, HTTP_API_USERNAME: "system" }
json = JSON.parse(response.body)
expect(json['topic_id']).to eq(topic_embed.topic.id)
expect(json['post_id']).to eq(topic_embed.post.id)
expect(json['topic_slug']).to eq(topic_embed.topic.slug)
end
end
context "without invalid embed url" do
it "returns error response" do
get '/embed/info.json',
params: { embed_url: "http://nope.com" },
headers: { HTTP_API_KEY: api_key.key, HTTP_API_USERNAME: "system" }
json = JSON.parse(response.body)
expect(json["error_type"]).to eq("not_found")
end
end
end
end
context "#topics" do
it "raises an error when not enabled" do
get '/embed/topics?embed_id=de-1234'
expect(response.status).to eq(400)
end
context "when enabled" do
before do
SiteSetting.embed_topics_list = true
end
it "raises an error with a weird id" do
get '/embed/topics?discourse_embed_id=../asdf/-1234', headers: headers
expect(response.status).to eq(400)
end
it "returns a list of topics" do
topic = Fabricate(:topic)
get '/embed/topics?discourse_embed_id=de-1234', headers: {
'REFERER' => 'https://example.com/evil-trout'
}
expect(response.status).to eq(200)
expect(response.headers['X-Frame-Options']).to eq("ALLOWALL")
expect(response.body).to match("data-embed-id=\"de-1234\"")
expect(response.body).to match("data-topic-id=\"#{topic.id}\"")
expect(response.body).to match("data-referer=\"https://example.com/evil-trout\"")
end
it "returns no referer if not supplied" do
get '/embed/topics?discourse_embed_id=de-1234'
expect(response.status).to eq(200)
expect(response.body).to match("data-referer=\"\"")
end
it "returns * for the referer if `embed_any_origin` is set" do
SiteSetting.embed_any_origin = true
get '/embed/topics?discourse_embed_id=de-1234'
expect(response.status).to eq(200)
expect(response.body).to match("data-referer=\"\\*\"")
end
end
end
context "with a host" do
let!(:embeddable_host) { Fabricate(:embeddable_host) }
let(:headers) { { 'REFERER' => embed_url } }
before do
Jobs.run_immediately!
end
it "raises an error with no referer" do
get '/embed/comments', params: { embed_url: embed_url }
expect(response.body).to match(I18n.t('embed.error'))
end
it "includes CSS from embedded_scss field" do
theme = Fabricate(:theme)
theme.set_default!
ThemeField.create!(
theme_id: theme.id,
name: "embedded_scss",
target_id: 0,
type_id: 1,
value: ".test-osama-15 {\n" + " color: red;\n" + "}\n"
)
topic_embed = Fabricate(:topic_embed, embed_url: embed_url)
post = Fabricate(:post, topic: topic_embed.topic)
get '/embed/comments', params: { embed_url: embed_url }, headers: headers
html = Nokogiri::HTML.fragment(response.body)
css_link = html.at("link[data-target=embedded_theme]").attribute("href").value
get css_link
expect(response.status).to eq(200)
expect(response.body).to include(".test-osama-15")
end
context "success" do
after do
expect(response.status).to eq(200)
expect(response.headers['X-Frame-Options']).to eq("ALLOWALL")
end
it "tells the topic retriever to work when no previous embed is found" do
TopicEmbed.expects(:topic_id_for_embed).returns(nil)
retriever = mock
TopicRetriever.expects(:new).returns(retriever)
retriever.expects(:retrieve)
get '/embed/comments', params: { embed_url: embed_url }, headers: headers
end
it "displays the right view" do
topic_embed = Fabricate(:topic_embed, embed_url: embed_url)
get '/embed/comments', params: { embed_url: embed_url_secure }, headers: headers
expect(response.body).to match(I18n.t('embed.start_discussion'))
end
it "creates a topic view when a topic_id is found" do
topic_embed = Fabricate(:topic_embed, embed_url: embed_url)
post = Fabricate(:post, topic: topic_embed.topic)
get '/embed/comments', params: { embed_url: embed_url }, headers: headers
expect(response.body).to match(I18n.t('embed.continue'))
expect(response.body).to match(post.cooked)
end
it "provides the topic retriever with the discourse username when provided" do
retriever = mock
retriever.expects(:retrieve).returns(nil)
TopicRetriever.expects(:new)
.with(embed_url, has_entry(author_username: discourse_username))
.returns(retriever)
get '/embed/comments',
params: { embed_url: embed_url, discourse_username: discourse_username },
headers: headers
end
end
end
context "with multiple hosts" do
before do
Fabricate(:embeddable_host)
Fabricate(:embeddable_host, host: 'http://discourse.org')
Fabricate(:embeddable_host, host: 'https://example.com/1234', class_name: 'example')
end
context "success" do
it "works with the first host" do
get '/embed/comments',
params: { embed_url: embed_url },
headers: { 'REFERER' => "http://eviltrout.com/wat/1-2-3.html" }
expect(response.status).to eq(200)
end
it "works with the second host" do
get '/embed/comments',
params: { embed_url: embed_url },
headers: { 'REFERER' => "http://eviltrout.com/wat/1-2-3.html" }
expect(response.status).to eq(200)
end
it "works with a host with a path" do
get '/embed/comments',
params: { embed_url: embed_url },
headers: { 'REFERER' => "https://example.com/some-other-path" }
expect(response.status).to eq(200)
end
it "contains custom class name" do
get '/embed/comments',
params: { embed_url: embed_url },
headers: { 'REFERER' => "https://example.com/some-other-path" }
expect(response.body).to match('class="example"')
end
it "doesn't work with a made up host" do
get '/embed/comments',
params: { embed_url: embed_url },
headers: { 'REFERER' => "http://codinghorror.com/invalid-url" }
expect(response.body).to match(I18n.t('embed.error'))
end
end
end
end