@nextblock-cms/db 0.17.6 → 0.17.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextblock-cms/db",
3
- "version": "0.17.6",
3
+ "version": "0.17.7",
4
4
  "main": "index.cjs.js",
5
5
  "module": "index.es.js",
6
6
  "types": "index.d.ts",
@@ -0,0 +1,102 @@
1
+ -- 02013: clear the Supabase Advisor warnings on RLS policies and trigger-function grants.
2
+ --
3
+ -- Performance advisor
4
+ -- * auth_rls_initplan: cms_interactions_insert_policy called auth.uid() per candidate row.
5
+ -- Wrapped as (select auth.uid()) it becomes an InitPlan evaluated once per statement.
6
+ -- * multiple_permissive_policies: cms_redirects and site_scripts each had two SELECT
7
+ -- policies for `authenticated` ("Admins read all …" and "Public read active …"), and
8
+ -- form_endpoints had an admin FOR ALL policy overlapping the editor SELECT policy. Every
9
+ -- permissive policy that matches a role + command is evaluated for every row, so the
10
+ -- policies are re-cut so exactly one applies per role + command. Who can read or write
11
+ -- what is unchanged:
12
+ -- - anon reads active redirects / scripts;
13
+ -- - authenticated reads active rows, ADMIN reads all;
14
+ -- - form_endpoints: ADMIN + WRITER read, ADMIN writes (now three command-scoped
15
+ -- policies instead of FOR ALL), service_role unchanged.
16
+ --
17
+ -- Security advisor
18
+ -- * anon_/authenticated_security_definer_function_executable: handle_new_user() and
19
+ -- update_product_ratings() are SECURITY DEFINER trigger functions. Postgres checks
20
+ -- EXECUTE on a trigger function only at CREATE TRIGGER time, never when the trigger
21
+ -- fires (and PostgREST cannot call a `RETURNS trigger` function via /rpc anyway), so
22
+ -- anon and authenticated never needed the privilege. 02003 already revokes it on
23
+ -- handle_new_user() for fresh installs, but production recorded the baseline as applied
24
+ -- without running it (docs/04 → "How a squash crosses live databases"), so the
25
+ -- generation-1 grants were still live there. Idempotent: safe on a fresh install too.
26
+ --
27
+ -- The two Auth-dashboard warnings (leaked password protection, MFA options) are project
28
+ -- settings, not schema, and are not addressed here.
29
+
30
+ -- ---------------------------------------------------------------------------
31
+ -- cms_interactions: InitPlan-friendly auth.uid()
32
+ -- ---------------------------------------------------------------------------
33
+ DROP POLICY IF EXISTS cms_interactions_insert_policy ON public.cms_interactions;
34
+ CREATE POLICY cms_interactions_insert_policy ON public.cms_interactions
35
+ FOR INSERT TO authenticated
36
+ WITH CHECK (
37
+ ((SELECT auth.uid()) = user_id)
38
+ AND (
39
+ status = 'pending'::public.approval_status
40
+ OR (SELECT public.get_current_user_role()) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role])
41
+ )
42
+ );
43
+
44
+ -- ---------------------------------------------------------------------------
45
+ -- cms_redirects: one SELECT policy per role
46
+ -- ---------------------------------------------------------------------------
47
+ DROP POLICY IF EXISTS "Admins read all redirects" ON public.cms_redirects;
48
+ DROP POLICY IF EXISTS "Public read active redirects" ON public.cms_redirects;
49
+ DROP POLICY IF EXISTS "Authenticated read redirects" ON public.cms_redirects;
50
+
51
+ CREATE POLICY "Public read active redirects" ON public.cms_redirects
52
+ FOR SELECT TO anon
53
+ USING (is_active);
54
+
55
+ CREATE POLICY "Authenticated read redirects" ON public.cms_redirects
56
+ FOR SELECT TO authenticated
57
+ USING (is_active OR (SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role);
58
+
59
+ -- ---------------------------------------------------------------------------
60
+ -- site_scripts: one SELECT policy per role
61
+ -- ---------------------------------------------------------------------------
62
+ DROP POLICY IF EXISTS "Admins read all site scripts" ON public.site_scripts;
63
+ DROP POLICY IF EXISTS "Public read active site scripts" ON public.site_scripts;
64
+ DROP POLICY IF EXISTS "Authenticated read site scripts" ON public.site_scripts;
65
+
66
+ CREATE POLICY "Public read active site scripts" ON public.site_scripts
67
+ FOR SELECT TO anon
68
+ USING (is_active);
69
+
70
+ CREATE POLICY "Authenticated read site scripts" ON public.site_scripts
71
+ FOR SELECT TO authenticated
72
+ USING (is_active OR (SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role);
73
+
74
+ -- ---------------------------------------------------------------------------
75
+ -- form_endpoints: admin FOR ALL -> INSERT / UPDATE / DELETE, editor SELECT stays the only read
76
+ -- ---------------------------------------------------------------------------
77
+ DROP POLICY IF EXISTS form_endpoints_admin_write_policy ON public.form_endpoints;
78
+ DROP POLICY IF EXISTS form_endpoints_admin_insert_policy ON public.form_endpoints;
79
+ DROP POLICY IF EXISTS form_endpoints_admin_update_policy ON public.form_endpoints;
80
+ DROP POLICY IF EXISTS form_endpoints_admin_delete_policy ON public.form_endpoints;
81
+
82
+ CREATE POLICY form_endpoints_admin_insert_policy ON public.form_endpoints
83
+ FOR INSERT TO authenticated
84
+ WITH CHECK ((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role);
85
+
86
+ CREATE POLICY form_endpoints_admin_update_policy ON public.form_endpoints
87
+ FOR UPDATE TO authenticated
88
+ USING ((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role)
89
+ WITH CHECK ((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role);
90
+
91
+ CREATE POLICY form_endpoints_admin_delete_policy ON public.form_endpoints
92
+ FOR DELETE TO authenticated
93
+ USING ((SELECT public.get_current_user_role()) = 'ADMIN'::public.user_role);
94
+
95
+ -- ---------------------------------------------------------------------------
96
+ -- SECURITY DEFINER trigger functions: not callable by API roles
97
+ -- ---------------------------------------------------------------------------
98
+ REVOKE EXECUTE ON FUNCTION public.handle_new_user() FROM PUBLIC, anon, authenticated;
99
+ GRANT EXECUTE ON FUNCTION public.handle_new_user() TO service_role;
100
+
101
+ REVOKE EXECUTE ON FUNCTION public.update_product_ratings() FROM PUBLIC, anon, authenticated;
102
+ GRANT EXECUTE ON FUNCTION public.update_product_ratings() TO service_role;