mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:51:12 -05:00
Add server-side validation
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user