@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.
- package/dist/auth.build.config.js +1 -1
- package/package.json +3 -3
- package/src/auth.build.config.ts +1 -1
- package/supabase/migrations/20251112000000_user_init.sql +35 -19
- package/supabase/migrations/20251112000001_auto_profile_and_admin_view.sql +8 -3
- package/supabase/migrations/20251112000002_sync_avatars.sql +7 -1
- package/supabase/migrations/20251124000001_add_get_admin_user_details.sql +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/module-auth",
|
|
3
|
-
"version": "2.0.
|
|
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.
|
|
36
|
-
"@lastbrain/ui": "^2.0.
|
|
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",
|
package/src/auth.build.config.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|