File size: 1,405 Bytes
a4fb0f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-- Fix for Insecure Public Verification Policy
-- This migration replaces the broad 'is_completed = true' policy with a secure RPC-based lookup.

-- 1. Remove the insecure anon SELECT policy
DROP POLICY "Public verification of certificates" ON public.user_achievements;

-- 2. Implement secure RPC function for certificate verification
-- This function is SECURITY DEFINER to bypass RLS and perform the specific lookup.
CREATE OR REPLACE FUNCTION public.verify_certificate_token(token UUID, slug TEXT)
RETURNS TABLE (
    user_id UUID,
    user_display_name TEXT,
    achievement_display_name TEXT,
    completed_at TIMESTAMPTZ
)
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
    RETURN QUERY
    SELECT
        ua.user_id,
        p.display_name as user_display_name,
        ad.display_name as achievement_display_name,
        ua.completed_at
    FROM public.user_achievements ua
    JOIN public.achievement_definitions ad ON ua.achievement_id = ad.id
    LEFT JOIN public.profiles p ON ua.user_id = p.id
    WHERE ua.verification_token = token
      AND ad.slug = slug
      AND ua.is_completed = true;
END;
$$;

-- 3. Add restrictive RLS policy to prevent direct anon access
-- This ensures that anon users cannot list achievements via SELECT * FROM user_achievements.
CREATE POLICY "Anon has no direct access to user_achievements"
  ON public.user_achievements FOR SELECT
  TO anon
  USING (false);