@strapi-community/plugin-better-auth-dashboard 1.0.0-alpha.3 → 1.0.0-alpha.4
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/admin/{Root-BnRbzS-u.js → Root-7EredGQZ.js} +258 -150
- package/dist/admin/{Root-DBjGZL7H.mjs → Root-B1LuKMEv.mjs} +259 -151
- package/dist/admin/{index-xZ2FHX3i.js → index-CIxfFlzU.js} +1 -1
- package/dist/admin/{index-BpruO4vo.mjs → index-QVlTR8eL.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +6 -5
- package/dist/server/index.mjs +6 -5
- package/package.json +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState, useRef, useMemo } from "react";
|
|
3
3
|
import { useQuery, useQueryClient, useMutation, QueryClient, QueryClientProvider } from "react-query";
|
|
4
|
-
import { Modal, Typography, Button, Portal, Flex, IconButton, Box, Field, TextInput, Combobox, ComboboxOption, Checkbox, SingleSelect, SingleSelectOption, NumberInput, JSONInput, Textarea, Alert, Tabs, Grid, SearchForm, Searchbar, Loader, Badge
|
|
4
|
+
import { Modal, Typography, Button, Portal, Flex, IconButton, Box, Field, TextInput, Combobox, ComboboxOption, Checkbox, SingleSelect, SingleSelectOption, NumberInput, JSONInput, Textarea, Alert, Tabs, Grid, SearchForm, Searchbar, Loader, Badge } from "@strapi/design-system";
|
|
5
5
|
import styled, { keyframes } from "styled-components";
|
|
6
6
|
import { dashClient } from "@better-auth/infra/client";
|
|
7
7
|
import { createAuthClient, InferPlugin } from "better-auth/client";
|
|
8
8
|
import { Cross, Images, Trash, Plus, Pencil } from "@strapi/icons";
|
|
9
9
|
import { useNotification, useFetchClient } from "@strapi/strapi/admin";
|
|
10
|
-
import { g as getMediaLibraryComponent, P as PluginIcon } from "./index-
|
|
10
|
+
import { g as getMediaLibraryComponent, P as PluginIcon } from "./index-QVlTR8eL.mjs";
|
|
11
11
|
const dashPathMethods = () => ({
|
|
12
12
|
id: "dash-path-methods",
|
|
13
13
|
pathMethods: {
|
|
@@ -1038,6 +1038,7 @@ function OrganizationDetail({
|
|
|
1038
1038
|
const schemaQuery = useModelSchema("organization");
|
|
1039
1039
|
const qc = useQueryClient();
|
|
1040
1040
|
const { toggleNotification } = useNotification();
|
|
1041
|
+
const { get, put } = useFetchClient();
|
|
1041
1042
|
const orgQuery = useQuery({
|
|
1042
1043
|
queryKey: ["dash-org", organizationId],
|
|
1043
1044
|
queryFn: async () => {
|
|
@@ -1084,6 +1085,16 @@ function OrganizationDetail({
|
|
|
1084
1085
|
return result.data ?? [];
|
|
1085
1086
|
}
|
|
1086
1087
|
});
|
|
1088
|
+
const strapiOrgQuery = useQuery({
|
|
1089
|
+
queryKey: ["dash-strapi-org", organizationId],
|
|
1090
|
+
enabled: !!orgQuery.data,
|
|
1091
|
+
queryFn: async () => {
|
|
1092
|
+
const { data } = await get(
|
|
1093
|
+
`/better-auth-dashboard/db?uid=plugin::better-auth.organization&filters[id][$eq]=${organizationId}&pagination[pageSize]=1`
|
|
1094
|
+
);
|
|
1095
|
+
return data.results?.[0] ?? null;
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1087
1098
|
const [activeTab, setActiveTab] = useState("details");
|
|
1088
1099
|
const [editName, setEditName] = useState(void 0);
|
|
1089
1100
|
const [editSlug, setEditSlug] = useState(void 0);
|
|
@@ -1113,13 +1124,13 @@ function OrganizationDetail({
|
|
|
1113
1124
|
if (editName !== void 0) body.name = editName;
|
|
1114
1125
|
if (editSlug !== void 0) body.slug = editSlug;
|
|
1115
1126
|
if (editLogo !== void 0) body.logo = editLogo;
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1127
|
+
const documentId = strapiOrgQuery.data?.documentId;
|
|
1128
|
+
if (!documentId)
|
|
1129
|
+
throw new Error("Could not resolve documentId for organization");
|
|
1130
|
+
await put(
|
|
1131
|
+
`/better-auth-dashboard/db/${documentId}?uid=plugin::better-auth.organization`,
|
|
1132
|
+
body
|
|
1119
1133
|
);
|
|
1120
|
-
if (result.error)
|
|
1121
|
-
throw new Error(result.error.message ?? "Update failed");
|
|
1122
|
-
return result.data;
|
|
1123
1134
|
},
|
|
1124
1135
|
onSuccess: () => {
|
|
1125
1136
|
qc.invalidateQueries({ queryKey: ["dash-org", organizationId] });
|
|
@@ -2132,6 +2143,7 @@ function OrgAvatar({ name, logo }) {
|
|
|
2132
2143
|
}
|
|
2133
2144
|
function OrganizationsPage({ teamsEnabled }) {
|
|
2134
2145
|
const qc = useQueryClient();
|
|
2146
|
+
const { toggleNotification } = useNotification();
|
|
2135
2147
|
const [page, setPage] = useState(1);
|
|
2136
2148
|
const [search, setSearch] = useState("");
|
|
2137
2149
|
const [searchInput, setSearchInput] = useState("");
|
|
@@ -2171,6 +2183,13 @@ function OrganizationsPage({ teamsEnabled }) {
|
|
|
2171
2183
|
onSuccess: () => {
|
|
2172
2184
|
setConfirmDelete(null);
|
|
2173
2185
|
qc.invalidateQueries({ queryKey: ["dash-organizations"] });
|
|
2186
|
+
toggleNotification({ type: "success", message: "Organization deleted" });
|
|
2187
|
+
},
|
|
2188
|
+
onError: (err) => {
|
|
2189
|
+
toggleNotification({
|
|
2190
|
+
type: "danger",
|
|
2191
|
+
message: err.message ?? "Failed to delete organization"
|
|
2192
|
+
});
|
|
2174
2193
|
}
|
|
2175
2194
|
});
|
|
2176
2195
|
const deleteManyMutation = useMutation({
|
|
@@ -2183,10 +2202,20 @@ function OrganizationsPage({ teamsEnabled }) {
|
|
|
2183
2202
|
throw new Error(result.error.message ?? "Delete failed");
|
|
2184
2203
|
return result.data;
|
|
2185
2204
|
},
|
|
2186
|
-
onSuccess: () => {
|
|
2205
|
+
onSuccess: (_data, organizationIds) => {
|
|
2187
2206
|
setConfirmDeleteMany(false);
|
|
2188
2207
|
setSelected(/* @__PURE__ */ new Set());
|
|
2189
2208
|
qc.invalidateQueries({ queryKey: ["dash-organizations"] });
|
|
2209
|
+
toggleNotification({
|
|
2210
|
+
type: "success",
|
|
2211
|
+
message: `${organizationIds.length} organization${organizationIds.length !== 1 ? "s" : ""} deleted`
|
|
2212
|
+
});
|
|
2213
|
+
},
|
|
2214
|
+
onError: (err) => {
|
|
2215
|
+
toggleNotification({
|
|
2216
|
+
type: "danger",
|
|
2217
|
+
message: err.message ?? "Failed to delete organizations"
|
|
2218
|
+
});
|
|
2190
2219
|
}
|
|
2191
2220
|
});
|
|
2192
2221
|
const orgs = orgsQuery.data && "organizations" in orgsQuery.data ? orgsQuery.data.organizations : [];
|
|
@@ -3269,6 +3298,42 @@ function OverviewPage() {
|
|
|
3269
3298
|
return r.data;
|
|
3270
3299
|
}
|
|
3271
3300
|
});
|
|
3301
|
+
const sessionsRaw = sessionsQuery.data ?? [];
|
|
3302
|
+
const activeUserIds = [];
|
|
3303
|
+
const lastActiveByUserId = /* @__PURE__ */ new Map();
|
|
3304
|
+
for (const s of sessionsRaw) {
|
|
3305
|
+
if (!lastActiveByUserId.has(s.userId)) {
|
|
3306
|
+
lastActiveByUserId.set(s.userId, s.createdAt);
|
|
3307
|
+
activeUserIds.push(s.userId);
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
const activeUsersQuery = useQuery({
|
|
3311
|
+
queryKey: ["dash-active-users", activeUserIds],
|
|
3312
|
+
queryFn: async () => {
|
|
3313
|
+
if (activeUserIds.length === 0) return [];
|
|
3314
|
+
const params = new URLSearchParams({ uid: "plugin::better-auth.user" });
|
|
3315
|
+
for (let i = 0; i < activeUserIds.length; i++) {
|
|
3316
|
+
params.set(`filters[id][$in][${i}]`, activeUserIds[i]);
|
|
3317
|
+
}
|
|
3318
|
+
params.set("pagination[pageSize]", "12");
|
|
3319
|
+
const { data } = await get(
|
|
3320
|
+
`/better-auth-dashboard/db?${params}`
|
|
3321
|
+
);
|
|
3322
|
+
return data.results ?? [];
|
|
3323
|
+
},
|
|
3324
|
+
enabled: feedMode === "active" && activeUserIds.length > 0
|
|
3325
|
+
});
|
|
3326
|
+
const chartRef = useRef(null);
|
|
3327
|
+
const [chartHeight, setChartHeight] = useState(0);
|
|
3328
|
+
useEffect(() => {
|
|
3329
|
+
const el = chartRef.current;
|
|
3330
|
+
if (!el) return;
|
|
3331
|
+
const ro = new ResizeObserver((entries) => {
|
|
3332
|
+
for (const entry of entries) setChartHeight(entry.contentRect.height);
|
|
3333
|
+
});
|
|
3334
|
+
ro.observe(el);
|
|
3335
|
+
return () => ro.disconnect();
|
|
3336
|
+
}, []);
|
|
3272
3337
|
if (statsQuery.isLoading) {
|
|
3273
3338
|
return /* @__PURE__ */ jsx(
|
|
3274
3339
|
Flex,
|
|
@@ -3286,8 +3351,12 @@ function OverviewPage() {
|
|
|
3286
3351
|
const graphData = graphQuery.data?.data ?? [];
|
|
3287
3352
|
const rtnData = retentionQuery.data?.data ?? [];
|
|
3288
3353
|
const users = usersQuery.data?.users ?? [];
|
|
3289
|
-
const sessions = sessionsQuery.data ?? [];
|
|
3290
3354
|
const orgCount = orgsQuery.data?.total ?? 0;
|
|
3355
|
+
const activeUserMap = /* @__PURE__ */ new Map();
|
|
3356
|
+
for (const u of activeUsersQuery.data ?? []) {
|
|
3357
|
+
activeUserMap.set(String(u.id), u);
|
|
3358
|
+
}
|
|
3359
|
+
const sortedActiveUsers = activeUserIds.map((uid) => activeUserMap.get(uid)).filter((u) => u !== void 0);
|
|
3291
3360
|
const totalSpark = graphData.map((d) => d.totalUsers);
|
|
3292
3361
|
const newSpark = graphData.map((d) => d.newUsers);
|
|
3293
3362
|
const activeSpark = graphData.map((d) => d.activeUsers);
|
|
@@ -3391,7 +3460,7 @@ function OverviewPage() {
|
|
|
3391
3460
|
/* @__PURE__ */ jsx(DivLine, {})
|
|
3392
3461
|
] }),
|
|
3393
3462
|
/* @__PURE__ */ jsxs(TwoPanel, { children: [
|
|
3394
|
-
/* @__PURE__ */ jsxs(ChartCard, { $delay: 5, children: [
|
|
3463
|
+
/* @__PURE__ */ jsxs(ChartCard, { ref: chartRef, $delay: 5, children: [
|
|
3395
3464
|
/* @__PURE__ */ jsxs(ChartHeader, { children: [
|
|
3396
3465
|
/* @__PURE__ */ jsx(ChartTitle, { children: "User Growth" }),
|
|
3397
3466
|
/* @__PURE__ */ jsx(SeriesRow, { children: ALL_SERIES.map((s) => /* @__PURE__ */ jsxs(
|
|
@@ -3427,57 +3496,57 @@ function OverviewPage() {
|
|
|
3427
3496
|
}
|
|
3428
3497
|
)
|
|
3429
3498
|
] }),
|
|
3430
|
-
/* @__PURE__ */ jsxs(
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
/* @__PURE__ */ jsx(FeedName, { title: u.name, children: u.name })
|
|
3499
|
+
/* @__PURE__ */ jsxs(
|
|
3500
|
+
FeedCard,
|
|
3501
|
+
{
|
|
3502
|
+
$delay: 6,
|
|
3503
|
+
style: chartHeight > 0 ? { height: chartHeight } : void 0,
|
|
3504
|
+
children: [
|
|
3505
|
+
/* @__PURE__ */ jsxs(FeedHead, { children: [
|
|
3506
|
+
/* @__PURE__ */ jsx("span", { children: feedMode === "signups" ? "Recent Sign-ups" : "Recently Active" }),
|
|
3507
|
+
/* @__PURE__ */ jsxs(
|
|
3508
|
+
FeedSelect,
|
|
3509
|
+
{
|
|
3510
|
+
value: feedMode,
|
|
3511
|
+
onChange: (e) => setFeedMode(e.target.value),
|
|
3512
|
+
children: [
|
|
3513
|
+
/* @__PURE__ */ jsx("option", { value: "signups", children: "Recent Sign-ups" }),
|
|
3514
|
+
/* @__PURE__ */ jsx("option", { value: "active", children: "Recently Active" })
|
|
3515
|
+
]
|
|
3516
|
+
}
|
|
3517
|
+
)
|
|
3450
3518
|
] }),
|
|
3451
|
-
/* @__PURE__ */ jsx(
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3519
|
+
/* @__PURE__ */ jsx(FeedScroll, { children: feedMode === "signups" ? usersQuery.isLoading ? /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Loader, { children: "Loading…" }) }) : users.length === 0 ? /* @__PURE__ */ jsx(Empty, { children: "No users yet" }) : users.map((u) => /* @__PURE__ */ jsxs(FeedItem, { children: [
|
|
3520
|
+
/* @__PURE__ */ jsxs(FeedTop, { children: [
|
|
3521
|
+
/* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 1, style: { minWidth: 0 }, children: [
|
|
3522
|
+
/* @__PURE__ */ jsx(Avatar, { name: u.name, src: u.image, size: 20 }),
|
|
3523
|
+
/* @__PURE__ */ jsx(FeedName, { title: u.name, children: u.name })
|
|
3524
|
+
] }),
|
|
3525
|
+
/* @__PURE__ */ jsx(FeedMeta, { children: relTime(u.createdAt) })
|
|
3526
|
+
] }),
|
|
3527
|
+
/* @__PURE__ */ jsx(FeedEmail, { title: u.email, children: u.email })
|
|
3528
|
+
] }, u.id)) : activeUsersQuery.isLoading || sessionsQuery.isLoading ? /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Loader, { children: "Loading…" }) }) : sortedActiveUsers.length === 0 ? /* @__PURE__ */ jsx(Empty, { children: "No recent activity" }) : sortedActiveUsers.map((u) => /* @__PURE__ */ jsxs(FeedItem, { children: [
|
|
3529
|
+
/* @__PURE__ */ jsxs(FeedTop, { children: [
|
|
3530
|
+
/* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 1, style: { minWidth: 0 }, children: [
|
|
3531
|
+
/* @__PURE__ */ jsx(
|
|
3532
|
+
Avatar,
|
|
3533
|
+
{
|
|
3534
|
+
name: u.name,
|
|
3535
|
+
src: u.image ?? void 0,
|
|
3536
|
+
size: 20
|
|
3537
|
+
}
|
|
3538
|
+
),
|
|
3539
|
+
/* @__PURE__ */ jsx(FeedName, { title: u.name, children: u.name })
|
|
3540
|
+
] }),
|
|
3541
|
+
/* @__PURE__ */ jsx(FeedMeta, { children: relTime(
|
|
3542
|
+
lastActiveByUserId.get(String(u.id)) ?? u.createdAt
|
|
3543
|
+
) })
|
|
3544
|
+
] }),
|
|
3545
|
+
/* @__PURE__ */ jsx(FeedEmail, { title: u.email, children: u.email })
|
|
3546
|
+
] }, u.documentId)) })
|
|
3547
|
+
]
|
|
3548
|
+
}
|
|
3549
|
+
)
|
|
3481
3550
|
] }),
|
|
3482
3551
|
/* @__PURE__ */ jsxs(SectionDivider, { children: [
|
|
3483
3552
|
/* @__PURE__ */ jsx(DivLabel, { children: "Retention & Activity" }),
|
|
@@ -3853,9 +3922,10 @@ const SessionCard = styled.div`
|
|
|
3853
3922
|
align-items: flex-start;
|
|
3854
3923
|
justify-content: space-between;
|
|
3855
3924
|
gap: 12px;
|
|
3856
|
-
padding: 10px
|
|
3857
|
-
|
|
3858
|
-
|
|
3925
|
+
padding: 10px 14px;
|
|
3926
|
+
background: white;
|
|
3927
|
+
border: 1px solid #eaeaef;
|
|
3928
|
+
border-radius: 8px;
|
|
3859
3929
|
`;
|
|
3860
3930
|
const SessionMeta = styled.div`
|
|
3861
3931
|
display: flex;
|
|
@@ -3961,6 +4031,7 @@ function UserDetailDrawer({
|
|
|
3961
4031
|
const [banExpiresDays, setBanExpiresDays] = useState("");
|
|
3962
4032
|
const [confirmRevokeAll, setConfirmRevokeAll] = useState(false);
|
|
3963
4033
|
const [confirmRevokeSessionId, setConfirmRevokeSessionId] = useState(null);
|
|
4034
|
+
const [confirmBan, setConfirmBan] = useState(false);
|
|
3964
4035
|
const [confirmUnban, setConfirmUnban] = useState(false);
|
|
3965
4036
|
const [confirmUnlinkAccountId, setConfirmUnlinkAccountId] = useState(null);
|
|
3966
4037
|
const [confirmDisable2FA, setConfirmDisable2FA] = useState(false);
|
|
@@ -3984,33 +4055,18 @@ function UserDetailDrawer({
|
|
|
3984
4055
|
};
|
|
3985
4056
|
const updateMutation = useMutation({
|
|
3986
4057
|
mutationFn: async () => {
|
|
3987
|
-
const
|
|
3988
|
-
if (editName !== void 0)
|
|
3989
|
-
if (editEmail !== void 0)
|
|
4058
|
+
const body = { ...editExtra };
|
|
4059
|
+
if (editName !== void 0) body.name = editName;
|
|
4060
|
+
if (editEmail !== void 0) body.email = editEmail;
|
|
3990
4061
|
if (editEmailVerified !== void 0)
|
|
3991
|
-
|
|
3992
|
-
if (editImage !== void 0)
|
|
3993
|
-
const
|
|
3994
|
-
if (
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
})
|
|
4000
|
-
);
|
|
4001
|
-
}
|
|
4002
|
-
if (Object.keys(editExtra).length > 0) {
|
|
4003
|
-
const documentId = strapiUserQuery.data?.documentId;
|
|
4004
|
-
if (!documentId)
|
|
4005
|
-
throw new Error("Could not resolve documentId for user");
|
|
4006
|
-
ops.push(
|
|
4007
|
-
put(
|
|
4008
|
-
`/better-auth-dashboard/db/${documentId}?uid=plugin::better-auth.user`,
|
|
4009
|
-
editExtra
|
|
4010
|
-
)
|
|
4011
|
-
);
|
|
4012
|
-
}
|
|
4013
|
-
await Promise.all(ops);
|
|
4062
|
+
body.emailVerified = editEmailVerified;
|
|
4063
|
+
if (editImage !== void 0) body.image = editImage;
|
|
4064
|
+
const documentId = strapiUserQuery.data?.documentId;
|
|
4065
|
+
if (!documentId) throw new Error("Could not resolve documentId for user");
|
|
4066
|
+
await put(
|
|
4067
|
+
`/better-auth-dashboard/db/${documentId}?uid=plugin::better-auth.user`,
|
|
4068
|
+
body
|
|
4069
|
+
);
|
|
4014
4070
|
},
|
|
4015
4071
|
onSuccess: () => {
|
|
4016
4072
|
qc.invalidateQueries({ queryKey: ["dash-user", userId] });
|
|
@@ -4092,6 +4148,7 @@ function UserDetailDrawer({
|
|
|
4092
4148
|
return result.data;
|
|
4093
4149
|
},
|
|
4094
4150
|
onSuccess: () => {
|
|
4151
|
+
setConfirmBan(false);
|
|
4095
4152
|
qc.invalidateQueries({ queryKey: ["dash-user", userId] });
|
|
4096
4153
|
qc.invalidateQueries({ queryKey: ["dash-users"] });
|
|
4097
4154
|
setBanReason("");
|
|
@@ -4707,7 +4764,8 @@ function UserDetailDrawer({
|
|
|
4707
4764
|
] })
|
|
4708
4765
|
] })
|
|
4709
4766
|
] }) }),
|
|
4710
|
-
banEnabled && /* @__PURE__ */ jsx(Tabs.Content, { value: "ban", children: /* @__PURE__ */ jsx(Flex, { direction: "column", gap:
|
|
4767
|
+
banEnabled && /* @__PURE__ */ jsx(Tabs.Content, { value: "ban", children: /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 5, paddingTop: 6, children: user?.banned ? /* @__PURE__ */ jsxs(FormSection, { children: [
|
|
4768
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Ban status" }),
|
|
4711
4769
|
/* @__PURE__ */ jsxs(WarnCard, { children: [
|
|
4712
4770
|
/* @__PURE__ */ jsx(
|
|
4713
4771
|
Typography,
|
|
@@ -4722,7 +4780,7 @@ function UserDetailDrawer({
|
|
|
4722
4780
|
"Reason: ",
|
|
4723
4781
|
user.banReason
|
|
4724
4782
|
] }),
|
|
4725
|
-
user.banExpires
|
|
4783
|
+
user.banExpires ? /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "danger600", children: [
|
|
4726
4784
|
"Expires:",
|
|
4727
4785
|
" ",
|
|
4728
4786
|
new Date(user.banExpires).toLocaleDateString(
|
|
@@ -4734,8 +4792,7 @@ function UserDetailDrawer({
|
|
|
4734
4792
|
day: "numeric"
|
|
4735
4793
|
}
|
|
4736
4794
|
)
|
|
4737
|
-
] }),
|
|
4738
|
-
!user.banExpires && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: "Duration: Permanent" })
|
|
4795
|
+
] }) : /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: "Duration: Permanent" })
|
|
4739
4796
|
] }),
|
|
4740
4797
|
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
4741
4798
|
Button,
|
|
@@ -4745,27 +4802,28 @@ function UserDetailDrawer({
|
|
|
4745
4802
|
children: "Lift ban"
|
|
4746
4803
|
}
|
|
4747
4804
|
) })
|
|
4748
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
4805
|
+
] }) : /* @__PURE__ */ jsxs(FormSection, { children: [
|
|
4806
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Apply ban" }),
|
|
4807
|
+
/* @__PURE__ */ jsxs(
|
|
4808
|
+
Field.Root,
|
|
4809
|
+
{
|
|
4810
|
+
hint: "Optional — will be shown to the user",
|
|
4811
|
+
style: { width: "100%" },
|
|
4812
|
+
children: [
|
|
4813
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Reason" }),
|
|
4814
|
+
/* @__PURE__ */ jsx(
|
|
4815
|
+
TextInput,
|
|
4816
|
+
{
|
|
4817
|
+
value: banReason,
|
|
4818
|
+
onChange: (e) => setBanReason(e.target.value),
|
|
4819
|
+
placeholder: "e.g. Violated terms of service"
|
|
4820
|
+
}
|
|
4821
|
+
),
|
|
4822
|
+
/* @__PURE__ */ jsx(Field.Hint, {})
|
|
4823
|
+
]
|
|
4824
|
+
}
|
|
4825
|
+
),
|
|
4749
4826
|
/* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
|
|
4750
|
-
/* @__PURE__ */ jsx(Grid.Item, { col: 12, children: /* @__PURE__ */ jsxs(
|
|
4751
|
-
Field.Root,
|
|
4752
|
-
{
|
|
4753
|
-
hint: "Optional — will be shown to the user",
|
|
4754
|
-
style: { width: "100%" },
|
|
4755
|
-
children: [
|
|
4756
|
-
/* @__PURE__ */ jsx(Field.Label, { children: "Reason" }),
|
|
4757
|
-
/* @__PURE__ */ jsx(
|
|
4758
|
-
TextInput,
|
|
4759
|
-
{
|
|
4760
|
-
value: banReason,
|
|
4761
|
-
onChange: (e) => setBanReason(e.target.value),
|
|
4762
|
-
placeholder: "e.g. Violated terms of service"
|
|
4763
|
-
}
|
|
4764
|
-
),
|
|
4765
|
-
/* @__PURE__ */ jsx(Field.Hint, {})
|
|
4766
|
-
]
|
|
4767
|
-
}
|
|
4768
|
-
) }),
|
|
4769
4827
|
/* @__PURE__ */ jsx(Grid.Item, { col: 6, children: /* @__PURE__ */ jsxs(
|
|
4770
4828
|
Field.Root,
|
|
4771
4829
|
{
|
|
@@ -4786,24 +4844,13 @@ function UserDetailDrawer({
|
|
|
4786
4844
|
]
|
|
4787
4845
|
}
|
|
4788
4846
|
) }),
|
|
4789
|
-
/* @__PURE__ */ jsx(Grid.Item, { col: 6, children:
|
|
4790
|
-
Flex,
|
|
4791
|
-
{
|
|
4792
|
-
direction: "column",
|
|
4793
|
-
justifyContent: "flex-end",
|
|
4794
|
-
style: { height: "100%", paddingBottom: 4 },
|
|
4795
|
-
children: /* @__PURE__ */ jsxs(PreviewPill, { children: [
|
|
4796
|
-
"⏱ Expires ",
|
|
4797
|
-
banExpiryPreview
|
|
4798
|
-
] })
|
|
4799
|
-
}
|
|
4800
|
-
) : /* @__PURE__ */ jsx(
|
|
4847
|
+
/* @__PURE__ */ jsx(Grid.Item, { col: 6, children: /* @__PURE__ */ jsx(
|
|
4801
4848
|
Flex,
|
|
4802
4849
|
{
|
|
4803
4850
|
direction: "column",
|
|
4804
4851
|
justifyContent: "flex-end",
|
|
4805
4852
|
style: { height: "100%", paddingBottom: 4 },
|
|
4806
|
-
children: /* @__PURE__ */ jsx(PreviewPill, { children: "♾ Permanent ban" })
|
|
4853
|
+
children: /* @__PURE__ */ jsx(PreviewPill, { children: banExpiryPreview ? `⏱ Expires ${banExpiryPreview}` : "♾ Permanent ban" })
|
|
4807
4854
|
}
|
|
4808
4855
|
) })
|
|
4809
4856
|
] }),
|
|
@@ -4811,8 +4858,7 @@ function UserDetailDrawer({
|
|
|
4811
4858
|
Button,
|
|
4812
4859
|
{
|
|
4813
4860
|
variant: "danger",
|
|
4814
|
-
|
|
4815
|
-
onClick: () => banMutation.mutate(),
|
|
4861
|
+
onClick: () => setConfirmBan(true),
|
|
4816
4862
|
children: "Ban user"
|
|
4817
4863
|
}
|
|
4818
4864
|
) })
|
|
@@ -4839,19 +4885,27 @@ function UserDetailDrawer({
|
|
|
4839
4885
|
] }),
|
|
4840
4886
|
/* @__PURE__ */ jsxs(FormSection, { children: [
|
|
4841
4887
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Active sessions" }),
|
|
4842
|
-
sessionsQuery.isLoading ? /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Loader, { children: "Loading sessions…" }) }) : (sessionsQuery.data ?? []).length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: "No active sessions." }) : /* @__PURE__ */ jsx(Flex, { direction: "column", gap:
|
|
4888
|
+
sessionsQuery.isLoading ? /* @__PURE__ */ jsx(Flex, { justifyContent: "center", padding: 4, children: /* @__PURE__ */ jsx(Loader, { children: "Loading sessions…" }) }) : (sessionsQuery.data ?? []).length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: "No active sessions." }) : /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 2, alignItems: "stretch", children: (sessionsQuery.data ?? []).map((session) => /* @__PURE__ */ jsxs(SessionCard, { children: [
|
|
4843
4889
|
/* @__PURE__ */ jsxs(SessionMeta, { children: [
|
|
4844
|
-
/* @__PURE__ */ jsxs(
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4890
|
+
/* @__PURE__ */ jsxs(
|
|
4891
|
+
Flex,
|
|
4892
|
+
{
|
|
4893
|
+
gap: 2,
|
|
4894
|
+
alignItems: "center",
|
|
4895
|
+
style: { flexWrap: "wrap" },
|
|
4896
|
+
children: [
|
|
4897
|
+
session.ipAddress && /* @__PURE__ */ jsx(IpChip, { children: session.ipAddress }),
|
|
4898
|
+
/* @__PURE__ */ jsxs(TimestampText, { children: [
|
|
4899
|
+
"Created",
|
|
4900
|
+
" ",
|
|
4901
|
+
new Date(session.createdAt).toLocaleString(),
|
|
4902
|
+
" · Expires",
|
|
4903
|
+
" ",
|
|
4904
|
+
new Date(session.expiresAt).toLocaleString()
|
|
4905
|
+
] })
|
|
4906
|
+
]
|
|
4907
|
+
}
|
|
4908
|
+
),
|
|
4855
4909
|
session.userAgent && /* @__PURE__ */ jsx(AgentText, { children: session.userAgent })
|
|
4856
4910
|
] }),
|
|
4857
4911
|
/* @__PURE__ */ jsx(
|
|
@@ -4913,6 +4967,18 @@ function UserDetailDrawer({
|
|
|
4913
4967
|
onCancel: () => setConfirmRevokeSessionId(null)
|
|
4914
4968
|
}
|
|
4915
4969
|
),
|
|
4970
|
+
confirmBan && /* @__PURE__ */ jsx(
|
|
4971
|
+
ConfirmDialog,
|
|
4972
|
+
{
|
|
4973
|
+
title: "Ban user",
|
|
4974
|
+
message: banReason ? `Ban this user for the following reason: "${banReason}"? They will be prevented from signing in.` : "Are you sure you want to ban this user? They will be prevented from signing in.",
|
|
4975
|
+
confirmLabel: "Ban user",
|
|
4976
|
+
variant: "danger",
|
|
4977
|
+
loading: banMutation.isLoading,
|
|
4978
|
+
onConfirm: () => banMutation.mutate(),
|
|
4979
|
+
onCancel: () => setConfirmBan(false)
|
|
4980
|
+
}
|
|
4981
|
+
),
|
|
4916
4982
|
confirmUnban && /* @__PURE__ */ jsx(
|
|
4917
4983
|
ConfirmDialog,
|
|
4918
4984
|
{
|
|
@@ -5143,6 +5209,7 @@ const Toolbar = styled.div`
|
|
|
5143
5209
|
`;
|
|
5144
5210
|
function UsersPage({ config }) {
|
|
5145
5211
|
const qc = useQueryClient();
|
|
5212
|
+
const { toggleNotification } = useNotification();
|
|
5146
5213
|
const banEnabled = hasPlugin(config, "admin");
|
|
5147
5214
|
const emailVerificationEnabled = config.emailVerification.sendVerificationEmailEnabled;
|
|
5148
5215
|
const twoFactorEnabled = hasPlugin(config, "two-factor");
|
|
@@ -5174,6 +5241,13 @@ function UsersPage({ config }) {
|
|
|
5174
5241
|
setConfirmDelete(null);
|
|
5175
5242
|
qc.invalidateQueries({ queryKey: ["dash-users"] });
|
|
5176
5243
|
qc.invalidateQueries({ queryKey: ["dash-user-stats"] });
|
|
5244
|
+
toggleNotification({ type: "success", message: "User deleted" });
|
|
5245
|
+
},
|
|
5246
|
+
onError: (err) => {
|
|
5247
|
+
toggleNotification({
|
|
5248
|
+
type: "danger",
|
|
5249
|
+
message: err.message ?? "Failed to delete user"
|
|
5250
|
+
});
|
|
5177
5251
|
}
|
|
5178
5252
|
});
|
|
5179
5253
|
const deleteManyMutation = useMutation({
|
|
@@ -5186,11 +5260,21 @@ function UsersPage({ config }) {
|
|
|
5186
5260
|
throw new Error(result.error.message ?? "Delete failed");
|
|
5187
5261
|
return result.data;
|
|
5188
5262
|
},
|
|
5189
|
-
onSuccess: () => {
|
|
5263
|
+
onSuccess: (_data, userIds) => {
|
|
5190
5264
|
setConfirmDeleteMany(false);
|
|
5191
5265
|
setSelected(/* @__PURE__ */ new Set());
|
|
5192
5266
|
qc.invalidateQueries({ queryKey: ["dash-users"] });
|
|
5193
5267
|
qc.invalidateQueries({ queryKey: ["dash-user-stats"] });
|
|
5268
|
+
toggleNotification({
|
|
5269
|
+
type: "success",
|
|
5270
|
+
message: `${userIds.length} user${userIds.length !== 1 ? "s" : ""} deleted`
|
|
5271
|
+
});
|
|
5272
|
+
},
|
|
5273
|
+
onError: (err) => {
|
|
5274
|
+
toggleNotification({
|
|
5275
|
+
type: "danger",
|
|
5276
|
+
message: err.message ?? "Failed to delete users"
|
|
5277
|
+
});
|
|
5194
5278
|
}
|
|
5195
5279
|
});
|
|
5196
5280
|
const banManyMutation = useMutation({
|
|
@@ -5202,10 +5286,20 @@ function UsersPage({ config }) {
|
|
|
5202
5286
|
if (result.error) throw new Error(result.error.message ?? "Ban failed");
|
|
5203
5287
|
return result.data;
|
|
5204
5288
|
},
|
|
5205
|
-
onSuccess: () => {
|
|
5289
|
+
onSuccess: (_data, userIds) => {
|
|
5206
5290
|
setConfirmBanMany(false);
|
|
5207
5291
|
setSelected(/* @__PURE__ */ new Set());
|
|
5208
5292
|
qc.invalidateQueries({ queryKey: ["dash-users"] });
|
|
5293
|
+
toggleNotification({
|
|
5294
|
+
type: "success",
|
|
5295
|
+
message: `${userIds.length} user${userIds.length !== 1 ? "s" : ""} banned`
|
|
5296
|
+
});
|
|
5297
|
+
},
|
|
5298
|
+
onError: (err) => {
|
|
5299
|
+
toggleNotification({
|
|
5300
|
+
type: "danger",
|
|
5301
|
+
message: err.message ?? "Failed to ban users"
|
|
5302
|
+
});
|
|
5209
5303
|
}
|
|
5210
5304
|
});
|
|
5211
5305
|
const toggleSelect = (id) => {
|
|
@@ -5384,14 +5478,28 @@ function UsersPage({ config }) {
|
|
|
5384
5478
|
user.id
|
|
5385
5479
|
)) })
|
|
5386
5480
|
] }) }),
|
|
5387
|
-
pageCount > 1 && /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5481
|
+
pageCount > 1 && /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
5482
|
+
/* @__PURE__ */ jsx(
|
|
5483
|
+
Button,
|
|
5484
|
+
{
|
|
5485
|
+
variant: "tertiary",
|
|
5486
|
+
size: "S",
|
|
5487
|
+
disabled: page === 1,
|
|
5488
|
+
onClick: () => setPage((p) => p - 1),
|
|
5489
|
+
children: "Previous"
|
|
5490
|
+
}
|
|
5491
|
+
),
|
|
5492
|
+
/* @__PURE__ */ jsx(
|
|
5493
|
+
Button,
|
|
5494
|
+
{
|
|
5495
|
+
variant: "tertiary",
|
|
5496
|
+
size: "S",
|
|
5497
|
+
disabled: page >= pageCount,
|
|
5498
|
+
onClick: () => setPage((p) => p + 1),
|
|
5499
|
+
children: "Next"
|
|
5500
|
+
}
|
|
5501
|
+
)
|
|
5502
|
+
] }) }),
|
|
5395
5503
|
showCreate && /* @__PURE__ */ jsx(CreateUserDialog, { onClose: () => setShowCreate(false) }),
|
|
5396
5504
|
detailUserId && /* @__PURE__ */ jsx(
|
|
5397
5505
|
UserDetailDrawer,
|
|
@@ -55,7 +55,7 @@ const index = {
|
|
|
55
55
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
56
56
|
defaultMessage: "Auth Dashboard"
|
|
57
57
|
},
|
|
58
|
-
Component: async () => Promise.resolve().then(() => require("./Root-
|
|
58
|
+
Component: async () => Promise.resolve().then(() => require("./Root-7EredGQZ.js"))
|
|
59
59
|
});
|
|
60
60
|
},
|
|
61
61
|
bootstrap() {
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED