Implement Sprint 1 stories: collections, RBAC, audit logging, load testing
Complete 6 Sprint 1 stories for Epic 1 web migration infrastructure. Portfolio Collection: - Add 7 fields: title, slug, url, image, description, websiteType, tags - Configure R2 storage and authenticated access control Categories Collection: - Add nameEn, order, textColor, backgroundColor fields - Add color picker UI configuration Posts Collection: - Add excerpt with 200 char limit and ogImage for social sharing - Add showInFooter checkbox and status select (draft/review/published) Role-Based Access Control: - Add role field to Users collection (admin/editor) - Create adminOnly and authenticated access functions - Apply access rules to Portfolio, Categories, Posts, Users collections Audit Logging System (NFR9): - Create Audit collection with timestamps for 90-day retention - Add auditLogger utility for login/logout/content change tracking - Add auditChange and auditGlobalChange hooks to all collections and globals - Add cleanupAuditLogs job with 90-day retention policy Load Testing Framework (NFR4): - Add k6 load testing with 3 scripts: public-browsing, admin-operations, api-performance - Configure targets: p95 < 500ms, error rate < 1%, 100 concurrent users - Add verification script and comprehensive documentation Other Changes: - Remove unused Form blocks - Add Header/Footer audit hooks - Regenerate Payload TypeScript types
This commit is contained in:
@@ -1,111 +0,0 @@
|
||||
import { RequiredDataFromCollectionSlug } from 'payload'
|
||||
|
||||
export const contactForm: RequiredDataFromCollectionSlug<'forms'> = {
|
||||
confirmationMessage: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'heading',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'The contact form has been submitted successfully.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
tag: 'h2',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
confirmationType: 'message',
|
||||
createdAt: '2023-01-12T21:47:41.374Z',
|
||||
emails: [
|
||||
{
|
||||
emailFrom: '"Payload" \u003Cdemo@payloadcms.com\u003E',
|
||||
emailTo: '{{email}}',
|
||||
message: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Your contact form submission was successfully received.',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
subject: "You've received a new message.",
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
name: 'full-name',
|
||||
blockName: 'full-name',
|
||||
blockType: 'text',
|
||||
label: 'Full Name',
|
||||
required: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
blockName: 'email',
|
||||
blockType: 'email',
|
||||
label: 'Email',
|
||||
required: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
blockName: 'phone',
|
||||
blockType: 'number',
|
||||
label: 'Phone',
|
||||
required: false,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
blockName: 'message',
|
||||
blockType: 'textarea',
|
||||
label: 'Message',
|
||||
required: true,
|
||||
width: 100,
|
||||
},
|
||||
],
|
||||
redirect: undefined,
|
||||
submitButtonLabel: 'Submit',
|
||||
title: 'Contact Form',
|
||||
updatedAt: '2023-01-12T21:47:41.374Z',
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { CollectionSlug, GlobalSlug, Payload, PayloadRequest, File } from 'payload'
|
||||
|
||||
import { contactForm as contactFormData } from './contact-form'
|
||||
import { contact as contactPageData } from './contact-page'
|
||||
import { home } from './home'
|
||||
import { image1 } from './image-1'
|
||||
@@ -15,8 +14,6 @@ const collections: CollectionSlug[] = [
|
||||
'media',
|
||||
'pages',
|
||||
'posts',
|
||||
'forms',
|
||||
'form-submissions',
|
||||
'search',
|
||||
]
|
||||
const globals: GlobalSlug[] = ['header', 'footer']
|
||||
@@ -257,14 +254,6 @@ export const seed = async ({
|
||||
},
|
||||
})
|
||||
|
||||
payload.logger.info(`— Seeding contact form...`)
|
||||
|
||||
const contactForm = await payload.create({
|
||||
collection: 'forms',
|
||||
depth: 0,
|
||||
data: contactFormData,
|
||||
})
|
||||
|
||||
payload.logger.info(`— Seeding pages...`)
|
||||
|
||||
const [_, contactPage] = await Promise.all([
|
||||
|
||||
Reference in New Issue
Block a user