mirror of
https://github.com/discourse/discourse.git
synced 2026-08-08 17:53:55 +08:00
## Summary EmbeddableHost allowed_paths values are stored as regular expression source and compiled during request handling without validation or error handling. Now new or updated allowlists are validated on save, and legacy invalid or timed-out patterns are safely skipped as non-matches rather than causing HTTP 500 errors on public embed endpoints. This prevents an administrator from accidentally breaking embed functionality across their site. ## Source - Patch Triage: `patch-triage/1556` Co-authored-by: discourse-patch-triage <272280883+discourse-patch-triage[bot]@users.noreply.github.com>
222 lines
6.4 KiB
Ruby
Vendored
222 lines
6.4 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe Admin::EmbeddableHostsController do
|
|
fab!(:admin)
|
|
fab!(:moderator)
|
|
fab!(:user)
|
|
fab!(:embeddable_host)
|
|
|
|
describe "#create" do
|
|
context "when logged in as an admin" do
|
|
before { sign_in(admin) }
|
|
|
|
it "logs embeddable host create" do
|
|
post "/admin/embeddable_hosts.json", params: { embeddable_host: { host: "test.com" } }
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(
|
|
UserHistory.where(
|
|
acting_user_id: admin.id,
|
|
action: UserHistory.actions[:embeddable_host_create],
|
|
).exists?,
|
|
).to eq(true)
|
|
end
|
|
|
|
it "rejects invalid path allowlists" do
|
|
post "/admin/embeddable_hosts.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "example.com",
|
|
allowed_paths: "[invalid",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(422)
|
|
expect(response.parsed_body["errors"]).to include(
|
|
"#{EmbeddableHost.human_attribute_name(:allowed_paths)} #{I18n.t("errors.messages.invalid")}",
|
|
)
|
|
expect(EmbeddableHost.where(host: "example.com")).not_to exist
|
|
end
|
|
|
|
it "creates an embeddable host with associated tags" do
|
|
tag1 = Fabricate(:tag)
|
|
tag2 = Fabricate(:tag)
|
|
|
|
post "/admin/embeddable_hosts.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "example.com",
|
|
tags: [tag1.id, tag2.id],
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(EmbeddableHost.last.tags).to contain_exactly(tag1, tag2)
|
|
end
|
|
|
|
it "updates an embeddable host with associated tags" do
|
|
tag1 = Fabricate(:tag)
|
|
tag2 = Fabricate(:tag)
|
|
|
|
put "/admin/embeddable_hosts/#{embeddable_host.id}.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "updated-example.com",
|
|
tags: [tag1.id, tag2.id],
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(EmbeddableHost.find(embeddable_host.id).tags).to contain_exactly(tag1, tag2)
|
|
end
|
|
|
|
it "creates an embeddable host with an associated author" do
|
|
user = Fabricate(:user, username: "johndoe")
|
|
|
|
post "/admin/embeddable_hosts.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "example.com",
|
|
user: "johndoe",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(EmbeddableHost.last.user).to eq(user)
|
|
end
|
|
|
|
it "updates an embeddable host with a new author" do
|
|
new_user = Fabricate(:user, username: "johndoe")
|
|
|
|
put "/admin/embeddable_hosts/#{embeddable_host.id}.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "updated-example.com",
|
|
user: "johndoe",
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(EmbeddableHost.find(embeddable_host.id).user).to eq(new_user)
|
|
end
|
|
end
|
|
|
|
shared_examples "embeddable host creation not allowed" do
|
|
it "prevents embeddable host creation with a 404 response" do
|
|
post "/admin/embeddable_hosts.json", params: { embeddable_host: { host: "test.com" } }
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
|
end
|
|
end
|
|
|
|
context "when logged in as a moderator" do
|
|
before { sign_in(moderator) }
|
|
|
|
include_examples "embeddable host creation not allowed"
|
|
end
|
|
|
|
context "when logged in as a non-staff user" do
|
|
before { sign_in(user) }
|
|
|
|
include_examples "embeddable host creation not allowed"
|
|
end
|
|
end
|
|
|
|
describe "#update" do
|
|
context "when logged in as an admin" do
|
|
before { sign_in(admin) }
|
|
|
|
it "logs embeddable host update" do
|
|
category = Fabricate(:category)
|
|
|
|
put "/admin/embeddable_hosts/#{embeddable_host.id}.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "test.com",
|
|
category_id: category.id,
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(200)
|
|
|
|
history_exists =
|
|
UserHistory.where(
|
|
acting_user_id: admin.id,
|
|
action: UserHistory.actions[:embeddable_host_update],
|
|
new_value: "category_id: #{category.id}, host: test.com",
|
|
).exists?
|
|
|
|
expect(history_exists).to eq(true)
|
|
end
|
|
end
|
|
|
|
shared_examples "embeddable host update not allowed" do
|
|
it "prevents updates with a 404 response" do
|
|
category = Fabricate(:category)
|
|
|
|
put "/admin/embeddable_hosts/#{embeddable_host.id}.json",
|
|
params: {
|
|
embeddable_host: {
|
|
host: "test.com",
|
|
category_id: category.id,
|
|
},
|
|
}
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
|
end
|
|
end
|
|
|
|
context "when logged in as a moderator" do
|
|
before { sign_in(moderator) }
|
|
|
|
include_examples "embeddable host update not allowed"
|
|
end
|
|
|
|
context "when logged in as a non-staff user" do
|
|
before { sign_in(user) }
|
|
|
|
include_examples "embeddable host update not allowed"
|
|
end
|
|
end
|
|
|
|
describe "#destroy" do
|
|
context "when logged in as an admin" do
|
|
before { sign_in(admin) }
|
|
|
|
it "logs embeddable host destroy" do
|
|
delete "/admin/embeddable_hosts/#{embeddable_host.id}.json", params: {}
|
|
|
|
expect(response.status).to eq(200)
|
|
expect(
|
|
UserHistory.where(
|
|
acting_user_id: admin.id,
|
|
action: UserHistory.actions[:embeddable_host_destroy],
|
|
).exists?,
|
|
).to eq(true)
|
|
end
|
|
end
|
|
|
|
shared_examples "embeddable host deletion not allowed" do
|
|
it "prevents deletion with a 404 response" do
|
|
delete "/admin/embeddable_hosts/#{embeddable_host.id}.json", params: {}
|
|
|
|
expect(response.status).to eq(404)
|
|
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
|
end
|
|
end
|
|
|
|
context "when logged in as a moderator" do
|
|
before { sign_in(moderator) }
|
|
|
|
include_examples "embeddable host deletion not allowed"
|
|
end
|
|
|
|
context "when logged in as a non-staff user" do
|
|
before { sign_in(user) }
|
|
|
|
include_examples "embeddable host deletion not allowed"
|
|
end
|
|
end
|
|
end
|