Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

# issue -6448 #6503

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 78 additions & 4 deletions apps/vite-ssr/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -66,13 +140,13 @@ export async function createServer(
let viteHead = !isProd
? await vite.transformIndexHtml(
url,
`<html><head></head><body></body></html>`,
`<html><head></head><body></body></html>`
)
: prodIndexHtml;

viteHead = viteHead.substring(
viteHead.indexOf('<head>') + 6,
viteHead.indexOf('</head>'),
viteHead.indexOf('</head>')
);

const entry = await (async () => {
Expand Down Expand Up @@ -102,7 +176,7 @@ if (!isTest) {
'0.0.0.0',
() => {
console.log('Client Server: http://localhost:3000');
},
),
}
)
);
}
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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}\"",
Expand Down
39 changes: 39 additions & 0 deletions packages/client/src/utils/sanitize.test.js
Original file line number Diff line number Diff line change
@@ -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@[email protected]', // 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@[email protected]') // 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
});
});