mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 14:31:12 -05:00
97 lines
2.8 KiB
TypeScript
97 lines
2.8 KiB
TypeScript
/**
|
|
* ⚠️ CRITICAL SECURITY PATTERN ⚠️
|
|
*
|
|
* These wrappers enforce the submission flow for all entity edits/creations.
|
|
* DO NOT bypass these - they ensure moderation queue → versioning → live display.
|
|
*
|
|
* Flow: User Submit → Moderation Queue → Approval → Versioning → Live
|
|
*
|
|
* @see docs/SUBMISSION_FLOW.md
|
|
*/
|
|
|
|
import {
|
|
submitParkCreation,
|
|
submitParkUpdate,
|
|
submitRideCreation,
|
|
submitRideUpdate,
|
|
ParkFormData,
|
|
RideFormData
|
|
} from './entitySubmissionHelpers';
|
|
import { logger } from './logger';
|
|
|
|
export type EntitySubmissionHandler<T> = (
|
|
data: T,
|
|
userId: string
|
|
) => Promise<{ submitted: boolean; submissionId: string }>;
|
|
|
|
/**
|
|
* Creates a type-safe submission handler for parks.
|
|
* Automatically routes to creation or update based on isEditing flag.
|
|
*
|
|
* @example
|
|
* const handleSubmit = enforceParkSubmissionFlow(true, park.id);
|
|
* await handleSubmit(formData, user.id);
|
|
*/
|
|
export function enforceParkSubmissionFlow(
|
|
isEditing: boolean,
|
|
existingId?: string
|
|
): EntitySubmissionHandler<ParkFormData> {
|
|
if (isEditing && !existingId) {
|
|
throw new Error('existingId is required when isEditing is true');
|
|
}
|
|
|
|
return async (data: ParkFormData, userId: string) => {
|
|
if (isEditing && existingId) {
|
|
return await submitParkUpdate(existingId, data, userId);
|
|
} else {
|
|
return await submitParkCreation(data, userId);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a type-safe submission handler for rides.
|
|
* Automatically routes to creation or update based on isEditing flag.
|
|
*
|
|
* @example
|
|
* const handleSubmit = enforceRideSubmissionFlow(true, ride.id);
|
|
* await handleSubmit(formData, user.id);
|
|
*/
|
|
export function enforceRideSubmissionFlow(
|
|
isEditing: boolean,
|
|
existingId?: string
|
|
): EntitySubmissionHandler<RideFormData> {
|
|
if (isEditing && !existingId) {
|
|
throw new Error('existingId is required when isEditing is true');
|
|
}
|
|
|
|
return async (data: RideFormData, userId: string) => {
|
|
if (isEditing && existingId) {
|
|
return await submitRideUpdate(existingId, data, userId);
|
|
} else {
|
|
return await submitRideCreation(data, userId);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Development-mode validation helper.
|
|
* Warns if a form's onSubmit handler doesn't use submission helpers.
|
|
*/
|
|
export function validateSubmissionHandler(
|
|
onSubmit: Function,
|
|
entityType: 'park' | 'ride'
|
|
): void {
|
|
if (process.env.NODE_ENV === 'development') {
|
|
const funcString = onSubmit.toString();
|
|
const expectedPattern = entityType === 'park' ? 'submitPark' : 'submitRide';
|
|
|
|
if (!funcString.includes(expectedPattern)) {
|
|
logger.warn(
|
|
`⚠️ ${entityType}Form: onSubmit should use ${expectedPattern}Creation/${expectedPattern}Update from entitySubmissionHelpers.\n` +
|
|
`Direct database writes bypass the moderation queue and versioning system.`
|
|
);
|
|
}
|
|
}
|
|
}
|