FIX: Check for permalinks before showing the 404 page

Limitations: the user profile "open external links in new tab setting" is
slightly broken for "External URL" permalinks.

Remove the copy from the admin permalinks page stating that this doesn't work.
This commit is contained in:
Kane York 2020-03-05 17:33:25 -08:00 committed by Kane York
parent dc1836573d
commit 4b8acce92b
7 changed files with 93 additions and 14 deletions

View File

@ -24,7 +24,6 @@ const SERVER_SIDE_ONLY = [
/^\/posts\/\d+\/raw/,
/^\/raw\/\d+/,
/^\/wizard/,
/^\/go\//, // EXPERIMENTAL: https://meta.discourse.org/t/-/142605
/\.rss$/,
/\.json$/,
/^\/admin\/upgrade$/,

View File

@ -1,8 +1,22 @@
import DiscourseRoute from "discourse/routes/discourse";
import { ajax } from "discourse/lib/ajax";
import DiscourseURL from "discourse/lib/url";
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
model() {
return ajax("/404-body", { dataType: "html" });
model(params, transition) {
const path = params.path;
return ajax("/permalink-check.json", {
data: { path }
}).then(results => {
if (results.found) {
// Avoid polluting the history stack for external links
transition.abort();
DiscourseURL.routeTo(results.target_url);
return "";
} else {
// 404 body HTML
return results.html;
}
});
}
});

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
class PermalinksController < ApplicationController
skip_before_action :check_xhr, :preload_json
skip_before_action :check_xhr, :preload_json, only: [:show]
def show
url = request.fullpath
@ -17,4 +17,28 @@ class PermalinksController < ApplicationController
end
end
def check
begin
raise Discourse::NotFound if params[:path].blank?
permalink = Permalink.find_by_url(params[:path])
raise Discourse::NotFound unless permalink
data = {
found: true,
internal: permalink.external_url.nil?,
target_url: permalink.target_url,
}
render json: MultiJson.dump(data)
rescue Discourse::NotFound
data = {
found: false,
html: build_not_found_page(status: 200),
}
render json: MultiJson.dump(data)
end
end
end

View File

@ -4578,7 +4578,7 @@ en:
permalink:
title: "Permalinks"
description: "Please note this only applies to external sources, links posted on your forum will not be redirected."
description: "Redirections to apply for URLs not known by the forum."
url: "URL"
topic_id: "Topic ID"
topic_title: "Topic"

View File

@ -954,6 +954,8 @@ Discourse::Application.routes.draw do
resources :csp_reports, only: [:create]
get "/permalink-check", to: 'permalinks#check'
get "*url", to: 'permalinks#show', constraints: PermalinkConstraint.new
end
end

View File

@ -1,8 +1,49 @@
import { acceptance } from "helpers/qunit-helpers";
import pretender from "helpers/create-pretender";
acceptance("Unknown");
QUnit.test("Unknown URL", async assert => {
assert.expect(1);
QUnit.test("Permalink Unknown URL", async assert => {
await visit("/url-that-doesn't-exist");
assert.ok(exists(".page-not-found"), "The not found content is present");
});
QUnit.test("Permalink URL to a Topic", async assert => {
pretender.get("/permalink-check.json", () => {
return [
200,
{ "Content-Type": "application/json" },
{
found: true,
internal: true,
target_url: "/t/internationalization-localization/280"
}
];
});
await visit("/viewtopic.php?f=8&t=280");
assert.ok(exists(".topic-post"));
});
QUnit.test("Permalink URL to a static page", async assert => {
pretender.get("/permalink-check.json", () => {
return [
200,
{ "Content-Type": "application/json" },
{
found: true,
internal: true,
target_url: "/faq"
}
];
});
await visit("/not-the-url-for-faq");
// body is outside of #ember-testing-container and needs to be targeted
// through document instead of find
assert.ok(
document.querySelector("body.static-faq"),
"routed to the faq page"
);
assert.ok(exists(".body-page"));
});

View File

@ -267,12 +267,11 @@ export function applyDefaultHandlers(pretender) {
pretender.put("/t/:id/recover", success);
pretender.put("/t/:id/publish", success);
pretender.get("/404-body", () => {
return [
200,
{ "Content-Type": "text/html" },
"<div class='page-not-found'>not found</div>"
];
pretender.get("/permalink-check.json", () => {
return response({
found: false,
html: "<div class='page-not-found'>not found</div>"
});
});
pretender.delete("/draft.json", success);