Gate the company-settings preview page behind Draft Mode
Unlike the email-templates preview (marketing copy), this page shows real bank/address details once filled in — it must not render for an unauthenticated visitor who finds the URL.
This commit is contained in:
@@ -408,9 +408,12 @@ updating as the admin edits `sellerName`/address/`taxRatePercent`/
|
||||
|
||||
- **`app/company-settings-preview/page.tsx`** + **`components/LiveCompanySettingsPreviewClient.tsx`**
|
||||
— same entrypoint pattern as `/email-preview/[type]` (Draft Mode via
|
||||
`app/api/preview/route.ts`, never a real visitor destination), but no
|
||||
`[type]` segment — there's only one kind of document here, unlike the 6
|
||||
email types.
|
||||
`app/api/preview/route.ts`), but no `[type]` segment — there's only one
|
||||
kind of document here, unlike the 6 email types. **Actually gated on
|
||||
`draftMode().isEnabled`** (calls `notFound()` otherwise), unlike
|
||||
`/email-preview` — this data includes a real bank IBAN/address once
|
||||
filled in, not just marketing email copy, so it must not render for an
|
||||
unauthenticated visitor who happens to find the URL.
|
||||
- **`@react-pdf/renderer`'s `<PDFViewer>`** (not `renderToBuffer()`) is
|
||||
what makes this a *live* preview rather than a static download — it's a
|
||||
browser-only component that renders a `Document` straight into an
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Metadata } from "next";
|
||||
import { draftMode } from "next/headers";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getCompanySettings, type CompanySettings } from "../lib/payload";
|
||||
import { LiveCompanySettingsPreviewClient } from "./components/LiveCompanySettingsPreviewClient";
|
||||
|
||||
@@ -22,13 +23,18 @@ const FALLBACK: CompanySettings = {
|
||||
|
||||
// Entered exclusively via CompanySettings.ts's admin.livePreview.url (a
|
||||
// Payload-admin-only iframe target, see buildPreviewUrl()/api/preview) —
|
||||
// not a page a real visitor would ever land on. Unlike email-templates
|
||||
// there's no draft/published distinction here (company-settings has no
|
||||
// content-versioning concept, it's just the current row) — the initial
|
||||
// fetch is the same live data getCompanySettings() always returns,
|
||||
// useLivePreview() takes over from there as the admin edits fields.
|
||||
// gated on Draft Mode actually being enabled, unlike email-templates'
|
||||
// preview: this data includes a real bank IBAN/address once filled in,
|
||||
// not just marketing email copy, so this page must not render for an
|
||||
// unauthenticated visitor who happens to find the URL. Unlike
|
||||
// email-templates there's no draft/published distinction in the data
|
||||
// itself (company-settings has no content-versioning concept, it's just
|
||||
// the current row) — the initial fetch is the same live data
|
||||
// getCompanySettings() always returns, useLivePreview() takes over from
|
||||
// there as the admin edits fields.
|
||||
export default async function CompanySettingsPreviewPage() {
|
||||
await draftMode();
|
||||
const draft = await draftMode();
|
||||
if (!draft.isEnabled) notFound();
|
||||
const initialSettings = (await getCompanySettings()) ?? FALLBACK;
|
||||
return <LiveCompanySettingsPreviewClient initialSettings={initialSettings} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user