@lastbrain/module-auth 2.0.13 → 2.0.16

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.
@@ -232,7 +232,7 @@ const authBuildConfig = {
232
232
  description: "Accédez à votre dossier personnel",
233
233
  icon: "FolderOpen",
234
234
  path: "/auth/folder",
235
- order: 2,
235
+ order: 99,
236
236
  shortcut: "cmd+shift+f",
237
237
  shortcutDisplay: "⌘⇧F",
238
238
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lastbrain/module-auth",
3
- "version": "2.0.13",
3
+ "version": "2.0.16",
4
4
  "description": "Module d'authentification complet pour LastBrain avec Supabase",
5
5
  "private": false,
6
6
  "type": "module",
@@ -32,8 +32,8 @@
32
32
  "supabase"
33
33
  ],
34
34
  "dependencies": {
35
- "@lastbrain/core": "^2.0.13",
36
- "@lastbrain/ui": "^2.0.13",
35
+ "@lastbrain/core": "^2.0.16",
36
+ "@lastbrain/ui": "^2.0.16",
37
37
  "@supabase/supabase-js": "^2.86.0",
38
38
  "lucide-react": "^0.554.0",
39
39
  "react": "^19.2.1",
@@ -235,7 +235,7 @@ const authBuildConfig: ModuleBuildConfig = {
235
235
  description: "Accédez à votre dossier personnel",
236
236
  icon: "FolderOpen",
237
237
  path: "/auth/folder",
238
- order: 2,
238
+ order: 99,
239
239
  shortcut: "cmd+shift+f",
240
240
  shortcutDisplay: "⌘⇧F",
241
241
  },
@@ -29,23 +29,23 @@ ALTER TABLE public.user_profil ENABLE ROW LEVEL SECURITY;
29
29
 
30
30
  DROP POLICY IF EXISTS user_profil_owner_select ON public.user_profil;
31
31
  CREATE POLICY user_profil_owner_select ON public.user_profil
32
- FOR SELECT USING (owner_id = auth.uid());
32
+ FOR SELECT USING (owner_id = (SELECT auth.uid()));
33
33
 
34
34
  DROP POLICY IF EXISTS user_profil_owner_insert ON public.user_profil;
35
35
  CREATE POLICY user_profil_owner_insert ON public.user_profil
36
- FOR INSERT WITH CHECK (owner_id = auth.uid());
36
+ FOR INSERT WITH CHECK (owner_id = (SELECT auth.uid()));
37
37
 
38
38
  DROP POLICY IF EXISTS user_profil_owner_update ON public.user_profil;
39
39
  CREATE POLICY user_profil_owner_update ON public.user_profil
40
- FOR UPDATE USING (owner_id = auth.uid());
40
+ FOR UPDATE USING (owner_id = (SELECT auth.uid()));
41
41
 
42
42
  DROP POLICY IF EXISTS user_profil_owner_delete ON public.user_profil;
43
43
  CREATE POLICY user_profil_owner_delete ON public.user_profil
44
- FOR DELETE USING (owner_id = auth.uid());
44
+ FOR DELETE USING (owner_id = (SELECT auth.uid()));
45
45
 
46
46
  DROP POLICY IF EXISTS user_profil_superadmin_all ON public.user_profil;
47
47
  CREATE POLICY user_profil_superadmin_all ON public.user_profil
48
- FOR ALL USING (is_superadmin(auth.uid()));
48
+ FOR ALL USING (is_superadmin((SELECT auth.uid())));
49
49
 
50
50
  -- Trigger updated_at
51
51
  CREATE OR REPLACE FUNCTION public.set_user_profil_updated_at()
@@ -54,7 +54,8 @@ BEGIN
54
54
  NEW.updated_at = now();
55
55
  RETURN NEW;
56
56
  END;
57
- $$ LANGUAGE plpgsql;
57
+ $$ LANGUAGE plpgsql
58
+ SET search_path = public;
58
59
 
59
60
  DROP TRIGGER IF EXISTS set_user_profil_updated_at ON public.user_profil;
60
61
  CREATE TRIGGER set_user_profil_updated_at
@@ -87,23 +88,23 @@ ALTER TABLE public.user_address ENABLE ROW LEVEL SECURITY;
87
88
 
88
89
  DROP POLICY IF EXISTS user_address_owner_select ON public.user_address;
89
90
  CREATE POLICY user_address_owner_select ON public.user_address
90
- FOR SELECT USING (owner_id = auth.uid());
91
+ FOR SELECT USING (owner_id = (SELECT auth.uid()));
91
92
 
92
93
  DROP POLICY IF EXISTS user_address_owner_insert ON public.user_address;
93
94
  CREATE POLICY user_address_owner_insert ON public.user_address
94
- FOR INSERT WITH CHECK (owner_id = auth.uid());
95
+ FOR INSERT WITH CHECK (owner_id = (SELECT auth.uid()));
95
96
 
96
97
  DROP POLICY IF EXISTS user_address_owner_update ON public.user_address;
97
98
  CREATE POLICY user_address_owner_update ON public.user_address
98
- FOR UPDATE USING (owner_id = auth.uid());
99
+ FOR UPDATE USING (owner_id = (SELECT auth.uid()));
99
100
 
100
101
  DROP POLICY IF EXISTS user_address_owner_delete ON public.user_address;
101
102
  CREATE POLICY user_address_owner_delete ON public.user_address
102
- FOR DELETE USING (owner_id = auth.uid());
103
+ FOR DELETE USING (owner_id = (SELECT auth.uid()));
103
104
 
104
105
  DROP POLICY IF EXISTS user_address_superadmin_all ON public.user_address;
105
106
  CREATE POLICY user_address_superadmin_all ON public.user_address
106
- FOR ALL USING (is_superadmin(auth.uid()));
107
+ FOR ALL USING (is_superadmin((SELECT auth.uid())));
107
108
 
108
109
  -- Trigger updated_at
109
110
  CREATE OR REPLACE FUNCTION public.set_user_address_updated_at()
@@ -112,7 +113,8 @@ BEGIN
112
113
  NEW.updated_at = now();
113
114
  RETURN NEW;
114
115
  END;
115
- $$ LANGUAGE plpgsql;
116
+ $$ LANGUAGE plpgsql
117
+ SET search_path = public;
116
118
 
117
119
  DROP TRIGGER IF EXISTS set_user_address_updated_at ON public.user_address;
118
120
  CREATE TRIGGER set_user_address_updated_at
@@ -141,23 +143,23 @@ ALTER TABLE public.user_notifications ENABLE ROW LEVEL SECURITY;
141
143
 
142
144
  DROP POLICY IF EXISTS user_notifications_owner_or_superadmin_select ON public.user_notifications;
143
145
  CREATE POLICY user_notifications_owner_or_superadmin_select ON public.user_notifications
144
- FOR SELECT USING (owner_id = auth.uid() OR is_superadmin(auth.uid()));
146
+ FOR SELECT USING (owner_id = (SELECT auth.uid()) OR is_superadmin((SELECT auth.uid())));
145
147
 
146
148
  DROP POLICY IF EXISTS user_notifications_owner_or_superadmin_insert ON public.user_notifications;
147
149
  CREATE POLICY user_notifications_owner_or_superadmin_insert ON public.user_notifications
148
- FOR INSERT WITH CHECK (owner_id = auth.uid() OR is_superadmin(auth.uid()));
150
+ FOR INSERT WITH CHECK (owner_id = (SELECT auth.uid()) OR is_superadmin((SELECT auth.uid())));
149
151
 
150
152
  DROP POLICY IF EXISTS user_notifications_owner_or_superadmin_update ON public.user_notifications;
151
153
  CREATE POLICY user_notifications_owner_or_superadmin_update ON public.user_notifications
152
- FOR UPDATE USING (owner_id = auth.uid() OR is_superadmin(auth.uid()));
154
+ FOR UPDATE USING (owner_id = (SELECT auth.uid()) OR is_superadmin((SELECT auth.uid())));
153
155
 
154
156
  DROP POLICY IF EXISTS user_notifications_owner_or_superadmin_delete ON public.user_notifications;
155
157
  CREATE POLICY user_notifications_owner_or_superadmin_delete ON public.user_notifications
156
- FOR DELETE USING (owner_id = auth.uid() OR is_superadmin(auth.uid()));
158
+ FOR DELETE USING (owner_id = (SELECT auth.uid()) OR is_superadmin((SELECT auth.uid())));
157
159
 
158
160
  DROP POLICY IF EXISTS user_notifications_superadmin_all ON public.user_notifications;
159
161
  CREATE POLICY user_notifications_superadmin_all ON public.user_notifications
160
- FOR ALL USING (is_superadmin(auth.uid()));
162
+ FOR ALL USING (is_superadmin((SELECT auth.uid())));
161
163
 
162
164
  -- Trigger updated_at
163
165
  CREATE OR REPLACE FUNCTION public.set_user_notifications_updated_at()
@@ -166,7 +168,8 @@ BEGIN
166
168
  NEW.updated_at = now();
167
169
  RETURN NEW;
168
170
  END;
169
- $$ LANGUAGE plpgsql;
171
+ $$ LANGUAGE plpgsql
172
+ SET search_path = public;
170
173
 
171
174
  DROP TRIGGER IF EXISTS set_user_notifications_updated_at ON public.user_notifications;
172
175
  CREATE TRIGGER set_user_notifications_updated_at
@@ -177,7 +180,20 @@ CREATE TRIGGER set_user_notifications_updated_at
177
180
  -- =====================================================
178
181
  -- Enable Realtime for user_notifications
179
182
  -- =====================================================
180
- ALTER PUBLICATION supabase_realtime ADD TABLE public.user_notifications;
183
+ -- Use DO block to handle idempotent add/remove
184
+ DO $$
185
+ BEGIN
186
+ -- Try to remove the table from publication if it exists
187
+ BEGIN
188
+ ALTER PUBLICATION supabase_realtime DROP TABLE public.user_notifications;
189
+ EXCEPTION WHEN OTHERS THEN
190
+ -- Table not in publication, continue
191
+ NULL;
192
+ END;
193
+
194
+ -- Now add it
195
+ ALTER PUBLICATION supabase_realtime ADD TABLE public.user_notifications;
196
+ END $$;
181
197
 
182
198
  -- Add signup_source to user_profil table
183
199
  -- Track where users signed up from (e.g., 'lastbrain', 'recipe', etc.)
@@ -36,7 +36,8 @@ EXCEPTION
36
36
  -- Profile already exists, ignore
37
37
  RETURN NEW;
38
38
  END;
39
- $$ LANGUAGE plpgsql SECURITY DEFINER;
39
+ $$ LANGUAGE plpgsql SECURITY DEFINER
40
+ SET search_path = public;
40
41
 
41
42
  -- Trigger to call the function when a new user is created
42
43
  DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
@@ -56,6 +57,7 @@ CREATE OR REPLACE FUNCTION public.get_admin_users(
56
57
  RETURNS JSON
57
58
  LANGUAGE plpgsql
58
59
  SECURITY DEFINER
60
+ SET search_path = public
59
61
  AS $$
60
62
  DECLARE
61
63
  offset_val INTEGER;
@@ -63,7 +65,7 @@ DECLARE
63
65
  total_count INTEGER;
64
66
  BEGIN
65
67
  -- Check if user is superadmin
66
- IF NOT is_superadmin(auth.uid()) THEN
68
+ IF NOT is_superadmin((SELECT auth.uid())) THEN
67
69
  RAISE EXCEPTION 'Access denied. Superadmin required.';
68
70
  END IF;
69
71
 
@@ -166,6 +168,8 @@ $$;
166
168
  -- Function: sync_fullname_to_metadata
167
169
  -- =====================================================
168
170
  -- Synchronize full_name in auth.users metadata when profile is updated
171
+ -- SECURITY: Runs as SECURITY DEFINER but only modifies the profile owner's metadata
172
+ -- Permission is controlled by RLS policies on user_profil table
169
173
  CREATE OR REPLACE FUNCTION public.sync_fullname_to_metadata()
170
174
  RETURNS TRIGGER AS $$
171
175
  DECLARE
@@ -193,7 +197,8 @@ BEGIN
193
197
 
194
198
  RETURN NEW;
195
199
  END;
196
- $$ LANGUAGE plpgsql SECURITY DEFINER;
200
+ $$ LANGUAGE plpgsql SECURITY DEFINER
201
+ SET search_path = public;
197
202
 
198
203
  -- Trigger to sync full_name when profile is updated
199
204
  DROP TRIGGER IF EXISTS sync_fullname_on_profile_update ON public.user_profil;
@@ -2,10 +2,13 @@
2
2
  -- Module: @lastbrain/module-auth
3
3
 
4
4
  -- Function to sync avatars from auth metadata to user_profil
5
+ -- SECURITY: Runs as SECURITY DEFINER but is an automated system operation
6
+ -- called only via triggers on auth.users - no caller validation needed
5
7
  CREATE OR REPLACE FUNCTION public.sync_avatar_from_auth_metadata()
6
8
  RETURNS VOID
7
9
  LANGUAGE plpgsql
8
10
  SECURITY DEFINER
11
+ SET search_path = public
9
12
  AS $$
10
13
  BEGIN
11
14
  -- Update user_profil with avatar URLs from auth.users metadata
@@ -26,6 +29,8 @@ END;
26
29
  $$;
27
30
 
28
31
  -- Create a trigger to automatically sync avatar when auth.users is updated
32
+ -- SECURITY: Runs as SECURITY DEFINER but is an automated system operation
33
+ -- Triggered only on auth.users updates - no caller validation needed
29
34
  CREATE OR REPLACE FUNCTION public.handle_auth_user_avatar_update()
30
35
  RETURNS TRIGGER AS $$
31
36
  BEGIN
@@ -42,7 +47,8 @@ BEGIN
42
47
 
43
48
  RETURN NEW;
44
49
  END;
45
- $$ LANGUAGE plpgsql SECURITY DEFINER;
50
+ $$ LANGUAGE plpgsql SECURITY DEFINER
51
+ SET search_path = public;
46
52
 
47
53
  -- Create trigger for avatar sync on auth.users update
48
54
  DROP TRIGGER IF EXISTS on_auth_user_avatar_updated ON auth.users;
@@ -9,12 +9,13 @@ CREATE OR REPLACE FUNCTION public.get_admin_user_details(user_id UUID)
9
9
  RETURNS JSON
10
10
  LANGUAGE plpgsql
11
11
  SECURITY DEFINER
12
+ SET search_path = public
12
13
  AS $$
13
14
  DECLARE
14
15
  result JSON;
15
16
  BEGIN
16
17
  -- Check if user is superadmin
17
- IF NOT is_superadmin(auth.uid()) THEN
18
+ IF NOT is_superadmin((SELECT auth.uid())) THEN
18
19
  RAISE EXCEPTION 'Access denied. Superadmin required.';
19
20
  END IF;
20
21