1bf32dd076ab420d3fba96cd197c796db196a519
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d2f960207e |
feat(cms): ContactSubmissions Payload collection (MITHOME-94)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Canceled after 0s
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Canceled after 0s
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Canceled after 0s
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Canceled after 0s
/api/contact used to write straight to a raw, Payload-external MongoDB
collection (contact_submissions, via proto/src/lib/mongodb.ts's
getCollection) — the client had no way to see incoming messages except
by reading the database directly. Rate limiting, length caps, email
validation, and spam-keyword filtering all stay on the route exactly
as before; only the persistence target changed.
New: src/collections/ContactSubmissions.ts (name, email, subject,
message, gdprConsent checkbox, status select defaulting to "new").
Deliberately no custom `access` block — Payload's default
(authenticated-only for every REST operation) is exactly right here:
the client reads submissions in the admin, nobody can read or write
them through the public REST API, and the route's own write uses the
Local API (payload.create), which runs with overrideAccess: true by
default and so isn't blocked by that same rule. No versions/drafts
(a submission is a fact, not editable content) and no field-level
length/format validation duplicated in the collection, matching the
ticket's explicit scope: those checks live on the route.
route.ts: replaced getCollection()/insertOne() with
getPayload({config}).create({ collection: 'contact-submissions', ... }).
Removed the now-unused getCollection() helper from lib/mongodb.ts
(checkMongoConnection/getDb stay, used by /api/health) and its test.
Test gotcha worth documenting: next/jest's SWC transform rewrites the
`@payload-config` tsconfig-path alias to a real relative specifier at
transform time, so `jest.mock('@payload-config', ...)` never actually
intercepts what route.ts requires — it silently falls through to the
real payload.config.ts (mongooseAdapter, live Mongo needed). Fixed by
mocking the resolved relative path instead
(`jest.mock('../../../payload.config', ...)`); documented inline in
route.unit.test.ts for whoever hits this next (MITHOME-96 will need
the same trick for other Payload-backed routes/collections).
Verified live end-to-end, not just the test suite: submitted the real
contact form on /hu/kapcsolat, got the success message, found the
submission in /admin/collections/contact-submissions with all fields
correct (including gdprConsent checked and status "Új"/New), then
deleted the test record. Zero console errors in a fresh tab. Gate:
tsc, lint, unit tests (50 passed — one fewer than before, the removed
getCollection test), production build all green.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
74e40329a0 |
feat(cms): admin quick-search across all content (MITHOME-120)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Canceled after 0s
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Canceled after 0s
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Canceled after 0s
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Canceled after 0s
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Canceled after 0s
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Canceled after 0s
Adds a search box to the top of every Payload admin page (admin.components.header) that searches by text across every field of every Global and Collection, in both locales — something Payload has no built-in equivalent for: collection list views only search their own title/slug fields, and Globals have no list view at all. Implementation is deliberately client-side and index-free rather than @payloadcms/plugin-search (a server-side search collection kept in sync via hooks): this project's entire content is 5 Globals + 2 small Collections, so a plugin-managed search index would be disproportionate maintenance for the actual data volume — the same reasoning already applied to the logo editor (MITHOME-118). On first use, the component fetches every Global/Collection doc in both locales via the existing REST API (same-origin, admin session cookie), recursively flattens every field to (path, value) pairs client-side, and filters by case-insensitive substring as the user types. Each result links straight to the right edit view (global or collection/id). New: src/components/admin/QuickSearch.tsx. Registered via payload.config.ts admin.components.header, which required a generate:importmap run — the useful gotcha this surfaced: Payload resolves component paths against admin.importMap.baseDir, which defaults to process.cwd() (the proto/ the CLI is run from), not dirname(payload.config.ts) — so the path needed to be './src/components/admin/QuickSearch#QuickSearch', not './components/admin/QuickSearch#QuickSearch'. Documented inline. Verified live in the browser (not just tsc/lint): search finds matches in both a Global (Home hero.cta.secondary.text / services description) and a Collection (Partners name/url), shows source + field path + locale + a snippet per result, clicking a result navigates to the correct edit view, and the search state persists across client-side admin navigation since the header component doesn't remount. Zero console errors in a fresh tab. Full gate green: tsc, lint, unit tests (51 passed), production build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
8407b45367 |
feat(cms): Users access control + lockout policy (MITHOME-90)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
Explicit, documented decisions instead of relying on implicit Payload
defaults:
- auth.maxLoginAttempts: 5, lockTime: 10 min — codifies the lockout
policy rather than leaving it as an unstated library default.
- auth.cookies: { secure: NODE_ENV === 'production', sameSite: 'Lax' }
— secure cookies once behind HTTPS (MITHOME-15), harmless over plain
HTTP in local dev.
- access.{create,read,update,delete,unlock}: explicit
requireAuthenticatedUser (== Payload's defaultAccess, Boolean(user)).
Investigated the known open advisory flagged in MITHOME-86
(GHSA-jg8r-5jh2-v2xj — any authenticated user can unlock any other
account) by reading Payload's unlock operation source: the gap only
matters when a less-privileged authenticated identity exists that
needs protecting from a more-privileged one. This project's single
"admin" role model (no role hierarchy — MITHOME-85 epic decision)
has no such identity, so the default is accepted as-is, with the
reasoning and a MITHOME-46 (central IDM/SSO) revisit trigger written
into the code comment rather than left implicit.
- Added an optional `name` field for a nicer admin identity than a
bare email (audit trail, header display).
Verified live: existing dev@mozdit.hu user unaffected (name column
shows "<No Name>", backward compatible). Reproduced the lockout for
real — 5 wrong POST /api/users/login attempts, 6th attempt with the
*correct* password still rejected ("locked due to too many failed
login attempts"), unlocked via Local API (overrideAccess), then the
correct password logged in successfully. build/lint/tsc/test (58
passed) all clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
6589289878 |
feat(cms): enable Payload localization — hu default + en (MITHOME-110)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
payload.config.ts: localization: { locales: ['hu','en'], defaultLocale:
'hu', fallback: true }. URL/routing side is separate (MITHOME-114).
Proved the mechanism on a real field rather than a throwaway one:
Common.buttons.* (contact/learnMore/webmail/sendMessage) marked
localized: true — these are genuinely translatable UI labels, so this
doubles as a first, correct slice of the full MITHOME-111 retrofit
instead of being disposable test scaffolding.
Gotcha discovered and documented in the migration script: marking an
existing field `localized: true` after data was already written non-
localized makes that value unreadable via `locale: defaultLocale` (the
storage shape changed) — the migration script must be re-run so it
gets rewritten under the localized shape. This will matter again for
the full MITHOME-111/112 retrofit.
Verified: Local API round-trip (set en, defaultLocale/hu re-seeded via
re-running the migration script) — hu reads "Kapcsolatfelvétel", en
reads "Contact". Real browser: admin UI locale switcher (hu/en) in the
top bar, fields show "— hu"/"— en" per-locale labels, switching
locale swaps the visible value correctly on the Common global editor.
build/lint/tsc/test (58 passed) all clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
776fa66bc8 |
feat(cms): Partners + Media collection MVP (MITHOME-89)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
Payload built-in upload collection (Media) + a Partners collection (name, url, logo -> Media relationship) mirroring home.json's partners.items. Scope decision (see Plane MITHOME-89/118): the old logo editor (crop/rotate/transparent-background — MITHOME-76/84) is entirely client-side canvas logic (scripts/cms-logo-client.js, 345 lines), not server-side processing. Porting that UX into the Payload admin is a real custom React field component, split into its own ticket (MITHOME-118) rather than bundled here. This ticket covers plain upload only. - src/collections/Media.ts, src/collections/Partners.ts, registered in payload.config.ts. - migrate-content-to-payload.ts: upsertPartner() uploads the existing processed logo file (filePath) into Media (idempotent — matched by `alt` == partner name) and upserts the Partner document (matched by `name`). - .gitignore: Payload's default local upload storage lands at proto/media/ (not proto/public/) — runtime data, not source, needs a persistent volume in staging/production (flagged for MITHOME-97). Also ignored the generated src/payload-types.ts. Verified: migration run twice against the real dev MongoDB produced exactly 1 Media doc + 1 Partner doc (no duplicates, confirmed via mongosh) with the correct file size (12289 bytes, matching the source PNG). Real browser: logged into /admin, Partners list shows the migrated entry, and the document editor renders the logo thumbnail (270x80, 12KB) correctly. build/lint/tsc/test (58 passed) all clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
17c6d63ae3 |
feat(cms): LegalPages collection + migration (MITHOME-88)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
Slug-based collection mirroring LegalPageContent (proto/src/content/ types.ts) for the two legal pages (adatvedelem, hasznalati-feltetelek). - src/collections/LegalPages.ts: slug (unique), title, lastUpdated, sections[] (id/title/content). `content` stays a plain textarea, not lexical richText — the current frontend (src/app/(frontend)/adatvedelem/page.tsx) renders it through a hand-rolled "•"/"**bold**" regex converter, not a real Markdown/ richText parser, matching the same bootstrap-scope call made for Contact.gdpr.label in MITHOME-87. - Registered in payload.config.ts. - migrate-content-to-payload.ts: added an idempotent upsertLegalPage helper (find-by-slug, then update or create — Collections don't have Globals' fixed-slug updateGlobal) and seeded both legal pages from their existing JSON. Verified: migration run twice against the real dev MongoDB produced exactly 2 documents (no duplicates) — confirmed via mongosh. Real browser: logged into /admin, Legal Pages list shows both entries with correct titles/slugs, opened the adatvedelem document and the slug/ title/body fields all show the migrated content correctly. build/lint/ tsc/test (58 passed) all clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
a3d7e9ce75 |
chore(cms): disable Payload's anonymous telemetry
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions
Payload sends anonymous usage telemetry to its own servers by default. The site is self-hosted specifically so the client's data never leaves our own infrastructure (see the legal/GDPR discussion in chat) — that reasoning extends to Payload's own runtime telemetry too, so opt out via telemetry: false in payload.config.ts. Verified: build and dev server produce no telemetry notice, and the admin dashboard's network requests (checked in a real browser) are all to localhost — no outbound telemetry calls. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
3132fcb8eb |
feat(cms): Home/About/Services/Contact/Common Globals + JSON migration (MITHOME-87)
Payload Global configs mirroring proto/src/content/types.ts:
- src/globals/{Home,About,Services,Contact,Common}.ts
- src/globals/fields/stringArray.ts — shared helper: Payload has no
native string[] field, so every plain string array from the old
content types (trustBullets, paragraphs, features, spec items, …)
becomes an array of one-field { value } objects.
- home.partners is intentionally NOT included — that becomes its own
Partners collection (logo -> Media upload) in MITHOME-89, to avoid
two disagreeing sources for the same data.
- contact.form.fields.gdpr.label stays a plain textarea (not lexical
richText): the JSON source is a hand-written HTML string with an
<a> tag; richText's node-tree serialization would need its own
migration/render logic, out of scope for this bootstrap pass.
scripts/migrate-content-to-payload.ts: one-shot, idempotent Local API
migration reading the existing JSON files and calling updateGlobal —
does not touch or delete the JSON files. Run via the new
`npm run migrate:content` script.
Registered the five Globals in payload.config.ts.
Also included here (belongs with the previous "resolve double-root-
layout conflict" commit but didn't actually get staged there —
verified only now by diffing HEAD against the working tree):
(frontend)/layout.tsx's relative imports corrected to ../../ instead
of ../ (one directory deeper than the original src/app/layout.tsx).
Verified:
- npm run build / lint, tsc --noEmit, npm test (58 passed) all clean
- npm run migrate:content against the real dev MongoDB container,
then read back via payload.findGlobal() — hero.title, trustBullets,
services.items[0].features, footer.address, faq.items.length all
match the JSON source
- Real browser: logged into /admin, opened the Home global editor —
Hero/Trust bullets group renders and shows the migrated Hungarian
content correctly (see screenshot shared in chat)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
1600d99c5d |
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> |