@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.
- package/package.json +1 -1
- package/supabase/config.toml +1 -1
- package/supabase/migrations/00000000000014_seed_homepage_blocks.sql +23 -10
- 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/20251112141000_seed_homepage_blocks.sql +0 -653
- 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,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;
|