SECURITY: Remove ember-cli specific response from application routes (#15155)
Under some conditions, these varied responses could lead to cache poisoning, hence the 'security' label. Previously the Rails application would serve JSON data in place of HTML whenever Ember CLI requested an `application.html.erb`-rendered page. This commit removes that logic, and instead parses the HTML out of the standard response. This means that Rails doesn't need to customize its response for Ember CLI.
This commit is contained in:
parent
f37375f582
commit
1fa7a87f86
|
@ -25,6 +25,9 @@ module.exports = function (defaults) {
|
|||
// This forces the use of `fast-sourcemap-concat` which works in production.
|
||||
enabled: true,
|
||||
},
|
||||
autoImport: {
|
||||
forbidEval: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Ember CLI does this by default for the app tree, but for our extra bundles we
|
||||
|
|
|
@ -6,6 +6,7 @@ const { encode } = require("html-entities");
|
|||
const cleanBaseURL = require("clean-base-url");
|
||||
const path = require("path");
|
||||
const { promises: fs } = require("fs");
|
||||
const { JSDOM } = require("jsdom");
|
||||
|
||||
// via https://stackoverflow.com/a/6248722/165668
|
||||
function generateUID() {
|
||||
|
@ -168,12 +169,14 @@ function replaceIn(bootstrap, template, id, headers, baseURL) {
|
|||
return template.replace(`<bootstrap-content key="${id}">`, contents);
|
||||
}
|
||||
|
||||
async function applyBootstrap(bootstrap, template, response, baseURL) {
|
||||
// If our initial page added some preload data let's not lose that.
|
||||
let json = await response.json();
|
||||
if (json && json.preloaded) {
|
||||
bootstrap.preloaded = Object.assign(json.preloaded, bootstrap.preloaded);
|
||||
}
|
||||
function extractPreloadJson(html) {
|
||||
const dom = new JSDOM(html);
|
||||
return dom.window.document.querySelector("#data-preloaded")?.dataset
|
||||
?.preloaded;
|
||||
}
|
||||
|
||||
async function applyBootstrap(bootstrap, template, response, baseURL, preload) {
|
||||
bootstrap.preloaded = Object.assign(JSON.parse(preload), bootstrap.preloaded);
|
||||
|
||||
Object.keys(BUILDERS).forEach((id) => {
|
||||
template = replaceIn(bootstrap, template, id, response.headers, baseURL);
|
||||
|
@ -181,23 +184,20 @@ async function applyBootstrap(bootstrap, template, response, baseURL) {
|
|||
return template;
|
||||
}
|
||||
|
||||
async function buildFromBootstrap(proxy, baseURL, req, response) {
|
||||
async function buildFromBootstrap(proxy, baseURL, req, response, preload) {
|
||||
try {
|
||||
const template = await fs.readFile(
|
||||
path.join(process.cwd(), "dist", "index.html"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
let url = `${proxy}${baseURL}bootstrap.json`;
|
||||
const queryLoc = req.url.indexOf("?");
|
||||
if (queryLoc !== -1) {
|
||||
url += req.url.substr(queryLoc);
|
||||
}
|
||||
let url = new URL(`${proxy}${baseURL}bootstrap.json`);
|
||||
url.searchParams.append("for_url", req.url);
|
||||
|
||||
const res = await fetch(url, { headers: req.headers });
|
||||
const json = await res.json();
|
||||
|
||||
return applyBootstrap(json.bootstrap, template, response, baseURL);
|
||||
return applyBootstrap(json.bootstrap, template, response, baseURL, preload);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Could not get ${proxy}${baseURL}bootstrap.json\n\n${error}`
|
||||
|
@ -229,7 +229,6 @@ async function handleRequest(proxy, baseURL, req, res) {
|
|||
|
||||
if (req.method === "GET") {
|
||||
req.headers["X-Discourse-Ember-CLI"] = "true";
|
||||
req.headers["X-Discourse-Asset-Path"] = req.path;
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
|
@ -251,20 +250,37 @@ async function handleRequest(proxy, baseURL, req, res) {
|
|||
|
||||
const csp = response.headers.get("content-security-policy");
|
||||
if (csp) {
|
||||
const newCSP = csp.replace(
|
||||
new RegExp(proxy, "g"),
|
||||
`http://${originalHost}`
|
||||
);
|
||||
const emberCliAdditions = [
|
||||
`http://${originalHost}/assets/`,
|
||||
`http://${originalHost}/ember-cli-live-reload.js`,
|
||||
`http://${originalHost}/_lr/`,
|
||||
];
|
||||
const newCSP = csp
|
||||
.replace(new RegExp(proxy, "g"), `http://${originalHost}`)
|
||||
.replace(
|
||||
new RegExp("script-src ", "g"),
|
||||
`script-src ${emberCliAdditions.join(" ")} `
|
||||
);
|
||||
res.set("content-security-policy", newCSP);
|
||||
}
|
||||
|
||||
if (response.headers.get("x-discourse-bootstrap-required") === "true") {
|
||||
const html = await buildFromBootstrap(proxy, baseURL, req, response);
|
||||
const isHTML = response.headers["content-type"]?.startsWith("text/html");
|
||||
const responseText = await response.text();
|
||||
const preload = isHTML ? extractPreloadJson(responseText) : null;
|
||||
|
||||
if (preload) {
|
||||
const html = await buildFromBootstrap(
|
||||
proxy,
|
||||
baseURL,
|
||||
req,
|
||||
response,
|
||||
preload
|
||||
);
|
||||
res.set("content-type", "text/html");
|
||||
res.send(html);
|
||||
} else {
|
||||
res.status(response.status);
|
||||
res.send(await response.text());
|
||||
res.send(responseText);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
"eslint": "^7.27.0",
|
||||
"html-entities": "^2.1.0",
|
||||
"js-yaml": "^4.0.0",
|
||||
"jsdom": "^18.1.1",
|
||||
"loader.js": "^4.7.0",
|
||||
"message-bus-client": "^3.3.0",
|
||||
"messageformat": "0.1.5",
|
||||
|
|
|
@ -1317,6 +1317,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
|
||||
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
|
||||
|
||||
"@transloadit/prettier-bytes@0.0.7":
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz#cdb5399f445fdd606ed833872fa0cabdbc51686b"
|
||||
|
@ -1715,11 +1720,23 @@ acorn@^8.1.0:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.1.tgz#fb0026885b9ac9f48bac1e185e4af472971149ff"
|
||||
integrity sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g==
|
||||
|
||||
acorn@^8.5.0:
|
||||
version "8.6.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
|
||||
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
|
||||
|
||||
after@0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
ajv-errors@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
|
||||
|
@ -4080,7 +4097,7 @@ colors@^1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
|
@ -4405,6 +4422,11 @@ cssom@^0.4.4:
|
|||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
|
||||
integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
|
||||
|
||||
cssom@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36"
|
||||
integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==
|
||||
|
||||
cssom@~0.3.6:
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
|
||||
|
@ -4443,6 +4465,15 @@ data-urls@^2.0.0:
|
|||
whatwg-mimetype "^2.3.0"
|
||||
whatwg-url "^8.0.0"
|
||||
|
||||
data-urls@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.1.tgz#597fc2ae30f8bc4dbcf731fcd1b1954353afc6f8"
|
||||
integrity sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==
|
||||
dependencies:
|
||||
abab "^2.0.3"
|
||||
whatwg-mimetype "^3.0.0"
|
||||
whatwg-url "^10.0.0"
|
||||
|
||||
debug@2.6.9, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
@ -4450,6 +4481,13 @@ debug@2.6.9, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.3.
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.0.1, debug@^3.1.0, debug@^3.1.1:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
|
@ -4457,13 +4495,6 @@ debug@^3.0.1, debug@^3.1.0, debug@^3.1.1:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@~3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
|
@ -4483,6 +4514,11 @@ decimal.js@^10.2.1:
|
|||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3"
|
||||
integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==
|
||||
|
||||
decimal.js@^10.3.1:
|
||||
version "10.3.1"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
|
||||
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
|
||||
|
||||
decode-uri-component@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
|
@ -4653,6 +4689,13 @@ domexception@^2.0.1:
|
|||
dependencies:
|
||||
webidl-conversions "^5.0.0"
|
||||
|
||||
domexception@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673"
|
||||
integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==
|
||||
dependencies:
|
||||
webidl-conversions "^7.0.0"
|
||||
|
||||
dot-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
|
||||
|
@ -6391,6 +6434,15 @@ forever-agent@~0.6.1:
|
|||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||
|
@ -7122,6 +7174,13 @@ html-encoding-sniffer@^2.0.1:
|
|||
dependencies:
|
||||
whatwg-encoding "^1.0.5"
|
||||
|
||||
html-encoding-sniffer@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9"
|
||||
integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==
|
||||
dependencies:
|
||||
whatwg-encoding "^2.0.0"
|
||||
|
||||
html-entities@^2.1.0:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488"
|
||||
|
@ -7169,6 +7228,15 @@ http-parser-js@>=0.5.1:
|
|||
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
|
||||
integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
|
||||
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
|
||||
dependencies:
|
||||
"@tootallnate/once" "2"
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
http-proxy@^1.13.1, http-proxy@^1.18.1:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||
|
@ -7192,6 +7260,14 @@ https-browserify@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
|
||||
https-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
|
||||
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
https@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4"
|
||||
|
@ -7209,6 +7285,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
|||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
|
@ -7584,7 +7667,7 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
|||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
is-potential-custom-element-name@^1.0.0:
|
||||
is-potential-custom-element-name@^1.0.0, is-potential-custom-element-name@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
|
||||
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
|
||||
|
@ -7803,6 +7886,39 @@ jsdom@^16.4.0:
|
|||
ws "^7.4.4"
|
||||
xml-name-validator "^3.0.0"
|
||||
|
||||
jsdom@^18.1.1:
|
||||
version "18.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-18.1.1.tgz#15ec896f5ab7df9669a62375606f47c8c09551aa"
|
||||
integrity sha512-NmJQbjQ/gpS/1at/ce3nCx89HbXL/f5OcenBe8wU1Eik0ROhyUc3LtmG3567dEHAGXkN8rmILW/qtCOPxPHQJw==
|
||||
dependencies:
|
||||
abab "^2.0.5"
|
||||
acorn "^8.5.0"
|
||||
acorn-globals "^6.0.0"
|
||||
cssom "^0.5.0"
|
||||
cssstyle "^2.3.0"
|
||||
data-urls "^3.0.1"
|
||||
decimal.js "^10.3.1"
|
||||
domexception "^4.0.0"
|
||||
escodegen "^2.0.0"
|
||||
form-data "^4.0.0"
|
||||
html-encoding-sniffer "^3.0.0"
|
||||
http-proxy-agent "^5.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
is-potential-custom-element-name "^1.0.1"
|
||||
nwsapi "^2.2.0"
|
||||
parse5 "6.0.1"
|
||||
saxes "^5.0.1"
|
||||
symbol-tree "^3.2.4"
|
||||
tough-cookie "^4.0.0"
|
||||
w3c-hr-time "^1.0.2"
|
||||
w3c-xmlserializer "^3.0.0"
|
||||
webidl-conversions "^7.0.0"
|
||||
whatwg-encoding "^2.0.0"
|
||||
whatwg-mimetype "^3.0.0"
|
||||
whatwg-url "^10.0.0"
|
||||
ws "^8.2.3"
|
||||
xml-name-validator "^4.0.0"
|
||||
|
||||
jsesc@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
|
||||
|
@ -10208,7 +10324,7 @@ safe-regex@^1.1.0:
|
|||
dependencies:
|
||||
ret "~0.1.10"
|
||||
|
||||
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
@ -11272,6 +11388,13 @@ tr46@^2.0.2:
|
|||
dependencies:
|
||||
punycode "^2.1.1"
|
||||
|
||||
tr46@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9"
|
||||
integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==
|
||||
dependencies:
|
||||
punycode "^2.1.1"
|
||||
|
||||
tr46@~0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
|
@ -11688,6 +11811,13 @@ w3c-xmlserializer@^2.0.0:
|
|||
dependencies:
|
||||
xml-name-validator "^3.0.0"
|
||||
|
||||
w3c-xmlserializer@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz#06cdc3eefb7e4d0b20a560a5a3aeb0d2d9a65923"
|
||||
integrity sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==
|
||||
dependencies:
|
||||
xml-name-validator "^4.0.0"
|
||||
|
||||
walk-sync@^0.2.5:
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.2.7.tgz#b49be4ee6867657aeb736978b56a29d10fa39969"
|
||||
|
@ -11785,6 +11915,11 @@ webidl-conversions@^6.1.0:
|
|||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
|
||||
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
|
||||
|
||||
webidl-conversions@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
|
||||
integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
|
||||
|
||||
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
|
||||
|
@ -11843,11 +11978,31 @@ whatwg-encoding@^1.0.5:
|
|||
dependencies:
|
||||
iconv-lite "0.4.24"
|
||||
|
||||
whatwg-encoding@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53"
|
||||
integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==
|
||||
dependencies:
|
||||
iconv-lite "0.6.3"
|
||||
|
||||
whatwg-mimetype@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
|
||||
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
|
||||
|
||||
whatwg-mimetype@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7"
|
||||
integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==
|
||||
|
||||
whatwg-url@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-10.0.0.tgz#37264f720b575b4a311bd4094ed8c760caaa05da"
|
||||
integrity sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==
|
||||
dependencies:
|
||||
tr46 "^3.0.0"
|
||||
webidl-conversions "^7.0.0"
|
||||
|
||||
whatwg-url@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||
|
@ -11987,6 +12142,11 @@ ws@^7.4.4, ws@~7.4.2:
|
|||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
|
||||
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
|
||||
|
||||
ws@^8.2.3:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d"
|
||||
integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==
|
||||
|
||||
x-is-array@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/x-is-array/-/x-is-array-0.1.0.tgz#de520171d47b3f416f5587d629b89d26b12dc29d"
|
||||
|
@ -12007,6 +12167,11 @@ xml-name-validator@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
||||
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
|
||||
|
||||
xml-name-validator@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
|
||||
integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
|
||||
|
||||
xmlchars@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||
|
|
|
@ -119,23 +119,9 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
class RenderEmpty < StandardError; end
|
||||
class PluginDisabled < StandardError; end
|
||||
class EmberCLIHijacked < StandardError; end
|
||||
|
||||
def catch_ember_cli_hijack
|
||||
yield
|
||||
rescue ActionView::Template::Error => ex
|
||||
raise ex unless ex.cause.is_a?(EmberCLIHijacked)
|
||||
send_ember_cli_bootstrap
|
||||
end
|
||||
|
||||
rescue_from RenderEmpty do
|
||||
catch_ember_cli_hijack do
|
||||
with_resolved_locale { render 'default/empty' }
|
||||
end
|
||||
end
|
||||
|
||||
rescue_from EmberCLIHijacked do
|
||||
send_ember_cli_bootstrap
|
||||
with_resolved_locale { render 'default/empty' }
|
||||
end
|
||||
|
||||
rescue_from ArgumentError do |e|
|
||||
|
@ -324,21 +310,13 @@ class ApplicationController < ActionController::Base
|
|||
rescue Discourse::InvalidAccess
|
||||
return render plain: message, status: status_code
|
||||
end
|
||||
catch_ember_cli_hijack do
|
||||
with_resolved_locale do
|
||||
error_page_opts[:layout] = opts[:include_ember] ? 'application' : 'no_ember'
|
||||
render html: build_not_found_page(error_page_opts)
|
||||
end
|
||||
with_resolved_locale do
|
||||
error_page_opts[:layout] = opts[:include_ember] ? 'application' : 'no_ember'
|
||||
render html: build_not_found_page(error_page_opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def send_ember_cli_bootstrap
|
||||
response.headers['X-Discourse-Bootstrap-Required'] = true
|
||||
response.headers['Content-Type'] = "application/json"
|
||||
render json: { preloaded: @preloaded }
|
||||
end
|
||||
|
||||
# If a controller requires a plugin, it will raise an exception if that plugin is
|
||||
# disabled. This allows plugins to be disabled programmatically.
|
||||
def self.requires_plugin(plugin_name)
|
||||
|
|
|
@ -27,12 +27,21 @@ class BootstrapController < ApplicationController
|
|||
add_style(mobile_view? ? :mobile : :desktop)
|
||||
end
|
||||
add_style(:admin) if staff?
|
||||
|
||||
assets_fake_request = ActionDispatch::Request.new(request.env.dup)
|
||||
assets_for_url = params[:for_url]
|
||||
if assets_for_url
|
||||
path, query = assets_for_url.split("?", 2)
|
||||
assets_fake_request.env["PATH_INFO"] = path
|
||||
assets_fake_request.env["QUERY_STRING"] = query
|
||||
end
|
||||
|
||||
Discourse.find_plugin_css_assets(
|
||||
include_official: allow_plugins?,
|
||||
include_unofficial: allow_third_party_plugins?,
|
||||
mobile_view: mobile_view?,
|
||||
desktop_view: !mobile_view?,
|
||||
request: request
|
||||
request: assets_fake_request
|
||||
).each do |file|
|
||||
add_style(file, plugin: true)
|
||||
end
|
||||
|
@ -49,7 +58,7 @@ class BootstrapController < ApplicationController
|
|||
plugin_js = Discourse.find_plugin_js_assets(
|
||||
include_official: allow_plugins?,
|
||||
include_unofficial: allow_third_party_plugins?,
|
||||
request: request
|
||||
request: assets_fake_request
|
||||
).map { |f| script_asset_path(f) }
|
||||
|
||||
bootstrap = {
|
||||
|
|
|
@ -647,10 +647,4 @@ module ApplicationHelper
|
|||
current_user ? nil : value
|
||||
end
|
||||
end
|
||||
|
||||
def hijack_if_ember_cli!
|
||||
if request.headers["HTTP_X_DISCOURSE_EMBER_CLI"] == "true"
|
||||
raise ApplicationController::EmberCLIHijacked.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -131,4 +131,3 @@
|
|||
<%- end %>
|
||||
</body>
|
||||
</html>
|
||||
<%- hijack_if_ember_cli! -%>
|
||||
|
|
|
@ -338,11 +338,6 @@ module Discourse
|
|||
path = request.fullpath
|
||||
result[:path] = path if path.present?
|
||||
|
||||
# When we bootstrap using the JSON method, we want to be able to filter assets on
|
||||
# the path we're bootstrapping for.
|
||||
asset_path = request.headers["HTTP_X_DISCOURSE_ASSET_PATH"]
|
||||
result[:path] = asset_path if asset_path.present?
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
|
|
|
@ -76,12 +76,6 @@ describe Discourse do
|
|||
opts = Discourse.asset_filter_options(:js, req)
|
||||
expect(opts[:path]).to eq("/hello")
|
||||
end
|
||||
|
||||
it "overwrites the path if the asset path is present" do
|
||||
req = stub(fullpath: "/bootstrap.json", headers: { "HTTP_X_DISCOURSE_ASSET_PATH" => "/hello" })
|
||||
opts = Discourse.asset_filter_options(:js, req)
|
||||
expect(opts[:path]).to eq("/hello")
|
||||
end
|
||||
end
|
||||
|
||||
context 'plugins' do
|
||||
|
|
|
@ -93,4 +93,38 @@ describe BootstrapController do
|
|||
expect(bootstrap['authentication_data']).to eq(cookie_data)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a plugin asset filter' do
|
||||
let :plugin do
|
||||
plugin = Plugin::Instance.new
|
||||
plugin.path = "#{Rails.root}/spec/fixtures/plugins/my_plugin/plugin.rb"
|
||||
plugin.register_asset_filter do |type, request|
|
||||
next true if request.path == "/mypluginroute"
|
||||
false
|
||||
end
|
||||
plugin
|
||||
end
|
||||
|
||||
before do
|
||||
Discourse.plugins << plugin
|
||||
plugin.activate!
|
||||
end
|
||||
|
||||
after do
|
||||
Discourse.plugins.delete plugin
|
||||
end
|
||||
|
||||
it "filters assets using the given path" do
|
||||
get "/bootstrap.json"
|
||||
expect(response.status).to eq(200)
|
||||
plugin_assets = response.parsed_body.dig("bootstrap", "plugin_js")
|
||||
expect(plugin_assets).not_to include(a_string_matching "my_plugin")
|
||||
|
||||
get "/bootstrap.json?for_url=/mypluginroute"
|
||||
expect(response.status).to eq(200)
|
||||
plugin_assets = response.parsed_body.dig("bootstrap", "plugin_js")
|
||||
expect(plugin_assets).to include(a_string_matching "my_plugin")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue