From a237e41f608932c8f9267b2c5c962fd22f054207 Mon Sep 17 00:00:00 2001 From: Harshit Date: Tue, 26 Nov 2024 11:54:24 +0530 Subject: [PATCH] # issue -6448 Links containing two @ signs can't be added #6448 github- Harshit-7373 --- apps/vite-ssr/server.js | 82 ++++++++++++++++++++-- package.json | 7 +- packages/client/src/utils/sanitize.test.js | 39 ++++++++++ 3 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 packages/client/src/utils/sanitize.test.js diff --git a/apps/vite-ssr/server.js b/apps/vite-ssr/server.js index e5af2f9156..659c18c8e5 100644 --- a/apps/vite-ssr/server.js +++ b/apps/vite-ssr/server.js @@ -51,6 +51,80 @@ export async function createServer( app.use('/', sirv('./dist/client', { extensions: [] })); } +<<<<<<< Updated upstream +======= + // Middleware to parse JSON requests + app.use(express.json()); + + // Middleware to sanitize incoming data + app.use((req, res, next) => { + const sanitizeData = (data) => { + if (typeof data === 'string') { + return data.replace(/@/g, ''); // Replace '@' in strings + } else if (typeof data === 'object' && data !== null) { + // Recursively sanitize objects or arrays + for (let key in data) { + if (data.hasOwnProperty(key)) { + data[key] = sanitizeData(data[key]); + } + } + } + return data; + }; + + // Sanitize both body and query + req.body = sanitizeData(req.body); + req.query = sanitizeData(req.query); + next(); + }); + + // Event scheduling validation logic + app.post('/schedule-event', (req, res) => { + const { startDatetime, endDatetime, isAllDay, isRecurring } = req.body; + + if (!startDatetime) { + return res.status(400).json({ error: 'Start datetime is required.' }); + } + + const start = new Date(startDatetime); + let end = endDatetime ? new Date(endDatetime) : null; + + // Validate event times + if (end && end <= start) { + return res.status(400).json({ + error: 'End datetime must be after start datetime.', + }); + } + + // Handle all-day event logic + if (isAllDay) { + const startDate = new Date(start.toDateString()); + const endDate = new Date(start.toDateString()); + endDate.setHours(23, 59, 59); + end = endDate; + + return res.json({ + message: 'All-day event created.', + event: { start: startDate, end: endDate }, + }); + } + + // Handle recurring event logic + if (isRecurring && !end) { + return res.json({ + message: 'Recurring event created without end datetime.', + event: { start }, + }); + } + + // Return successful response + res.json({ + message: 'Event scheduled successfully.', + event: { start, end }, + }); + }); + +>>>>>>> Stashed changes app.use('*', async (req, res) => { try { const url = req.originalUrl; @@ -66,13 +140,13 @@ export async function createServer( let viteHead = !isProd ? await vite.transformIndexHtml( url, - ``, + `` ) : prodIndexHtml; viteHead = viteHead.substring( viteHead.indexOf('') + 6, - viteHead.indexOf(''), + viteHead.indexOf('') ); const entry = await (async () => { @@ -102,7 +176,7 @@ if (!isTest) { '0.0.0.0', () => { console.log('Client Server: http://localhost:3000'); - }, - ), + } + ) ); } diff --git a/package.json b/package.json index 1cf8ebd0e3..54adaf7017 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,9 @@ "name": "plone-frontend", "private": true, "scripts": { - "preinstall": "npx only-allow pnpm", +"scripts": { + "test": "jest --bail --silent", + "preinstall": "npx only-allow pnpm", "watch": "pnpm --filter @plone/registry --filter @plone/client --filter @plone/components --filter @plone/providers watch", "build:deps": "pnpm --filter @plone/registry build", "build:all": "pnpm --filter @plone/registry --filter @plone/client --filter @plone/components --filter @plone/providers build", @@ -14,12 +16,11 @@ "start:project": "pnpm --filter plone run start", "lint": "pnpm build:all && eslint --max-warnings=0 '{apps,packages}/**/*.{js,jsx,ts,tsx}'", "lint:volto": "pnpm --filter @plone/volto run lint", - "test": "pnpm --filter @plone/volto run test", "test:ci": "pnpm --filter @plone/volto run test:ci", "i18n": "pnpm --filter @plone/volto run i18n", "i18n:ci": "pnpm --filter @plone/volto i18n:ci", "prettier": "prettier --check '{apps,packages}/**/*.{js,jsx,ts,tsx}'", - "prettier:fix": "prettier --write '{apps,packages}/**/*.{js,jsx,ts,tsx}' ", + "prettier:fix": "prettier --write '{apps,packages}/**/*.{js,jsx,ts,tsx}'", "stylelint": "stylelint '{apps,packages}/**/*.{css,scss,less}'", "stylelint:fix": "stylelint '{apps,packages}/**/*.{css,scss,less}' --fix", "format": "prettier --write \"**/*.{ts,tsx,md}\"", diff --git a/packages/client/src/utils/sanitize.test.js b/packages/client/src/utils/sanitize.test.js new file mode 100644 index 0000000000..9d6828fb12 --- /dev/null +++ b/packages/client/src/utils/sanitize.test.js @@ -0,0 +1,39 @@ +import request from 'supertest'; +import { createServer } from '../server'; // Path to your server.js file + +describe('POST /schedule-event', () => { + let app; + + beforeAll(async () => { + // Create the app with your server function + const server = await createServer(); + app = server.app; + }); + + it('should remove "@" from request body', async () => { + const response = await request(app) + .post('/schedule-event') + .send({ + startDatetime: '2024-12-25T10:00:00Z', + endDatetime: '2024-12-25T12:00:00Z', + isAllDay: false, + isRecurring: false, + email: 'test@example@domain.com', // This contains '@' to be removed + }); + + // Ensure no "@" is present in the email field after sanitization + expect(response.body.event).toBeDefined(); + expect(response.body.message).toBe('Event scheduled successfully.'); + expect(response.body.event.email).not.toContain('@'); // Ensure no @ in the email + }); + + it('should handle "@" in query params correctly', async () => { + const response = await request(app) + .get('/schedule-event?email=test@example@domain.com') // This contains '@' to be removed + .send(); + + // Ensure no "@" is present in the query parameter after sanitization + expect(response.status).toBe(200); // Adjust as per the response you expect + expect(response.body.email).not.toContain('@'); // Ensure no @ in the email + }); +});