Skip to content

Commit f970ad0

Browse files
feat: use error page instead of redirections, prevent arbitrary URLs
1 parent 990d2ba commit f970ad0

File tree

7 files changed

+106
-13
lines changed

7 files changed

+106
-13
lines changed

src/app.d.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
// See https://svelte.dev/docs/kit/types#app.d.ts
22
// for information about these interfaces
3+
import type { ResolvedPathname } from "$app/types";
34
import type { PostHog } from "posthog-node";
45

56
declare global {
67
namespace App {
7-
// interface Error {}
8+
interface Error {
9+
/**
10+
* A description, going in pair with a custom message.
11+
* When provided, the error code is shown much more subtly
12+
* and the description is shown where the title used to be.
13+
*/
14+
description?: string;
15+
/**
16+
* A link to suggest going to in a button on the error page.
17+
* Internal links must be `resolve`d for safety purposes, while
18+
* external links can also be provided.
19+
*/
20+
link?: {
21+
text: string;
22+
href: ResolvedPathname | `https://${string}`;
23+
};
24+
}
825
interface Locals {
926
posthog: PostHog;
1027
}

src/routes/+error.svelte

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
11
<script lang="ts">
22
import { page } from "$app/state";
3+
import { Button } from "$lib/components/ui/button";
34
</script>
45

56
<svelte:head>
67
<title>Error {page.status} | Svelte Changelog</title>
78
</svelte:head>
89

9-
<div class="flex h-[75vh] w-full flex-col items-center justify-center">
10-
<h1 class="text-[15rem] leading-none">{page.status}</h1>
11-
{#if page.error}
12-
<h3 class="text-2xl font-semibold text-muted-foreground">{page.error.message}</h3>
10+
<div
11+
class={[
12+
"flex h-[75vh] w-full flex-col justify-center",
13+
page.error?.description ? "items-start gap-2" : "items-center"
14+
]}
15+
>
16+
{#if page.error?.description}
17+
<div class="relative w-full">
18+
<h1 class="text-5xl leading-none">{page.error.message}</h1>
19+
<h3 class="max-w-prose text-xl font-semibold text-muted-foreground">
20+
{page.error.description}
21+
</h3>
22+
<span
23+
class="absolute inset-y-0 right-0 -translate-y-4 font-display text-9xl text-muted-foreground opacity-20"
24+
>
25+
{page.status}
26+
</span>
27+
</div>
28+
{:else}
29+
<h1 class="text-[15rem] leading-none">{page.status}</h1>
30+
{#if page.error}
31+
<h3 class="text-2xl font-semibold text-muted-foreground">{page.error.message}</h3>
32+
{/if}
33+
{/if}
34+
{#if page.error?.link}
35+
<Button href={page.error.link.href} class="mt-8">{page.error.link.text}</Button>
1336
{/if}
1437
</div>
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
import { redirect } from "@sveltejs/kit";
1+
import { error } from "@sveltejs/kit";
22
import { resolve } from "$app/paths";
33

44
export function load() {
5-
redirect(308, resolve("/"));
5+
error(403, {
6+
message: "Unable to visit an organization/user",
7+
description: "Paste a whole PR/issue/discussion link to display it in Svelte Changelog.",
8+
link: {
9+
text: "Go home",
10+
href: resolve("/")
11+
}
12+
});
613
}
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
import { redirect } from "@sveltejs/kit";
1+
import { error } from "@sveltejs/kit";
22
import { resolve } from "$app/paths";
33

44
export function load() {
5-
redirect(308, resolve("/"));
5+
error(403, {
6+
message: "Unable to visit a repository",
7+
description: "Paste a whole PR/issue/discussion link to display it in Svelte Changelog.",
8+
link: {
9+
text: "Go home",
10+
href: resolve("/")
11+
}
12+
});
613
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
import { redirect } from "@sveltejs/kit";
1+
import { error } from "@sveltejs/kit";
22
import { resolve } from "$app/paths";
33

4-
export function load() {
5-
redirect(308, resolve("/"));
4+
export function load({ params: { pid: type } }) {
5+
const element =
6+
type === "issues" ? "issue" : type === "discussions" ? "discussion" : "pull request";
7+
error(403, {
8+
message: `Unable to determine the ${element} to visit`,
9+
description: `Please specify the exact ${element} link to display in Svelte Changelog.`,
10+
link: {
11+
text: "Go home",
12+
href: resolve("/")
13+
}
14+
});
615
}

src/routes/[pid=pid]/[org]/[repo]/[id=number]/+page.server.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
import { error, redirect } from "@sveltejs/kit";
22
import { resolve } from "$app/paths";
3-
import { publicRepos } from "$lib/repositories";
3+
import { publicRepos, uniqueRepos } from "$lib/repositories";
44
import { githubCache } from "$lib/server/github-cache";
55
import type { BranchCommit } from "$lib/types";
66

77
type Type = "pull" | "issue" | "discussion";
88

99
export async function load({ params: { pid: type, org, repo, id }, fetch }) {
10+
const isKnownRepo = uniqueRepos.some(({ owner, name }) => org === owner && repo === name);
11+
if (!isKnownRepo) {
12+
error(403, {
13+
message: "Unknown repository",
14+
description:
15+
"Svelte Changelog can only display the details of known repositories. Is this a mistake? Open an issue from the GitHub link in the navigation bar!",
16+
link: {
17+
text: "Go home",
18+
href: resolve("/")
19+
}
20+
});
21+
}
22+
1023
const item = await githubCache.getItemDetails(org, repo, +id);
1124
if (!item) {
1225
error(404, `${type} #${id} doesn't exist in repo ${org}/${repo}`);

src/routes/tracker/[org]/[repo]/+page.server.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { error } from "@sveltejs/kit";
2+
import { resolve } from "$app/paths";
3+
import { uniqueRepos } from "$lib/repositories";
24
import { githubCache } from "$lib/server/github-cache";
35

46
// source: https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
@@ -15,6 +17,21 @@ const closingKeywords = [
1517
];
1618

1719
export async function load({ params }) {
20+
const isKnownRepo = uniqueRepos.some(
21+
({ owner, name }) => params.org === owner && params.repo === name
22+
);
23+
if (!isKnownRepo) {
24+
error(403, {
25+
message: "Unknown repository",
26+
description:
27+
"Svelte Changelog can only track known repositories. Is this a mistake? Open an issue from the GitHub link in the navigation bar!",
28+
link: {
29+
text: "Tracker home page",
30+
href: resolve("/tracker")
31+
}
32+
});
33+
}
34+
1835
const members = await githubCache.getOrganizationMembers(params.org);
1936
if (!members.length) error(404, `Organization ${params.org} not found or empty`);
2037

0 commit comments

Comments
 (0)