@nextblock-cms/db 0.2.7 → 0.2.9
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 +319 -0
- package/supabase/migrations/20250513194738_setup_roles_and_profiles.sql +41 -0
- package/supabase/migrations/20250513194910_auto_create_profile_trigger.sql +48 -0
- package/supabase/migrations/20250513194916_rls_for_profiles.sql +85 -0
- package/supabase/migrations/20250514125634_fix_recursive_rls_policies.sql +51 -0
- package/supabase/migrations/20250514143016_setup_languages_table.sql +66 -0
- package/supabase/migrations/20250514171549_create_pages_table.sql +73 -0
- package/supabase/migrations/20250514171550_create_posts_table.sql +61 -0
- package/supabase/migrations/20250514171552_create_media_table.sql +45 -0
- package/supabase/migrations/20250514171553_create_blocks_table.sql +54 -0
- package/supabase/migrations/20250514171615_create_navigation_table.sql +56 -0
- package/supabase/migrations/20250514171627_rls_policies_for_content_tables.sql +70 -0
- package/supabase/migrations/20250515194800_add_translation_group_id.sql +39 -0
- package/supabase/migrations/20250520171900_add_translation_group_to_nav_items.sql +21 -0
- package/supabase/migrations/20250521143933_seed_homepage_and_nav.sql +64 -0
- package/supabase/migrations/20250523145833_add_feature_image_to_posts.sql +8 -0
- package/supabase/migrations/20250523151737_add_rls_to_media_table.sql +18 -0
- package/supabase/migrations/20250526110400_add_image_dimensions_to_media.sql +14 -0
- package/supabase/migrations/20250526153321_optimize_rls_policies.sql +188 -0
- package/supabase/migrations/20250526172513_resolve_select_policy_overlaps.sql +96 -0
- package/supabase/migrations/20250526172853_resolve_remaining_rls_v5.sql +107 -0
- package/supabase/migrations/20250526173538_finalize_rls_cleanup_v7.sql +110 -0
- package/supabase/migrations/20250526174710_separate_write_policies_v8.sql +147 -0
- package/supabase/migrations/20250526175359_fix_languages_select_rls_v9.sql +81 -0
- package/supabase/migrations/20250526182940_fix_nav_read_policy_v10.sql +27 -0
- package/supabase/migrations/20250526183239_fix_posts_read_rls_v11.sql +59 -0
- package/supabase/migrations/20250526183746_fix_media_select_rls_v12.sql +39 -0
- package/supabase/migrations/20250526184205_consolidate_content_read_rls_v13.sql +61 -0
- package/supabase/migrations/20250526185854_optimize_indexes.sql +47 -0
- package/supabase/migrations/20250526190900_debug_blocks_rls.sql +56 -0
- package/supabase/migrations/20250526191217_consolidate_blocks_select_rls.sql +79 -0
- package/supabase/migrations/20250526192822_fix_handle_languages_update_search_path.sql +32 -0
- package/supabase/migrations/20250527150500_fix_blocks_rls_policy.sql +54 -0
- package/supabase/migrations/20250602150602_add_blur_data_url_to_media.sql +4 -0
- package/supabase/migrations/20250602150959_add_variants_to_media.sql +4 -0
- package/supabase/migrations/20250618124000_create_get_my_claim_function.sql +5 -0
- package/supabase/migrations/20250618124100_create_logos_table.sql +29 -0
- package/supabase/migrations/20250618130000_fix_linter_warnings.sql +58 -0
- package/supabase/migrations/20250618151500_revert_storage_rls.sql +6 -0
- package/supabase/migrations/20250619084800_reinstate_storage_rls.sql +13 -0
- package/supabase/migrations/20250619092430_widen_logo_insert_policy.sql +6 -0
- package/supabase/migrations/20250619093122_fix_get_my_claim_volatility.sql +5 -0
- package/supabase/migrations/20250619104249_consolidated_logo_rls_fix.sql +56 -0
- package/supabase/migrations/20250619110700_fix_logo_rls_again.sql +59 -0
- package/supabase/migrations/20250619113200_add_file_path_to_media.sql +4 -0
- package/supabase/migrations/20250619124100_fix_rls_performance_warnings.sql +74 -0
- package/supabase/migrations/20250619195500_create_site_settings_table.sql +28 -0
- package/supabase/migrations/20250619201500_add_anon_read_to_site_settings.sql +7 -0
- package/supabase/migrations/20250619202000_add_is_active_to_languages.sql +5 -0
- package/supabase/migrations/20250620085700_fix_site_settings_write_rls.sql +27 -0
- package/supabase/migrations/20250620095500_fix_profiles_read_rls.sql +11 -0
- package/supabase/migrations/20250620100000_use_security_definer_for_rls.sql +39 -0
- package/supabase/migrations/20250620130000_add_public_read_to_logos.sql +4 -0
- package/supabase/migrations/20250708091700_create_translations_table.sql +55 -0
- package/supabase/migrations/20250708093403_seed_translations_table.sql +20 -0
- package/supabase/migrations/20250708110600_fix_translations_rls_policies.sql +11 -0
- package/supabase/migrations/20250708112300_add_new_translations.sql +9 -0
- package/supabase/migrations/20250709120000_create_revisions_tables.sql +109 -0
- package/supabase/migrations/20251001113000_add_folder_to_media.sql +14 -0
- package/supabase/migrations/20251112113736_fix_search_path_functions.sql +74 -0
- package/supabase/migrations/20251112124444_fix_rls_performance.sql +63 -0
- package/supabase/migrations/20251112125935_fix_combined_policies.sql +194 -0
- package/supabase/migrations/20251112132146_fix_foreign_key_indexes.sql +21 -0
- package/supabase/migrations/20251112132525_cleanup_unused_indexes.sql +10 -0
- package/supabase/migrations/20251112132822_fix_final_indexes.sql +14 -0
- package/supabase/migrations/20251112140000_scaffold_foundational_content.sql +95 -0
- package/supabase/migrations/20251112141000_seed_homepage_blocks.sql +656 -0
- package/supabase/migrations/20251112142000_seed_how_it_works_post_blocks.sql +100 -0
- package/supabase/migrations/20251112143000_seed_additional_translations.sql +102 -0
- package/supabase/migrations/20251112145000_grant_public_schema_usage.sql +6 -0
- package/supabase/migrations/20251112145500_grant_select_on_public_tables.sql +19 -0
- package/supabase/migrations/20251117093000_add_admin_created_flag.sql +21 -0
- package/supabase/migrations/20251117103000_relax_profile_username_constraint.sql +6 -0
- package/supabase/migrations/20251117110000_relax_profiles_site_settings_rls_for_signup.sql +20 -0
- package/supabase/migrations/20251117112000_fix_handle_new_user_role_enum.sql +45 -0
- package/supabase/migrations/20251117113000_cleanup_rls_duplicates.sql +20 -0
- package/supabase/migrations/20251117200000_media_service_role_insert.sql +14 -0
- package/supabase/migrations/20251117201500_media_service_role_select.sql +11 -0
- package/supabase/migrations/20251117203000_media_admin_writer_select.sql +11 -0
- package/supabase/migrations/20251117204500_fix_media_permissions.sql +43 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
-- supabase/migrations/20251112142000_seed_how_it_works_post_blocks.sql
|
|
2
|
+
-- Populates the English "How NextBlock Works" post with a synthesized technical article.
|
|
3
|
+
|
|
4
|
+
WITH target_posts AS (
|
|
5
|
+
SELECT id, language_id, slug
|
|
6
|
+
FROM public.posts
|
|
7
|
+
WHERE slug IN ('how-nextblock-works', 'comment-nextblock-fonctionne')
|
|
8
|
+
),
|
|
9
|
+
purged AS (
|
|
10
|
+
DELETE FROM public.blocks
|
|
11
|
+
WHERE post_id IN (SELECT id FROM target_posts)
|
|
12
|
+
)
|
|
13
|
+
INSERT INTO public.blocks (post_id, language_id, block_type, content, "order")
|
|
14
|
+
SELECT
|
|
15
|
+
target_posts.id,
|
|
16
|
+
target_posts.language_id,
|
|
17
|
+
'text',
|
|
18
|
+
jsonb_build_object(
|
|
19
|
+
'html_content',
|
|
20
|
+
$$<h2>How NextBlock Works: Architecture for a Visual-First CMS</h2>
|
|
21
|
+
<p>NextBlock is purpose-built to feel like a polished product from day one, and that polish starts with the Nx monorepo. Applications and libraries sit side-by-side so the same code that powers the hosted CMS experience also ships inside the open-source template and CLI. Instead of scattering configuration across projects, TypeScript paths, Tailwind presets, and shared lint rules all originate from the workspace root, which keeps every downstream package aligned.</p>
|
|
22
|
+
<div class='flex flex-col md:flex-row gap-8 items-start my-8'>
|
|
23
|
+
<div class='w-full md:w-3/5 space-y-4'>
|
|
24
|
+
<h3>Monorepo Layout and Dependency Flow</h3>
|
|
25
|
+
<p>The <code>apps/nextblock</code> directory contains the production Next.js interface—both the public site and the authenticated CMS. The <code>apps/create-nextblock</code> CLI mirrors it, syncing files from the main app before publishing a scaffolding tool. Reusable primitives live under <code>libs/</code>. UI components and design tokens are exported from <code>@nextblock-cms/ui</code>, cross-cutting helpers (translations, R2 clients, Supabase environment guards) live in <code>@nextblock-cms/utils</code>, and database code plus migrations are centralized inside <code>@nextblock-cms/db</code>. Future-facing work, like the SDK and e-commerce module, already have dedicated libraries so they can mature without disrupting the core runtime.</p>
|
|
26
|
+
<p>This organization matters because Nx understands project boundaries. When you run <code>nx graph</code> you see exactly how a change in the editor package might ripple into the Next.js app. Path aliases from <code>tsconfig.base.json</code> and the shared <code>tailwind.config.js</code> ensure that every consumer sees the same theme scales and helper utilities, which is crucial for a system that promises design parity between marketing pages, admin screens, and scaffolded customer projects.</p>
|
|
27
|
+
<p>Together, those guardrails mean features can ship quickly without regressions. Schema migrations live in <code>libs/db</code>, UI primitives live in <code>libs/ui</code>, and the CLI simply syncs changes downstream—no copy/paste debt, no drifting configs.</p>
|
|
28
|
+
</div>
|
|
29
|
+
<aside class='md:w-2/5 bg-muted/40 border border-border/40 rounded-2xl p-4 shadow-lg text-center'>
|
|
30
|
+
<img src='/images/nx-graph.webp' alt='Nx project graph preview' class='w-full h-auto object-cover rounded-lg' />
|
|
31
|
+
<p class='text-sm text-muted-foreground mt-3'>Nx keeps every workspace relationship visible.</p>
|
|
32
|
+
</aside>
|
|
33
|
+
</div>
|
|
34
|
+
<h3>Inside the CMS Application</h3>
|
|
35
|
+
<p>Within <code>apps/nextblock/app/cms</code>, each feature area—pages, posts, media, navigation, users, settings—follows a predictable file pattern: a list page, creation and edit routes, server actions, and scoped client components. The root CMS layout enforces authentication, builds the shell (sidebar, responsive header, profile menu), and injects role-aware navigation. That means writers can jump straight into the block editor while admins unlock additional menus such as language management or user provisioning, all without duplicating layout logic.</p>
|
|
36
|
+
<p>Server actions wrap Supabase calls so mutations never leak credentials into the browser. Media uploads coordinate with Cloudflare R2, navigation management includes drag-and-drop ordering, and every table interaction respects the row-level security policies defined in the Supabase migrations—e.g., only admins and writers can mutate pages or posts while anonymous traffic can only read published content.</p>
|
|
37
|
+
<h3>Tech Stack and Runtime</h3>
|
|
38
|
+
<p>The stack highlighted in the project README—Next.js 15, Supabase, Tailwind CSS, and shadcn/ui—was selected to balance developer velocity with runtime performance. Next.js App Router unlocks Server Components, streaming, and incremental static regeneration so marketing experiences remain edge-fast. Supabase covers Postgres, Auth, and Storage, shrinking the operational footprint while still allowing custom SQL migrations. Tailwind plus shadcn/ui provide composable building blocks so the CMS interface, marketing site, and generated client projects all inherit the same visual language.</p>
|
|
39
|
+
<p>Nx tooling ties it together. Common commands such as <code>nx serve nextblock</code>, <code>nx build nextblock</code>, or workspace-wide tasks like <code>nx run-many -t lint --all</code> respect dependency caching, so even large rebuilds feel snappy during the 100-day roadmap.</p>
|
|
40
|
+
<pre><code>nx serve nextblock
|
|
41
|
+
nx run-many -t build --all
|
|
42
|
+
supabase db push
|
|
43
|
+
</code></pre>
|
|
44
|
+
<h3>The Tiptap-Based Block Editor</h3>
|
|
45
|
+
<p>The <code>@nextblock-cms/editor</code> package turns Tiptap v3 into a polished, reusable editing surface. It ships rich-text formatting, tables, task lists, slash commands, floating and bubble menus, character counts, focus mode, and syntax-highlighted code blocks. Under the hood it bundles StarterKit, TextStyleKit, CodeBlockLowlight, Image, TaskList, Table, Link, TextAlign, Highlight, Typography, and more. Because the editor is published as a standalone library, both the CMS and the generated template pull identical behavior, ensuring content parity.</p>
|
|
46
|
+
<p>From an implementation standpoint, the editor exposes granular components—EditorToolbar, BubbleMenu, FloatingMenu—so the CMS can embed one cohesive editing experience while keeping the door open for agencies or plugin developers to compose their own UI. Comprehensive CSS hooks (e.g., <code>.tiptap pre</code> for code blocks) mean that teams can layer in dark-mode friendly themes without forking the core package.</p>
|
|
47
|
+
<h3>Putting It All Together</h3>
|
|
48
|
+
<p>The result is a platform where architecture decisions reinforce each other: the Nx workspace keeps libraries honest, the Next.js app enforces UX consistency, Supabase migrations codify access rules, and the Tiptap editor guarantees that content collaborators see the same tooling regardless of deployment. When a new team runs <code>npm create nextblock</code>, they inherit not just a starter site, but the entire operational philosophy described above—ready to extend with SDKs, premium modules, and marketplace blocks as the ecosystem grows.</p>$$
|
|
49
|
+
),
|
|
50
|
+
0
|
|
51
|
+
FROM target_posts
|
|
52
|
+
WHERE target_posts.slug = 'how-nextblock-works'
|
|
53
|
+
|
|
54
|
+
UNION ALL
|
|
55
|
+
|
|
56
|
+
SELECT
|
|
57
|
+
target_posts.id,
|
|
58
|
+
target_posts.language_id,
|
|
59
|
+
'text',
|
|
60
|
+
jsonb_build_object(
|
|
61
|
+
'html_content',
|
|
62
|
+
$$<h2>Comment NextBlock fonctionne : architecture pour un CMS axé sur l'expérience visuelle</h2>
|
|
63
|
+
<p>NextBlock est conçu pour fonctionner dès le premier jour avec un socle Nx. Applications et librairies cohabitent pour que le même code propulse l'expérience CMS hébergée et le template open-source. Au lieu d'éparpiller la configuration, les chemins TypeScript, le preset Tailwind et les règles lint sont centralisés à la racine, gardant tous les packages alignés.</p>
|
|
64
|
+
<div class='flex flex-col md:flex-row gap-8 items-start my-8'>
|
|
65
|
+
<div class='w-full md:w-3/5 space-y-4'>
|
|
66
|
+
<h3>Architecture monorepo et flux de dépendances</h3>
|
|
67
|
+
<p>Le dossier <code>apps/nextblock</code> contient l'interface Next.js (site public + CMS). Le CLI <code>apps/create-nextblock</code> la reflète et publie un outil de scaffolding. Les briques réutilisables vivent dans <code>libs/</code> : UI et design tokens via <code>@nextblock-cms/ui</code>, helpers (traductions, R2, règles Supabase) via <code>@nextblock-cms/utils</code>, et la base de données + migrations dans <code>@nextblock-cms/db</code>. Les travaux futurs (SDK, e-commerce) ont déjà leurs librairies dédiées.</p>
|
|
68
|
+
<p>Ce découplage est lisible via <code>nx graph</code> : un changement dans l'éditeur impacte clairement les apps dépendantes. Les alias de <code>tsconfig.base.json</code> et le <code>tailwind.config.js</code> partagé assurent une cohérence de thème et d'outils entre pages marketing, back-office et projets générés.</p>
|
|
69
|
+
<p>En pratique, cela accélère les livraisons sans régressions : migrations dans <code>libs/db</code>, primitives UI dans <code>libs/ui</code>, et le CLI synchronise simplement en aval—pas de dettes de copier/coller ni de configs divergentes.</p>
|
|
70
|
+
</div>
|
|
71
|
+
<aside class='md:w-2/5 bg-muted/40 border border-border/40 rounded-2xl p-4 shadow-lg text-center'>
|
|
72
|
+
<img src='/images/nx-graph.webp' alt='Aperçu du graph Nx' class='w-full h-auto object-cover rounded-lg' />
|
|
73
|
+
<p class='text-sm text-muted-foreground mt-3'>Nx rend visibles toutes les relations du workspace.</p>
|
|
74
|
+
</aside>
|
|
75
|
+
</div>
|
|
76
|
+
<h3>Stack technique et exécution</h3>
|
|
77
|
+
<p>Le stack—Next.js 15, Supabase, Tailwind CSS, shadcn/ui—équilibre vélocité et performance. L'App Router active les Server Components et l'ISR pour un rendu edge rapide. Supabase gère Postgres/Auth/Storage, réduisant l'opérationnel tout en gardant la liberté SQL. Tailwind + shadcn/ui fournissent des blocs réutilisables pour le CMS, le site marketing et les projets générés.</p>
|
|
78
|
+
<pre><code>nx serve nextblock
|
|
79
|
+
nx run-many -t build --all
|
|
80
|
+
supabase db push
|
|
81
|
+
</code></pre>
|
|
82
|
+
<h3>Éditeur basé sur Tiptap</h3>
|
|
83
|
+
<p>Le package <code>@nextblock-cms/editor</code> transforme Tiptap v3 en surface d'édition robuste : mise en forme riche, menus contextuels, compteurs de caractères, blocs de code avec syntax highlighting, tables, listes de tâches, et plus. Éditor et template consomment la même librairie pour garantir la parité de contenu.</p>
|
|
84
|
+
<h3>En résumé</h3>
|
|
85
|
+
<p>Chaque choix architectural se renforce : Nx garde les dépendances lisibles, l'app Next.js impose une UX cohérente, les migrations Supabase codifient l'accès, et l'éditeur Tiptap assure une expérience identique pour tous les contributeurs.</p>$$
|
|
86
|
+
),
|
|
87
|
+
0
|
|
88
|
+
FROM target_posts
|
|
89
|
+
WHERE target_posts.slug = 'comment-nextblock-fonctionne';
|
|
90
|
+
|
|
91
|
+
SELECT id AS how_it_works_post_block_id, "order"
|
|
92
|
+
FROM public.blocks
|
|
93
|
+
WHERE post_id = (
|
|
94
|
+
SELECT id FROM public.posts
|
|
95
|
+
WHERE slug = 'how-nextblock-works'
|
|
96
|
+
AND language_id = (SELECT id FROM public.languages WHERE code = 'en' LIMIT 1)
|
|
97
|
+
ORDER BY created_at DESC
|
|
98
|
+
LIMIT 1
|
|
99
|
+
)
|
|
100
|
+
ORDER BY "order";
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
-- supabase/migrations/20251112143000_seed_additional_translations.sql
|
|
2
|
+
-- Adds French values to every existing translation key.
|
|
3
|
+
|
|
4
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
5
|
+
('sign_in', '{"fr": "Connexion"}')
|
|
6
|
+
ON CONFLICT (key) DO UPDATE
|
|
7
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
8
|
+
|
|
9
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
10
|
+
('sign_up', '{"fr": "Inscription"}')
|
|
11
|
+
ON CONFLICT (key) DO UPDATE
|
|
12
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
13
|
+
|
|
14
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
15
|
+
('sign_out', '{"fr": "Déconnexion"}')
|
|
16
|
+
ON CONFLICT (key) DO UPDATE
|
|
17
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
18
|
+
|
|
19
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
20
|
+
('dont_have_account', '{"fr": "Pas encore de compte ?"}')
|
|
21
|
+
ON CONFLICT (key) DO UPDATE
|
|
22
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
23
|
+
|
|
24
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
25
|
+
('email', '{"fr": "Email"}')
|
|
26
|
+
ON CONFLICT (key) DO UPDATE
|
|
27
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
28
|
+
|
|
29
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
30
|
+
('you_at_example_com', '{"fr": "vous@example.com"}')
|
|
31
|
+
ON CONFLICT (key) DO UPDATE
|
|
32
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
33
|
+
|
|
34
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
35
|
+
('password', '{"fr": "Mot de passe"}')
|
|
36
|
+
ON CONFLICT (key) DO UPDATE
|
|
37
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
38
|
+
|
|
39
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
40
|
+
('forgot_password', '{"fr": "Mot de passe oublié ?"}')
|
|
41
|
+
ON CONFLICT (key) DO UPDATE
|
|
42
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
43
|
+
|
|
44
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
45
|
+
('your_password', '{"fr": "Votre mot de passe"}')
|
|
46
|
+
ON CONFLICT (key) DO UPDATE
|
|
47
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
48
|
+
|
|
49
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
50
|
+
('signing_in_pending', '{"fr": "Connexion en cours..."}')
|
|
51
|
+
ON CONFLICT (key) DO UPDATE
|
|
52
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
53
|
+
|
|
54
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
55
|
+
('already_have_account', '{"fr": "Déjà un compte ?"}')
|
|
56
|
+
ON CONFLICT (key) DO UPDATE
|
|
57
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
58
|
+
|
|
59
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
60
|
+
('signing_up_pending', '{"fr": "Inscription en cours..."}')
|
|
61
|
+
ON CONFLICT (key) DO UPDATE
|
|
62
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
63
|
+
|
|
64
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
65
|
+
('reset_password', '{"fr": "Réinitialiser le mot de passe"}')
|
|
66
|
+
ON CONFLICT (key) DO UPDATE
|
|
67
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
68
|
+
|
|
69
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
70
|
+
('edit_page', '{"fr": "Éditer la page"}')
|
|
71
|
+
ON CONFLICT (key) DO UPDATE
|
|
72
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
73
|
+
|
|
74
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
75
|
+
('edit_post', '{"fr": "Éditer l''article"}')
|
|
76
|
+
ON CONFLICT (key) DO UPDATE
|
|
77
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
78
|
+
|
|
79
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
80
|
+
('open_main_menu', '{"fr": "Ouvrir le menu principal"}')
|
|
81
|
+
ON CONFLICT (key) DO UPDATE
|
|
82
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
83
|
+
|
|
84
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
85
|
+
('mobile_navigation_menu', '{"fr": "Menu de navigation mobile"}')
|
|
86
|
+
ON CONFLICT (key) DO UPDATE
|
|
87
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
88
|
+
|
|
89
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
90
|
+
('cms_dashboard', '{"fr": "Tableau de bord CMS"}')
|
|
91
|
+
ON CONFLICT (key) DO UPDATE
|
|
92
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
93
|
+
|
|
94
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
95
|
+
('update_env_file_warning', '{"fr": "Veuillez mettre à jour .env.local avec l''anon key et l''URL"}')
|
|
96
|
+
ON CONFLICT (key) DO UPDATE
|
|
97
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
98
|
+
|
|
99
|
+
INSERT INTO public.translations (key, translations) VALUES
|
|
100
|
+
('greeting', '{"fr": "Salut, {username} !"}')
|
|
101
|
+
ON CONFLICT (key) DO UPDATE
|
|
102
|
+
SET translations = public.translations.translations || EXCLUDED.translations;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Ensure anon/authenticated roles can read existing and future public tables/sequences
|
|
2
|
+
|
|
3
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO anon;
|
|
4
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO authenticated;
|
|
5
|
+
|
|
6
|
+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO anon;
|
|
7
|
+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO authenticated;
|
|
8
|
+
|
|
9
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
10
|
+
GRANT SELECT ON TABLES TO anon;
|
|
11
|
+
|
|
12
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
13
|
+
GRANT SELECT ON TABLES TO authenticated;
|
|
14
|
+
|
|
15
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
16
|
+
GRANT USAGE, SELECT ON SEQUENCES TO anon;
|
|
17
|
+
|
|
18
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
19
|
+
GRANT USAGE, SELECT ON SEQUENCES TO authenticated;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- Ensure the admin flag exists as a key/value entry
|
|
2
|
+
INSERT INTO public.site_settings (key, value)
|
|
3
|
+
VALUES ('is_admin_created', 'false'::jsonb)
|
|
4
|
+
ON CONFLICT (key) DO NOTHING;
|
|
5
|
+
|
|
6
|
+
-- Allow the security definer function (owned by postgres/service_role) to read/update this flag
|
|
7
|
+
DROP POLICY IF EXISTS site_settings_admin_seed ON public.site_settings;
|
|
8
|
+
CREATE POLICY site_settings_admin_seed
|
|
9
|
+
ON public.site_settings
|
|
10
|
+
FOR ALL
|
|
11
|
+
TO postgres, service_role
|
|
12
|
+
USING (true)
|
|
13
|
+
WITH CHECK (true);
|
|
14
|
+
|
|
15
|
+
-- Ensure the trigger can insert profiles under RLS by allowing service_role to insert
|
|
16
|
+
DROP POLICY IF EXISTS profiles_service_role_insert ON public.profiles;
|
|
17
|
+
CREATE POLICY profiles_service_role_insert
|
|
18
|
+
ON public.profiles
|
|
19
|
+
FOR INSERT
|
|
20
|
+
TO service_role, postgres
|
|
21
|
+
WITH CHECK (true);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Broaden RLS to ensure auth signup trigger can run without RLS conflicts
|
|
2
|
+
|
|
3
|
+
-- Profiles: allow service_role, authenticated, and anon to insert (trigger runs after auth.users insert)
|
|
4
|
+
DROP POLICY IF EXISTS profiles_service_role_insert ON public.profiles;
|
|
5
|
+
CREATE POLICY profiles_service_role_insert
|
|
6
|
+
ON public.profiles
|
|
7
|
+
FOR INSERT
|
|
8
|
+
TO service_role, postgres, authenticated, anon
|
|
9
|
+
WITH CHECK (true);
|
|
10
|
+
|
|
11
|
+
-- Profiles: allow reading own row or admin policies remain; no change needed for select/update here
|
|
12
|
+
|
|
13
|
+
-- Site settings: allow service_role/authenticated/anon to read and update the admin flag row
|
|
14
|
+
DROP POLICY IF EXISTS site_settings_admin_seed ON public.site_settings;
|
|
15
|
+
CREATE POLICY site_settings_admin_seed
|
|
16
|
+
ON public.site_settings
|
|
17
|
+
FOR ALL
|
|
18
|
+
TO service_role, postgres, authenticated, anon
|
|
19
|
+
USING (true)
|
|
20
|
+
WITH CHECK (true);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- Ensure handle_new_user uses the enum type and works with the KV admin flag
|
|
2
|
+
|
|
3
|
+
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
|
4
|
+
RETURNS TRIGGER
|
|
5
|
+
LANGUAGE plpgsql
|
|
6
|
+
SECURITY DEFINER
|
|
7
|
+
SET search_path = 'public'
|
|
8
|
+
AS $$
|
|
9
|
+
DECLARE
|
|
10
|
+
admin_flag_set BOOLEAN := FALSE;
|
|
11
|
+
user_role public.user_role;
|
|
12
|
+
BEGIN
|
|
13
|
+
-- Ensure the admin flag row exists
|
|
14
|
+
INSERT INTO public.site_settings (key, value)
|
|
15
|
+
VALUES ('is_admin_created', 'false'::jsonb)
|
|
16
|
+
ON CONFLICT (key) DO NOTHING;
|
|
17
|
+
|
|
18
|
+
-- Lock and read the flag
|
|
19
|
+
SELECT COALESCE((value)::jsonb::boolean, FALSE)
|
|
20
|
+
INTO admin_flag_set
|
|
21
|
+
FROM public.site_settings
|
|
22
|
+
WHERE key = 'is_admin_created'
|
|
23
|
+
FOR UPDATE;
|
|
24
|
+
|
|
25
|
+
IF admin_flag_set = FALSE THEN
|
|
26
|
+
user_role := 'ADMIN'::public.user_role;
|
|
27
|
+
UPDATE public.site_settings
|
|
28
|
+
SET value = 'true'::jsonb
|
|
29
|
+
WHERE key = 'is_admin_created';
|
|
30
|
+
ELSE
|
|
31
|
+
user_role := 'USER'::public.user_role;
|
|
32
|
+
END IF;
|
|
33
|
+
|
|
34
|
+
INSERT INTO public.profiles (id, role)
|
|
35
|
+
VALUES (NEW.id, user_role);
|
|
36
|
+
|
|
37
|
+
RETURN NEW;
|
|
38
|
+
END;
|
|
39
|
+
$$;
|
|
40
|
+
|
|
41
|
+
-- Drop and recreate the trigger to use the updated function
|
|
42
|
+
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
|
|
43
|
+
CREATE TRIGGER on_auth_user_created
|
|
44
|
+
AFTER INSERT ON auth.users
|
|
45
|
+
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Consolidate RLS policies to avoid multiple permissive policies per role/action
|
|
2
|
+
|
|
3
|
+
-- Profiles: keep a dedicated insert policy only for service_role/postgres (trigger context)
|
|
4
|
+
DROP POLICY IF EXISTS profiles_service_role_insert ON public.profiles;
|
|
5
|
+
CREATE POLICY profiles_service_role_insert
|
|
6
|
+
ON public.profiles
|
|
7
|
+
FOR INSERT
|
|
8
|
+
TO service_role, postgres
|
|
9
|
+
WITH CHECK (true);
|
|
10
|
+
|
|
11
|
+
-- Site settings: keep a dedicated policy only for service_role/postgres for trigger/maintenance
|
|
12
|
+
DROP POLICY IF EXISTS site_settings_admin_seed ON public.site_settings;
|
|
13
|
+
CREATE POLICY site_settings_admin_seed
|
|
14
|
+
ON public.site_settings
|
|
15
|
+
FOR ALL
|
|
16
|
+
TO service_role, postgres
|
|
17
|
+
USING (true)
|
|
18
|
+
WITH CHECK (true);
|
|
19
|
+
|
|
20
|
+
-- Leave the existing combined authenticated/anon policies in place (no duplicates per role/action)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Allows service_role to insert media records (used by signed upload flows)
|
|
2
|
+
-- without weakening existing RLS for other roles.
|
|
3
|
+
|
|
4
|
+
BEGIN;
|
|
5
|
+
|
|
6
|
+
-- Ensure idempotency for Supabase PG version (CREATE POLICY IF NOT EXISTS not available)
|
|
7
|
+
DROP POLICY IF EXISTS media_service_role_insert ON public.media;
|
|
8
|
+
|
|
9
|
+
CREATE POLICY media_service_role_insert ON public.media
|
|
10
|
+
FOR INSERT
|
|
11
|
+
TO service_role
|
|
12
|
+
WITH CHECK (true);
|
|
13
|
+
|
|
14
|
+
COMMIT;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Ensure service_role can read media rows (needed when uploads write media + linked inserts)
|
|
2
|
+
|
|
3
|
+
BEGIN;
|
|
4
|
+
|
|
5
|
+
DROP POLICY IF EXISTS media_service_role_select ON public.media;
|
|
6
|
+
CREATE POLICY media_service_role_select ON public.media
|
|
7
|
+
FOR SELECT
|
|
8
|
+
TO service_role
|
|
9
|
+
USING (true);
|
|
10
|
+
|
|
11
|
+
COMMIT;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Allow ADMIN/WRITER to read media rows (needed for media library + logos)
|
|
2
|
+
|
|
3
|
+
BEGIN;
|
|
4
|
+
|
|
5
|
+
DROP POLICY IF EXISTS media_admin_writer_can_read ON public.media;
|
|
6
|
+
CREATE POLICY media_admin_writer_can_read ON public.media
|
|
7
|
+
FOR SELECT
|
|
8
|
+
TO authenticated
|
|
9
|
+
USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
|
|
10
|
+
|
|
11
|
+
COMMIT;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Fix media permissions: ensure grants and RLS policies for admin/writer and service_role
|
|
2
|
+
|
|
3
|
+
BEGIN;
|
|
4
|
+
|
|
5
|
+
-- Privileges (required in addition to RLS)
|
|
6
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.media TO authenticated, service_role;
|
|
7
|
+
|
|
8
|
+
-- Reset policies to known good set
|
|
9
|
+
DROP POLICY IF EXISTS media_admin_writer_can_insert ON public.media;
|
|
10
|
+
DROP POLICY IF EXISTS media_admin_writer_can_update ON public.media;
|
|
11
|
+
DROP POLICY IF EXISTS media_admin_writer_can_delete ON public.media;
|
|
12
|
+
DROP POLICY IF EXISTS media_admin_writer_can_read ON public.media;
|
|
13
|
+
DROP POLICY IF EXISTS media_service_role_insert ON public.media;
|
|
14
|
+
DROP POLICY IF EXISTS media_service_role_select ON public.media;
|
|
15
|
+
|
|
16
|
+
-- Admin/Writer: full CRUD
|
|
17
|
+
CREATE POLICY media_admin_writer_can_insert ON public.media
|
|
18
|
+
FOR INSERT TO authenticated
|
|
19
|
+
WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
|
|
20
|
+
|
|
21
|
+
CREATE POLICY media_admin_writer_can_update ON public.media
|
|
22
|
+
FOR UPDATE TO authenticated
|
|
23
|
+
USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'))
|
|
24
|
+
WITH CHECK (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
|
|
25
|
+
|
|
26
|
+
CREATE POLICY media_admin_writer_can_delete ON public.media
|
|
27
|
+
FOR DELETE TO authenticated
|
|
28
|
+
USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
|
|
29
|
+
|
|
30
|
+
CREATE POLICY media_admin_writer_can_read ON public.media
|
|
31
|
+
FOR SELECT TO authenticated
|
|
32
|
+
USING (public.get_current_user_role() IN ('ADMIN', 'WRITER'));
|
|
33
|
+
|
|
34
|
+
-- service_role: insert + read (used by upload flows)
|
|
35
|
+
CREATE POLICY media_service_role_insert ON public.media
|
|
36
|
+
FOR INSERT TO service_role
|
|
37
|
+
WITH CHECK (true);
|
|
38
|
+
|
|
39
|
+
CREATE POLICY media_service_role_select ON public.media
|
|
40
|
+
FOR SELECT TO service_role
|
|
41
|
+
USING (true);
|
|
42
|
+
|
|
43
|
+
COMMIT;
|