mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 09:31:13 -05:00
Fix ride model submissions
Implement rate limiting, ban checks, retry logic, and breadcrumb tracking for ride model creation and update functions. Wrap existing ban checks and database operations in retry logic.
This commit is contained in:
@@ -1755,15 +1755,30 @@ export async function submitRideModelCreation(
|
|||||||
data: RideModelFormData,
|
data: RideModelFormData,
|
||||||
userId: string
|
userId: string
|
||||||
): Promise<{ submitted: boolean; submissionId: string }> {
|
): Promise<{ submitted: boolean; submissionId: string }> {
|
||||||
|
// Rate limiting check
|
||||||
|
checkRateLimitOrThrow(userId, 'ride_model_creation');
|
||||||
|
recordSubmissionAttempt(userId);
|
||||||
|
|
||||||
|
// Breadcrumb tracking
|
||||||
|
breadcrumb.userAction('Start ride model submission', 'submitRideModelCreation', { userId });
|
||||||
|
|
||||||
// Validate required fields client-side
|
// Validate required fields client-side
|
||||||
assertValid(validateRideModelCreateFields(data));
|
assertValid(validateRideModelCreateFields(data));
|
||||||
|
|
||||||
// Check if user is banned
|
// Ban check with retry logic
|
||||||
|
const { withRetry } = await import('./retryHelpers');
|
||||||
|
breadcrumb.apiCall('profiles', 'SELECT');
|
||||||
|
const profile = await withRetry(
|
||||||
|
async () => {
|
||||||
const { data: profile } = await supabase
|
const { data: profile } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('banned')
|
.select('banned')
|
||||||
.eq('user_id', userId)
|
.eq('user_id', userId)
|
||||||
.single();
|
.single();
|
||||||
|
return profile;
|
||||||
|
},
|
||||||
|
{ maxAttempts: 2 }
|
||||||
|
);
|
||||||
|
|
||||||
if (profile?.banned) {
|
if (profile?.banned) {
|
||||||
throw new Error('Account suspended. Contact support for assistance.');
|
throw new Error('Account suspended. Contact support for assistance.');
|
||||||
@@ -1786,6 +1801,10 @@ export async function submitRideModelCreation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Submit with retry logic
|
||||||
|
breadcrumb.apiCall('content_submissions', 'INSERT');
|
||||||
|
const result = await withRetry(
|
||||||
|
async () => {
|
||||||
// Create the main submission record
|
// Create the main submission record
|
||||||
const { data: submissionData, error: submissionError } = await supabase
|
const { data: submissionData, error: submissionError } = await supabase
|
||||||
.from('content_submissions')
|
.from('content_submissions')
|
||||||
@@ -1868,6 +1887,28 @@ export async function submitRideModelCreation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return { submitted: true, submissionId: submissionData.id };
|
return { submitted: true, submissionId: submissionData.id };
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxAttempts: 3,
|
||||||
|
onRetry: (attempt, error, delay) => {
|
||||||
|
logger.warn('Retrying ride model submission', { attempt, delay });
|
||||||
|
window.dispatchEvent(new CustomEvent('submission-retry', {
|
||||||
|
detail: { attempt, maxAttempts: 3, delay, type: 'ride_model' }
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
shouldRetry: (error) => {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
const message = error.message.toLowerCase();
|
||||||
|
if (message.includes('required')) return false;
|
||||||
|
if (message.includes('banned')) return false;
|
||||||
|
if (message.includes('slug')) return false;
|
||||||
|
}
|
||||||
|
return isRetryableError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1881,12 +1922,27 @@ export async function submitRideModelUpdate(
|
|||||||
data: RideModelFormData,
|
data: RideModelFormData,
|
||||||
userId: string
|
userId: string
|
||||||
): Promise<{ submitted: boolean; submissionId: string }> {
|
): Promise<{ submitted: boolean; submissionId: string }> {
|
||||||
// Check if user is banned
|
// Rate limiting check
|
||||||
|
checkRateLimitOrThrow(userId, 'ride_model_update');
|
||||||
|
recordSubmissionAttempt(userId);
|
||||||
|
|
||||||
|
// Breadcrumb tracking
|
||||||
|
breadcrumb.userAction('Start ride model update', 'submitRideModelUpdate', { userId, rideModelId });
|
||||||
|
|
||||||
|
// Ban check with retry logic
|
||||||
|
const { withRetry } = await import('./retryHelpers');
|
||||||
|
breadcrumb.apiCall('profiles', 'SELECT');
|
||||||
|
const profile = await withRetry(
|
||||||
|
async () => {
|
||||||
const { data: profile } = await supabase
|
const { data: profile } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.select('banned')
|
.select('banned')
|
||||||
.eq('user_id', userId)
|
.eq('user_id', userId)
|
||||||
.single();
|
.single();
|
||||||
|
return profile;
|
||||||
|
},
|
||||||
|
{ maxAttempts: 2 }
|
||||||
|
);
|
||||||
|
|
||||||
if (profile?.banned) {
|
if (profile?.banned) {
|
||||||
throw new Error('Account suspended. Contact support for assistance.');
|
throw new Error('Account suspended. Contact support for assistance.');
|
||||||
@@ -1909,6 +1965,10 @@ export async function submitRideModelUpdate(
|
|||||||
|
|
||||||
let processedImages = data.images;
|
let processedImages = data.images;
|
||||||
|
|
||||||
|
// Submit with retry logic
|
||||||
|
breadcrumb.apiCall('content_submissions', 'INSERT');
|
||||||
|
const result = await withRetry(
|
||||||
|
async () => {
|
||||||
// Create the main submission record
|
// Create the main submission record
|
||||||
const { data: submissionData, error: submissionError } = await supabase
|
const { data: submissionData, error: submissionError } = await supabase
|
||||||
.from('content_submissions')
|
.from('content_submissions')
|
||||||
@@ -1989,6 +2049,28 @@ export async function submitRideModelUpdate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return { submitted: true, submissionId: submissionData.id };
|
return { submitted: true, submissionId: submissionData.id };
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxAttempts: 3,
|
||||||
|
onRetry: (attempt, error, delay) => {
|
||||||
|
logger.warn('Retrying ride model update', { attempt, delay });
|
||||||
|
window.dispatchEvent(new CustomEvent('submission-retry', {
|
||||||
|
detail: { attempt, maxAttempts: 3, delay, type: 'ride_model_update' }
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
shouldRetry: (error) => {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
const message = error.message.toLowerCase();
|
||||||
|
if (message.includes('required')) return false;
|
||||||
|
if (message.includes('banned')) return false;
|
||||||
|
if (message.includes('slug')) return false;
|
||||||
|
}
|
||||||
|
return isRetryableError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user