WIP: lokalen Stand vor dem Aufräumen sichern

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
denshooter
2026-10-15 15:32:22 +02:00
parent 7e910ce23d
commit e4f99255bd
68 changed files with 3510 additions and 5343 deletions
@@ -0,0 +1,132 @@
-- nightly — Fix migration: align DB with iOS app + add missing features
-- Run after 001_schema.sql
-- ── 1. Fix mood enum: replace old values with iOS app values ─────────────────
-- Drop dependent objects first
DROP VIEW IF EXISTS public.feed_posts;
ALTER TABLE public.posts ALTER COLUMN mood TYPE text USING mood::text;
DROP TYPE IF EXISTS public.post_mood;
CREATE TYPE public.post_mood AS ENUM ('still', 'unruhig', 'schwer', 'geladen', 'zart', 'dunkel');
ALTER TABLE public.posts ALTER COLUMN mood TYPE public.post_mood USING mood::public.post_mood;
-- ── 2. Increase content length from 280 to 420 ───────────────────────────────
ALTER TABLE public.posts DROP CONSTRAINT posts_content_check;
ALTER TABLE public.posts ADD CONSTRAINT posts_content_check
CHECK (LENGTH(TRIM(content)) BETWEEN 1 AND 420);
-- ── 3. Add content warning columns to posts ─────────────────────────────────
ALTER TABLE public.posts ADD COLUMN IF NOT EXISTS has_content_warning BOOLEAN DEFAULT FALSE NOT NULL;
ALTER TABLE public.posts ADD COLUMN IF NOT EXISTS content_warning_type TEXT;
-- ── 4. Recreate feed_posts view with content_warning fields ──────────────────
CREATE OR REPLACE VIEW public.feed_posts AS
SELECT
p.id,
p.content,
p.mood,
p.is_anonymous,
p.created_at,
p.has_content_warning,
p.content_warning_type,
CASE WHEN p.is_anonymous THEN NULL ELSE p.user_id END AS author_id,
CASE WHEN p.is_anonymous THEN NULL ELSE pr.username END AS author_username,
CASE WHEN p.is_anonymous THEN NULL ELSE pr.display_name END AS author_display_name,
CASE WHEN p.is_anonymous THEN NULL ELSE pr.avatar_url END AS author_avatar_url,
COALESCE((
SELECT COUNT(*) FROM public.resonances r WHERE r.post_id = p.id
), 0)::int AS resonance_count
FROM public.posts p
JOIN public.profiles pr ON pr.id = p.user_id
WHERE p.deleted_at IS NULL
AND p.review_status IN ('ok', 'approved')
AND p.created_at > NOW() - INTERVAL '14 hours';
-- ── 5. Add get_streak RPC ────────────────────────────────────────────────────
CREATE OR REPLACE FUNCTION public.get_streak(p_user_id UUID)
RETURNS TABLE(streak INT) LANGUAGE plpgsql STABLE AS $$
DECLARE
v_streak INT := 0;
v_check_date DATE := CURRENT_DATE;
v_has_post BOOLEAN;
BEGIN
LOOP
SELECT EXISTS(
SELECT 1 FROM public.posts
WHERE user_id = p_user_id
AND deleted_at IS NULL
AND (created_at AT TIME ZONE 'Europe/Berlin')::DATE = v_check_date
) INTO v_has_post;
IF v_has_post THEN
v_streak := v_streak + 1;
v_check_date := v_check_date - 1;
ELSE
EXIT;
END IF;
END LOOP;
-- Check if user posted today; if not, streak is 0
IF v_streak = 0 THEN
RETURN NEXT;
ELSE
RETURN QUERY SELECT v_streak;
END IF;
END;
$$;
-- ── 6. Add get_resonance_count RPC ───────────────────────────────────────────
CREATE OR REPLACE FUNCTION public.get_resonance_count(p_user_id UUID)
RETURNS TABLE(count INT) LANGUAGE plpgsql STABLE AS $$
BEGIN
RETURN QUERY
SELECT COUNT(*)::int AS count
FROM public.resonances r
JOIN public.posts p ON p.id = r.post_id
WHERE p.user_id = p_user_id
AND p.deleted_at IS NULL;
END;
$$;
-- ── 7. Add public_profile view for other-user profile lookups ────────────────
CREATE OR REPLACE VIEW public.public_profile AS
SELECT
p.id,
p.username,
p.display_name,
p.bio,
p.avatar_url,
p.is_pro,
p.is_admin,
p.created_at,
(SELECT COUNT(*) FROM public.posts WHERE user_id = p.id AND deleted_at IS NULL)::int AS post_count,
(SELECT COUNT(*) FROM public.resonances r JOIN public.posts p2 ON p2.id = r.post_id WHERE p2.user_id = p.id AND p2.deleted_at IS NULL)::int AS resonance_count,
(SELECT COUNT(*) FROM public.follows WHERE following_id = p.id)::int AS follower_count,
(SELECT COUNT(*) FROM public.follows WHERE follower_id = p.id)::int AS following_count
FROM public.profiles p;
-- ── 8. Add profile view RLS (public_profile is a view, inherits from profiles) ─
-- Allow updates to profiles row
-- (already handled by existing policy, no change needed)
-- ── 9. Enable Realtime for posts table ────────────────────────────────────────
ALTER PUBLICATION supabase_realtime ADD TABLE public.posts;
-- ── 10. Fix RLS for posts: allow reading all non-deleted approved posts ───────
DROP POLICY IF EXISTS posts_select ON public.posts;
CREATE POLICY "posts_select" ON public.posts FOR SELECT
USING (
deleted_at IS NULL
AND review_status IN ('ok', 'approved')
);