feat: Dynamic credit initialization based on subscription plan

New trigger creates:
- Profile (username from metadata)
- Subscription (starter plan by default)
- Credits (from plan's monthly_credits, not hardcoded)

Includes RLS policies for self-insert fallback
This commit is contained in:
2025-12-26 23:11:58 +01:00
parent 37634c26c8
commit a3915bd610

View File

@@ -1,30 +1,72 @@
-- Fix for user registration trigger -- Dynamic Credit Initialization Migration
-- Run this in Supabase SQL Editor -- Run this in Supabase SQL Editor
-- Simplified trigger - only creates profile, no subscription insert -- Updated trigger: Creates profile, subscription, AND credits dynamically
-- (subscription is handled client-side after signup)
CREATE OR REPLACE FUNCTION public.handle_new_user() CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger AS $$ RETURNS trigger AS $$
DECLARE
starter_plan_id UUID;
plan_credits INTEGER;
BEGIN BEGIN
-- Create profile only -- Create profile
INSERT INTO public.profiles (id, username, avatar_url) INSERT INTO public.profiles (id, username, avatar_url)
VALUES ( VALUES (
new.id, new.id,
COALESCE(new.raw_user_meta_data->>'username', 'user_' || substr(new.id::text, 1, 8)), COALESCE(new.raw_user_meta_data->>'username', 'user_' || substr(new.id::text, 1, 8)),
new.raw_user_meta_data->>'avatar_url' new.raw_user_meta_data->>'avatar_url'
) )
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
RETURN new; -- Get starter plan ID and credits
SELECT id, monthly_credits INTO starter_plan_id, plan_credits
FROM subscription_plans
WHERE name = 'starter'
LIMIT 1;
-- Create subscription with starter plan
IF starter_plan_id IS NOT NULL THEN
INSERT INTO public.user_subscriptions (user_id, plan_id)
VALUES (new.id, starter_plan_id)
ON CONFLICT (user_id) DO NOTHING;
END IF;
-- Create user_credits with plan's monthly_credits
INSERT INTO public.user_credits (user_id, balance, total_purchased, total_used)
VALUES (new.id, COALESCE(plan_credits, 10), 0, 0)
ON CONFLICT (user_id) DO NOTHING;
RETURN new;
EXCEPTION WHEN OTHERS THEN EXCEPTION WHEN OTHERS THEN
-- Log but don't fail user creation -- Log but don't fail user creation
RAISE WARNING 'handle_new_user failed: %', SQLERRM; RAISE WARNING 'handle_new_user failed: %', SQLERRM;
RETURN new; RETURN new;
END; END;
$$ LANGUAGE plpgsql SECURITY DEFINER; $$ LANGUAGE plpgsql SECURITY DEFINER;
-- Allow users to insert their own subscription -- RLS Policy for user_subscriptions insert (for client-side fallback)
CREATE POLICY "user_subscriptions_insert_self" ON user_subscriptions DO $$
FOR INSERT WITH CHECK ( BEGIN
(SELECT auth.uid()) = user_id IF NOT EXISTS (
); SELECT 1 FROM pg_policies
WHERE schemaname = 'public'
AND tablename = 'user_subscriptions'
AND policyname = 'user_subscriptions_insert_self'
) THEN
CREATE POLICY "user_subscriptions_insert_self" ON user_subscriptions
FOR INSERT WITH CHECK ((SELECT auth.uid()) = user_id);
END IF;
END $$;
-- RLS Policy for user_credits insert (for lazy initialization fallback)
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_policies
WHERE schemaname = 'public'
AND tablename = 'user_credits'
AND policyname = 'user_credits_insert_self'
) THEN
CREATE POLICY "user_credits_insert_self" ON user_credits
FOR INSERT WITH CHECK ((SELECT auth.uid()) = user_id);
END IF;
END $$;