Add server-side validation

This commit is contained in:
gpt-engineer-app[bot]
2025-10-20 20:26:23 +00:00
parent a109e90ca6
commit 0f7bb7f928

View File

@@ -160,12 +160,25 @@ export function validateEntityDataStrict(
if (!data.cloudflare_image_id) {
result.blockingErrors.push('Image ID is required');
}
// Validate Cloudflare image ID format (standard UUID format)
if (data.cloudflare_image_id && !/^[a-zA-Z0-9-]{36}$/.test(data.cloudflare_image_id)) {
result.blockingErrors.push('Invalid Cloudflare image ID format');
}
if (!data.entity_type) {
result.blockingErrors.push('Entity type is required');
}
// Validate entity type is one of the allowed types
const validPhotoEntityTypes = ['park', 'ride', 'company', 'ride_model'];
if (data.entity_type && !validPhotoEntityTypes.includes(data.entity_type)) {
result.blockingErrors.push(`Invalid entity type. Must be one of: ${validPhotoEntityTypes.join(', ')}`);
}
if (!data.entity_id) {
result.blockingErrors.push('Entity ID is required');
}
// Validate entity_id is a valid UUID
if (data.entity_id && !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(data.entity_id)) {
result.blockingErrors.push('Entity ID must be a valid UUID');
}
if (data.caption && data.caption.length > 500) {
result.blockingErrors.push('Caption must be less than 500 characters');
}
@@ -218,12 +231,42 @@ export function validateEntityDataStrict(
if (!data.event_date) {
result.blockingErrors.push('Event date is required');
}
// Validate event date is not too far in the future (max 5 years)
if (data.event_date) {
const eventDate = new Date(data.event_date);
const maxFutureDate = new Date();
maxFutureDate.setFullYear(maxFutureDate.getFullYear() + 5);
if (eventDate > maxFutureDate) {
result.blockingErrors.push('Event date cannot be more than 5 years in the future');
}
// Also validate it's not absurdly old (before 1800)
const minDate = new Date('1800-01-01');
if (eventDate < minDate) {
result.blockingErrors.push('Event date cannot be before year 1800');
}
}
// For change events (name_change, location_change, status_change), require from/to values
const changeEventTypes = ['name_change', 'location_change', 'status_change', 'ownership_change'];
if (data.event_type && changeEventTypes.includes(data.event_type)) {
if (!data.from_value && !data.to_value) {
result.blockingErrors.push(`Change event (${data.event_type}) requires at least one of from_value or to_value`);
}
}
if (!data.entity_type) {
result.blockingErrors.push('Entity type is required');
}
// Validate entity type is one of the allowed types
const validTimelineEntityTypes = ['park', 'ride', 'company', 'ride_model'];
if (data.entity_type && !validTimelineEntityTypes.includes(data.entity_type)) {
result.blockingErrors.push(`Invalid entity type. Must be one of: ${validTimelineEntityTypes.join(', ')}`);
}
if (!data.entity_id) {
result.blockingErrors.push('Entity ID is required');
}
// Validate entity_id is a valid UUID
if (data.entity_id && !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(data.entity_id)) {
result.blockingErrors.push('Entity ID must be a valid UUID');
}
break;
}