@strapi-community/plugin-better-auth-dashboard 1.0.0-alpha.9 → 1.0.0-beta.1
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 +65 -0
- package/dist/admin/Avatar-Cvk89aMx.js +67 -0
- package/dist/admin/Avatar-DNczJU0i.mjs +66 -0
- package/dist/admin/Root-2FMy-qQg.mjs +357 -0
- package/dist/admin/Root-DDi0mtve.js +359 -0
- package/dist/admin/index-BHfYu0uA.js +402 -0
- package/dist/admin/index-BQi_BUi6.mjs +1968 -0
- package/dist/admin/index-BV-4M_Fp.js +1970 -0
- package/dist/admin/index-CANDPUGD.mjs +1215 -0
- package/dist/admin/index-CqR8WpOa.js +1217 -0
- package/dist/admin/index-D6ktNZcj.js +1685 -0
- package/dist/admin/index-D9CiI8Yr.mjs +403 -0
- package/dist/admin/index-DszX3ibA.mjs +1683 -0
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.mjs +2 -2
- package/dist/admin/useModelSchema-B2tmzlwQ.mjs +733 -0
- package/dist/admin/useModelSchema-CqOTI7P1.js +734 -0
- package/dist/server/index.js +219 -9
- package/dist/server/index.mjs +219 -9
- package/package.json +3 -2
- package/dist/admin/Root-BYdYQBE5.mjs +0 -5742
- package/dist/admin/Root-D_vCtQoC.js +0 -5744
- package/dist/admin/index-BMTIuxZI.mjs +0 -96
- package/dist/admin/index-CkSsWnBx.js +0 -95
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useQuery } from "react-query";
|
|
3
|
+
import { dashClient } from "@better-auth/infra/client";
|
|
4
|
+
import { createAuthClient, InferPlugin } from "better-auth/client";
|
|
5
|
+
import { Page } from "@strapi/strapi/admin";
|
|
6
|
+
import { createElement } from "react";
|
|
7
|
+
const PluginIcon = ({
|
|
8
|
+
size = 16,
|
|
9
|
+
background = "transparent",
|
|
10
|
+
opacity = 1,
|
|
11
|
+
rotation = 0,
|
|
12
|
+
shadow = 0,
|
|
13
|
+
flipHorizontal = false,
|
|
14
|
+
flipVertical = false,
|
|
15
|
+
padding = 0
|
|
16
|
+
}) => {
|
|
17
|
+
const transforms = [];
|
|
18
|
+
if (rotation !== 0) transforms.push(`rotate(${rotation}deg)`);
|
|
19
|
+
if (flipHorizontal) transforms.push("scaleX(-1)");
|
|
20
|
+
if (flipVertical) transforms.push("scaleY(-1)");
|
|
21
|
+
const viewBoxSize = 24 + padding * 2;
|
|
22
|
+
const viewBoxOffset = -padding;
|
|
23
|
+
const viewBox = `${viewBoxOffset} ${viewBoxOffset} ${viewBoxSize} ${viewBoxSize}`;
|
|
24
|
+
return /* @__PURE__ */ jsxs(
|
|
25
|
+
"svg",
|
|
26
|
+
{
|
|
27
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
28
|
+
viewBox,
|
|
29
|
+
width: size,
|
|
30
|
+
height: size,
|
|
31
|
+
fill: "none",
|
|
32
|
+
style: {
|
|
33
|
+
opacity,
|
|
34
|
+
transform: transforms.join(" ") || void 0,
|
|
35
|
+
filter: shadow > 0 ? `drop-shadow(0 ${shadow}px ${shadow * 2}px rgba(0,0,0,0.3))` : void 0,
|
|
36
|
+
backgroundColor: background !== "transparent" ? background : void 0
|
|
37
|
+
},
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsx("title", { children: "Better Auth Logo" }),
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"path",
|
|
42
|
+
{
|
|
43
|
+
fill: "currentColor",
|
|
44
|
+
d: "M0 3.39v17.22h5.783v-5.55h6.434V8.939H5.783V3.39Zm12.217 5.55h5.638v6.122h-5.638v5.548H24V3.391H12.217Z"
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
const PLUGIN_ID = "better-auth-dashboard";
|
|
52
|
+
const PERMISSIONS = {
|
|
53
|
+
overview: [{ action: `plugin::${PLUGIN_ID}.overview.read`, subject: null }],
|
|
54
|
+
user: [
|
|
55
|
+
{ action: `plugin::${PLUGIN_ID}.user.create`, subject: null },
|
|
56
|
+
{ action: `plugin::${PLUGIN_ID}.user.read`, subject: null },
|
|
57
|
+
{ action: `plugin::${PLUGIN_ID}.user.update`, subject: null },
|
|
58
|
+
{ action: `plugin::${PLUGIN_ID}.user.delete`, subject: null }
|
|
59
|
+
],
|
|
60
|
+
organization: [
|
|
61
|
+
{ action: `plugin::${PLUGIN_ID}.organization.create`, subject: null },
|
|
62
|
+
{ action: `plugin::${PLUGIN_ID}.organization.read`, subject: null },
|
|
63
|
+
{ action: `plugin::${PLUGIN_ID}.organization.update`, subject: null },
|
|
64
|
+
{ action: `plugin::${PLUGIN_ID}.organization.delete`, subject: null }
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
const dashPathMethods = () => ({
|
|
68
|
+
id: "dash-path-methods",
|
|
69
|
+
pathMethods: {
|
|
70
|
+
"/dash/organization/directory/create": "POST",
|
|
71
|
+
"/dash/organization/directory/delete": "POST",
|
|
72
|
+
"/dash/organization/directory/regenerate-token": "POST",
|
|
73
|
+
"/dash/execute-adapter": "POST",
|
|
74
|
+
"/dash/complete-invitation": "POST",
|
|
75
|
+
"/dash/check-user-exists": "POST",
|
|
76
|
+
"/dash/organization/invite-member": "POST",
|
|
77
|
+
"/dash/organization/check-user-by-email": "POST",
|
|
78
|
+
"/dash/organization/cancel-invitation": "POST",
|
|
79
|
+
"/dash/organization/resend-invitation": "POST",
|
|
80
|
+
"/dash/organization/add-member": "POST",
|
|
81
|
+
"/dash/organization/remove-member": "POST",
|
|
82
|
+
"/dash/organization/update-member-role": "POST",
|
|
83
|
+
"/dash/organization/delete": "POST",
|
|
84
|
+
"/dash/organization/delete-many": "POST",
|
|
85
|
+
"/dash/organization/create": "POST",
|
|
86
|
+
"/dash/organization/update": "POST",
|
|
87
|
+
"/dash/organization/update-team": "POST",
|
|
88
|
+
"/dash/organization/delete-team": "POST",
|
|
89
|
+
"/dash/organization/create-team": "POST",
|
|
90
|
+
"/dash/organization/add-team-member": "POST",
|
|
91
|
+
"/dash/organization/remove-team-member": "POST",
|
|
92
|
+
"/dash/sessions/revoke": "POST",
|
|
93
|
+
"/dash/sessions/revoke-all": "POST",
|
|
94
|
+
"/dash/sessions/revoke-many": "POST",
|
|
95
|
+
"/dash/organization/:id/sso-provider/create": "POST",
|
|
96
|
+
"/dash/organization/:id/sso-provider/update": "POST",
|
|
97
|
+
"/dash/organization/:id/sso-provider/request-verification-token": "POST",
|
|
98
|
+
"/dash/organization/:id/sso-provider/verify-domain": "POST",
|
|
99
|
+
"/dash/organization/:id/sso-provider/delete": "POST",
|
|
100
|
+
"/dash/organization/:id/sso-provider/mark-domain-verified": "POST",
|
|
101
|
+
"/dash/enable-two-factor": "POST",
|
|
102
|
+
"/dash/view-two-factor-totp-uri": "POST",
|
|
103
|
+
"/dash/view-backup-codes": "POST",
|
|
104
|
+
"/dash/disable-two-factor": "POST",
|
|
105
|
+
"/dash/generate-backup-codes": "POST",
|
|
106
|
+
"/dash/delete-user": "POST",
|
|
107
|
+
"/dash/delete-many-users": "POST",
|
|
108
|
+
"/dash/create-user": "POST",
|
|
109
|
+
"/dash/set-password": "POST",
|
|
110
|
+
"/dash/unlink-account": "POST",
|
|
111
|
+
"/dash/update-user": "POST",
|
|
112
|
+
"/dash/ban-user": "POST",
|
|
113
|
+
"/dash/ban-many-users": "POST",
|
|
114
|
+
"/dash/unban-user": "POST",
|
|
115
|
+
"/dash/send-verification-email": "POST",
|
|
116
|
+
"/dash/send-many-verification-emails": "POST",
|
|
117
|
+
"/dash/send-reset-password-email": "POST"
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const STORAGE_KEYS = {
|
|
121
|
+
TOKEN: "jwtToken"
|
|
122
|
+
};
|
|
123
|
+
const getCookieValue = (name) => {
|
|
124
|
+
let result = null;
|
|
125
|
+
const cookieArray = document.cookie.split(";");
|
|
126
|
+
cookieArray.forEach((cookie) => {
|
|
127
|
+
const [key, value] = cookie.split("=").map((item) => item.trim());
|
|
128
|
+
if (key === name) {
|
|
129
|
+
result = decodeURIComponent(value);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return result;
|
|
133
|
+
};
|
|
134
|
+
const getToken = () => {
|
|
135
|
+
const fromLocalStorage = localStorage.getItem(STORAGE_KEYS.TOKEN);
|
|
136
|
+
if (fromLocalStorage) {
|
|
137
|
+
return JSON.parse(fromLocalStorage);
|
|
138
|
+
}
|
|
139
|
+
const fromCookie = getCookieValue(STORAGE_KEYS.TOKEN);
|
|
140
|
+
return fromCookie ?? null;
|
|
141
|
+
};
|
|
142
|
+
function getAuthHeaders() {
|
|
143
|
+
const token = getToken();
|
|
144
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
145
|
+
}
|
|
146
|
+
const client = createAuthClient({
|
|
147
|
+
baseURL: window.location.origin,
|
|
148
|
+
basePath: "/auth",
|
|
149
|
+
plugins: [
|
|
150
|
+
dashClient(),
|
|
151
|
+
dashPathMethods(),
|
|
152
|
+
InferPlugin()
|
|
153
|
+
],
|
|
154
|
+
fetchOptions: {
|
|
155
|
+
headers: getAuthHeaders()
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
async function getDashConfig() {
|
|
159
|
+
const result = await client.dash.config();
|
|
160
|
+
if (result.error) {
|
|
161
|
+
throw new Error(result.error.message ?? "Failed to load config");
|
|
162
|
+
}
|
|
163
|
+
return result.data;
|
|
164
|
+
}
|
|
165
|
+
function useDashConfig() {
|
|
166
|
+
return useQuery({
|
|
167
|
+
queryKey: ["dash-config"],
|
|
168
|
+
queryFn: getDashConfig,
|
|
169
|
+
staleTime: 5 * 60 * 1e3
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function useOrganizationOptions(enabled = true) {
|
|
173
|
+
return useQuery({
|
|
174
|
+
queryKey: ["dash-org-options"],
|
|
175
|
+
queryFn: async () => {
|
|
176
|
+
const result = await client.dash.organization.options();
|
|
177
|
+
if (result.error) return { teamsEnabled: false };
|
|
178
|
+
return result.data ?? { teamsEnabled: false };
|
|
179
|
+
},
|
|
180
|
+
enabled
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function hasPlugin(config, id) {
|
|
184
|
+
return config?.plugins.some((p) => p.id === id) ?? false;
|
|
185
|
+
}
|
|
186
|
+
const DASH_LINK_AVAILABILITY_STALE_TIME = 5 * 60 * 1e3;
|
|
187
|
+
const getDashLinkAvailabilityQueryKey = (link) => [
|
|
188
|
+
PLUGIN_ID,
|
|
189
|
+
"link-availability",
|
|
190
|
+
link.id,
|
|
191
|
+
link.to
|
|
192
|
+
];
|
|
193
|
+
const resolveDashLinkAvailability = async (link) => {
|
|
194
|
+
try {
|
|
195
|
+
return await link.isAvailable?.() ?? true;
|
|
196
|
+
} catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
let currentStore = {};
|
|
201
|
+
const getDashLinks = () => currentStore;
|
|
202
|
+
const RouteProtector = Page.Protect;
|
|
203
|
+
const AvailabilityProtector = ({
|
|
204
|
+
link,
|
|
205
|
+
children
|
|
206
|
+
}) => {
|
|
207
|
+
const { data: isAvailable, isLoading } = useQuery({
|
|
208
|
+
queryKey: getDashLinkAvailabilityQueryKey(link),
|
|
209
|
+
queryFn: () => resolveDashLinkAvailability(link),
|
|
210
|
+
staleTime: DASH_LINK_AVAILABILITY_STALE_TIME
|
|
211
|
+
});
|
|
212
|
+
if (isLoading) return createElement(Page.Loading);
|
|
213
|
+
if (!isAvailable) return createElement(Page.NoPermissions);
|
|
214
|
+
return children;
|
|
215
|
+
};
|
|
216
|
+
const initDash = (app) => {
|
|
217
|
+
const store = {};
|
|
218
|
+
currentStore = store;
|
|
219
|
+
const addDashLink = (section, link) => {
|
|
220
|
+
const router = app.router;
|
|
221
|
+
const storeIndex = router._routes.findIndex(
|
|
222
|
+
(route2) => route2.path === `plugins/${PLUGIN_ID}/*`
|
|
223
|
+
);
|
|
224
|
+
const route = router._routes[storeIndex];
|
|
225
|
+
if (section) {
|
|
226
|
+
if (!route) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Dashboard route for plugin ${PLUGIN_ID} was not found`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (!route.children) {
|
|
233
|
+
route.children = [];
|
|
234
|
+
}
|
|
235
|
+
route.children?.push(mapLinkToRoute(link));
|
|
236
|
+
const sectionId = typeof section === "string" ? section : section.id;
|
|
237
|
+
const existing = store[sectionId];
|
|
238
|
+
if (!existing) {
|
|
239
|
+
if (typeof section === "string") {
|
|
240
|
+
throw new Error(`Dashboard section ${sectionId} does not exist`);
|
|
241
|
+
}
|
|
242
|
+
store[sectionId] = {
|
|
243
|
+
...section,
|
|
244
|
+
links: []
|
|
245
|
+
};
|
|
246
|
+
} else if (typeof section.priority === "number" && section.priority !== existing.priority) {
|
|
247
|
+
console.warn(
|
|
248
|
+
"[DASH] Only the first instance of section can declare its priority."
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
store[sectionId].links.push(link);
|
|
252
|
+
};
|
|
253
|
+
const addDashSection = (section) => {
|
|
254
|
+
const existing = store[section.id];
|
|
255
|
+
if (existing) {
|
|
256
|
+
console.warn("[DASH] A section with this ID already exists.");
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
store[section.id] = {
|
|
260
|
+
...section,
|
|
261
|
+
links: []
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
const getDashLinks2 = () => {
|
|
265
|
+
return store;
|
|
266
|
+
};
|
|
267
|
+
return {
|
|
268
|
+
addDashLink,
|
|
269
|
+
addDashSection,
|
|
270
|
+
getDashLinks: getDashLinks2
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
const mapLinkToRoute = (link) => {
|
|
274
|
+
if (!link.Component)
|
|
275
|
+
throw new Error(
|
|
276
|
+
`Link with id ${link.to} does not have a Component property`
|
|
277
|
+
);
|
|
278
|
+
const permissions = link.permissions;
|
|
279
|
+
const hasPermissions = Array.isArray(permissions) && permissions.length > 0;
|
|
280
|
+
return {
|
|
281
|
+
path: `${link.to.replace(/^\/+|\/+$/g, "")}/*`,
|
|
282
|
+
lazy: async () => {
|
|
283
|
+
const mod = await link.Component();
|
|
284
|
+
const Component = "default" in mod ? mod.default : mod;
|
|
285
|
+
return {
|
|
286
|
+
Component: () => createElement(
|
|
287
|
+
AvailabilityProtector,
|
|
288
|
+
{ link },
|
|
289
|
+
hasPermissions ? createElement(
|
|
290
|
+
RouteProtector,
|
|
291
|
+
{ permissions },
|
|
292
|
+
createElement(Component)
|
|
293
|
+
) : createElement(Component)
|
|
294
|
+
)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
const panels = [];
|
|
300
|
+
function addEditViewSidePanel(config) {
|
|
301
|
+
if (panels.some((p) => p.id === config.id)) {
|
|
302
|
+
console.warn(
|
|
303
|
+
`[better-auth-dashboard] Panel with id "${config.id}" is already registered.`
|
|
304
|
+
);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
panels.push(config);
|
|
308
|
+
}
|
|
309
|
+
function getEditViewSidePanels(model) {
|
|
310
|
+
return panels.filter((p) => {
|
|
311
|
+
if (!p.model) return true;
|
|
312
|
+
if (Array.isArray(p.model)) return p.model.includes(model);
|
|
313
|
+
return p.model === model;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function captureApp(app) {
|
|
317
|
+
window.__betterAuthDashApp = app;
|
|
318
|
+
}
|
|
319
|
+
function getMediaLibraryComponent() {
|
|
320
|
+
return window.__betterAuthDashApp?.library?.components?.["media-library"] ?? null;
|
|
321
|
+
}
|
|
322
|
+
const plugin = {
|
|
323
|
+
register(app) {
|
|
324
|
+
captureApp(app);
|
|
325
|
+
const dash = initDash(app);
|
|
326
|
+
app.registerPlugin({
|
|
327
|
+
id: PLUGIN_ID,
|
|
328
|
+
name: "Auth Dashboard",
|
|
329
|
+
apis: { addEditViewSidePanel, ...dash }
|
|
330
|
+
});
|
|
331
|
+
app.addMenuLink({
|
|
332
|
+
to: `/plugins/${PLUGIN_ID}`,
|
|
333
|
+
icon: PluginIcon,
|
|
334
|
+
intlLabel: {
|
|
335
|
+
id: `${PLUGIN_ID}.plugin.name`,
|
|
336
|
+
defaultMessage: "Auth Dashboard"
|
|
337
|
+
},
|
|
338
|
+
Component: async () => import("./Root-2FMy-qQg.mjs"),
|
|
339
|
+
permissions: [
|
|
340
|
+
...PERMISSIONS.overview,
|
|
341
|
+
...PERMISSIONS.user,
|
|
342
|
+
...PERMISSIONS.organization
|
|
343
|
+
]
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
bootstrap(app) {
|
|
347
|
+
const dash = app.getPlugin(PLUGIN_ID).apis;
|
|
348
|
+
dash.addDashSection({
|
|
349
|
+
id: "general",
|
|
350
|
+
intlLabel: {
|
|
351
|
+
id: `${PLUGIN_ID}.settings.general`,
|
|
352
|
+
defaultMessage: "General"
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
dash.addDashLink("general", {
|
|
356
|
+
id: "overview",
|
|
357
|
+
intlLabel: {
|
|
358
|
+
id: `${PLUGIN_ID}.settings.overview`,
|
|
359
|
+
defaultMessage: "Overview"
|
|
360
|
+
},
|
|
361
|
+
to: "/overview",
|
|
362
|
+
Component: () => import("./index-CANDPUGD.mjs"),
|
|
363
|
+
permissions: PERMISSIONS.overview
|
|
364
|
+
});
|
|
365
|
+
dash.addDashLink("general", {
|
|
366
|
+
id: "users",
|
|
367
|
+
intlLabel: {
|
|
368
|
+
id: `${PLUGIN_ID}.settings.users`,
|
|
369
|
+
defaultMessage: "User Management"
|
|
370
|
+
},
|
|
371
|
+
to: "/users",
|
|
372
|
+
Component: () => import("./index-BQi_BUi6.mjs"),
|
|
373
|
+
permissions: PERMISSIONS.user
|
|
374
|
+
});
|
|
375
|
+
dash.addDashLink("general", {
|
|
376
|
+
id: "organizations",
|
|
377
|
+
intlLabel: {
|
|
378
|
+
id: `${PLUGIN_ID}.settings.organizations`,
|
|
379
|
+
defaultMessage: "Organization Management"
|
|
380
|
+
},
|
|
381
|
+
to: "/organizations",
|
|
382
|
+
Component: () => import("./index-DszX3ibA.mjs"),
|
|
383
|
+
permissions: PERMISSIONS.organization,
|
|
384
|
+
isAvailable: async () => hasPlugin(await getDashConfig(), "organization")
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
export {
|
|
389
|
+
DASH_LINK_AVAILABILITY_STALE_TIME as D,
|
|
390
|
+
PLUGIN_ID as P,
|
|
391
|
+
getDashLinkAvailabilityQueryKey as a,
|
|
392
|
+
PERMISSIONS as b,
|
|
393
|
+
client as c,
|
|
394
|
+
getAuthHeaders as d,
|
|
395
|
+
useOrganizationOptions as e,
|
|
396
|
+
getMediaLibraryComponent as f,
|
|
397
|
+
getDashLinks as g,
|
|
398
|
+
hasPlugin as h,
|
|
399
|
+
getEditViewSidePanels as i,
|
|
400
|
+
plugin as p,
|
|
401
|
+
resolveDashLinkAvailability as r,
|
|
402
|
+
useDashConfig as u
|
|
403
|
+
};
|