-- Migration 001: User profiles for admin flag and account suspension -- Run this in Supabase SQL editor CREATE TABLE IF NOT EXISTS user_profiles ( user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, is_admin BOOLEAN DEFAULT FALSE NOT NULL, suspended_at TIMESTAMPTZ, suspended_reason TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Enable RLS: users can only read their own profile; service role bypasses RLS ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY; CREATE POLICY "users_read_own_profile" ON user_profiles FOR SELECT USING (auth.uid() = user_id); -- Index for fast admin lookups CREATE INDEX IF NOT EXISTS idx_user_profiles_admin ON user_profiles(is_admin) WHERE is_admin = TRUE; -- Backfill existing users INSERT INTO user_profiles (user_id) SELECT id FROM auth.users ON CONFLICT (user_id) DO NOTHING; -- Trigger: auto-create profile row when a new user signs up CREATE OR REPLACE FUNCTION create_user_profile() RETURNS TRIGGER AS $$ BEGIN INSERT INTO user_profiles (user_id) VALUES (NEW.id) ON CONFLICT (user_id) DO NOTHING; RETURN NEW; END; $$ LANGUAGE plpgsql SECURITY DEFINER; DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users; CREATE TRIGGER on_auth_user_created AFTER INSERT ON auth.users FOR EACH ROW EXECUTE FUNCTION create_user_profile(); -- To grant admin to the first admin user (run separately after applying migration): -- UPDATE user_profiles SET is_admin = TRUE WHERE user_id = '';