aboutsummaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/api/badges/+server.ts14
-rw-r--r--src/routes/api/notifications/subscribe/+server.ts17
-rw-r--r--src/routes/updates/+page.svelte34
-rw-r--r--src/routes/user/[user]/badges/+page.svelte13
4 files changed, 55 insertions, 23 deletions
diff --git a/src/routes/api/badges/+server.ts b/src/routes/api/badges/+server.ts
index 2673273c..10b63125 100644
--- a/src/routes/api/badges/+server.ts
+++ b/src/routes/api/badges/+server.ts
@@ -16,6 +16,7 @@ import {
import { decodeAuthCookieOrNull } from "$lib/Effect/authCookie";
import { decodeRequestJsonOrThrow } from "$lib/Effect/requestBody";
import { appOrigin, appOriginHeaders } from "$lib/Utility/appOrigin";
+import { isOwnerOrPrivileged } from "$lib/Utility/authorisation";
import privilegedUser from "$lib/Utility/privilegedUser";
const unauthorised = () => new Response("Unauthorised", { status: 401 });
@@ -76,11 +77,14 @@ export const PUT = async ({ cookies, url, request }) => {
if (!identity) return unauthorised();
const authorised = privilegedUser(identity.id);
- if (url.searchParams.get("shadowHide"))
- await setShadowHidden(
- Number(url.searchParams.get("shadowHide")),
- authorised,
- );
+ if (url.searchParams.get("shadowHide")) {
+ const targetUserId = Number(url.searchParams.get("shadowHide"));
+
+ if (!isOwnerOrPrivileged(identity.id, targetUserId, authorised))
+ return unauthorised();
+
+ await setShadowHidden(targetUserId, authorised);
+ }
if (url.searchParams.get("import") || undefined) {
const importedBadges = await decodeRequestJsonOrThrow(
diff --git a/src/routes/api/notifications/subscribe/+server.ts b/src/routes/api/notifications/subscribe/+server.ts
index 51dbf340..b1913e5d 100644
--- a/src/routes/api/notifications/subscribe/+server.ts
+++ b/src/routes/api/notifications/subscribe/+server.ts
@@ -3,6 +3,7 @@ import { safeUserIdentity } from "$lib/Data/AniList/identity";
import { setUserSubscription } from "$lib/Database/SB/User/notifications";
import { decodeAuthCookieOrNull } from "$lib/Effect/authCookie";
import { decodeRequestJsonOrThrow } from "$lib/Effect/requestBody";
+import { isAllowedPushEndpoint } from "$lib/Utility/pushEndpoint";
const unauthorised = new Response("Unauthorised", { status: 401 });
@@ -20,12 +21,20 @@ export const POST = async ({ cookies, request, url }) => {
if (!userId) return unauthorised;
+ const subscription = await decodeRequestJsonOrThrow(
+ request,
+ Schema.Record(Schema.String, Schema.Unknown),
+ );
+
+ if (
+ typeof subscription.endpoint !== "string" ||
+ !isAllowedPushEndpoint(subscription.endpoint)
+ )
+ return new Response("Invalid push endpoint", { status: 400 });
+
await setUserSubscription(
userId,
- (await decodeRequestJsonOrThrow(
- request,
- Schema.Record(Schema.String, Schema.Unknown),
- )) as unknown as JSON,
+ subscription as unknown as JSON,
fingerprint,
);
diff --git a/src/routes/updates/+page.svelte b/src/routes/updates/+page.svelte
index 357a5906..bbcb087d 100644
--- a/src/routes/updates/+page.svelte
+++ b/src/routes/updates/+page.svelte
@@ -5,6 +5,7 @@ import HeadTitle from "$lib/Home/HeadTitle.svelte";
import Skeleton from "$lib/Loading/Skeleton.svelte";
import { createHeightObserver } from "$lib/Utility/html";
import root from "$lib/Utility/root";
+import { sanitizeFeedHtml } from "$lib/Utility/sanitizeHtml";
import locale from "$stores/locale";
let feed:
@@ -22,6 +23,7 @@ let novelFeed:
}[];
};
}
+ | null
| undefined;
let startTime: number;
let mangaEndTime: number;
@@ -31,14 +33,42 @@ let directLink = browser
: false;
let removeHeightObserver: (() => void) | undefined;
+const fetchJson = async (path: string) => {
+ try {
+ const response = await fetch(root(path));
+
+ return response.ok ? await response.json() : null;
+ } catch {
+ return null;
+ }
+};
+
onMount(async () => {
removeHeightObserver = createHeightObserver(false);
startTime = performance.now();
- novelFeed = await (await fetch(root("/api/updates/all-novels"))).json();
+
+ const allNovels = await fetchJson("/api/updates/all-novels");
+
+ if (allNovels?.data?.items)
+ for (const item of allNovels.data.items) {
+ if (item.postfix) item.postfix = sanitizeFeedHtml(item.postfix);
+ if (item.series) item.series.name = sanitizeFeedHtml(item.series.name);
+ }
+
+ novelFeed = allNovels?.data?.items ? allNovels : null;
novelEndTime = performance.now() - startTime;
startTime = performance.now();
- feed = await (await fetch(root("/api/updates/manga"))).json();
+
+ const mangaFeed = await fetchJson("/api/updates/manga");
+
+ if (mangaFeed?.items)
+ for (const item of mangaFeed.items) {
+ item.title = sanitizeFeedHtml(item.title);
+ item.content = sanitizeFeedHtml(item.content);
+ }
+
+ feed = mangaFeed?.items ? mangaFeed : null;
mangaEndTime = performance.now() - startTime;
});
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
index dc43fc08..605f5675 100644
--- a/src/routes/user/[user]/badges/+page.svelte
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -40,21 +40,10 @@ $: preferences = $BadgeWallUser.fetching
: ($BadgeWallUser.data?.User?.preferences as Preferences | undefined);
$: if (browser && preferences && preferences.badge_wall_css) {
- const sanitise = (css: string) =>
- css
- .replace(/\/\*[\s\S]*?\*\//g, "")
- .replace(/<\/?[^>]+(>|$)/g, "")
- .replace(
- /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi,
- "",
- )
- .replace(/(behaviour|behavior|moz-binding|content):/gi, "")
- .replace(/\s+/g, " ")
- .trim();
const style = document.createElement("style");
style.dataset.badgeWall = "true";
- style.innerHTML = sanitise(preferences.badge_wall_css);
+ style.textContent = preferences.badge_wall_css;
document.head.appendChild(style);
}