@nextblock-cms/db 0.2.27 → 0.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/supabase/config.toml +1 -1
- package/supabase/migrations/00000000000013_seed_data.sql +6 -1
- package/supabase/migrations/00000000000014_seed_homepage_blocks.sql +21 -8
- package/supabase/migrations/{20251112141000_seed_homepage_blocks.sql → 00000000000016_sandbox_setup.sql} +834 -653
- package/supabase/migrations/20250513194738_setup_roles_and_profiles.sql +0 -41
- package/supabase/migrations/20250513194910_auto_create_profile_trigger.sql +0 -48
- package/supabase/migrations/20250513194916_rls_for_profiles.sql +0 -85
- package/supabase/migrations/20250514125634_fix_recursive_rls_policies.sql +0 -51
- package/supabase/migrations/20250514143016_setup_languages_table.sql +0 -66
- package/supabase/migrations/20250514171549_create_pages_table.sql +0 -73
- package/supabase/migrations/20250514171550_create_posts_table.sql +0 -61
- package/supabase/migrations/20250514171552_create_media_table.sql +0 -45
- package/supabase/migrations/20250514171553_create_blocks_table.sql +0 -54
- package/supabase/migrations/20250514171615_create_navigation_table.sql +0 -56
- package/supabase/migrations/20250514171627_rls_policies_for_content_tables.sql +0 -70
- package/supabase/migrations/20250515194800_add_translation_group_id.sql +0 -39
- package/supabase/migrations/20250520171900_add_translation_group_to_nav_items.sql +0 -21
- package/supabase/migrations/20250521143933_seed_homepage_and_nav.sql +0 -52
- package/supabase/migrations/20250523145833_add_feature_image_to_posts.sql +0 -8
- package/supabase/migrations/20250523151737_add_rls_to_media_table.sql +0 -18
- package/supabase/migrations/20250526110400_add_image_dimensions_to_media.sql +0 -14
- package/supabase/migrations/20250526153321_optimize_rls_policies.sql +0 -188
- package/supabase/migrations/20250526172513_resolve_select_policy_overlaps.sql +0 -96
- package/supabase/migrations/20250526172853_resolve_remaining_rls_v5.sql +0 -107
- package/supabase/migrations/20250526173538_finalize_rls_cleanup_v7.sql +0 -110
- package/supabase/migrations/20250526174710_separate_write_policies_v8.sql +0 -147
- package/supabase/migrations/20250526175359_fix_languages_select_rls_v9.sql +0 -81
- package/supabase/migrations/20250526182940_fix_nav_read_policy_v10.sql +0 -27
- package/supabase/migrations/20250526183239_fix_posts_read_rls_v11.sql +0 -59
- package/supabase/migrations/20250526183746_fix_media_select_rls_v12.sql +0 -39
- package/supabase/migrations/20250526184205_consolidate_content_read_rls_v13.sql +0 -61
- package/supabase/migrations/20250526185854_optimize_indexes.sql +0 -47
- package/supabase/migrations/20250526190900_debug_blocks_rls.sql +0 -56
- package/supabase/migrations/20250526191217_consolidate_blocks_select_rls.sql +0 -79
- package/supabase/migrations/20250526192822_fix_handle_languages_update_search_path.sql +0 -32
- package/supabase/migrations/20250527150500_fix_blocks_rls_policy.sql +0 -54
- package/supabase/migrations/20250602150602_add_blur_data_url_to_media.sql +0 -4
- package/supabase/migrations/20250602150959_add_variants_to_media.sql +0 -4
- package/supabase/migrations/20250618124000_create_get_my_claim_function.sql +0 -5
- package/supabase/migrations/20250618124100_create_logos_table.sql +0 -29
- package/supabase/migrations/20250618130000_fix_linter_warnings.sql +0 -58
- package/supabase/migrations/20250618151500_revert_storage_rls.sql +0 -6
- package/supabase/migrations/20250619084800_reinstate_storage_rls.sql +0 -13
- package/supabase/migrations/20250619092430_widen_logo_insert_policy.sql +0 -6
- package/supabase/migrations/20250619093122_fix_get_my_claim_volatility.sql +0 -5
- package/supabase/migrations/20250619104249_consolidated_logo_rls_fix.sql +0 -56
- package/supabase/migrations/20250619110700_fix_logo_rls_again.sql +0 -59
- package/supabase/migrations/20250619113200_add_file_path_to_media.sql +0 -4
- package/supabase/migrations/20250619124100_fix_rls_performance_warnings.sql +0 -74
- package/supabase/migrations/20250619195500_create_site_settings_table.sql +0 -28
- package/supabase/migrations/20250619201500_add_anon_read_to_site_settings.sql +0 -7
- package/supabase/migrations/20250619202000_add_is_active_to_languages.sql +0 -5
- package/supabase/migrations/20250620085700_fix_site_settings_write_rls.sql +0 -27
- package/supabase/migrations/20250620095500_fix_profiles_read_rls.sql +0 -11
- package/supabase/migrations/20250620100000_use_security_definer_for_rls.sql +0 -39
- package/supabase/migrations/20250620130000_add_public_read_to_logos.sql +0 -4
- package/supabase/migrations/20250708091700_create_translations_table.sql +0 -55
- package/supabase/migrations/20250708093403_seed_translations_table.sql +0 -20
- package/supabase/migrations/20250708110600_fix_translations_rls_policies.sql +0 -11
- package/supabase/migrations/20250708112300_add_new_translations.sql +0 -9
- package/supabase/migrations/20250709120000_create_revisions_tables.sql +0 -109
- package/supabase/migrations/20251001113000_add_folder_to_media.sql +0 -14
- package/supabase/migrations/20251112113736_fix_search_path_functions.sql +0 -74
- package/supabase/migrations/20251112124444_fix_rls_performance.sql +0 -63
- package/supabase/migrations/20251112125935_fix_combined_policies.sql +0 -194
- package/supabase/migrations/20251112132146_fix_foreign_key_indexes.sql +0 -21
- package/supabase/migrations/20251112132525_cleanup_unused_indexes.sql +0 -10
- package/supabase/migrations/20251112132822_fix_final_indexes.sql +0 -14
- package/supabase/migrations/20251112140000_scaffold_foundational_content.sql +0 -108
- package/supabase/migrations/20251112142000_seed_how_it_works_post_blocks.sql +0 -100
- package/supabase/migrations/20251112143000_seed_additional_translations.sql +0 -102
- package/supabase/migrations/20251112145000_grant_public_schema_usage.sql +0 -6
- package/supabase/migrations/20251112145500_grant_select_on_public_tables.sql +0 -19
- package/supabase/migrations/20251117093000_add_admin_created_flag.sql +0 -21
- package/supabase/migrations/20251117103000_relax_profile_username_constraint.sql +0 -6
- package/supabase/migrations/20251117110000_relax_profiles_site_settings_rls_for_signup.sql +0 -20
- package/supabase/migrations/20251117112000_fix_handle_new_user_role_enum.sql +0 -45
- package/supabase/migrations/20251117113000_cleanup_rls_duplicates.sql +0 -20
- package/supabase/migrations/20251117200000_media_service_role_insert.sql +0 -14
- package/supabase/migrations/20251117201500_media_service_role_select.sql +0 -11
- package/supabase/migrations/20251117203000_media_admin_writer_select.sql +0 -11
- package/supabase/migrations/20251117204500_fix_media_permissions.sql +0 -43
- package/supabase/migrations/20251126100000_seed_site_logo.sql +0 -33
- package/supabase/migrations/20251126133000_fix_blocks_rls.sql +0 -49
- package/supabase/migrations/20251127110000_fix_blocks_visibility_for_missing_profiles.sql +0 -23
- package/supabase/migrations/20251127120000_fix_duplicate_rls_policies.sql +0 -36
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
-- supabase/migrations/YYYYMMDDHHMMSS_consolidate_blocks_select_rls.sql
|
|
2
|
-
-- (Replace YYYYMMDDHHMMSS with the actual timestamp of this migration file)
|
|
3
|
-
|
|
4
|
-
BEGIN;
|
|
5
|
-
|
|
6
|
-
-- Drop existing policies for 'public.blocks' that will be replaced or refined.
|
|
7
|
-
-- This includes the broad "FOR ALL" policy and the specific "USER" SELECT policy
|
|
8
|
-
-- created in the previous debug migration.
|
|
9
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_management_reinstated" ON public.blocks;
|
|
10
|
-
DROP POLICY IF EXISTS "blocks_auth_users_can_read_published_parents" ON public.blocks;
|
|
11
|
-
|
|
12
|
-
-- The "blocks_anon_can_read_published_content" policy can remain as it targets 'anon'
|
|
13
|
-
-- and does not conflict with 'authenticated' role policies for the linter's warning.
|
|
14
|
-
-- However, if you wish to have a completely clean slate before adding the consolidated one,
|
|
15
|
-
-- you can drop and re-add it. For this exercise, we'll assume it's fine and already specific.
|
|
16
|
-
-- If it was named "blocks_anon_can_read_published" from 20250526153321_optimize_rls_policies.sql:
|
|
17
|
-
-- DROP POLICY IF EXISTS "blocks_anon_can_read_published" ON public.blocks;
|
|
18
|
-
-- Or if it was "blocks_are_readable_if_parent_is_published" from 20250514171553_create_blocks_table.sql:
|
|
19
|
-
-- DROP POLICY IF EXISTS "blocks_are_readable_if_parent_is_published" ON public.blocks;
|
|
20
|
-
-- Re-creating the anon policy for clarity and to ensure it's exactly as needed:
|
|
21
|
-
DROP POLICY IF EXISTS "blocks_anon_can_read_published_content" ON public.blocks; -- From debug migration
|
|
22
|
-
DROP POLICY IF EXISTS "blocks_anon_can_read_published" ON public.blocks; -- From optimize_rls_policies
|
|
23
|
-
DROP POLICY IF EXISTS "blocks_are_readable_if_parent_is_published" ON public.blocks; -- From initial table creation
|
|
24
|
-
|
|
25
|
-
CREATE POLICY "blocks_anon_can_read_published_blocks" ON public.blocks
|
|
26
|
-
FOR SELECT
|
|
27
|
-
TO anon
|
|
28
|
-
USING (
|
|
29
|
-
(page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
|
|
30
|
-
(post_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.posts pt WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())))
|
|
31
|
-
);
|
|
32
|
-
COMMENT ON POLICY "blocks_anon_can_read_published_blocks" ON public.blocks IS 'Anonymous users can read blocks of published parent content.';
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
-- Create a single, comprehensive SELECT policy for ALL authenticated users on blocks
|
|
36
|
-
CREATE POLICY "blocks_authenticated_comprehensive_select" ON public.blocks
|
|
37
|
-
FOR SELECT
|
|
38
|
-
TO authenticated
|
|
39
|
-
USING (
|
|
40
|
-
(
|
|
41
|
-
-- Condition for ADMIN or WRITER: they can read ALL blocks
|
|
42
|
-
(SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')
|
|
43
|
-
) OR
|
|
44
|
-
(
|
|
45
|
-
-- Condition for USER: they can read blocks of published parents
|
|
46
|
-
((SELECT public.get_current_user_role()) = 'USER') AND
|
|
47
|
-
(
|
|
48
|
-
(page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
|
|
49
|
-
(post_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.posts pt WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())))
|
|
50
|
-
)
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
|
-
COMMENT ON POLICY "blocks_authenticated_comprehensive_select" ON public.blocks IS 'Comprehensive SELECT policy for authenticated users on the blocks table, differentiating access by role (ADMIN/WRITER see all, USER sees blocks of published parents).';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-- Re-add the specific management policies for INSERT, UPDATE, DELETE for ADMIN/WRITER.
|
|
57
|
-
-- These only have WITH CHECK (for INSERT/UPDATE) or USING (for DELETE/UPDATE) based on role.
|
|
58
|
-
-- These were the ones created in 20250526174710_separate_write_policies_v8.sql and are fine.
|
|
59
|
-
|
|
60
|
-
CREATE POLICY "blocks_admin_writer_can_insert" ON public.blocks
|
|
61
|
-
FOR INSERT
|
|
62
|
-
TO authenticated
|
|
63
|
-
WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
|
|
64
|
-
COMMENT ON POLICY "blocks_admin_writer_can_insert" ON public.blocks IS 'Admins/Writers can insert blocks.';
|
|
65
|
-
|
|
66
|
-
CREATE POLICY "blocks_admin_writer_can_update" ON public.blocks
|
|
67
|
-
FOR UPDATE
|
|
68
|
-
TO authenticated
|
|
69
|
-
USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')) -- Who can be targeted by an update
|
|
70
|
-
WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')); -- What rows can be created/modified by them
|
|
71
|
-
COMMENT ON POLICY "blocks_admin_writer_can_update" ON public.blocks IS 'Admins/Writers can update blocks.';
|
|
72
|
-
|
|
73
|
-
CREATE POLICY "blocks_admin_writer_can_delete" ON public.blocks
|
|
74
|
-
FOR DELETE
|
|
75
|
-
TO authenticated
|
|
76
|
-
USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
|
|
77
|
-
COMMENT ON POLICY "blocks_admin_writer_can_delete" ON public.blocks IS 'Admins/Writers can delete blocks.';
|
|
78
|
-
|
|
79
|
-
COMMIT;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
-- supabase/migrations/YYYYMMDDHHMMSS_fix_handle_languages_update_search_path.sql
|
|
2
|
-
-- (Replace YYYYMMDDHHMMSS with the actual timestamp of this migration file)
|
|
3
|
-
|
|
4
|
-
BEGIN;
|
|
5
|
-
|
|
6
|
-
-- Step 1: Drop the existing trigger that depends on the function.
|
|
7
|
-
DROP TRIGGER IF EXISTS on_languages_update ON public.languages;
|
|
8
|
-
|
|
9
|
-
-- Step 2: Now it's safe to drop and recreate the function.
|
|
10
|
-
DROP FUNCTION IF EXISTS public.handle_languages_update();
|
|
11
|
-
|
|
12
|
-
CREATE OR REPLACE FUNCTION public.handle_languages_update()
|
|
13
|
-
RETURNS TRIGGER
|
|
14
|
-
LANGUAGE plpgsql
|
|
15
|
-
SECURITY DEFINER -- Explicitly set security context
|
|
16
|
-
SET search_path = public -- Explicitly set search_path
|
|
17
|
-
AS $$
|
|
18
|
-
BEGIN
|
|
19
|
-
NEW.updated_at = now();
|
|
20
|
-
RETURN NEW;
|
|
21
|
-
END;
|
|
22
|
-
$$;
|
|
23
|
-
|
|
24
|
-
COMMENT ON FUNCTION public.handle_languages_update() IS 'Sets updated_at timestamp on language update. Includes explicit search_path and security definer.';
|
|
25
|
-
|
|
26
|
-
-- Step 3: Re-create the trigger to use the updated function.
|
|
27
|
-
CREATE TRIGGER on_languages_update
|
|
28
|
-
BEFORE UPDATE ON public.languages
|
|
29
|
-
FOR EACH ROW
|
|
30
|
-
EXECUTE PROCEDURE public.handle_languages_update();
|
|
31
|
-
|
|
32
|
-
COMMIT;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
-- Fix blocks RLS policy to resolve joined query issues
|
|
2
|
-
-- Replace public.get_current_user_role() with direct EXISTS queries
|
|
3
|
-
|
|
4
|
-
BEGIN;
|
|
5
|
-
|
|
6
|
-
-- Drop the existing comprehensive SELECT policy that uses the problematic function
|
|
7
|
-
DROP POLICY IF EXISTS "blocks_authenticated_comprehensive_select" ON public.blocks;
|
|
8
|
-
|
|
9
|
-
-- Drop the existing management policies that use the problematic function
|
|
10
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_insert" ON public.blocks;
|
|
11
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_update" ON public.blocks;
|
|
12
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_delete" ON public.blocks;
|
|
13
|
-
|
|
14
|
-
-- Create a new comprehensive SELECT policy using direct EXISTS queries
|
|
15
|
-
CREATE POLICY "blocks_authenticated_comprehensive_select" ON public.blocks
|
|
16
|
-
FOR SELECT
|
|
17
|
-
TO authenticated
|
|
18
|
-
USING (
|
|
19
|
-
(
|
|
20
|
-
-- Condition for ADMIN or WRITER: they can read ALL blocks
|
|
21
|
-
EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role IN ('ADMIN', 'WRITER'))
|
|
22
|
-
) OR
|
|
23
|
-
(
|
|
24
|
-
-- Condition for USER: they can read blocks of published parents
|
|
25
|
-
EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role = 'USER') AND
|
|
26
|
-
(
|
|
27
|
-
(page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
|
|
28
|
-
(post_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.posts pt WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())))
|
|
29
|
-
)
|
|
30
|
-
)
|
|
31
|
-
);
|
|
32
|
-
COMMENT ON POLICY "blocks_authenticated_comprehensive_select" ON public.blocks IS 'Comprehensive SELECT policy for authenticated users on the blocks table, differentiating access by role (ADMIN/WRITER see all, USER sees blocks of published parents). Uses direct EXISTS queries to avoid function call issues in joined queries.';
|
|
33
|
-
|
|
34
|
-
-- Re-create the management policies using direct EXISTS queries
|
|
35
|
-
CREATE POLICY "blocks_admin_writer_can_insert" ON public.blocks
|
|
36
|
-
FOR INSERT
|
|
37
|
-
TO authenticated
|
|
38
|
-
WITH CHECK (EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role IN ('ADMIN', 'WRITER')));
|
|
39
|
-
COMMENT ON POLICY "blocks_admin_writer_can_insert" ON public.blocks IS 'Admins/Writers can insert blocks.';
|
|
40
|
-
|
|
41
|
-
CREATE POLICY "blocks_admin_writer_can_update" ON public.blocks
|
|
42
|
-
FOR UPDATE
|
|
43
|
-
TO authenticated
|
|
44
|
-
USING (EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role IN ('ADMIN', 'WRITER'))) -- Who can be targeted by an update
|
|
45
|
-
WITH CHECK (EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role IN ('ADMIN', 'WRITER'))); -- What rows can be created/modified by them
|
|
46
|
-
COMMENT ON POLICY "blocks_admin_writer_can_update" ON public.blocks IS 'Admins/Writers can update blocks.';
|
|
47
|
-
|
|
48
|
-
CREATE POLICY "blocks_admin_writer_can_delete" ON public.blocks
|
|
49
|
-
FOR DELETE
|
|
50
|
-
TO authenticated
|
|
51
|
-
USING (EXISTS (SELECT 1 FROM public.profiles WHERE id = auth.uid() AND role IN ('ADMIN', 'WRITER')));
|
|
52
|
-
COMMENT ON POLICY "blocks_admin_writer_can_delete" ON public.blocks IS 'Admins/Writers can delete blocks.';
|
|
53
|
-
|
|
54
|
-
COMMIT;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
CREATE TABLE public.logos (
|
|
2
|
-
id uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
3
|
-
created_at timestamp with time zone NOT NULL DEFAULT now(),
|
|
4
|
-
name text NOT NULL,
|
|
5
|
-
media_id uuid,
|
|
6
|
-
CONSTRAINT logos_pkey PRIMARY KEY (id),
|
|
7
|
-
CONSTRAINT logos_media_id_fkey FOREIGN KEY (media_id) REFERENCES public.media(id) ON DELETE SET NULL
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
COMMENT ON TABLE public.logos IS 'Stores company and brand logos.';
|
|
11
|
-
COMMENT ON COLUMN public.logos.name IS 'The name of the brand or company for the logo.';
|
|
12
|
-
COMMENT ON COLUMN public.logos.media_id IS 'Foreign key to the media table for the logo image.';
|
|
13
|
-
|
|
14
|
-
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.logos TO authenticated;
|
|
15
|
-
|
|
16
|
-
ALTER TABLE public.logos ENABLE ROW LEVEL SECURITY;
|
|
17
|
-
|
|
18
|
-
CREATE POLICY "Allow read access for authenticated users on logos"
|
|
19
|
-
ON public.logos
|
|
20
|
-
FOR SELECT
|
|
21
|
-
TO authenticated
|
|
22
|
-
USING (true);
|
|
23
|
-
|
|
24
|
-
CREATE POLICY "Allow admin users to manage logos"
|
|
25
|
-
ON public.logos
|
|
26
|
-
FOR ALL
|
|
27
|
-
TO authenticated
|
|
28
|
-
USING (((SELECT get_my_claim('user_role'::text)) = '"admin"'::jsonb))
|
|
29
|
-
WITH CHECK (((SELECT get_my_claim('user_role'::text)) = '"admin"'::jsonb));
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
-- Fix multiple permissive policies on logos table
|
|
2
|
-
DROP POLICY IF EXISTS "Allow admin users to manage logos" ON public.logos;
|
|
3
|
-
DROP POLICY IF EXISTS "Allow read access for authenticated users on logos" ON public.logos;
|
|
4
|
-
|
|
5
|
-
CREATE POLICY "Allow read access for authenticated users on logos"
|
|
6
|
-
ON public.logos
|
|
7
|
-
FOR SELECT
|
|
8
|
-
TO authenticated
|
|
9
|
-
USING (true);
|
|
10
|
-
|
|
11
|
-
CREATE POLICY "Allow admin users to insert logos"
|
|
12
|
-
ON public.logos
|
|
13
|
-
FOR INSERT TO authenticated
|
|
14
|
-
WITH CHECK ((get_my_claim('user_role'::text) = '"admin"'::jsonb));
|
|
15
|
-
|
|
16
|
-
CREATE POLICY "Allow admin users to update logos"
|
|
17
|
-
ON public.logos
|
|
18
|
-
FOR UPDATE TO authenticated
|
|
19
|
-
USING ((get_my_claim('user_role'::text) = '"admin"'::jsonb))
|
|
20
|
-
WITH CHECK ((get_my_claim('user_role'::text) = '"admin"'::jsonb));
|
|
21
|
-
|
|
22
|
-
CREATE POLICY "Allow admin users to delete logos"
|
|
23
|
-
ON public.logos
|
|
24
|
-
FOR DELETE TO authenticated
|
|
25
|
-
USING ((get_my_claim('user_role'::text) = '"admin"'::jsonb));
|
|
26
|
-
|
|
27
|
-
-- Fix mutable search path for get_my_claim
|
|
28
|
-
CREATE OR REPLACE FUNCTION get_my_claim(claim TEXT)
|
|
29
|
-
RETURNS JSONB AS $$
|
|
30
|
-
SET search_path = '';
|
|
31
|
-
SELECT COALESCE(current_setting('request.jwt.claims', true)::JSONB ->> claim, NULL)::JSONB
|
|
32
|
-
$$ LANGUAGE SQL STABLE;
|
|
33
|
-
|
|
34
|
-
-- Optimize RLS policies on blocks table
|
|
35
|
-
DROP POLICY IF EXISTS "blocks_are_readable_if_parent_is_published" ON public.blocks;
|
|
36
|
-
DROP POLICY IF EXISTS "admins_and_writers_can_manage_blocks" ON public.blocks;
|
|
37
|
-
|
|
38
|
-
CREATE POLICY "blocks_are_readable_if_parent_is_published"
|
|
39
|
-
ON public.blocks FOR SELECT
|
|
40
|
-
TO anon, authenticated
|
|
41
|
-
USING (
|
|
42
|
-
(page_id IS NOT NULL AND EXISTS (
|
|
43
|
-
SELECT 1
|
|
44
|
-
FROM public.pages p
|
|
45
|
-
WHERE p.id = blocks.page_id AND p.status = 'published'
|
|
46
|
-
)) OR
|
|
47
|
-
(post_id IS NOT NULL AND EXISTS (
|
|
48
|
-
SELECT 1
|
|
49
|
-
FROM public.posts pt
|
|
50
|
-
WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())
|
|
51
|
-
))
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
CREATE POLICY "admins_and_writers_can_manage_blocks"
|
|
55
|
-
ON public.blocks FOR ALL
|
|
56
|
-
TO authenticated
|
|
57
|
-
USING ((SELECT get_my_claim('user_role'::text)) IN ('"admin"', '"writer"'))
|
|
58
|
-
WITH CHECK ((SELECT get_my_claim('user_role'::text)) IN ('"admin"', '"writer"'));
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
-- Reverts the RLS policies on storage.objects that caused the upload failure.
|
|
2
|
-
|
|
3
|
-
DROP POLICY IF EXISTS "allow_authenticated_uploads" ON storage.objects;
|
|
4
|
-
DROP POLICY IF EXISTS "allow_authenticated_select" ON storage.objects;
|
|
5
|
-
DROP POLICY IF EXISTS "allow_authenticated_updates" ON storage.objects;
|
|
6
|
-
DROP POLICY IF EXISTS "allow_authenticated_deletes" ON storage.objects;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- Re-enables RLS policies for storage.objects to allow authenticated uploads.
|
|
2
|
-
|
|
3
|
-
-- Adds a policy allowing authenticated users to upload files
|
|
4
|
-
CREATE POLICY "allow_authenticated_uploads" ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'public' AND owner = auth.uid());
|
|
5
|
-
|
|
6
|
-
-- Allow authenticated users to SELECT files
|
|
7
|
-
CREATE POLICY "allow_authenticated_select" ON storage.objects FOR SELECT TO authenticated USING (bucket_id = 'public');
|
|
8
|
-
|
|
9
|
-
-- Allow authenticated users to UPDATE their own files
|
|
10
|
-
CREATE POLICY "allow_authenticated_updates" ON storage.objects FOR UPDATE TO authenticated USING (bucket_id = 'public' AND owner = auth.uid());
|
|
11
|
-
|
|
12
|
-
-- Allow authenticated users to DELETE their own files
|
|
13
|
-
CREATE POLICY "allow_authenticated_deletes" ON storage.objects FOR DELETE TO authenticated USING (bucket_id = 'public' AND owner = auth.uid());
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
DROP POLICY IF EXISTS "Allow admins to manage logos" ON public.logos;
|
|
2
|
-
|
|
3
|
-
CREATE POLICY "Allow admin and writer users to insert logos"
|
|
4
|
-
ON public.logos
|
|
5
|
-
FOR INSERT TO authenticated
|
|
6
|
-
WITH CHECK ((get_my_claim('user_role'::text) IN ('"admin"'::jsonb, '"writer"'::jsonb)));
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
-- Step 1: Drop all dependent policies first.
|
|
2
|
-
DROP POLICY IF EXISTS "Allow admins to manage logos" ON public.logos;
|
|
3
|
-
DROP POLICY IF EXISTS "Allow users to insert logos" ON public.logos;
|
|
4
|
-
DROP POLICY IF EXISTS "Allow logo insert for writers and admins" ON public.logos;
|
|
5
|
-
DROP POLICY IF EXISTS "Allow logo update for admins" ON public.logos;
|
|
6
|
-
DROP POLICY IF EXISTS "Allow logo delete for admins" ON public.logos;
|
|
7
|
-
|
|
8
|
-
-- Step 2: Drop the old function to avoid return type conflicts.
|
|
9
|
-
-- Note: It's critical to drop policies before the function they depend on.
|
|
10
|
-
DROP FUNCTION IF EXISTS get_my_claim(text) CASCADE;
|
|
11
|
-
|
|
12
|
-
-- Step 3: Redefine the get_my_claim function to be more robust and return TEXT.
|
|
13
|
-
-- This avoids JSON casting errors and type mismatches in policies.
|
|
14
|
-
CREATE OR REPLACE FUNCTION get_my_claim(claim TEXT)
|
|
15
|
-
RETURNS TEXT AS $$
|
|
16
|
-
DECLARE
|
|
17
|
-
claims jsonb;
|
|
18
|
-
claim_value text;
|
|
19
|
-
BEGIN
|
|
20
|
-
-- Safely get claims, defaulting to NULL if not present or invalid JSON
|
|
21
|
-
BEGIN
|
|
22
|
-
claims := current_setting('request.jwt.claims', true)::jsonb;
|
|
23
|
-
EXCEPTION
|
|
24
|
-
WHEN invalid_text_representation THEN
|
|
25
|
-
claims := NULL;
|
|
26
|
-
END;
|
|
27
|
-
|
|
28
|
-
-- If claims are NULL, return NULL
|
|
29
|
-
IF claims IS NULL THEN
|
|
30
|
-
RETURN NULL;
|
|
31
|
-
END IF;
|
|
32
|
-
|
|
33
|
-
-- Safely extract the claim value as text, removing quotes
|
|
34
|
-
claim_value := claims ->> claim;
|
|
35
|
-
|
|
36
|
-
RETURN claim_value;
|
|
37
|
-
END;
|
|
38
|
-
$$ LANGUAGE plpgsql VOLATILE;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-- Create the new, correct policies using the updated function
|
|
42
|
-
CREATE POLICY "Allow logo insert for authenticated users"
|
|
43
|
-
ON public.logos
|
|
44
|
-
FOR INSERT
|
|
45
|
-
WITH CHECK (auth.role() = 'authenticated');
|
|
46
|
-
|
|
47
|
-
CREATE POLICY "Allow logo update for authenticated users"
|
|
48
|
-
ON public.logos
|
|
49
|
-
FOR UPDATE
|
|
50
|
-
USING (auth.role() = 'authenticated')
|
|
51
|
-
WITH CHECK (auth.role() = 'authenticated');
|
|
52
|
-
|
|
53
|
-
CREATE POLICY "Allow logo delete for authenticated users"
|
|
54
|
-
ON public.logos
|
|
55
|
-
FOR DELETE
|
|
56
|
-
USING (auth.role() = 'authenticated');
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
-- Step 1: Drop all dependent policies first.
|
|
2
|
-
DROP POLICY IF EXISTS "Allow admins to manage logos" ON public.logos;
|
|
3
|
-
DROP POLICY IF EXISTS "Allow users to insert logos" ON public.logos;
|
|
4
|
-
DROP POLICY IF EXISTS "Allow logo insert for writers and admins" ON public.logos;
|
|
5
|
-
DROP POLICY IF EXISTS "Allow logo update for admins" ON public.logos;
|
|
6
|
-
DROP POLICY IF EXISTS "Allow logo delete for admins" ON public.logos;
|
|
7
|
-
DROP POLICY IF EXISTS "Allow logo insert for authenticated users" ON public.logos;
|
|
8
|
-
DROP POLICY IF EXISTS "Allow logo update for authenticated users" ON public.logos;
|
|
9
|
-
DROP POLICY IF EXISTS "Allow logo delete for authenticated users" ON public.logos;
|
|
10
|
-
|
|
11
|
-
-- Step 2: Drop the old function to avoid return type conflicts.
|
|
12
|
-
-- Note: It's critical to drop policies before the function they depend on.
|
|
13
|
-
DROP FUNCTION IF EXISTS get_my_claim(text) CASCADE;
|
|
14
|
-
|
|
15
|
-
-- Step 3: Redefine the get_my_claim function to be more robust and return TEXT.
|
|
16
|
-
-- This avoids JSON casting errors and type mismatches in policies.
|
|
17
|
-
CREATE OR REPLACE FUNCTION get_my_claim(claim TEXT)
|
|
18
|
-
RETURNS TEXT AS $$
|
|
19
|
-
DECLARE
|
|
20
|
-
claims jsonb;
|
|
21
|
-
claim_value text;
|
|
22
|
-
BEGIN
|
|
23
|
-
-- Safely get claims, defaulting to NULL if not present or invalid JSON
|
|
24
|
-
BEGIN
|
|
25
|
-
claims := current_setting('request.jwt.claims', true)::jsonb;
|
|
26
|
-
EXCEPTION
|
|
27
|
-
WHEN invalid_text_representation THEN
|
|
28
|
-
claims := NULL;
|
|
29
|
-
END;
|
|
30
|
-
|
|
31
|
-
-- If claims are NULL, return NULL
|
|
32
|
-
IF claims IS NULL THEN
|
|
33
|
-
RETURN NULL;
|
|
34
|
-
END IF;
|
|
35
|
-
|
|
36
|
-
-- Safely extract the claim value as text, removing quotes
|
|
37
|
-
claim_value := claims ->> claim;
|
|
38
|
-
|
|
39
|
-
RETURN claim_value;
|
|
40
|
-
END;
|
|
41
|
-
$$ LANGUAGE plpgsql VOLATILE;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-- Create the new, correct policies using the updated function
|
|
45
|
-
CREATE POLICY "Allow logo insert for authenticated users"
|
|
46
|
-
ON public.logos
|
|
47
|
-
FOR INSERT
|
|
48
|
-
WITH CHECK (auth.role() = 'authenticated');
|
|
49
|
-
|
|
50
|
-
CREATE POLICY "Allow logo update for authenticated users"
|
|
51
|
-
ON public.logos
|
|
52
|
-
FOR UPDATE
|
|
53
|
-
USING (auth.role() = 'authenticated')
|
|
54
|
-
WITH CHECK (auth.role() = 'authenticated');
|
|
55
|
-
|
|
56
|
-
CREATE POLICY "Allow logo delete for authenticated users"
|
|
57
|
-
ON public.logos
|
|
58
|
-
FOR DELETE
|
|
59
|
-
USING (auth.role() = 'authenticated');
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
BEGIN;
|
|
2
|
-
|
|
3
|
-
-- Drop existing policies for 'public.logos'
|
|
4
|
-
DROP POLICY IF EXISTS "Allow logo insert for authenticated users" ON public.logos;
|
|
5
|
-
DROP POLICY IF EXISTS "Allow logo update for authenticated users" ON public.logos;
|
|
6
|
-
DROP POLICY IF EXISTS "Allow logo delete for authenticated users" ON public.logos;
|
|
7
|
-
|
|
8
|
-
-- Recreate policies for 'public.logos' with optimized auth calls
|
|
9
|
-
CREATE POLICY "Allow logo insert for authenticated users"
|
|
10
|
-
ON public.logos
|
|
11
|
-
FOR INSERT
|
|
12
|
-
WITH CHECK ((SELECT auth.role()) = 'authenticated');
|
|
13
|
-
|
|
14
|
-
CREATE POLICY "Allow logo update for authenticated users"
|
|
15
|
-
ON public.logos
|
|
16
|
-
FOR UPDATE
|
|
17
|
-
USING ((SELECT auth.role()) = 'authenticated')
|
|
18
|
-
WITH CHECK ((SELECT auth.role()) = 'authenticated');
|
|
19
|
-
|
|
20
|
-
CREATE POLICY "Allow logo delete for authenticated users"
|
|
21
|
-
ON public.logos
|
|
22
|
-
FOR DELETE
|
|
23
|
-
USING ((SELECT auth.role()) = 'authenticated');
|
|
24
|
-
|
|
25
|
-
-- Drop existing policies for 'public.blocks'
|
|
26
|
-
DROP POLICY IF EXISTS "blocks_authenticated_comprehensive_select" ON public.blocks;
|
|
27
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_insert" ON public.blocks;
|
|
28
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_update" ON public.blocks;
|
|
29
|
-
DROP POLICY IF EXISTS "blocks_admin_writer_can_delete" ON public.blocks;
|
|
30
|
-
DROP POLICY IF EXISTS "blocks_anon_can_read_published_blocks" ON public.blocks;
|
|
31
|
-
DROP POLICY IF EXISTS "blocks_are_readable_if_parent_is_published" ON public.blocks;
|
|
32
|
-
|
|
33
|
-
-- Create a new comprehensive SELECT policy for 'public.blocks'
|
|
34
|
-
CREATE POLICY "Allow read access to blocks" ON public.blocks
|
|
35
|
-
FOR SELECT USING (
|
|
36
|
-
(
|
|
37
|
-
-- Anonymous users can read blocks of published content
|
|
38
|
-
(SELECT auth.role()) = 'anon' AND
|
|
39
|
-
(
|
|
40
|
-
(page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
|
|
41
|
-
(post_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.posts pt WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())))
|
|
42
|
-
)
|
|
43
|
-
) OR (
|
|
44
|
-
-- Authenticated users have role-based access
|
|
45
|
-
(SELECT auth.role()) = 'authenticated' AND
|
|
46
|
-
(
|
|
47
|
-
(
|
|
48
|
-
-- ADMIN or WRITER can read all blocks
|
|
49
|
-
EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER'))
|
|
50
|
-
) OR
|
|
51
|
-
(
|
|
52
|
-
-- USER can read blocks of published parents
|
|
53
|
-
EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role = 'USER') AND
|
|
54
|
-
(
|
|
55
|
-
(page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
|
|
56
|
-
(post_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.posts pt WHERE pt.id = blocks.post_id AND pt.status = 'published' AND (pt.published_at IS NULL OR pt.published_at <= now())))
|
|
57
|
-
)
|
|
58
|
-
)
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
-- Re-create the management policies for 'public.blocks' with optimized auth calls
|
|
64
|
-
CREATE POLICY "Allow insert for admins and writers on blocks" ON public.blocks
|
|
65
|
-
FOR INSERT WITH CHECK (EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')));
|
|
66
|
-
|
|
67
|
-
CREATE POLICY "Allow update for admins and writers on blocks" ON public.blocks
|
|
68
|
-
FOR UPDATE USING (EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')))
|
|
69
|
-
WITH CHECK (EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')));
|
|
70
|
-
|
|
71
|
-
CREATE POLICY "Allow delete for admins and writers on blocks" ON public.blocks
|
|
72
|
-
FOR DELETE USING (EXISTS (SELECT 1 FROM public.profiles WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')));
|
|
73
|
-
|
|
74
|
-
COMMIT;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
-- supabase/migrations/20250619195500_create_site_settings_table.sql
|
|
2
|
-
|
|
3
|
-
CREATE TABLE public.site_settings (
|
|
4
|
-
key TEXT PRIMARY KEY,
|
|
5
|
-
value JSONB
|
|
6
|
-
);
|
|
7
|
-
|
|
8
|
-
-- Enable RLS
|
|
9
|
-
ALTER TABLE public.site_settings ENABLE ROW LEVEL SECURITY;
|
|
10
|
-
|
|
11
|
-
-- Allow admins to do everything
|
|
12
|
-
CREATE POLICY "Allow admins full access on site_settings"
|
|
13
|
-
ON public.site_settings
|
|
14
|
-
FOR ALL
|
|
15
|
-
TO authenticated
|
|
16
|
-
USING (get_my_claim('user_role') = '"admin"');
|
|
17
|
-
|
|
18
|
-
-- Allow authenticated users to read settings
|
|
19
|
-
CREATE POLICY "Allow authenticated users to read site_settings"
|
|
20
|
-
ON public.site_settings
|
|
21
|
-
FOR SELECT
|
|
22
|
-
TO authenticated
|
|
23
|
-
USING (true);
|
|
24
|
-
|
|
25
|
-
-- Seed initial copyright setting
|
|
26
|
-
INSERT INTO public.site_settings (key, value)
|
|
27
|
-
VALUES ('footer_copyright', '{"en": "© {year} Nextblock CMS. All rights reserved.", "fr": "© {year} Nextblock CMS. Tous droits réservés."}')
|
|
28
|
-
ON CONFLICT (key) DO NOTHING;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
-- Drop existing policies if they exist to avoid conflicts.
|
|
2
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to insert into site_settings" ON public.site_settings;
|
|
3
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to update site_settings" ON public.site_settings;
|
|
4
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to modify site_settings" ON public.site_settings;
|
|
5
|
-
|
|
6
|
-
-- This policy grants permission to insert into the site_settings table
|
|
7
|
-
-- to any authenticated user whose role in the profiles table is 'ADMIN' or 'WRITER'.
|
|
8
|
-
CREATE POLICY "Allow ADMIN and WRITER to insert into site_settings"
|
|
9
|
-
ON public.site_settings
|
|
10
|
-
FOR INSERT
|
|
11
|
-
TO authenticated
|
|
12
|
-
WITH CHECK (
|
|
13
|
-
(SELECT role FROM public.profiles WHERE id = auth.uid()) IN ('ADMIN', 'WRITER')
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- This policy grants permission to update the site_settings table
|
|
17
|
-
-- to any authenticated user whose role in the profiles table is 'ADMIN' or 'WRITER'.
|
|
18
|
-
CREATE POLICY "Allow ADMIN and WRITER to update site_settings"
|
|
19
|
-
ON public.site_settings
|
|
20
|
-
FOR UPDATE
|
|
21
|
-
TO authenticated
|
|
22
|
-
USING (
|
|
23
|
-
(SELECT role FROM public.profiles WHERE id = auth.uid()) IN ('ADMIN', 'WRITER')
|
|
24
|
-
)
|
|
25
|
-
WITH CHECK (
|
|
26
|
-
(SELECT role FROM public.profiles WHERE id = auth.uid()) IN ('ADMIN', 'WRITER')
|
|
27
|
-
);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
-- Drop the policy if it exists to ensure a clean state.
|
|
2
|
-
DROP POLICY IF EXISTS "Allow user to read their own profile" ON public.profiles;
|
|
3
|
-
|
|
4
|
-
-- This policy allows an authenticated user to read their own row from the profiles table.
|
|
5
|
-
-- This is necessary for other RLS policies (like the one on site_settings) to be able
|
|
6
|
-
-- to look up the user's role during policy evaluation.
|
|
7
|
-
CREATE POLICY "Allow user to read their own profile"
|
|
8
|
-
ON public.profiles
|
|
9
|
-
FOR SELECT
|
|
10
|
-
TO authenticated
|
|
11
|
-
USING (auth.uid() = id);
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
-- Drop all previous policies on site_settings to ensure a clean slate.
|
|
2
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to insert into site_settings" ON public.site_settings;
|
|
3
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to update site_settings" ON public.site_settings;
|
|
4
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to modify site_settings" ON public.site_settings;
|
|
5
|
-
|
|
6
|
-
-- Create a trusted, elevated-privilege function to get the current user's role.
|
|
7
|
-
-- SECURITY DEFINER makes it run with the permissions of the function owner, bypassing nested RLS.
|
|
8
|
-
CREATE OR REPLACE FUNCTION get_my_role()
|
|
9
|
-
RETURNS TEXT AS $$
|
|
10
|
-
DECLARE
|
|
11
|
-
user_role TEXT;
|
|
12
|
-
BEGIN
|
|
13
|
-
SELECT role INTO user_role FROM public.profiles WHERE id = auth.uid();
|
|
14
|
-
RETURN user_role;
|
|
15
|
-
END;
|
|
16
|
-
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
17
|
-
|
|
18
|
-
-- This policy grants permission to insert into the site_settings table
|
|
19
|
-
-- by using the trusted function to check the user's role.
|
|
20
|
-
CREATE POLICY "Allow insert based on user role"
|
|
21
|
-
ON public.site_settings
|
|
22
|
-
FOR INSERT
|
|
23
|
-
TO authenticated
|
|
24
|
-
WITH CHECK (
|
|
25
|
-
get_my_role() IN ('ADMIN', 'WRITER')
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
-- This policy grants permission to update the site_settings table
|
|
29
|
-
-- by using the trusted function to check the user's role.
|
|
30
|
-
CREATE POLICY "Allow update based on user role"
|
|
31
|
-
ON public.site_settings
|
|
32
|
-
FOR UPDATE
|
|
33
|
-
TO authenticated
|
|
34
|
-
USING (
|
|
35
|
-
get_my_role() IN ('ADMIN', 'WRITER')
|
|
36
|
-
)
|
|
37
|
-
WITH CHECK (
|
|
38
|
-
get_my_role() IN ('ADMIN', 'WRITER')
|
|
39
|
-
);
|