@nextblock-cms/db 0.2.26 → 0.2.28

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.
Files changed (86) hide show
  1. package/package.json +1 -1
  2. package/supabase/config.toml +1 -1
  3. package/supabase/migrations/00000000000014_seed_homepage_blocks.sql +23 -10
  4. package/supabase/migrations/20250513194738_setup_roles_and_profiles.sql +0 -41
  5. package/supabase/migrations/20250513194910_auto_create_profile_trigger.sql +0 -48
  6. package/supabase/migrations/20250513194916_rls_for_profiles.sql +0 -85
  7. package/supabase/migrations/20250514125634_fix_recursive_rls_policies.sql +0 -51
  8. package/supabase/migrations/20250514143016_setup_languages_table.sql +0 -66
  9. package/supabase/migrations/20250514171549_create_pages_table.sql +0 -73
  10. package/supabase/migrations/20250514171550_create_posts_table.sql +0 -61
  11. package/supabase/migrations/20250514171552_create_media_table.sql +0 -45
  12. package/supabase/migrations/20250514171553_create_blocks_table.sql +0 -54
  13. package/supabase/migrations/20250514171615_create_navigation_table.sql +0 -56
  14. package/supabase/migrations/20250514171627_rls_policies_for_content_tables.sql +0 -70
  15. package/supabase/migrations/20250515194800_add_translation_group_id.sql +0 -39
  16. package/supabase/migrations/20250520171900_add_translation_group_to_nav_items.sql +0 -21
  17. package/supabase/migrations/20250521143933_seed_homepage_and_nav.sql +0 -52
  18. package/supabase/migrations/20250523145833_add_feature_image_to_posts.sql +0 -8
  19. package/supabase/migrations/20250523151737_add_rls_to_media_table.sql +0 -18
  20. package/supabase/migrations/20250526110400_add_image_dimensions_to_media.sql +0 -14
  21. package/supabase/migrations/20250526153321_optimize_rls_policies.sql +0 -188
  22. package/supabase/migrations/20250526172513_resolve_select_policy_overlaps.sql +0 -96
  23. package/supabase/migrations/20250526172853_resolve_remaining_rls_v5.sql +0 -107
  24. package/supabase/migrations/20250526173538_finalize_rls_cleanup_v7.sql +0 -110
  25. package/supabase/migrations/20250526174710_separate_write_policies_v8.sql +0 -147
  26. package/supabase/migrations/20250526175359_fix_languages_select_rls_v9.sql +0 -81
  27. package/supabase/migrations/20250526182940_fix_nav_read_policy_v10.sql +0 -27
  28. package/supabase/migrations/20250526183239_fix_posts_read_rls_v11.sql +0 -59
  29. package/supabase/migrations/20250526183746_fix_media_select_rls_v12.sql +0 -39
  30. package/supabase/migrations/20250526184205_consolidate_content_read_rls_v13.sql +0 -61
  31. package/supabase/migrations/20250526185854_optimize_indexes.sql +0 -47
  32. package/supabase/migrations/20250526190900_debug_blocks_rls.sql +0 -56
  33. package/supabase/migrations/20250526191217_consolidate_blocks_select_rls.sql +0 -79
  34. package/supabase/migrations/20250526192822_fix_handle_languages_update_search_path.sql +0 -32
  35. package/supabase/migrations/20250527150500_fix_blocks_rls_policy.sql +0 -54
  36. package/supabase/migrations/20250602150602_add_blur_data_url_to_media.sql +0 -4
  37. package/supabase/migrations/20250602150959_add_variants_to_media.sql +0 -4
  38. package/supabase/migrations/20250618124000_create_get_my_claim_function.sql +0 -5
  39. package/supabase/migrations/20250618124100_create_logos_table.sql +0 -29
  40. package/supabase/migrations/20250618130000_fix_linter_warnings.sql +0 -58
  41. package/supabase/migrations/20250618151500_revert_storage_rls.sql +0 -6
  42. package/supabase/migrations/20250619084800_reinstate_storage_rls.sql +0 -13
  43. package/supabase/migrations/20250619092430_widen_logo_insert_policy.sql +0 -6
  44. package/supabase/migrations/20250619093122_fix_get_my_claim_volatility.sql +0 -5
  45. package/supabase/migrations/20250619104249_consolidated_logo_rls_fix.sql +0 -56
  46. package/supabase/migrations/20250619110700_fix_logo_rls_again.sql +0 -59
  47. package/supabase/migrations/20250619113200_add_file_path_to_media.sql +0 -4
  48. package/supabase/migrations/20250619124100_fix_rls_performance_warnings.sql +0 -74
  49. package/supabase/migrations/20250619195500_create_site_settings_table.sql +0 -28
  50. package/supabase/migrations/20250619201500_add_anon_read_to_site_settings.sql +0 -7
  51. package/supabase/migrations/20250619202000_add_is_active_to_languages.sql +0 -5
  52. package/supabase/migrations/20250620085700_fix_site_settings_write_rls.sql +0 -27
  53. package/supabase/migrations/20250620095500_fix_profiles_read_rls.sql +0 -11
  54. package/supabase/migrations/20250620100000_use_security_definer_for_rls.sql +0 -39
  55. package/supabase/migrations/20250620130000_add_public_read_to_logos.sql +0 -4
  56. package/supabase/migrations/20250708091700_create_translations_table.sql +0 -55
  57. package/supabase/migrations/20250708093403_seed_translations_table.sql +0 -20
  58. package/supabase/migrations/20250708110600_fix_translations_rls_policies.sql +0 -11
  59. package/supabase/migrations/20250708112300_add_new_translations.sql +0 -9
  60. package/supabase/migrations/20250709120000_create_revisions_tables.sql +0 -109
  61. package/supabase/migrations/20251001113000_add_folder_to_media.sql +0 -14
  62. package/supabase/migrations/20251112113736_fix_search_path_functions.sql +0 -74
  63. package/supabase/migrations/20251112124444_fix_rls_performance.sql +0 -63
  64. package/supabase/migrations/20251112125935_fix_combined_policies.sql +0 -194
  65. package/supabase/migrations/20251112132146_fix_foreign_key_indexes.sql +0 -21
  66. package/supabase/migrations/20251112132525_cleanup_unused_indexes.sql +0 -10
  67. package/supabase/migrations/20251112132822_fix_final_indexes.sql +0 -14
  68. package/supabase/migrations/20251112140000_scaffold_foundational_content.sql +0 -108
  69. package/supabase/migrations/20251112141000_seed_homepage_blocks.sql +0 -653
  70. package/supabase/migrations/20251112142000_seed_how_it_works_post_blocks.sql +0 -100
  71. package/supabase/migrations/20251112143000_seed_additional_translations.sql +0 -102
  72. package/supabase/migrations/20251112145000_grant_public_schema_usage.sql +0 -6
  73. package/supabase/migrations/20251112145500_grant_select_on_public_tables.sql +0 -19
  74. package/supabase/migrations/20251117093000_add_admin_created_flag.sql +0 -21
  75. package/supabase/migrations/20251117103000_relax_profile_username_constraint.sql +0 -6
  76. package/supabase/migrations/20251117110000_relax_profiles_site_settings_rls_for_signup.sql +0 -20
  77. package/supabase/migrations/20251117112000_fix_handle_new_user_role_enum.sql +0 -45
  78. package/supabase/migrations/20251117113000_cleanup_rls_duplicates.sql +0 -20
  79. package/supabase/migrations/20251117200000_media_service_role_insert.sql +0 -14
  80. package/supabase/migrations/20251117201500_media_service_role_select.sql +0 -11
  81. package/supabase/migrations/20251117203000_media_admin_writer_select.sql +0 -11
  82. package/supabase/migrations/20251117204500_fix_media_permissions.sql +0 -43
  83. package/supabase/migrations/20251126100000_seed_site_logo.sql +0 -33
  84. package/supabase/migrations/20251126133000_fix_blocks_rls.sql +0 -49
  85. package/supabase/migrations/20251127110000_fix_blocks_visibility_for_missing_profiles.sql +0 -23
  86. package/supabase/migrations/20251127120000_fix_duplicate_rls_policies.sql +0 -36
@@ -1,56 +0,0 @@
1
- -- lowercase sql
2
-
3
- do $$
4
- begin
5
- if not exists (select 1 from pg_type where typname = 'menu_location') then
6
- create type public.menu_location as enum ('HEADER', 'FOOTER', 'SIDEBAR');
7
- end if;
8
- end
9
- $$;
10
-
11
- create table public.navigation_items (
12
- id bigint generated by default as identity primary key,
13
- language_id bigint not null references public.languages(id) on delete cascade,
14
- menu_key public.menu_location not null,
15
- label text not null,
16
- url text not null,
17
- parent_id bigint references public.navigation_items(id) on delete cascade,
18
- "order" integer not null default 0,
19
- page_id bigint references public.pages(id) on delete set null,
20
- created_at timestamp with time zone not null default now(),
21
- updated_at timestamp with time zone not null default now()
22
- );
23
-
24
- comment on table public.navigation_items is 'stores navigation menu items.';
25
- comment on column public.navigation_items.menu_key is 'identifies the menu this item belongs to.';
26
-
27
- create index idx_navigation_items_menu_lang_order on public.navigation_items (menu_key, language_id, "order");
28
-
29
- alter table public.navigation_items enable row level security;
30
-
31
- create policy "navigation_is_publicly_readable"
32
- on public.navigation_items for select
33
- to anon, authenticated
34
- using (true);
35
-
36
- create policy "admins_can_manage_navigation"
37
- on public.navigation_items for all
38
- to authenticated
39
- using (public.get_current_user_role() = 'ADMIN')
40
- with check (public.get_current_user_role() = 'ADMIN');
41
-
42
- create or replace function public.handle_navigation_items_update()
43
- returns trigger
44
- language plpgsql
45
- security definer set search_path = public
46
- as $$
47
- begin
48
- new.updated_at = now();
49
- return new;
50
- end;
51
- $$;
52
-
53
- create trigger on_navigation_items_update
54
- before update on public.navigation_items
55
- for each row
56
- execute procedure public.handle_navigation_items_update();
@@ -1,70 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_rls_policies_for_content_tables.sql
2
- -- lowercase sql
3
-
4
- begin;
5
-
6
- --
7
- -- Pages Table RLS
8
- --
9
- alter table public.pages enable row level security;
10
-
11
- drop policy if exists "authors_writers_admins_can_read_own_or_all_drafts" on public.pages;
12
- -- allow authenticated users (authors, writers, admins) to read their own or all non-published pages
13
- create policy "authors_writers_admins_can_read_own_or_all_drafts"
14
- on public.pages for select
15
- to authenticated
16
- using (
17
- (status <> 'published' and author_id = auth.uid()) or -- author can read their own non-published
18
- (status <> 'published' and public.get_current_user_role() in ('ADMIN', 'WRITER')) -- admins/writers can read all non-published
19
- );
20
-
21
- --
22
- -- Posts Table RLS
23
- --
24
- alter table public.posts enable row level security;
25
-
26
- drop policy if exists "authors_writers_admins_can_read_own_or_all_draft_posts" on public.posts;
27
- -- allow authenticated users (authors, writers, admins) to read their own or all non-published posts
28
- create policy "authors_writers_admins_can_read_own_or_all_draft_posts"
29
- on public.posts for select
30
- to authenticated
31
- using (
32
- (status <> 'published' and author_id = auth.uid()) or
33
- (status <> 'published'and public.get_current_user_role() in ('ADMIN', 'WRITER'))
34
- );
35
-
36
- --
37
- -- Media Table RLS
38
- --
39
- alter table public.media enable row level security;
40
-
41
-
42
- --
43
- -- Blocks Table RLS
44
- --
45
- alter table public.blocks enable row level security;
46
-
47
- drop policy if exists "blocks_are_readable_if_parent_is_published" on public.blocks;
48
- -- allow anonymous and authenticated users to read blocks if their parent page/post is published
49
- create policy "blocks_are_readable_if_parent_is_published"
50
- on public.blocks for select
51
- to anon, authenticated
52
- using (
53
- (page_id is not null and exists(select 1 from public.pages p where p.id = blocks.page_id and p.status = 'published')) or
54
- (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())))
55
- );
56
-
57
- -- allow admins and writers to insert, update, delete blocks
58
- drop policy if exists "admins_and_writers_can_manage_blocks" on public.blocks;
59
- create policy "admins_and_writers_can_manage_blocks"
60
- on public.blocks for all
61
- to authenticated
62
- using (public.get_current_user_role() in ('ADMIN', 'WRITER'))
63
- with check (public.get_current_user_role() in ('ADMIN', 'WRITER'));
64
-
65
- --
66
- -- Navigation Items Table RLS
67
- --
68
- alter table public.navigation_items enable row level security;
69
-
70
- commit;
@@ -1,39 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_add_translation_group_id.sql
2
-
3
- ALTER TABLE public.pages
4
- ADD COLUMN translation_group_id UUID DEFAULT gen_random_uuid() NOT NULL;
5
-
6
- COMMENT ON COLUMN public.pages.translation_group_id IS 'Groups different language versions of the same conceptual page.';
7
-
8
- CREATE INDEX IF NOT EXISTS idx_pages_translation_group_id ON public.pages(translation_group_id);
9
-
10
- -- For existing pages, you'll need to manually group them.
11
- -- Example: If page ID 1 (EN) and page ID 10 (FR) are the same conceptual page:
12
- -- UPDATE public.pages SET translation_group_id = (SELECT translation_group_id FROM public.pages WHERE id = 1) WHERE id = 10;
13
- -- Or, for all pages that share a slug currently (from the previous model):
14
- -- WITH slug_groups AS (
15
- -- SELECT slug, MIN(id) as first_id, gen_random_uuid() as new_group_id
16
- -- FROM public.pages
17
- -- GROUP BY slug
18
- -- HAVING COUNT(*) > 1 -- Only for slugs that were shared
19
- -- )
20
- -- UPDATE public.pages p
21
- -- SET translation_group_id = sg.new_group_id
22
- -- FROM slug_groups sg
23
- -- WHERE p.slug = sg.slug;
24
- --
25
- -- UPDATE public.pages p
26
- -- SET translation_group_id = gen_random_uuid()
27
- -- WHERE p.translation_group_id IS NULL AND EXISTS (
28
- -- SELECT 1 FROM (
29
- -- SELECT slug, COUNT(*) as c FROM public.pages GROUP BY slug
30
- -- ) counts WHERE counts.slug = p.slug AND counts.c = 1
31
- -- );
32
-
33
-
34
- ALTER TABLE public.posts
35
- ADD COLUMN translation_group_id UUID DEFAULT gen_random_uuid() NOT NULL;
36
-
37
- COMMENT ON COLUMN public.posts.translation_group_id IS 'Groups different language versions of the same conceptual post.';
38
-
39
- CREATE INDEX IF NOT EXISTS idx_posts_translation_group_id ON public.posts(translation_group_id);
@@ -1,21 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_add_translation_group_to_nav_items.sql
2
- -- Replace YYYYMMDDHHMMSS with the actual timestamp, e.g., 20250520171700
3
-
4
- ALTER TABLE public.navigation_items
5
- ADD COLUMN translation_group_id UUID DEFAULT gen_random_uuid() NOT NULL;
6
-
7
- COMMENT ON COLUMN public.navigation_items.translation_group_id IS 'Groups different language versions of the same conceptual navigation item.';
8
-
9
- CREATE INDEX IF NOT EXISTS idx_navigation_items_translation_group_id ON public.navigation_items(translation_group_id);
10
-
11
- -- Note: For existing navigation items, you will need to manually group them if they are translations of each other.
12
- -- For example, if item ID 5 (EN) and item ID 25 (FR) are the same conceptual link:
13
- -- UPDATE public.navigation_items SET translation_group_id = (SELECT translation_group_id FROM public.navigation_items WHERE id = 5 LIMIT 1) WHERE id = 25;
14
- -- Or, assign a new group ID to both if they weren't grouped yet:
15
- -- WITH new_group AS (SELECT gen_random_uuid() as new_id)
16
- -- UPDATE public.navigation_items
17
- -- SET translation_group_id = (SELECT new_id FROM new_group)
18
- -- WHERE id IN (5, 25);
19
- --
20
- -- It's recommended to do this grouping manually based on your existing data logic.
21
- -- New items created through the updated CMS logic will automatically get grouped.
@@ -1,52 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_seed_homepage_and_nav.sql
2
- -- Replace YYYYMMDDHHMMSS with the actual timestamp, e.g., 20250521100000
3
-
4
- DO $$
5
- DECLARE
6
- en_lang_id BIGINT;
7
- fr_lang_id BIGINT;
8
- admin_user_id UUID;
9
- home_page_translation_group UUID;
10
- home_nav_translation_group UUID;
11
- en_home_page_id BIGINT;
12
- fr_home_page_id BIGINT;
13
- BEGIN
14
- -- Get language IDs
15
- SELECT id INTO en_lang_id FROM public.languages WHERE code = 'en' LIMIT 1;
16
- SELECT id INTO fr_lang_id FROM public.languages WHERE code = 'fr' LIMIT 1;
17
-
18
- -- Get an admin user ID to set as author (optional, fallback to NULL)
19
- SELECT id INTO admin_user_id FROM public.profiles WHERE role = 'ADMIN' LIMIT 1;
20
-
21
- -- Check if languages were found
22
- IF en_lang_id IS NULL THEN
23
- RAISE EXCEPTION 'English language (en) not found. Please seed languages first.';
24
- END IF;
25
- IF fr_lang_id IS NULL THEN
26
- RAISE EXCEPTION 'French language (fr) not found. Please seed languages first.';
27
- END IF;
28
-
29
- -- Generate translation group UUIDs
30
- home_page_translation_group := gen_random_uuid();
31
- home_nav_translation_group := gen_random_uuid();
32
-
33
- -- Seed English Homepage
34
- INSERT INTO public.pages (language_id, author_id, title, slug, status, meta_title, meta_description, translation_group_id)
35
- VALUES (en_lang_id, admin_user_id, 'Home', 'home', 'published', 'Homepage', 'This is the homepage.', home_page_translation_group)
36
- RETURNING id INTO en_home_page_id;
37
-
38
- -- Seed French Homepage (Accueil)
39
- INSERT INTO public.pages (language_id, author_id, title, slug, status, meta_title, meta_description, translation_group_id)
40
- VALUES (fr_lang_id, admin_user_id, 'Accueil', 'accueil', 'published', 'Page d''accueil', 'Ceci est la page d''accueil.', home_page_translation_group)
41
- RETURNING id INTO fr_home_page_id;
42
-
43
- -- Seed English Navigation Item for Homepage (linked to the English page, but URL is root)
44
- INSERT INTO public.navigation_items (language_id, menu_key, label, url, "order", page_id, translation_group_id)
45
- VALUES (en_lang_id, 'HEADER', 'Home', '/', 0, en_home_page_id, home_nav_translation_group);
46
-
47
- -- Seed French Navigation Item for Homepage (linked to the French page, but URL is root)
48
- INSERT INTO public.navigation_items (language_id, menu_key, label, url, "order", page_id, translation_group_id)
49
- VALUES (fr_lang_id, 'HEADER', 'Accueil', '/', 0, fr_home_page_id, home_nav_translation_group);
50
-
51
- RAISE NOTICE 'Homepage and navigation links seeded for EN and FR.';
52
- END $$;
@@ -1,8 +0,0 @@
1
- ALTER TABLE public.posts
2
- ADD COLUMN feature_image_id UUID,
3
- ADD CONSTRAINT fk_feature_image
4
- FOREIGN KEY (feature_image_id)
5
- REFERENCES public.media(id)
6
- ON DELETE SET NULL;
7
-
8
- COMMENT ON COLUMN public.posts.feature_image_id IS 'ID of the media item to be used as the post''s feature image.';
@@ -1,18 +0,0 @@
1
- -- Drop existing policies if they exist, then recreate them.
2
-
3
- -- Policy for public read access
4
- DROP POLICY IF EXISTS "media_are_publicly_readable" ON public.media;
5
-
6
- CREATE POLICY "media_are_publicly_readable"
7
- ON public.media FOR SELECT
8
- TO anon, authenticated
9
- USING (true);
10
-
11
- -- Policy for admin/writer management
12
- DROP POLICY IF EXISTS "admins_and_writers_can_manage_media" ON public.media;
13
-
14
- CREATE POLICY "admins_and_writers_can_manage_media"
15
- ON public.media FOR ALL
16
- TO authenticated
17
- USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
18
- WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
@@ -1,14 +0,0 @@
1
- ALTER TABLE public.media
2
- ADD COLUMN width INTEGER,
3
- ADD COLUMN height INTEGER;
4
-
5
- -- Optional: Add a comment to describe the new columns
6
- COMMENT ON COLUMN public.media.width IS 'Width of the image in pixels.';
7
- COMMENT ON COLUMN public.media.height IS 'Height of the image in pixels.';
8
-
9
- -- Backfill existing image media with nulls, or you might want to run a script later to populate them if possible
10
- -- For now, they will be NULL by default.
11
-
12
- -- Re-apply RLS policies if necessary, though ADD COLUMN usually doesn't require it unless policies are column-specific
13
- -- and these new columns need to be included or excluded.
14
- -- For simplicity, assuming existing policies are fine.
@@ -1,188 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_optimize_rls_policies_v2.sql
2
- -- Replace YYYYMMDDHHMMSS with the actual timestamp of this migration file.
3
-
4
- BEGIN;
5
-
6
- -- == PROFILES ==
7
- DROP POLICY IF EXISTS "users_can_select_own_profile" ON public.profiles;
8
- DROP POLICY IF EXISTS "users_can_update_own_profile" ON public.profiles;
9
- DROP POLICY IF EXISTS "admins_can_select_any_profile" ON public.profiles;
10
- DROP POLICY IF EXISTS "admins_can_update_any_profile" ON public.profiles;
11
-
12
- CREATE POLICY "authenticated_can_read_profiles" ON public.profiles
13
- FOR SELECT
14
- TO authenticated
15
- USING (
16
- (id = (SELECT auth.uid())) OR
17
- (public.get_current_user_role() = 'ADMIN')
18
- );
19
- COMMENT ON POLICY "authenticated_can_read_profiles" ON public.profiles IS 'Authenticated users can read their own profile, and admins can read any profile.';
20
-
21
- CREATE POLICY "authenticated_can_update_profiles" ON public.profiles
22
- FOR UPDATE
23
- TO authenticated
24
- USING (
25
- (id = (SELECT auth.uid())) OR
26
- (public.get_current_user_role() = 'ADMIN')
27
- )
28
- WITH CHECK (
29
- (id = (SELECT auth.uid())) OR
30
- (public.get_current_user_role() = 'ADMIN')
31
- );
32
- COMMENT ON POLICY "authenticated_can_update_profiles" ON public.profiles IS 'Authenticated users can update their own profile, and admins can update any profile.';
33
-
34
- -- Ensure admin insert policy is present and correct (it typically uses WITH CHECK on the role, not USING for insert)
35
- DROP POLICY IF EXISTS "admins_can_insert_profiles" ON public.profiles;
36
- CREATE POLICY "admins_can_insert_profiles" ON public.profiles
37
- FOR INSERT TO authenticated
38
- WITH CHECK (public.get_current_user_role() = 'ADMIN');
39
- COMMENT ON POLICY "admins_can_insert_profiles" ON public.profiles IS 'Admin users can insert new profiles.';
40
-
41
-
42
- -- == PAGES ==
43
- DROP POLICY IF EXISTS "pages_are_publicly_readable_when_published" ON public.pages;
44
- DROP POLICY IF EXISTS "authors_writers_admins_can_read_own_drafts" ON public.pages;
45
- DROP POLICY IF EXISTS "authors_writers_admins_can_read_own_or_all_drafts" ON public.pages;
46
- DROP POLICY IF EXISTS "admins_and_writers_can_manage_pages" ON public.pages;
47
-
48
- CREATE POLICY "pages_anon_can_read_published" ON public.pages
49
- FOR SELECT
50
- TO anon
51
- USING (status = 'published');
52
- COMMENT ON POLICY "pages_anon_can_read_published" ON public.pages IS 'Anonymous users can read published pages.';
53
-
54
- CREATE POLICY "pages_authenticated_access" ON public.pages
55
- FOR SELECT
56
- TO authenticated
57
- USING (
58
- (status = 'published') OR
59
- (author_id = (SELECT auth.uid()) AND status <> 'published') OR
60
- (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
61
- );
62
- COMMENT ON POLICY "pages_authenticated_access" ON public.pages IS 'Authenticated users can read published pages, their own drafts, or all pages if admin/writer.';
63
-
64
- CREATE POLICY "pages_admin_writer_management" ON public.pages
65
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
66
- TO authenticated
67
- USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
68
- WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
69
- COMMENT ON POLICY "pages_admin_writer_management" ON public.pages IS 'Admins and Writers can manage pages.';
70
-
71
-
72
- -- == POSTS ==
73
- DROP POLICY IF EXISTS "posts_are_publicly_readable_when_published" ON public.posts;
74
- DROP POLICY IF EXISTS "authors_writers_admins_can_read_own_draft_posts" ON public.posts;
75
- DROP POLICY IF EXISTS "authors_writers_admins_can_read_own_or_all_draft_posts" ON public.posts;
76
- DROP POLICY IF EXISTS "admins_and_writers_can_manage_posts" ON public.posts;
77
-
78
- CREATE POLICY "posts_anon_can_read_published" ON public.posts
79
- FOR SELECT
80
- TO anon
81
- USING (status = 'published' AND (published_at IS NULL OR published_at <= now()));
82
- COMMENT ON POLICY "posts_anon_can_read_published" ON public.posts IS 'Anonymous users can read published posts.';
83
-
84
- CREATE POLICY "posts_authenticated_access" ON public.posts
85
- FOR SELECT
86
- TO authenticated
87
- USING (
88
- (status = 'published' AND (published_at IS NULL OR published_at <= now())) OR
89
- (author_id = (SELECT auth.uid()) AND status <> 'published') OR
90
- (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
91
- );
92
- COMMENT ON POLICY "posts_authenticated_access" ON public.posts IS 'Authenticated users can read published posts, their own drafts, or all posts if admin/writer.';
93
-
94
- CREATE POLICY "posts_admin_writer_management" ON public.posts
95
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
96
- TO authenticated
97
- USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
98
- WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
99
- COMMENT ON POLICY "posts_admin_writer_management" ON public.posts IS 'Admins and Writers can manage posts.';
100
-
101
-
102
- -- == BLOCKS ==
103
- DROP POLICY IF EXISTS "blocks_are_readable_if_parent_is_published" ON public.blocks;
104
- DROP POLICY IF EXISTS "admins_and_writers_can_manage_blocks" ON public.blocks;
105
-
106
- CREATE POLICY "blocks_anon_can_read_published" ON public.blocks
107
- FOR SELECT
108
- TO anon
109
- USING (
110
- (page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
111
- (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())))
112
- );
113
- COMMENT ON POLICY "blocks_anon_can_read_published" ON public.blocks IS 'Anonymous users can read blocks of published parent pages/posts.';
114
-
115
- CREATE POLICY "blocks_authenticated_access" ON public.blocks
116
- FOR SELECT
117
- TO authenticated
118
- USING (
119
- (public.get_current_user_role() IN ('ADMIN', 'WRITER')) OR
120
- (
121
- (public.get_current_user_role() = 'USER') AND (
122
- (page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
123
- (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())))
124
- )
125
- )
126
- );
127
- COMMENT ON POLICY "blocks_authenticated_access" ON public.blocks IS 'Admins/Writers can read all blocks; Users can read blocks of published parents.';
128
-
129
- CREATE POLICY "blocks_admin_writer_management" ON public.blocks
130
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
131
- TO authenticated
132
- USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
133
- WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
134
- COMMENT ON POLICY "blocks_admin_writer_management" ON public.blocks IS 'Admins and Writers can manage blocks.';
135
-
136
-
137
- -- == LANGUAGES ==
138
- DROP POLICY IF EXISTS "languages_are_publicly_readable" ON public.languages;
139
- DROP POLICY IF EXISTS "admins_can_manage_languages" ON public.languages;
140
-
141
- CREATE POLICY "languages_are_publicly_readable_by_all" ON public.languages
142
- FOR SELECT
143
- USING (true);
144
- COMMENT ON POLICY "languages_are_publicly_readable_by_all" ON public.languages IS 'All users (anon and authenticated) can read languages.';
145
-
146
- CREATE POLICY "languages_admin_management" ON public.languages
147
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
148
- TO authenticated
149
- USING (public.get_current_user_role() = 'ADMIN')
150
- WITH CHECK (public.get_current_user_role() = 'ADMIN');
151
- COMMENT ON POLICY "languages_admin_management" ON public.languages IS 'Admins can manage languages.';
152
-
153
-
154
- -- == MEDIA ==
155
- DROP POLICY IF EXISTS "media_is_readable_by_all" ON public.media;
156
- DROP POLICY IF EXISTS "media_are_publicly_readable" ON public.media;
157
- DROP POLICY IF EXISTS "admins_and_writers_can_manage_media" ON public.media;
158
-
159
- CREATE POLICY "media_is_publicly_readable_by_all" ON public.media
160
- FOR SELECT
161
- USING (true);
162
- COMMENT ON POLICY "media_is_publicly_readable_by_all" ON public.media IS 'All users (anon and authenticated) can read media records.';
163
-
164
- CREATE POLICY "media_admin_writer_management" ON public.media
165
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
166
- TO authenticated
167
- USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
168
- WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
169
- COMMENT ON POLICY "media_admin_writer_management" ON public.media IS 'Admins and Writers can manage media records.';
170
-
171
-
172
- -- == NAVIGATION ITEMS ==
173
- DROP POLICY IF EXISTS "navigation_is_publicly_readable" ON public.navigation_items;
174
- DROP POLICY IF EXISTS "admins_can_manage_navigation" ON public.navigation_items;
175
-
176
- CREATE POLICY "nav_items_are_publicly_readable_by_all" ON public.navigation_items
177
- FOR SELECT
178
- USING (true);
179
- COMMENT ON POLICY "nav_items_are_publicly_readable_by_all" ON public.navigation_items IS 'All users (anon and authenticated) can read navigation items.';
180
-
181
- CREATE POLICY "nav_items_admin_management" ON public.navigation_items
182
- FOR ALL -- Changed from INSERT, UPDATE, DELETE
183
- TO authenticated
184
- USING (public.get_current_user_role() = 'ADMIN')
185
- WITH CHECK (public.get_current_user_role() = 'ADMIN');
186
- COMMENT ON POLICY "nav_items_admin_management" ON public.navigation_items IS 'Admins can manage navigation items.';
187
-
188
- COMMIT;
@@ -1,96 +0,0 @@
1
- -- supabase/migrations/YYYYMMDDHHMMSS_resolve_select_policy_overlaps.sql
2
- -- (Ensure YYYYMMDDHHMMSS is the current timestamp)
3
-
4
- BEGIN;
5
-
6
- -- == BLOCKS ==
7
- -- Assuming "blocks_admin_writer_management" is FOR ALL and covers SELECT for ADMIN/WRITER.
8
- -- Make "blocks_authenticated_access" specific to non-ADMIN/WRITER authenticated users.
9
- DROP POLICY IF EXISTS "blocks_authenticated_access" ON public.blocks;
10
- CREATE POLICY "blocks_authenticated_user_access" ON public.blocks -- Renamed for clarity
11
- FOR SELECT
12
- TO authenticated
13
- USING (
14
- (public.get_current_user_role() NOT IN ('ADMIN', 'WRITER')) AND -- This is the key change
15
- (
16
- (page_id IS NOT NULL AND EXISTS(SELECT 1 FROM public.pages p WHERE p.id = blocks.page_id AND p.status = 'published')) OR
17
- (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())))
18
- )
19
- );
20
- COMMENT ON POLICY "blocks_authenticated_user_access" ON public.blocks IS 'Authenticated USERS (non-admin/writer) can read blocks of published parents. Admin/Writer SELECT via their management policy.';
21
- -- Note: "blocks_anon_can_read_published" (FOR SELECT TO anon) should remain unchanged.
22
- -- Note: "blocks_admin_writer_management" (FOR ALL TO authenticated USING role IN (ADMIN,WRITER)) should remain unchanged.
23
-
24
- -- == LANGUAGES ==
25
- -- Assuming "languages_admin_management" is FOR ALL and covers SELECT for ADMIN.
26
- -- Make "languages_are_publicly_readable_by_all" not apply to authenticated ADMINs.
27
- DROP POLICY IF EXISTS "languages_are_publicly_readable_by_all" ON public.languages;
28
- CREATE POLICY "languages_readable_by_anon_and_non_admins" ON public.languages -- Renamed
29
- FOR SELECT
30
- USING (
31
- NOT (auth.role() = 'authenticated' AND public.get_current_user_role() = 'ADMIN')
32
- );
33
- COMMENT ON POLICY "languages_readable_by_anon_and_non_admins" ON public.languages IS 'Anonymous users and authenticated non-admins can read languages. Admin SELECT via management policy.';
34
- -- Note: "languages_admin_management" (FOR ALL TO authenticated USING role = ADMIN) should remain unchanged.
35
-
36
- -- == MEDIA ==
37
- -- Assuming "media_admin_writer_management" is FOR ALL and covers SELECT for ADMIN/WRITER.
38
- -- Make "media_is_publicly_readable_by_all" not apply to authenticated ADMIN/WRITERs.
39
- DROP POLICY IF EXISTS "media_is_publicly_readable_by_all" ON public.media;
40
- CREATE POLICY "media_readable_by_anon_and_non_privileged_users" ON public.media -- Renamed
41
- FOR SELECT
42
- USING (
43
- NOT (auth.role() = 'authenticated' AND public.get_current_user_role() IN ('ADMIN', 'WRITER'))
44
- );
45
- COMMENT ON POLICY "media_readable_by_anon_and_non_privileged_users" ON public.media IS 'Anonymous users and authenticated non-admin/writer users can read media. Admin/Writer SELECT via management policy.';
46
- -- Note: "media_admin_writer_management" (FOR ALL TO authenticated USING role IN (ADMIN,WRITER)) should remain unchanged.
47
-
48
- -- == NAVIGATION ITEMS ==
49
- -- Assuming "nav_items_admin_management" is FOR ALL and covers SELECT for ADMIN.
50
- -- Make "nav_items_are_publicly_readable_by_all" not apply to authenticated ADMINs.
51
- DROP POLICY IF EXISTS "nav_items_are_publicly_readable_by_all" ON public.navigation_items;
52
- CREATE POLICY "nav_items_readable_by_anon_and_non_admins" ON public.navigation_items -- Renamed
53
- FOR SELECT
54
- USING (
55
- NOT (auth.role() = 'authenticated' AND public.get_current_user_role() = 'ADMIN')
56
- );
57
- COMMENT ON POLICY "nav_items_readable_by_anon_and_non_admins" ON public.navigation_items IS 'Anonymous users and authenticated non-admins can read nav items. Admin SELECT via management policy.';
58
- -- Note: "nav_items_admin_management" (FOR ALL TO authenticated USING role = ADMIN) should remain unchanged.
59
-
60
- -- == PAGES ==
61
- -- Assuming "pages_admin_writer_management" is FOR ALL and covers SELECT for ADMIN/WRITER.
62
- -- Make "pages_authenticated_access" specific to non-ADMIN/WRITER authenticated users.
63
- DROP POLICY IF EXISTS "pages_authenticated_access" ON public.pages;
64
- CREATE POLICY "pages_user_authenticated_access" ON public.pages -- Renamed
65
- FOR SELECT
66
- TO authenticated
67
- USING (
68
- (public.get_current_user_role() NOT IN ('ADMIN', 'WRITER')) AND -- This is the key change
69
- (
70
- (status = 'published') OR
71
- (author_id = (SELECT auth.uid()) AND status <> 'published')
72
- )
73
- );
74
- COMMENT ON POLICY "pages_user_authenticated_access" ON public.pages IS 'Authenticated USERS (non-admin/writer) can read published pages or their own drafts. Admin/Writer SELECT via their management policy.';
75
- -- Note: "pages_anon_can_read_published" (FOR SELECT TO anon) should remain unchanged.
76
- -- Note: "pages_admin_writer_management" (FOR ALL TO authenticated USING role IN (ADMIN,WRITER)) should remain unchanged.
77
-
78
- -- == POSTS ==
79
- -- Assuming "posts_admin_writer_management" is FOR ALL and covers SELECT for ADMIN/WRITER.
80
- -- Make "posts_authenticated_access" specific to non-ADMIN/WRITER authenticated users.
81
- DROP POLICY IF EXISTS "posts_authenticated_access" ON public.posts;
82
- CREATE POLICY "posts_user_authenticated_access" ON public.posts -- Renamed
83
- FOR SELECT
84
- TO authenticated
85
- USING (
86
- (public.get_current_user_role() NOT IN ('ADMIN', 'WRITER')) AND -- This is the key change
87
- (
88
- (status = 'published' AND (published_at IS NULL OR published_at <= now())) OR
89
- (author_id = (SELECT auth.uid()) AND status <> 'published')
90
- )
91
- );
92
- COMMENT ON POLICY "posts_user_authenticated_access" ON public.posts IS 'Authenticated USERS (non-admin/writer) can read published posts or their own drafts. Admin/Writer SELECT via their management policy.';
93
- -- Note: "posts_anon_can_read_published" (FOR SELECT TO anon) should remain unchanged.
94
- -- Note: "posts_admin_writer_management" (FOR ALL TO authenticated USING role IN (ADMIN,WRITER)) should remain unchanged.
95
-
96
- COMMIT;