Compare commits

..

4 Commits

Author SHA1 Message Date
gpt-engineer-app[bot]
1180ae2b3b Fix trigger function for content submissions 2025-11-04 01:24:46 +00:00
gpt-engineer-app[bot]
949b502ec0 Fix interval parameter format 2025-11-04 01:20:41 +00:00
gpt-engineer-app[bot]
26e5ca6dbe Fix RPC call transaction mode 2025-11-04 01:17:14 +00:00
gpt-engineer-app[bot]
dbe5ec2a07 Update function to bypass RLS 2025-11-04 01:12:12 +00:00
3 changed files with 165 additions and 6 deletions

View File

@@ -162,7 +162,7 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => {
const { data, error } = await supabase.rpc('extend_submission_lock', { const { data, error } = await supabase.rpc('extend_submission_lock', {
submission_id: submissionId, submission_id: submissionId,
moderator_id: user.id, moderator_id: user.id,
extension_duration: '15 minutes', extension_duration: 'PT15M', // ISO 8601 format: 15 minutes
}); });
if (error) throw error; if (error) throw error;
@@ -325,13 +325,34 @@ export const useModerationQueue = (config?: UseModerationQueueConfig) => {
const expiresAt = new Date(Date.now() + 15 * 60 * 1000); const expiresAt = new Date(Date.now() + 15 * 60 * 1000);
const { data, error } = await supabase.rpc('claim_specific_submission', { // Use direct fetch to force read-write transaction
p_submission_id: submissionId, const supabaseUrl = 'https://api.thrillwiki.com';
p_moderator_id: user.id, const supabaseKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4';
p_lock_duration: '15 minutes',
const { data: sessionData } = await supabase.auth.getSession();
const token = sessionData.session?.access_token;
const response = await fetch(`${supabaseUrl}/rest/v1/rpc/claim_specific_submission`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': supabaseKey,
'Authorization': `Bearer ${token}`,
'Prefer': 'tx=commit', // Force read-write transaction
},
body: JSON.stringify({
p_submission_id: submissionId,
p_moderator_id: user.id,
p_lock_duration: 'PT15M', // ISO 8601 format: 15 minutes
}),
}); });
if (error) throw error; if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to claim submission' }));
throw new Error(errorData.message || 'Failed to claim submission');
}
const data = await response.json();
if (!data) { if (!data) {
throw new Error('Submission is already claimed or no longer available'); throw new Error('Submission is already claimed or no longer available');

View File

@@ -0,0 +1,57 @@
-- Update claim_specific_submission function to bypass RLS
CREATE OR REPLACE FUNCTION public.claim_specific_submission(
p_submission_id UUID,
p_moderator_id UUID,
p_lock_duration INTERVAL DEFAULT '15 minutes'
) RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
rows_updated INTEGER;
BEGIN
-- Temporarily disable RLS for this transaction
SET LOCAL row_security = off;
-- Atomically update the submission if it's unclaimed or lock expired
UPDATE content_submissions
SET
assigned_to = p_moderator_id,
assigned_at = NOW(),
locked_until = NOW() + p_lock_duration,
first_reviewed_at = COALESCE(first_reviewed_at, NOW())
WHERE id = p_submission_id
AND (
assigned_to IS NULL
OR locked_until < NOW()
)
AND status = 'pending';
GET DIAGNOSTICS rows_updated = ROW_COUNT;
-- Re-enable RLS (will auto-reset at end of transaction anyway)
SET LOCAL row_security = on;
-- Log the action if successful
IF rows_updated > 0 THEN
BEGIN
PERFORM log_admin_action(
p_moderator_id,
(SELECT user_id FROM content_submissions WHERE id = p_submission_id),
'submission_claimed',
jsonb_build_object(
'submission_id', p_submission_id,
'claim_type', 'specific'
)
);
EXCEPTION WHEN OTHERS THEN
RAISE WARNING 'Failed to log submission claim audit: %', SQLERRM;
END;
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$$;

View File

@@ -0,0 +1,81 @@
-- Fix notify_moderators_on_new_submission trigger to work with relational data model
-- Removes references to non-existent NEW.content column
CREATE OR REPLACE FUNCTION public.notify_moderators_on_new_submission()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path TO 'public'
AS $function$
DECLARE
submitter_profile record;
base_url text;
edge_function_url text;
content_preview text;
has_photos boolean := false;
item_count integer := 0;
BEGIN
-- Get submitter's username or display name
SELECT username, display_name INTO submitter_profile
FROM public.profiles
WHERE user_id = NEW.user_id;
-- Build simple content preview based on submission type
content_preview := CASE NEW.submission_type
WHEN 'park' THEN 'New park submission'
WHEN 'ride' THEN 'New ride submission'
WHEN 'company' THEN 'New company submission'
WHEN 'ride_model' THEN 'New ride model submission'
WHEN 'photo' THEN 'New photo submission'
ELSE 'New submission'
END;
-- Check if this submission has photos
has_photos := EXISTS (
SELECT 1 FROM photo_submissions ps
WHERE ps.submission_id = NEW.id
);
-- Count submission items
SELECT COALESCE(COUNT(*), 0)::integer INTO item_count
FROM submission_items
WHERE submission_id = NEW.id;
-- Get base URL from settings
SELECT setting_value::text INTO base_url
FROM admin_settings
WHERE setting_key = 'supabase_api_url';
base_url := trim(both '"' from base_url);
IF base_url IS NULL THEN
base_url := 'https://api.thrillwiki.com';
END IF;
edge_function_url := base_url || '/functions/v1/notify-moderators-submission';
-- Call the edge function via pg_net
PERFORM public.pg_net.http_post(
edge_function_url,
jsonb_build_object(
'submission_id', NEW.id,
'submission_type', NEW.submission_type,
'submitter_name', COALESCE(submitter_profile.display_name, submitter_profile.username, 'Unknown'),
'action', 'create',
'content_preview', content_preview,
'submitted_at', NEW.created_at,
'has_photos', has_photos,
'item_count', item_count,
'is_escalated', false
)::text,
'application/json'
);
RETURN NEW;
EXCEPTION
WHEN OTHERS THEN
-- Log error but don't fail the submission
RAISE NOTICE 'Failed to notify moderators: %', SQLERRM;
RETURN NEW;
END;
$function$;