Reputation: 2715
I'm trying to figure out how to incorporate RLS into a supabase app that uses clerk authentication.
I i make the RLS policy (public) and
alter policy "allow create"
on "public"."events"
to public
with check (
true
);
then i can post to supabase.
If i change public to authenticated, then I get an error saying:
Event Creation Error: { code: '42501', details: null, hint: null, message: 'new row violates row-level security policy for table "events"' }
I really want to make it true if authenticated and host_id = auth.uid().
If I try that I get the same error as posted above.
I have a users table (that holds a clerk_id and a user.id). I have an events table that holds a host_id. This is a uuid and is a foreign key to users.id.
I can see that the local host knows im authenticated and knows my user.id, because if I use the RLS policy that is true for public (the first alternative), then I can post an event and my server action (next/app router) correctly uses the user.id to make the host id.
'use server';
import { createSupabaseServerClient } from '../../lib/supabase/supabaseServerClient';
import { revalidatePath } from 'next/cache';
import { Database } from '../../lib/supabase/types/supabase';
async function getSupabaseUserId(clerkUserId: string) {
const supabase = await createSupabaseServerClient();
const { data, error } = await supabase
.from('users')
.select('id, clerk_id')
.eq('clerk_id', clerkUserId)
.single();
console.log('Debug Information:', {
clerkUserId,
supabaseUserId: data?.id,
clerkIdFromDatabase: data?.clerk_id
});
if (error) {
console.error('Error fetching Supabase user:', error);
return null;
}
return data?.id;
}
export async function createEvent(eventData: Omit<Database['public']['Tables']['events']['Insert'], 'host_id'>, clerkUserId: string) {
try {
const supabaseUserId = await getSupabaseUserId(clerkUserId);
if (!supabaseUserId) {
throw new Error('Supabase user not found');
}
console.log('Verification Details:', {
clerkUserId,
supabaseUserId,
eventDataWithHostId: {
...eventData,
host_id: supabaseUserId
}
});
const supabase = await createSupabaseServerClient();
const { data, error } = await supabase
.from('events')
.insert({ ...eventData, host_id: supabaseUserId })
.select()
.single();
if (error) throw error;
revalidatePath('/events');
return { success: true, event: data };
} catch (error) {
console.error('Event Creation Error:', error);
return {
success: false,
error: error instanceof Error ? error.message : JSON.stringify(error)
};
}
}
How can i make my RLS policy restricted to allowing inserts if host_id = auth.uid()?
Is the problem something to do with the point that the host_id has not been created at the time the RLS policy is checking to see if the server action is permitted? I mean that if the action is permitted and the event is created, then the host_id will be the currently authenticated user's user.id, but maybe supabse can't check that until the action has run?
That doesn't seem to make sense given I cant even set the RLS policy to be the second option above (changing default public to authenticated and still just using true).
Upvotes: 0
Views: 90