feat(cms): Payload CMS bootstrap — config, MongoDB adapter, admin routes (MITHOME-86)
Alapinstalláció a Payload CMS-re való áttéréshez (EPIC MITHOME-85): - payload@3.88.0, @payloadcms/next, @payloadcms/db-mongodb, @payloadcms/richtext-lexical, graphql, sharp telepítve - src/payload.config.ts: mongooseAdapter a meglévő MONGODB_URI-ra (ugyanaz az adatbázis, mint a Mongoose/mongodb rétegnek), lexical editor, PAYLOAD_SECRET env-ből - src/collections/Users.ts: minimális auth collection — Payload nem tud admin felületet renderelni auth collection nélkül. Ez csak a bootstraphez kell; a valódi access control/jelszó-politika MITHOME-90 feladata. - App Router route group (src/app/(payload)/): admin UI ([[...segments]]), REST (api/[...slug]), GraphQL + playground route-ok, root layout — a szokásos Payload v3 Next.js integrációs minta szerint - next.config.ts: withPayload() wrapper a route handler bundling-hoz - tsconfig.json: @payload-config path alias -> src/payload.config.ts (ez oldja fel a webpack/turbopack importot is, nem csak a type-checket) - PAYLOAD_SECRET env var: generált dev érték a .env.local-ban (gitignore-olt), changeme placeholder + generálási megjegyzés a staging/production .env példafájlokban, dokumentálva a CLAUDE.md env-lista részében Ismert, még nem javított biztonsági advisory a felvett payload@3.88.0-ban (GHSA-jg8r-5jh2-v2xj, moderate, CWE-307: az admin account-unlock alapból más fiókok lockoutját is felold hitelesített usernek) — nincs újabb patch-elt verzió jelenleg, nyomon követve MITHOME-90 alatt. Ellenőrizve ezen a commiton: npm run build, npm run lint, tsc --noEmit, npm test (58 passed) — mind zöld. Az admin bejelentkezés/DB-kapcsolat élő tesztje MongoDB-t igényel (jelen környezetben Docker daemon nem fut, ez lokálisan `docker compose -f docker-compose.dev.yml up -d mongodb` után `npm run dev` + http://localhost:3000/admin-mal ellenőrizhető). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
30364fcab7
commit
1600d99c5d
@@ -7,6 +7,11 @@ MONGODB_DB=mozdit
|
||||
MONGO_ROOT_USER=admin
|
||||
MONGO_ROOT_PASSWORD=changeme
|
||||
|
||||
# Payload CMS (MITHOME-86) — generálj egyedi, erős titkot ehhez a
|
||||
# környezethez (pl. `openssl rand -hex 32`); ne ossz meg értéket másik
|
||||
# environmenttel.
|
||||
PAYLOAD_SECRET=changeme
|
||||
|
||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||
NEXT_PUBLIC_SITE_URL=https://mozdit.hu
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ MONGODB_DB=mozdit
|
||||
MONGO_ROOT_USER=admin
|
||||
MONGO_ROOT_PASSWORD=changeme
|
||||
|
||||
# Payload CMS (MITHOME-86) — generálj egyedi, erős titkot ehhez a
|
||||
# környezethez (pl. `openssl rand -hex 32`); ne ossz meg értéket másik
|
||||
# environmenttel.
|
||||
PAYLOAD_SECRET=changeme
|
||||
|
||||
# Publikus site URL (beég build időben a Dockerfile-ba)
|
||||
NEXT_PUBLIC_SITE_URL=https://stage.mozdit.hu
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ Szükséges változók (`.env` és `proto/.env.local`):
|
||||
- `NEXT_PUBLIC_WEBMAIL_URL` — Webmail service URL
|
||||
- `NEXT_PUBLIC_CONTACT_EMAIL` — Kapcsolati email cím
|
||||
- `PLANE_API_KEY` — Plane szinkronizációhoz (a `.mcp.json`-ban is lehet)
|
||||
- `PAYLOAD_SECRET` — Payload CMS JWT/session aláíráshoz (MITHOME-86); környezetenként egyedi, erős érték
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { NextConfig } from "next";
|
||||
import { withPayload } from "@payloadcms/next/withPayload";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
// Enable standalone output for Docker deployment
|
||||
@@ -70,4 +71,8 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
// MITHOME-86: bundles the admin UI's route handlers correctly under
|
||||
// Turbopack/webpack. `@payload-config` itself resolves via the `paths`
|
||||
// alias in tsconfig.json (./src/payload.config.ts) — this wrapper's
|
||||
// installed version has no separate configPath option.
|
||||
export default withPayload(nextConfig);
|
||||
|
||||
Generated
+3714
-83
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -30,11 +30,17 @@
|
||||
"docker:run": "docker run -p 3000:3000 --env-file .env.local mozdit-app"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "^3.88.0",
|
||||
"@payloadcms/next": "^3.88.0",
|
||||
"@payloadcms/richtext-lexical": "^3.88.0",
|
||||
"graphql": "^16.14.2",
|
||||
"mongodb": "^6.5",
|
||||
"mongoose": "^8.2",
|
||||
"next": "^16.3.4",
|
||||
"payload": "^3.88.0",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
"react-dom": "19.1.0",
|
||||
"sharp": "^0.35.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Metadata } from 'next'
|
||||
import config from '@payload-config'
|
||||
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
import { importMap } from '../importMap'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{ segments: string[] }>
|
||||
searchParams: Promise<{ [key: string]: string | string[] }>
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const NotFound = ({ params, searchParams }: Args) =>
|
||||
NotFoundPage({ config, params, searchParams, importMap })
|
||||
|
||||
export default NotFound
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { Metadata } from 'next'
|
||||
import config from '@payload-config'
|
||||
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
import { importMap } from '../importMap'
|
||||
|
||||
type Args = {
|
||||
params: Promise<{ segments: string[] }>
|
||||
searchParams: Promise<{ [key: string]: string | string[] }>
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams, importMap })
|
||||
|
||||
export default Page
|
||||
@@ -0,0 +1,4 @@
|
||||
// Auto-generated by Payload (`npx payload generate:importmap`).
|
||||
// Kept empty until a collection/global config references a custom admin
|
||||
// component — regenerate with the CLI command whenever one does.
|
||||
export const importMap = {}
|
||||
@@ -0,0 +1,16 @@
|
||||
import config from '@payload-config'
|
||||
import {
|
||||
REST_DELETE,
|
||||
REST_GET,
|
||||
REST_OPTIONS,
|
||||
REST_PATCH,
|
||||
REST_POST,
|
||||
REST_PUT,
|
||||
} from '@payloadcms/next/routes'
|
||||
|
||||
export const GET = REST_GET(config)
|
||||
export const POST = REST_POST(config)
|
||||
export const DELETE = REST_DELETE(config)
|
||||
export const PATCH = REST_PATCH(config)
|
||||
export const PUT = REST_PUT(config)
|
||||
export const OPTIONS = REST_OPTIONS(config)
|
||||
@@ -0,0 +1,4 @@
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
|
||||
|
||||
export const GET = GRAPHQL_PLAYGROUND_GET(config)
|
||||
@@ -0,0 +1,4 @@
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_POST } from '@payloadcms/next/routes'
|
||||
|
||||
export const POST = GRAPHQL_POST(config)
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { ServerFunctionClient } from 'payload'
|
||||
import config from '@payload-config'
|
||||
import { handleServerFunctions, RootLayout } from '@payloadcms/next/layouts'
|
||||
import React from 'react'
|
||||
|
||||
import { importMap } from './admin/importMap'
|
||||
|
||||
import '@payloadcms/next/css'
|
||||
|
||||
type Args = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const serverFunction: ServerFunctionClient = async function (args) {
|
||||
'use server'
|
||||
return handleServerFunctions({
|
||||
...args,
|
||||
config,
|
||||
importMap,
|
||||
})
|
||||
}
|
||||
|
||||
const Layout = ({ children }: Args) => (
|
||||
<RootLayout config={config} importMap={importMap} serverFunction={serverFunction}>
|
||||
{children}
|
||||
</RootLayout>
|
||||
)
|
||||
|
||||
export default Layout
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
/**
|
||||
* Admin bejelentkezés (MITHOME-86 bootstrap). A teljes access control /
|
||||
* jelszó-politika finomítása MITHOME-90 feladata — itt csak a Payload
|
||||
* indulásához szükséges minimális auth collection.
|
||||
*/
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
fields: [],
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Payload CMS configuration (MITHOME-86 — alapinstalláció).
|
||||
*
|
||||
* WHY a saját MongoDB kapcsolatot használjuk: a projekt már MongoDB-t futtat
|
||||
* (proto/src/lib/mongodb.ts) — Payload a `mongooseAdapter`-en keresztül
|
||||
* ugyanabba az adatbázisba ír, nincs szükség külön DB-re/szerverre.
|
||||
*
|
||||
* Ez a fájl jelenleg csak a bootstrap-hez szükséges minimumot tartalmazza
|
||||
* (Users collection az admin bejelentkezéshez — Payload nem tud admin
|
||||
* felületet renderelni auth collection nélkül). A tényleges tartalom-
|
||||
* collectionök/globalok (Home, About, Services, Contact, Common, LegalPages,
|
||||
* Partners, Media) a MITHOME-87..90 ticketekben kerülnek be.
|
||||
*/
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { buildConfig } from 'payload'
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import sharp from 'sharp'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
// Admin felület — bejelentkezés az Users collection-nel (MITHOME-90-ben
|
||||
// finomodik: access control, jelszó-politika stb.)
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
|
||||
editor: lexicalEditor(),
|
||||
|
||||
collections: [Users],
|
||||
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
|
||||
db: mongooseAdapter({
|
||||
url: process.env.MONGODB_URI || '',
|
||||
}),
|
||||
|
||||
sharp,
|
||||
})
|
||||
@@ -25,6 +25,9 @@
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@payload-config": [
|
||||
"./src/payload.config.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user