@lastbrain/module-auth 0.1.16 → 0.1.19
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/README.md +1 -0
- package/dist/auth.build.config.d.ts.map +1 -1
- package/dist/auth.build.config.js +114 -10
- package/dist/components/AccountButton.d.ts +18 -0
- package/dist/components/AccountButton.d.ts.map +1 -0
- package/dist/components/AccountButton.js +40 -0
- package/dist/components/NotificationButton.d.ts +18 -0
- package/dist/components/NotificationButton.d.ts.map +1 -0
- package/dist/components/NotificationButton.js +8 -0
- package/dist/components/ThemeSwitcherButton.d.ts +9 -0
- package/dist/components/ThemeSwitcherButton.d.ts.map +1 -0
- package/dist/components/ThemeSwitcherButton.js +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/web/admin/user-detail.d.ts.map +1 -1
- package/dist/web/admin/user-detail.js +27 -6
- package/dist/web/admin/users.d.ts.map +1 -1
- package/dist/web/admin/users.js +6 -6
- package/dist/web/auth/profile.js +17 -17
- package/package.json +2 -1
- package/src/auth.build.config.ts +114 -10
- package/src/components/AccountButton.tsx +157 -0
- package/src/components/NotificationButton.tsx +41 -0
- package/src/components/ThemeSwitcherButton.tsx +14 -0
- package/src/index.ts +6 -0
- package/src/web/admin/user-detail.tsx +244 -51
- package/src/web/admin/users.tsx +21 -3
- package/src/web/auth/profile.tsx +34 -34
- package/supabase/migrations/20251112000000_user_init.sql +6 -1
- package/supabase/migrations/20251112000001_auto_profile_and_admin_view.sql +6 -1
- package/supabase/migrations/20251124000001_add_get_admin_user_details.sql +1 -0
- package/supabase/migrations/20251127100000_rename_body_to_message.sql +9 -0
package/src/auth.build.config.ts
CHANGED
|
@@ -122,18 +122,34 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
122
122
|
menu: {
|
|
123
123
|
public: [
|
|
124
124
|
{
|
|
125
|
-
title: "
|
|
126
|
-
description: "
|
|
127
|
-
icon: "
|
|
128
|
-
path: "
|
|
129
|
-
order:
|
|
125
|
+
title: "Notifications",
|
|
126
|
+
description: "Vos notifications",
|
|
127
|
+
icon: "Bell",
|
|
128
|
+
path: "#",
|
|
129
|
+
order: 998,
|
|
130
|
+
type: "icon",
|
|
131
|
+
position: "end",
|
|
132
|
+
componentExport: "NotificationButton",
|
|
130
133
|
},
|
|
131
134
|
{
|
|
132
|
-
title: "
|
|
133
|
-
description: "
|
|
134
|
-
icon: "
|
|
135
|
-
path: "
|
|
136
|
-
order:
|
|
135
|
+
title: "Compte",
|
|
136
|
+
description: "Gérer votre compte",
|
|
137
|
+
icon: "User",
|
|
138
|
+
path: "#",
|
|
139
|
+
order: 999,
|
|
140
|
+
type: "icon",
|
|
141
|
+
position: "end",
|
|
142
|
+
componentExport: "AccountButton",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
title: "Theme",
|
|
146
|
+
description: "Changer le thème",
|
|
147
|
+
icon: "Palette",
|
|
148
|
+
path: "#",
|
|
149
|
+
order: 9999,
|
|
150
|
+
type: "icon",
|
|
151
|
+
position: "end",
|
|
152
|
+
componentExport: "ThemeSwitcherButton",
|
|
137
153
|
},
|
|
138
154
|
],
|
|
139
155
|
admin: [
|
|
@@ -146,6 +162,36 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
146
162
|
shortcut: "cmd+shift+u",
|
|
147
163
|
shortcutDisplay: "⌘⇧U",
|
|
148
164
|
},
|
|
165
|
+
{
|
|
166
|
+
title: "Notifications",
|
|
167
|
+
description: "Vos notifications",
|
|
168
|
+
icon: "Bell",
|
|
169
|
+
path: "#",
|
|
170
|
+
order: 998,
|
|
171
|
+
type: "icon",
|
|
172
|
+
position: "end",
|
|
173
|
+
componentExport: "NotificationButton",
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
title: "Compte",
|
|
177
|
+
description: "Gérer votre compte",
|
|
178
|
+
icon: "User",
|
|
179
|
+
path: "#",
|
|
180
|
+
order: 999,
|
|
181
|
+
type: "icon",
|
|
182
|
+
position: "end",
|
|
183
|
+
componentExport: "AccountButton",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
title: "Theme",
|
|
187
|
+
description: "Changer le thème",
|
|
188
|
+
icon: "Palette",
|
|
189
|
+
path: "#",
|
|
190
|
+
order: 9999,
|
|
191
|
+
type: "icon",
|
|
192
|
+
position: "end",
|
|
193
|
+
componentExport: "ThemeSwitcherButton",
|
|
194
|
+
},
|
|
149
195
|
],
|
|
150
196
|
auth: [
|
|
151
197
|
{
|
|
@@ -166,6 +212,36 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
166
212
|
shortcut: "cmd+shift+f",
|
|
167
213
|
shortcutDisplay: "⌘⇧F",
|
|
168
214
|
},
|
|
215
|
+
{
|
|
216
|
+
title: "Notifications",
|
|
217
|
+
description: "Vos notifications",
|
|
218
|
+
icon: "Bell",
|
|
219
|
+
path: "#",
|
|
220
|
+
order: 998,
|
|
221
|
+
type: "icon",
|
|
222
|
+
position: "end",
|
|
223
|
+
componentExport: "NotificationButton",
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
title: "Compte",
|
|
227
|
+
description: "Gérer votre compte",
|
|
228
|
+
icon: "User",
|
|
229
|
+
path: "#",
|
|
230
|
+
order: 999,
|
|
231
|
+
type: "icon",
|
|
232
|
+
position: "end",
|
|
233
|
+
componentExport: "AccountButton",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
title: "Theme",
|
|
237
|
+
description: "Changer le thème",
|
|
238
|
+
icon: "Palette",
|
|
239
|
+
path: "#",
|
|
240
|
+
order: 9999,
|
|
241
|
+
type: "icon",
|
|
242
|
+
position: "end",
|
|
243
|
+
componentExport: "ThemeSwitcherButton",
|
|
244
|
+
},
|
|
169
245
|
],
|
|
170
246
|
account: [
|
|
171
247
|
{
|
|
@@ -221,6 +297,34 @@ const authBuildConfig: ModuleBuildConfig = {
|
|
|
221
297
|
},
|
|
222
298
|
],
|
|
223
299
|
},
|
|
300
|
+
storage: {
|
|
301
|
+
buckets: [
|
|
302
|
+
{
|
|
303
|
+
name: "app",
|
|
304
|
+
public: false,
|
|
305
|
+
description: "Private user files and documents /{userId}/...",
|
|
306
|
+
maxFileSize: 100 * 1024 * 1024, // 100MB
|
|
307
|
+
customAccessControl: (userId: string, filePath: string) => {
|
|
308
|
+
// Users can only access files in their own folder (app/{userId}/...)
|
|
309
|
+
return filePath.startsWith(`${userId}/`);
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: "avatar",
|
|
314
|
+
public: true,
|
|
315
|
+
description: "Public user avatar images",
|
|
316
|
+
allowedMimeTypes: [
|
|
317
|
+
"image/jpeg",
|
|
318
|
+
"image/jpg",
|
|
319
|
+
"image/png",
|
|
320
|
+
"image/webp",
|
|
321
|
+
"image/gif",
|
|
322
|
+
],
|
|
323
|
+
maxFileSize: 5242880, // 5MB
|
|
324
|
+
fileSizeLimit: "5MB",
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
},
|
|
224
328
|
};
|
|
225
329
|
|
|
226
330
|
export default authBuildConfig;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Button, Link } from "@lastbrain/ui";
|
|
4
|
+
import { Avatar } from "@lastbrain/ui";
|
|
5
|
+
import {
|
|
6
|
+
Dropdown,
|
|
7
|
+
DropdownItem,
|
|
8
|
+
DropdownMenu,
|
|
9
|
+
DropdownTrigger,
|
|
10
|
+
} from "@lastbrain/ui";
|
|
11
|
+
import * as LucideIcons from "lucide-react";
|
|
12
|
+
import type { User } from "@supabase/supabase-js";
|
|
13
|
+
import { use } from "react";
|
|
14
|
+
|
|
15
|
+
interface AccountButtonProps {
|
|
16
|
+
item: {
|
|
17
|
+
path: string;
|
|
18
|
+
title: string;
|
|
19
|
+
};
|
|
20
|
+
user?: User | null;
|
|
21
|
+
accountMenu?: Array<{
|
|
22
|
+
title: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
icon?: string;
|
|
25
|
+
path: string;
|
|
26
|
+
}>;
|
|
27
|
+
onLogout?: () => void | Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Fonction pour récupérer l'icône Lucide
|
|
31
|
+
const getIcon = (iconName?: string) => {
|
|
32
|
+
if (!iconName) return null;
|
|
33
|
+
const Icon = (LucideIcons as any)[iconName];
|
|
34
|
+
return Icon ? Icon : null;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const AccountButton = ({
|
|
38
|
+
user,
|
|
39
|
+
accountMenu = [],
|
|
40
|
+
onLogout,
|
|
41
|
+
}: AccountButtonProps) => {
|
|
42
|
+
if (!user)
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<div className="block md:hidden">
|
|
46
|
+
<Button
|
|
47
|
+
as={Link}
|
|
48
|
+
href="/signin"
|
|
49
|
+
radius="full"
|
|
50
|
+
isIconOnly
|
|
51
|
+
variant="light"
|
|
52
|
+
color="primary"
|
|
53
|
+
>
|
|
54
|
+
<LucideIcons.LogIn size={16} />
|
|
55
|
+
</Button>
|
|
56
|
+
<Button
|
|
57
|
+
as={Link}
|
|
58
|
+
href="/signup"
|
|
59
|
+
radius="full"
|
|
60
|
+
isIconOnly
|
|
61
|
+
variant="flat"
|
|
62
|
+
className="ml-2"
|
|
63
|
+
color="secondary"
|
|
64
|
+
>
|
|
65
|
+
<LucideIcons.UserPlus2 size={16} />
|
|
66
|
+
</Button>
|
|
67
|
+
</div>
|
|
68
|
+
<div className="hidden md:block">
|
|
69
|
+
<Button
|
|
70
|
+
as={Link}
|
|
71
|
+
href="/signin"
|
|
72
|
+
startContent={<LucideIcons.LogIn size={16} />}
|
|
73
|
+
variant="light"
|
|
74
|
+
color="primary"
|
|
75
|
+
>
|
|
76
|
+
Se connecter
|
|
77
|
+
</Button>
|
|
78
|
+
<Button
|
|
79
|
+
as={Link}
|
|
80
|
+
href="/signup"
|
|
81
|
+
variant="flat"
|
|
82
|
+
className="ml-2"
|
|
83
|
+
color="secondary"
|
|
84
|
+
startContent={<LucideIcons.UserPlus2 size={16} />}
|
|
85
|
+
>
|
|
86
|
+
S'inscrire
|
|
87
|
+
</Button>
|
|
88
|
+
</div>
|
|
89
|
+
</>
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<Dropdown>
|
|
94
|
+
<DropdownTrigger>
|
|
95
|
+
<Avatar
|
|
96
|
+
size="sm"
|
|
97
|
+
src={`/api/storage/${user?.user_metadata.avatar}`}
|
|
98
|
+
title={user.email}
|
|
99
|
+
fallback={<LucideIcons.User2 size={18} />}
|
|
100
|
+
classNames={{
|
|
101
|
+
base: "bg-white/0",
|
|
102
|
+
icon: "text-default-700",
|
|
103
|
+
}}
|
|
104
|
+
/>
|
|
105
|
+
</DropdownTrigger>
|
|
106
|
+
|
|
107
|
+
<DropdownMenu
|
|
108
|
+
items={[
|
|
109
|
+
{
|
|
110
|
+
key: "hello",
|
|
111
|
+
label: `Bonjour ${user?.user_metadata?.full_name || user.email}`,
|
|
112
|
+
isReadOnly: true,
|
|
113
|
+
},
|
|
114
|
+
...accountMenu.map((item) => ({
|
|
115
|
+
key: item.path,
|
|
116
|
+
label: item.title,
|
|
117
|
+
description: item.description,
|
|
118
|
+
icon: item.icon,
|
|
119
|
+
isLogout:
|
|
120
|
+
item.path.includes("signout") || item.path.includes("logout"),
|
|
121
|
+
href:
|
|
122
|
+
item.path.includes("signout") || item.path.includes("logout")
|
|
123
|
+
? undefined
|
|
124
|
+
: item.path,
|
|
125
|
+
})),
|
|
126
|
+
]}
|
|
127
|
+
>
|
|
128
|
+
{(item: {
|
|
129
|
+
key: string;
|
|
130
|
+
label: string;
|
|
131
|
+
description?: string;
|
|
132
|
+
icon?: string;
|
|
133
|
+
isLogout?: boolean;
|
|
134
|
+
href?: string;
|
|
135
|
+
isReadOnly?: boolean;
|
|
136
|
+
}) => {
|
|
137
|
+
const Icon = item.icon ? getIcon(item.icon) : null;
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<DropdownItem
|
|
141
|
+
key={item.key}
|
|
142
|
+
href={item.href}
|
|
143
|
+
onPress={item.isLogout ? () => onLogout?.() : undefined}
|
|
144
|
+
color={item.isLogout ? "danger" : "default"}
|
|
145
|
+
description={item.description}
|
|
146
|
+
startContent={Icon && <Icon size={16} />}
|
|
147
|
+
isDisabled={item.isReadOnly}
|
|
148
|
+
isReadOnly={item.isReadOnly}
|
|
149
|
+
>
|
|
150
|
+
{item.label}
|
|
151
|
+
</DropdownItem>
|
|
152
|
+
);
|
|
153
|
+
}}
|
|
154
|
+
</DropdownMenu>
|
|
155
|
+
</Dropdown>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Notification, type UserNotification } from "@lastbrain/ui";
|
|
4
|
+
import type { User } from "@supabase/supabase-js";
|
|
5
|
+
|
|
6
|
+
interface NotificationButtonProps {
|
|
7
|
+
item: {
|
|
8
|
+
path: string;
|
|
9
|
+
title: string;
|
|
10
|
+
};
|
|
11
|
+
user?: User | null;
|
|
12
|
+
notifications?: UserNotification[];
|
|
13
|
+
unreadCount?: number;
|
|
14
|
+
notificationsLoading?: boolean;
|
|
15
|
+
onMarkAsRead?: (id: string) => void;
|
|
16
|
+
onMarkAllAsRead?: () => void;
|
|
17
|
+
onDeleteNotification?: (id: string) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const NotificationButton = ({
|
|
21
|
+
user,
|
|
22
|
+
notifications = [],
|
|
23
|
+
unreadCount = 0,
|
|
24
|
+
notificationsLoading = false,
|
|
25
|
+
onMarkAsRead = () => {},
|
|
26
|
+
onMarkAllAsRead = () => {},
|
|
27
|
+
onDeleteNotification = () => {},
|
|
28
|
+
}: NotificationButtonProps) => {
|
|
29
|
+
if (!user) return null;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Notification
|
|
33
|
+
notifications={notifications}
|
|
34
|
+
unreadCount={unreadCount}
|
|
35
|
+
loading={notificationsLoading}
|
|
36
|
+
onMarkAsRead={onMarkAsRead}
|
|
37
|
+
onMarkAllAsRead={onMarkAllAsRead}
|
|
38
|
+
onDelete={onDeleteNotification}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ThemeSwitcher } from "@lastbrain/ui";
|
|
4
|
+
|
|
5
|
+
interface ThemeSwitcherButtonProps {
|
|
6
|
+
item: {
|
|
7
|
+
path: string;
|
|
8
|
+
title: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ThemeSwitcherButton = (_props: ThemeSwitcherButtonProps) => {
|
|
13
|
+
return <ThemeSwitcher />;
|
|
14
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,12 @@ export { ReglagePage } from "./web/auth/reglage.js";
|
|
|
9
9
|
export { AdminUsersPage } from "./web/admin/users.js";
|
|
10
10
|
export { default as UserPage } from "./web/admin/users/[id].js";
|
|
11
11
|
export { UserDetailPage } from "./web/admin/user-detail.js";
|
|
12
|
+
|
|
13
|
+
// Header Components
|
|
14
|
+
export { AccountButton } from "./components/AccountButton.js";
|
|
15
|
+
export { NotificationButton } from "./components/NotificationButton.js";
|
|
16
|
+
export { ThemeSwitcherButton } from "./components/ThemeSwitcherButton.js";
|
|
17
|
+
|
|
12
18
|
// Documentation
|
|
13
19
|
export { Doc } from "./components/Doc.js";
|
|
14
20
|
export { Doc as AuthModuleDoc } from "./components/Doc.js";
|