fix: resolve RLS infinite recursion in tastings and sessions

This commit is contained in:
2025-12-18 11:24:04 +01:00
parent e6974cd060
commit 5923dd0474
4 changed files with 24 additions and 18 deletions

View File

@@ -89,9 +89,9 @@ export default function Home() {
});
setBottles(processedBottles);
} catch (err) {
} catch (err: any) {
console.error('Detailed fetch error:', err);
setFetchError('Die Sammlung konnte nicht geladen werden. Bitte versuche es später erneut.');
setFetchError(err.message || JSON.stringify(err));
} finally {
setIsLoading(false);
}
@@ -153,12 +153,12 @@ export default function Home() {
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-amber-600"></div>
</div>
) : fetchError ? (
<div className="p-8 bg-red-50 dark:bg-red-900/10 border border-red-200 dark:border-red-900/30 rounded-3xl text-center">
<p className="text-red-600 dark:text-red-400 font-bold mb-2">Hoppla!</p>
<p className="text-red-500/80 text-sm italic">{fetchError}</p>
<div className="p-8 bg-zinc-100 dark:bg-zinc-900/50 border border-zinc-200 dark:border-zinc-800 rounded-3xl text-center">
<p className="text-zinc-800 dark:text-zinc-200 font-bold mb-2">Sammlung konnte nicht geladen werden</p>
<p className="text-zinc-500 text-sm italic mb-4">Möglicherweise müssen die Datenbank-Regeln aktualisiert werden.</p>
<button
onClick={fetchCollection}
className="mt-4 px-6 py-2 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-xl text-xs font-bold uppercase tracking-widest"
className="px-6 py-2 bg-amber-600 hover:bg-amber-700 text-white rounded-xl text-xs font-bold uppercase tracking-widest transition-all"
>
Erneut versuchen
</button>

View File

@@ -99,9 +99,16 @@ export default function SessionDetailPage() {
const handleAddParticipant = async (buddyId: string) => {
if (participants.some(p => p.buddy_id === buddyId)) return;
const { data: { user } } = await supabase.auth.getUser();
if (!user) return;
const { error } = await supabase
.from('session_participants')
.insert([{ session_id: id, buddy_id: buddyId }]);
.insert([{
session_id: id,
buddy_id: buddyId,
user_id: user.id
}]);
if (!error) {
fetchSessionData();

View File

@@ -41,7 +41,8 @@ export async function saveTasting(data: {
if (data.buddy_ids && data.buddy_ids.length > 0) {
const tags = data.buddy_ids.map(buddyId => ({
tasting_id: tasting.id,
buddy_id: buddyId
buddy_id: buddyId,
user_id: session.user.id
}));
const { error: tagError } = await supabase
.from('tasting_tags')

View File

@@ -64,10 +64,11 @@ CREATE TABLE IF NOT EXISTS tasting_sessions (
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
);
-- Session Participants junction
-- Session Participants junction (updated with user_id to avoid RLS recursion)
CREATE TABLE IF NOT EXISTS session_participants (
session_id UUID REFERENCES tasting_sessions(id) ON DELETE CASCADE NOT NULL,
buddy_id UUID REFERENCES buddies(id) ON DELETE CASCADE NOT NULL,
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL, -- The owner of the session
PRIMARY KEY (session_id, buddy_id)
);
@@ -85,10 +86,11 @@ CREATE TABLE IF NOT EXISTS tastings (
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
);
-- Tasting Tagging (to tag buddies in a tasting)
-- Tasting Tagging (updated with user_id to avoid RLS recursion)
CREATE TABLE IF NOT EXISTS tasting_tags (
tasting_id UUID REFERENCES tastings(id) ON DELETE CASCADE NOT NULL,
buddy_id UUID REFERENCES buddies(id) ON DELETE CASCADE NOT NULL,
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL, -- The owner of the tasting
PRIMARY KEY (tasting_id, buddy_id)
);
@@ -160,10 +162,8 @@ CREATE POLICY "Users can see sessions they participate in" ON tasting_sessions
-- Policies for Session Participants
ALTER TABLE session_participants ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage participants of their sessions" ON session_participants
FOR ALL USING (
session_id IN (SELECT id FROM tasting_sessions WHERE user_id = auth.uid())
);
CREATE POLICY "Users can manage their own session participants" ON session_participants
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Participants can see session membership" ON session_participants
FOR SELECT USING (
buddy_id IN (SELECT id FROM buddies WHERE buddy_profile_id = auth.uid())
@@ -171,10 +171,8 @@ CREATE POLICY "Participants can see session membership" ON session_participants
-- Policies for Tasting Tags
ALTER TABLE tasting_tags ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage tags on their tastings" ON tasting_tags
FOR ALL USING (
tasting_id IN (SELECT id FROM tastings WHERE user_id = auth.uid())
);
CREATE POLICY "Users can manage their own tasting tags" ON tasting_tags
FOR ALL USING (auth.uid() = user_id);
CREATE POLICY "Tagged users can see the tags" ON tasting_tags
FOR SELECT USING (
buddy_id IN (SELECT id FROM buddies WHERE buddy_profile_id = auth.uid())