initial commit: rocket.new export of broadcastbeat
This commit is contained in:
156
supabase/migrations/20260322120000_user_badges.sql
Normal file
156
supabase/migrations/20260322120000_user_badges.sql
Normal file
@@ -0,0 +1,156 @@
|
||||
-- User Badges Migration for BroadcastBeat
|
||||
-- Adds earned badges (Contributor, Mentor, Expert, Moderator) based on reputation and activity
|
||||
|
||||
-- ============================================================
|
||||
-- 1. USER BADGES TABLE
|
||||
-- ============================================================
|
||||
CREATE TABLE IF NOT EXISTS public.user_badges (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE,
|
||||
badge_type TEXT NOT NULL CHECK (badge_type IN ('contributor', 'mentor', 'expert', 'moderator')),
|
||||
awarded_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
awarded_reason TEXT
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_badges_unique
|
||||
ON public.user_badges (user_id, badge_type);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_badges_user_id
|
||||
ON public.user_badges (user_id);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. FUNCTION: EVALUATE AND AWARD BADGES
|
||||
-- ============================================================
|
||||
CREATE OR REPLACE FUNCTION public.evaluate_user_badges(p_user_id UUID)
|
||||
RETURNS VOID
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_reputation INTEGER;
|
||||
v_thread_count INTEGER;
|
||||
v_reply_count INTEGER;
|
||||
v_upvotes_received INTEGER;
|
||||
v_is_moderator BOOLEAN := false;
|
||||
BEGIN
|
||||
-- Get reputation
|
||||
SELECT COALESCE(reputation, 0) INTO v_reputation
|
||||
FROM public.user_profiles WHERE id = p_user_id;
|
||||
|
||||
-- Get thread count
|
||||
SELECT COUNT(*) INTO v_thread_count
|
||||
FROM public.forum_threads WHERE author_id = p_user_id;
|
||||
|
||||
-- Get reply count
|
||||
SELECT COUNT(*) INTO v_reply_count
|
||||
FROM public.forum_replies WHERE author_id = p_user_id;
|
||||
|
||||
-- Get total upvotes received
|
||||
SELECT COALESCE(SUM(upvotes), 0) INTO v_upvotes_received
|
||||
FROM (
|
||||
SELECT upvotes FROM public.forum_threads WHERE author_id = p_user_id
|
||||
UNION ALL
|
||||
SELECT upvotes FROM public.forum_replies WHERE author_id = p_user_id
|
||||
) AS all_posts;
|
||||
|
||||
-- Check moderator role (if user_roles table exists)
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = 'public' AND table_name = 'user_roles'
|
||||
) THEN
|
||||
SELECT EXISTS(
|
||||
SELECT 1 FROM public.user_roles
|
||||
WHERE user_id = p_user_id AND role IN ('moderator', 'admin')
|
||||
) INTO v_is_moderator;
|
||||
END IF;
|
||||
|
||||
-- Award CONTRIBUTOR badge: reputation >= 100 OR (threads >= 5 AND replies >= 10)
|
||||
IF v_reputation >= 100 OR (v_thread_count >= 5 AND v_reply_count >= 10) THEN
|
||||
INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
|
||||
VALUES (p_user_id, 'contributor', 'Reached 100 reputation or posted 5+ threads and 10+ replies')
|
||||
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
||||
END IF;
|
||||
|
||||
-- Award MENTOR badge: reputation >= 300 OR upvotes_received >= 50
|
||||
IF v_reputation >= 300 OR v_upvotes_received >= 50 THEN
|
||||
INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
|
||||
VALUES (p_user_id, 'mentor', 'Reached 300 reputation or received 50+ upvotes')
|
||||
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
||||
END IF;
|
||||
|
||||
-- Award EXPERT badge: reputation >= 1000 OR (upvotes_received >= 200 AND thread_count >= 20)
|
||||
IF v_reputation >= 1000 OR (v_upvotes_received >= 200 AND v_thread_count >= 20) THEN
|
||||
INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
|
||||
VALUES (p_user_id, 'expert', 'Reached 1000 reputation or received 200+ upvotes with 20+ threads')
|
||||
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
||||
END IF;
|
||||
|
||||
-- Award MODERATOR badge: has moderator/admin role
|
||||
IF v_is_moderator THEN
|
||||
INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
|
||||
VALUES (p_user_id, 'moderator', 'Assigned moderator or admin role')
|
||||
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================
|
||||
-- 3. TRIGGER FUNCTION: AUTO-EVALUATE BADGES ON REPUTATION CHANGE
|
||||
-- ============================================================
|
||||
CREATE OR REPLACE FUNCTION public.trigger_evaluate_badges()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
BEGIN
|
||||
PERFORM public.evaluate_user_badges(NEW.id);
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- ============================================================
|
||||
-- 4. ENABLE RLS
|
||||
-- ============================================================
|
||||
ALTER TABLE public.user_badges ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- ============================================================
|
||||
-- 5. RLS POLICIES
|
||||
-- ============================================================
|
||||
DROP POLICY IF EXISTS "public_read_user_badges" ON public.user_badges;
|
||||
CREATE POLICY "public_read_user_badges"
|
||||
ON public.user_badges FOR SELECT TO public USING (true);
|
||||
|
||||
DROP POLICY IF EXISTS "service_role_manage_user_badges" ON public.user_badges;
|
||||
CREATE POLICY "service_role_manage_user_badges"
|
||||
ON public.user_badges FOR ALL TO service_role USING (true) WITH CHECK (true);
|
||||
|
||||
-- ============================================================
|
||||
-- 6. TRIGGER: EVALUATE BADGES WHEN REPUTATION CHANGES
|
||||
-- ============================================================
|
||||
DROP TRIGGER IF EXISTS on_reputation_change_evaluate_badges ON public.user_profiles;
|
||||
CREATE TRIGGER on_reputation_change_evaluate_badges
|
||||
AFTER UPDATE OF reputation ON public.user_profiles
|
||||
FOR EACH ROW
|
||||
WHEN (OLD.reputation IS DISTINCT FROM NEW.reputation)
|
||||
EXECUTE FUNCTION public.trigger_evaluate_badges();
|
||||
|
||||
-- ============================================================
|
||||
-- 7. BACKFILL BADGES FOR EXISTING USERS
|
||||
-- ============================================================
|
||||
DO $$
|
||||
DECLARE
|
||||
v_user_id UUID;
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.tables
|
||||
WHERE table_schema = 'public' AND table_name = 'user_profiles'
|
||||
) THEN
|
||||
FOR v_user_id IN SELECT id FROM public.user_profiles LOOP
|
||||
PERFORM public.evaluate_user_badges(v_user_id);
|
||||
END LOOP;
|
||||
RAISE NOTICE 'Badge backfill completed for all existing users.';
|
||||
END IF;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE NOTICE 'Badge backfill failed: %', SQLERRM;
|
||||
END $$;
|
||||
Reference in New Issue
Block a user