From f03701cc9415cc1aa424d30a42d9cb742cf841f7 Mon Sep 17 00:00:00 2001 From: Chris Villa Date: Wed, 13 Dec 2023 19:19:21 +0000 Subject: [PATCH] chore: use explicit deployment URLs for versions for security --- .../docs/components/ReleaseSwitcher/index.tsx | 15 ++++----- apps/docs/package.json | 1 - apps/docs/pages/api/releases.ts | 32 ++----------------- apps/docs/pages/v/[[...fullPath]].tsx | 29 ++++++++++++----- turbo.json | 3 +- yarn.lock | 5 --- 6 files changed, 32 insertions(+), 53 deletions(-) diff --git a/apps/docs/components/ReleaseSwitcher/index.tsx b/apps/docs/components/ReleaseSwitcher/index.tsx index 0c2d47699b..9981065344 100644 --- a/apps/docs/components/ReleaseSwitcher/index.tsx +++ b/apps/docs/components/ReleaseSwitcher/index.tsx @@ -5,6 +5,8 @@ import { getClassNameFactory } from "@/core/lib"; import styles from "./styles.module.css"; +const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "https://puckeditor.com"; + const { version } = packageJson; const getClassName = getClassNameFactory("ReleaseSwitcher", styles); @@ -31,14 +33,11 @@ export const ReleaseSwitcher = () => { ]); useEffect(() => { - fetch("/api/releases").then(async (res) => { + fetch(`${BASE_URL}/api/releases`).then(async (res) => { const { releases } = await res.json(); - - if (releases.length === 0) return; - - const releaseOptions = releases.map((release) => ({ - label: release.name.split("releases/")[1], - value: release.name.split("releases/v")[1], // remove the leading `v` + const releaseOptions = Object.keys(releases).map((key) => ({ + label: key, + value: key, })); releaseOptions[0].label = `${releaseOptions[0].label} (latest)`; @@ -54,7 +53,7 @@ export const ReleaseSwitcher = () => { value={currentValue} onChange={(e) => { const newHref = e.currentTarget.value - ? `https://puckeditor.com/v/${e.currentTarget.value}` + ? `/v/${e.currentTarget.value}` : "https://puckeditor.com"; if (window.parent) { diff --git a/apps/docs/package.json b/apps/docs/package.json index 55651b1b1d..a1a0b23ab4 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -16,7 +16,6 @@ "typescript": "^4.5.3" }, "dependencies": { - "lru-cache": "^10.1.0", "next": "^13.5.4", "nextra": "^2.13.2", "nextra-theme-docs": "^2.13.2", diff --git a/apps/docs/pages/api/releases.ts b/apps/docs/pages/api/releases.ts index 809316ded5..1d96811ed5 100644 --- a/apps/docs/pages/api/releases.ts +++ b/apps/docs/pages/api/releases.ts @@ -1,41 +1,13 @@ import type { NextApiRequest, NextApiResponse } from "next"; -import { LRUCache } from "lru-cache"; -type ResponseData = { - releases: object; -}; - -const cache = new LRUCache({ - ttl: 1000 * 60 * 2, // 2 minutes - ttlAutopurge: true, -}); +import releases from "../../releases.json"; /** * Proxy GitHub and rely on Next.js cache to prevent rate limiting */ export default async function handler( req: NextApiRequest, - res: NextApiResponse + res: NextApiResponse ) { - const cached = cache.get("releases"); - - if (cached) { - res.status(200).json({ releases: cached }); - - return; - } - - const data = [{ name: "releases/v0.12.0", protected: false }]; - - const releases: { name: string; protected: boolean }[] = data - .filter( - (item) => - item.name.indexOf("releases") === 0 && - item.name.indexOf(`v0.11.`) === -1 // Filter out any release branches before v0.12.0 - ) - .reverse(); - res.status(200).json({ releases }); - - cache.set("releases", releases); } diff --git a/apps/docs/pages/v/[[...fullPath]].tsx b/apps/docs/pages/v/[[...fullPath]].tsx index a3d9dbecff..26817bbd9c 100644 --- a/apps/docs/pages/v/[[...fullPath]].tsx +++ b/apps/docs/pages/v/[[...fullPath]].tsx @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; export type Message = { type: "routeChange"; @@ -6,17 +6,28 @@ export type Message = { title: string; }; -export default function Version({ path, version = "" }) { - const versionSlug = version.replace(/\./g, ""); +const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "https://puckeditor.com"; - const base = - version === "canary" - ? `https://puck-docs-git-main-measured.vercel.app` - : `https://puck-docs-git-releases-v${versionSlug}-measured.vercel.app`; +export default function Version({ path, version = "" }) { + const [base, setBase] = useState(""); const src = `${base}/${path}`; useEffect(() => { + fetch(`${BASE_URL}/api/releases`).then(async (res) => { + const { releases } = await res.json(); + + setBase( + version === "canary" + ? `https://puck-docs-git-main-measured.vercel.app` + : releases[version] + ); + }); + }, [version]); + + useEffect(() => { + if (!base) return; + const handleMessageReceived = (event: MessageEvent) => { if (event.data.type === "routeChange") { if (event.origin !== base) { @@ -42,7 +53,9 @@ export default function Version({ path, version = "" }) { window.addEventListener("message", handleMessageReceived); return () => window.removeEventListener("message", handleMessageReceived); - }, []); + }, [base, version]); + + if (!base) return
; return (