@nextblock-cms/db 0.2.8 → 0.2.10
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/lib/supabase/client.d.ts +9 -0
- package/lib/supabase/middleware.d.ts +2 -0
- package/lib/supabase/server.d.ts +7 -0
- package/lib/supabase/ssg-client.d.ts +2 -0
- package/lib/supabase/types.d.ts +635 -0
- package/package.json +3 -13
- package/supabase/config.toml +0 -319
- 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 -64
- 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 -95
- package/supabase/migrations/20251112141000_seed_homepage_blocks.sql +0 -656
- 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
|
@@ -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
|
-
);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
-- Create the translations table
|
|
2
|
-
CREATE TABLE translations (
|
|
3
|
-
key TEXT PRIMARY KEY,
|
|
4
|
-
translations JSONB NOT NULL,
|
|
5
|
-
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
|
6
|
-
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
-- Add comments on the columns
|
|
10
|
-
COMMENT ON COLUMN translations.key IS 'A unique, slugified identifier (e.g., "sign_in_button_text").';
|
|
11
|
-
COMMENT ON COLUMN translations.translations IS 'Stores translations as key-value pairs (e.g., {"en": "Sign In", "fr": "s''inscrire"}).';
|
|
12
|
-
|
|
13
|
-
-- Enable Row Level Security
|
|
14
|
-
ALTER TABLE translations ENABLE ROW LEVEL SECURITY;
|
|
15
|
-
|
|
16
|
-
-- RLS Policies
|
|
17
|
-
CREATE POLICY "Allow all access to ADMIN"
|
|
18
|
-
ON public.translations
|
|
19
|
-
FOR ALL
|
|
20
|
-
TO authenticated
|
|
21
|
-
USING (
|
|
22
|
-
(auth.jwt() ->> 'user_role') = 'ADMIN'
|
|
23
|
-
)
|
|
24
|
-
WITH CHECK (
|
|
25
|
-
(auth.jwt() ->> 'user_role') = 'ADMIN'
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
CREATE POLICY "Allow read access to all authenticated users"
|
|
29
|
-
ON public.translations
|
|
30
|
-
FOR SELECT
|
|
31
|
-
TO authenticated
|
|
32
|
-
USING (true);
|
|
33
|
-
|
|
34
|
-
CREATE POLICY "Allow read access to all anonymous users"
|
|
35
|
-
ON public.translations
|
|
36
|
-
FOR SELECT
|
|
37
|
-
TO anon
|
|
38
|
-
USING (true);
|
|
39
|
-
|
|
40
|
-
-- Trigger to update updated_at timestamp
|
|
41
|
-
CREATE OR REPLACE FUNCTION public.set_current_timestamp_updated_at()
|
|
42
|
-
RETURNS TRIGGER AS $$
|
|
43
|
-
DECLARE
|
|
44
|
-
_new record;
|
|
45
|
-
BEGIN
|
|
46
|
-
_new := NEW;
|
|
47
|
-
_new."updated_at" = NOW();
|
|
48
|
-
RETURN _new;
|
|
49
|
-
END;
|
|
50
|
-
$$ LANGUAGE plpgsql;
|
|
51
|
-
|
|
52
|
-
CREATE TRIGGER set_updated_at
|
|
53
|
-
BEFORE UPDATE ON public.translations
|
|
54
|
-
FOR EACH ROW
|
|
55
|
-
EXECUTE FUNCTION public.set_current_timestamp_updated_at();
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
INSERT INTO public.translations (key, translations) VALUES
|
|
2
|
-
('sign_in', '{"en": "Sign in", "fr": "Connexion"}'),
|
|
3
|
-
('sign_up', '{"en": "Sign up", "fr": "Inscription"}'),
|
|
4
|
-
('sign_out', '{"en": "Sign out", "fr": "Déconnexion"}'),
|
|
5
|
-
('dont_have_account', '{"en": "Don''t have an account?", "fr": "Pas encore de compte ?"}'),
|
|
6
|
-
('email', '{"en": "Email", "fr": "Email"}'),
|
|
7
|
-
('you_at_example_com', '{"en": "you@example.com", "fr": "vous@example.com"}'),
|
|
8
|
-
('password', '{"en": "Password", "fr": "Mot de passe"}'),
|
|
9
|
-
('forgot_password', '{"en": "Forgot Password?", "fr": "Mot de passe oublié ?"}'),
|
|
10
|
-
('your_password', '{"en": "Your password", "fr": "Votre mot de passe"}'),
|
|
11
|
-
('signing_in_pending', '{"en": "Signing In...", "fr": "Connexion en cours..."}'),
|
|
12
|
-
('already_have_account', '{"en": "Already have an account?", "fr": "Déjà un compte ?"}'),
|
|
13
|
-
('signing_up_pending', '{"en": "Signing up...", "fr": "Inscription en cours..."}'),
|
|
14
|
-
('reset_password', '{"en": "Reset Password", "fr": "Réinitialiser le mot de passe"}');
|
|
15
|
-
|
|
16
|
-
-- Route prefix for the blog section
|
|
17
|
-
INSERT INTO public.translations (key, translations) VALUES
|
|
18
|
-
('blog_prefix', '{"en": "article", "fr": "article"}')
|
|
19
|
-
ON CONFLICT (key) DO UPDATE
|
|
20
|
-
SET translations = EXCLUDED.translations;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
-- Drop the existing restrictive policy for updates
|
|
2
|
-
DROP POLICY IF EXISTS "Allow all access to ADMIN" ON public.translations;
|
|
3
|
-
|
|
4
|
-
-- Create a more permissive policy that allows authenticated users to update translations
|
|
5
|
-
-- This assumes that access to the CMS is already controlled at the application level
|
|
6
|
-
CREATE POLICY "Allow authenticated users to manage translations"
|
|
7
|
-
ON public.translations
|
|
8
|
-
FOR ALL
|
|
9
|
-
TO authenticated
|
|
10
|
-
USING (true)
|
|
11
|
-
WITH CHECK (true);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
INSERT INTO public.translations (key, translations) VALUES
|
|
2
|
-
('edit_page', '{"en": "Edit Page", "fr": "Éditer la page"}'),
|
|
3
|
-
('edit_post', '{"en": "Edit Post", "fr": "Éditer l''article"}'),
|
|
4
|
-
('open_main_menu', '{"en": "Open main menu", "fr": "Ouvrir le menu principal"}'),
|
|
5
|
-
('mobile_navigation_menu', '{"en": "Mobile navigation menu", "fr": "Menu de navigation mobile"}'),
|
|
6
|
-
('cms_dashboard', '{"en": "CMS Dashboard", "fr": "Tableau de bord CMS"}'),
|
|
7
|
-
('update_env_file_warning', '{"en": "Please update .env.local file with anon key and url", "fr": "Veuillez mettre à jour .env.local avec l''anon key et l''URL"}'),
|
|
8
|
-
('greeting', '{"en": "Hey, {username}!", "fr": "Salut, {username} !"}')
|
|
9
|
-
ON CONFLICT (key) DO NOTHING;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
-- supabase/migrations/20250709120000_create_revisions_tables.sql
|
|
2
|
-
-- Hybrid revision history for pages and posts
|
|
3
|
-
|
|
4
|
-
begin;
|
|
5
|
-
|
|
6
|
-
-- Create enum for revision type if not exists
|
|
7
|
-
do $$
|
|
8
|
-
begin
|
|
9
|
-
if not exists (select 1 from pg_type where typname = 'revision_type') then
|
|
10
|
-
create type public.revision_type as enum ('snapshot', 'diff');
|
|
11
|
-
end if;
|
|
12
|
-
end
|
|
13
|
-
$$;
|
|
14
|
-
|
|
15
|
-
-- Add version column to pages and posts if not exists
|
|
16
|
-
do $$
|
|
17
|
-
begin
|
|
18
|
-
if not exists (
|
|
19
|
-
select 1 from information_schema.columns
|
|
20
|
-
where table_schema = 'public' and table_name = 'pages' and column_name = 'version'
|
|
21
|
-
) then
|
|
22
|
-
alter table public.pages add column version integer not null default 1;
|
|
23
|
-
comment on column public.pages.version is 'Monotonic version number for hybrid revisions.';
|
|
24
|
-
end if;
|
|
25
|
-
end
|
|
26
|
-
$$;
|
|
27
|
-
|
|
28
|
-
do $$
|
|
29
|
-
begin
|
|
30
|
-
if not exists (
|
|
31
|
-
select 1 from information_schema.columns
|
|
32
|
-
where table_schema = 'public' and table_name = 'posts' and column_name = 'version'
|
|
33
|
-
) then
|
|
34
|
-
alter table public.posts add column version integer not null default 1;
|
|
35
|
-
comment on column public.posts.version is 'Monotonic version number for hybrid revisions.';
|
|
36
|
-
end if;
|
|
37
|
-
end
|
|
38
|
-
$$;
|
|
39
|
-
|
|
40
|
-
-- Create page_revisions table
|
|
41
|
-
create table if not exists public.page_revisions (
|
|
42
|
-
id bigint generated by default as identity primary key,
|
|
43
|
-
page_id bigint not null references public.pages(id) on delete cascade,
|
|
44
|
-
author_id uuid references public.profiles(id) on delete set null,
|
|
45
|
-
version integer not null,
|
|
46
|
-
revision_type public.revision_type not null,
|
|
47
|
-
content jsonb not null,
|
|
48
|
-
created_at timestamp with time zone not null default now(),
|
|
49
|
-
constraint page_revisions_page_version_key unique (page_id, version)
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
comment on table public.page_revisions is 'Hybrid (snapshot/diff) revisions for pages.';
|
|
53
|
-
comment on column public.page_revisions.content is 'If snapshot: full content; if diff: JSON Patch array.';
|
|
54
|
-
|
|
55
|
-
create index if not exists idx_page_revisions_page_id on public.page_revisions(page_id);
|
|
56
|
-
create index if not exists idx_page_revisions_page_id_version on public.page_revisions(page_id, version);
|
|
57
|
-
|
|
58
|
-
-- Create post_revisions table
|
|
59
|
-
create table if not exists public.post_revisions (
|
|
60
|
-
id bigint generated by default as identity primary key,
|
|
61
|
-
post_id bigint not null references public.posts(id) on delete cascade,
|
|
62
|
-
author_id uuid references public.profiles(id) on delete set null,
|
|
63
|
-
version integer not null,
|
|
64
|
-
revision_type public.revision_type not null,
|
|
65
|
-
content jsonb not null,
|
|
66
|
-
created_at timestamp with time zone not null default now(),
|
|
67
|
-
constraint post_revisions_post_version_key unique (post_id, version)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
comment on table public.post_revisions is 'Hybrid (snapshot/diff) revisions for posts.';
|
|
71
|
-
comment on column public.post_revisions.content is 'If snapshot: full content; if diff: JSON Patch array.';
|
|
72
|
-
|
|
73
|
-
create index if not exists idx_post_revisions_post_id on public.post_revisions(post_id);
|
|
74
|
-
create index if not exists idx_post_revisions_post_id_version on public.post_revisions(post_id, version);
|
|
75
|
-
|
|
76
|
-
-- Enable RLS and add policies (admins and writers manage; authenticated can read)
|
|
77
|
-
alter table public.page_revisions enable row level security;
|
|
78
|
-
alter table public.post_revisions enable row level security;
|
|
79
|
-
|
|
80
|
-
-- Page revisions policies
|
|
81
|
-
drop policy if exists "page_revisions_admin_writer_management" on public.page_revisions;
|
|
82
|
-
create policy "page_revisions_admin_writer_management"
|
|
83
|
-
on public.page_revisions for all
|
|
84
|
-
to authenticated
|
|
85
|
-
using (public.get_current_user_role() in ('ADMIN', 'WRITER'))
|
|
86
|
-
with check (public.get_current_user_role() in ('ADMIN', 'WRITER'));
|
|
87
|
-
|
|
88
|
-
drop policy if exists "page_revisions_authenticated_read" on public.page_revisions;
|
|
89
|
-
create policy "page_revisions_authenticated_read"
|
|
90
|
-
on public.page_revisions for select
|
|
91
|
-
to authenticated
|
|
92
|
-
using (true);
|
|
93
|
-
|
|
94
|
-
-- Post revisions policies
|
|
95
|
-
drop policy if exists "post_revisions_admin_writer_management" on public.post_revisions;
|
|
96
|
-
create policy "post_revisions_admin_writer_management"
|
|
97
|
-
on public.post_revisions for all
|
|
98
|
-
to authenticated
|
|
99
|
-
using (public.get_current_user_role() in ('ADMIN', 'WRITER'))
|
|
100
|
-
with check (public.get_current_user_role() in ('ADMIN', 'WRITER'));
|
|
101
|
-
|
|
102
|
-
drop policy if exists "post_revisions_authenticated_read" on public.post_revisions;
|
|
103
|
-
create policy "post_revisions_authenticated_read"
|
|
104
|
-
on public.post_revisions for select
|
|
105
|
-
to authenticated
|
|
106
|
-
using (true);
|
|
107
|
-
|
|
108
|
-
commit;
|
|
109
|
-
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
-- Add a folder column to organize media by path prefix
|
|
2
|
-
ALTER TABLE public.media
|
|
3
|
-
ADD COLUMN IF NOT EXISTS folder TEXT;
|
|
4
|
-
|
|
5
|
-
COMMENT ON COLUMN public.media.folder IS 'Folder path prefix for the R2 object (e.g., images/summer/).';
|
|
6
|
-
|
|
7
|
-
-- Backfill existing rows by deriving folder from object_key (everything up to last slash)
|
|
8
|
-
UPDATE public.media
|
|
9
|
-
SET folder = NULLIF(regexp_replace(object_key, '[^/]*$', ''), '')
|
|
10
|
-
WHERE folder IS NULL;
|
|
11
|
-
|
|
12
|
-
-- Index to speed up filtering by folder
|
|
13
|
-
CREATE INDEX IF NOT EXISTS media_folder_idx ON public.media (folder);
|
|
14
|
-
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
-- Ensure critical auth/public functions always use a safe search_path.
|
|
2
|
-
BEGIN;
|
|
3
|
-
|
|
4
|
-
CREATE OR REPLACE FUNCTION public.handle_languages_update()
|
|
5
|
-
RETURNS TRIGGER
|
|
6
|
-
LANGUAGE plpgsql
|
|
7
|
-
SECURITY DEFINER
|
|
8
|
-
SET search_path TO pg_temp, public
|
|
9
|
-
AS $$
|
|
10
|
-
BEGIN
|
|
11
|
-
NEW.updated_at = now();
|
|
12
|
-
RETURN NEW;
|
|
13
|
-
END;
|
|
14
|
-
$$;
|
|
15
|
-
|
|
16
|
-
CREATE OR REPLACE FUNCTION public.get_my_claim(claim TEXT)
|
|
17
|
-
RETURNS TEXT
|
|
18
|
-
LANGUAGE plpgsql
|
|
19
|
-
VOLATILE
|
|
20
|
-
SET search_path TO pg_temp, public
|
|
21
|
-
AS $$
|
|
22
|
-
DECLARE
|
|
23
|
-
claims jsonb;
|
|
24
|
-
claim_value text;
|
|
25
|
-
BEGIN
|
|
26
|
-
-- Safely get claims, defaulting to NULL if not present or invalid JSON
|
|
27
|
-
BEGIN
|
|
28
|
-
claims := current_setting('request.jwt.claims', true)::jsonb;
|
|
29
|
-
EXCEPTION
|
|
30
|
-
WHEN invalid_text_representation THEN
|
|
31
|
-
claims := NULL;
|
|
32
|
-
END;
|
|
33
|
-
|
|
34
|
-
-- If claims are NULL, return NULL
|
|
35
|
-
IF claims IS NULL THEN
|
|
36
|
-
RETURN NULL;
|
|
37
|
-
END IF;
|
|
38
|
-
|
|
39
|
-
-- Safely extract the claim value as text, removing quotes
|
|
40
|
-
claim_value := claims ->> claim;
|
|
41
|
-
|
|
42
|
-
RETURN claim_value;
|
|
43
|
-
END;
|
|
44
|
-
$$;
|
|
45
|
-
|
|
46
|
-
CREATE OR REPLACE FUNCTION public.get_my_role()
|
|
47
|
-
RETURNS TEXT
|
|
48
|
-
LANGUAGE plpgsql
|
|
49
|
-
SECURITY DEFINER
|
|
50
|
-
SET search_path TO pg_temp, public
|
|
51
|
-
AS $$
|
|
52
|
-
DECLARE
|
|
53
|
-
user_role TEXT;
|
|
54
|
-
BEGIN
|
|
55
|
-
SELECT role INTO user_role FROM public.profiles WHERE id = auth.uid();
|
|
56
|
-
RETURN user_role;
|
|
57
|
-
END;
|
|
58
|
-
$$;
|
|
59
|
-
|
|
60
|
-
CREATE OR REPLACE FUNCTION public.set_current_timestamp_updated_at()
|
|
61
|
-
RETURNS TRIGGER
|
|
62
|
-
LANGUAGE plpgsql
|
|
63
|
-
SET search_path TO pg_temp, public
|
|
64
|
-
AS $$
|
|
65
|
-
DECLARE
|
|
66
|
-
_new record;
|
|
67
|
-
BEGIN
|
|
68
|
-
_new := NEW;
|
|
69
|
-
_new."updated_at" = now();
|
|
70
|
-
RETURN _new;
|
|
71
|
-
END;
|
|
72
|
-
$$;
|
|
73
|
-
|
|
74
|
-
COMMIT;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
BEGIN;
|
|
2
|
-
|
|
3
|
-
-- Ensure profile read access uses a single policy and wraps auth.uid() safely.
|
|
4
|
-
DROP POLICY IF EXISTS "Allow user to read their own profile" ON public.profiles;
|
|
5
|
-
DROP POLICY IF EXISTS "authenticated_can_read_profiles" ON public.profiles;
|
|
6
|
-
|
|
7
|
-
CREATE POLICY "authenticated_can_read_profiles" ON public.profiles
|
|
8
|
-
FOR SELECT
|
|
9
|
-
TO authenticated
|
|
10
|
-
USING (
|
|
11
|
-
(id = (SELECT auth.uid())) OR
|
|
12
|
-
(public.get_current_user_role() = 'ADMIN')
|
|
13
|
-
);
|
|
14
|
-
COMMENT ON POLICY "authenticated_can_read_profiles" ON public.profiles IS 'Authenticated users can read their own profile; admins can read any profile.';
|
|
15
|
-
|
|
16
|
-
-- Harden storage.objects ownership checks.
|
|
17
|
-
DROP POLICY IF EXISTS "allow_authenticated_uploads" ON storage.objects;
|
|
18
|
-
DROP POLICY IF EXISTS "allow_authenticated_updates" ON storage.objects;
|
|
19
|
-
DROP POLICY IF EXISTS "allow_authenticated_deletes" ON storage.objects;
|
|
20
|
-
|
|
21
|
-
CREATE POLICY "allow_authenticated_uploads" ON storage.objects
|
|
22
|
-
FOR INSERT TO authenticated
|
|
23
|
-
WITH CHECK (bucket_id = 'public' AND owner = (SELECT auth.uid()));
|
|
24
|
-
|
|
25
|
-
CREATE POLICY "allow_authenticated_updates" ON storage.objects
|
|
26
|
-
FOR UPDATE TO authenticated
|
|
27
|
-
USING (bucket_id = 'public' AND owner = (SELECT auth.uid()));
|
|
28
|
-
|
|
29
|
-
CREATE POLICY "allow_authenticated_deletes" ON storage.objects
|
|
30
|
-
FOR DELETE TO authenticated
|
|
31
|
-
USING (bucket_id = 'public' AND owner = (SELECT auth.uid()));
|
|
32
|
-
|
|
33
|
-
-- Keep select policy as-is (bucket scoped) since it does not reference auth.uid().
|
|
34
|
-
|
|
35
|
-
-- Update site_settings policies to avoid initplan warnings.
|
|
36
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to insert into site_settings" ON public.site_settings;
|
|
37
|
-
DROP POLICY IF EXISTS "Allow ADMIN and WRITER to update site_settings" ON public.site_settings;
|
|
38
|
-
|
|
39
|
-
CREATE POLICY "Allow ADMIN and WRITER to insert into site_settings" ON public.site_settings
|
|
40
|
-
FOR INSERT TO authenticated
|
|
41
|
-
WITH CHECK (
|
|
42
|
-
EXISTS (
|
|
43
|
-
SELECT 1 FROM public.profiles
|
|
44
|
-
WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')
|
|
45
|
-
)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
CREATE POLICY "Allow ADMIN and WRITER to update site_settings" ON public.site_settings
|
|
49
|
-
FOR UPDATE TO authenticated
|
|
50
|
-
USING (
|
|
51
|
-
EXISTS (
|
|
52
|
-
SELECT 1 FROM public.profiles
|
|
53
|
-
WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')
|
|
54
|
-
)
|
|
55
|
-
)
|
|
56
|
-
WITH CHECK (
|
|
57
|
-
EXISTS (
|
|
58
|
-
SELECT 1 FROM public.profiles
|
|
59
|
-
WHERE id = (SELECT auth.uid()) AND role IN ('ADMIN', 'WRITER')
|
|
60
|
-
)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
COMMIT;
|