@xk2800/nextjs-template 0.5.3
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 +339 -0
- package/components/auth/authCard.tsx +92 -0
- package/components/auth/authShell.tsx +46 -0
- package/components/auth/deviceCheck.tsx +52 -0
- package/components/auth/emailPasswordLogin.tsx +136 -0
- package/components/auth/emailPasswordSignup.tsx +178 -0
- package/components/auth/forgotPasswordForm.tsx +66 -0
- package/components/auth/loginErrorRecovery.tsx +117 -0
- package/components/auth/logoutButtons.tsx +26 -0
- package/components/auth/oneTap.tsx +50 -0
- package/components/auth/passkeyLogin.tsx +50 -0
- package/components/auth/resetPasswordForm.tsx +112 -0
- package/components/auth/socialLogin.tsx +51 -0
- package/components/auth/twoFactorVerifyForm.tsx +100 -0
- package/components/dashboard/accountDetailsCard.tsx +58 -0
- package/components/dashboard/activityLogsCard.tsx +141 -0
- package/components/dashboard/activityLogsCardSkeleton.tsx +20 -0
- package/components/dashboard/activityLogsSection.tsx +16 -0
- package/components/dashboard/admin/activityLogsSection.tsx +13 -0
- package/components/dashboard/admin/adminActivityLogsSkeleton.tsx +34 -0
- package/components/dashboard/admin/adminActivityLogsTable.tsx +319 -0
- package/components/dashboard/admin/adminStatsGrid.tsx +30 -0
- package/components/dashboard/admin/adminStatsGridSkeleton.tsx +16 -0
- package/components/dashboard/admin/adminUserActivityLogCard.tsx +53 -0
- package/components/dashboard/admin/adminUserActivityLogTable.tsx +69 -0
- package/components/dashboard/admin/adminUserLoginInfoCard.tsx +50 -0
- package/components/dashboard/admin/adminUserLoginInfoTable.tsx +63 -0
- package/components/dashboard/admin/adminUserSessionsCard.tsx +225 -0
- package/components/dashboard/admin/adminUserStatusCard.tsx +57 -0
- package/components/dashboard/admin/adminUsersSkeleton.tsx +30 -0
- package/components/dashboard/admin/adminUsersTable.tsx +596 -0
- package/components/dashboard/admin/deviceThrottleCard.tsx +59 -0
- package/components/dashboard/admin/deviceThrottleTable.tsx +93 -0
- package/components/dashboard/admin/impersonationLogCard.tsx +73 -0
- package/components/dashboard/admin/newDeviceCard.tsx +35 -0
- package/components/dashboard/admin/newDeviceTable.tsx +71 -0
- package/components/dashboard/admin/revokeAllSessionsButton.tsx +77 -0
- package/components/dashboard/admin/sharedDeviceCard.tsx +42 -0
- package/components/dashboard/admin/sharedDeviceTable.tsx +75 -0
- package/components/dashboard/admin/systemSettingsForm.tsx +200 -0
- package/components/dashboard/admin/systemSettingsSection.tsx +9 -0
- package/components/dashboard/admin/systemSettingsSkeleton.tsx +29 -0
- package/components/dashboard/admin/usersSection.tsx +13 -0
- package/components/dashboard/adminSection.tsx +31 -0
- package/components/dashboard/appSidebar.tsx +170 -0
- package/components/dashboard/dashboardHeader.tsx +85 -0
- package/components/dashboard/heartbeat.tsx +22 -0
- package/components/dashboard/impersonationBanner.tsx +50 -0
- package/components/dashboard/passkeysCard.tsx +187 -0
- package/components/dashboard/profileCard.tsx +42 -0
- package/components/dashboard/sectionErrorFallback.tsx +18 -0
- package/components/dashboard/sessionsCard.tsx +194 -0
- package/components/dashboard/sessionsCardSkeleton.tsx +20 -0
- package/components/dashboard/sessionsSection.tsx +22 -0
- package/components/dashboard/twoFactorCard.tsx +344 -0
- package/components/dashboard/verifyEmailButton.tsx +32 -0
- package/components/email/email-template-2.tsx +44 -0
- package/components/email/email-template-new-device.tsx +80 -0
- package/components/email/email-template-passkey-change.tsx +81 -0
- package/components/email/email-template-reset-password.tsx +56 -0
- package/components/email/email-template-verify-email.tsx +55 -0
- package/components/email/email-template-welcome.tsx +53 -0
- package/components/email/email-template.tsx +33 -0
- package/components/email/send-email-button.tsx +61 -0
- package/components/providers/theme-provider.tsx +9 -0
- package/components/theme/theme-toggle.tsx +53 -0
- package/components/ui/alert-dialog.tsx +141 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/badge.tsx +46 -0
- package/components/ui/button.tsx +64 -0
- package/components/ui/card.tsx +92 -0
- package/components/ui/checkbox.tsx +32 -0
- package/components/ui/data-table.tsx +302 -0
- package/components/ui/dialog.tsx +143 -0
- package/components/ui/dropdown-menu.tsx +203 -0
- package/components/ui/input.tsx +21 -0
- package/components/ui/label.tsx +26 -0
- package/components/ui/password-input.tsx +38 -0
- package/components/ui/separator.tsx +28 -0
- package/components/ui/sheet.tsx +143 -0
- package/components/ui/sidebar.tsx +726 -0
- package/components/ui/skeleton.tsx +13 -0
- package/components/ui/switch.tsx +35 -0
- package/components/ui/table.tsx +116 -0
- package/components/ui/textarea.tsx +18 -0
- package/components/ui/tooltip.tsx +57 -0
- package/dist/activity/logger.d.mts +18 -0
- package/dist/activity/logger.d.ts +18 -0
- package/dist/activity/logger.js +289 -0
- package/dist/activity/logger.js.map +1 -0
- package/dist/activity/logger.mjs +7 -0
- package/dist/activity/logger.mjs.map +1 -0
- package/dist/activity/queries.d.mts +98 -0
- package/dist/activity/queries.d.ts +98 -0
- package/dist/activity/queries.js +372 -0
- package/dist/activity/queries.js.map +1 -0
- package/dist/activity/queries.mjs +124 -0
- package/dist/activity/queries.mjs.map +1 -0
- package/dist/admin/queries.d.mts +68 -0
- package/dist/admin/queries.d.ts +68 -0
- package/dist/admin/queries.js +450 -0
- package/dist/admin/queries.js.map +1 -0
- package/dist/admin/queries.mjs +143 -0
- package/dist/admin/queries.mjs.map +1 -0
- package/dist/auth/helpers.d.mts +111 -0
- package/dist/auth/helpers.d.ts +111 -0
- package/dist/auth/helpers.js +1023 -0
- package/dist/auth/helpers.js.map +1 -0
- package/dist/auth/helpers.mjs +67 -0
- package/dist/auth/helpers.mjs.map +1 -0
- package/dist/auth/index.d.mts +6589 -0
- package/dist/auth/index.d.ts +6589 -0
- package/dist/auth/index.js +968 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +10 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth-client/index.d.mts +4864 -0
- package/dist/auth-client/index.d.ts +4864 -0
- package/dist/auth-client/index.js +55 -0
- package/dist/auth-client/index.js.map +1 -0
- package/dist/auth-client/index.mjs +49 -0
- package/dist/auth-client/index.mjs.map +1 -0
- package/dist/chunk-2FW7C3KS.mjs +556 -0
- package/dist/chunk-2FW7C3KS.mjs.map +1 -0
- package/dist/chunk-ENGYO4K7.mjs +189 -0
- package/dist/chunk-ENGYO4K7.mjs.map +1 -0
- package/dist/chunk-GTPTVNY2.mjs +40 -0
- package/dist/chunk-GTPTVNY2.mjs.map +1 -0
- package/dist/chunk-HYKUB3A2.mjs +30 -0
- package/dist/chunk-HYKUB3A2.mjs.map +1 -0
- package/dist/chunk-JIYHBWAU.mjs +79 -0
- package/dist/chunk-JIYHBWAU.mjs.map +1 -0
- package/dist/chunk-K6OJCSJS.mjs +41 -0
- package/dist/chunk-K6OJCSJS.mjs.map +1 -0
- package/dist/chunk-N6ECRCHY.mjs +61 -0
- package/dist/chunk-N6ECRCHY.mjs.map +1 -0
- package/dist/chunk-YN4436PK.mjs +33 -0
- package/dist/chunk-YN4436PK.mjs.map +1 -0
- package/dist/config/env.d.mts +15 -0
- package/dist/config/env.d.ts +15 -0
- package/dist/config/env.js +42 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/env.mjs +4 -0
- package/dist/config/env.mjs.map +1 -0
- package/dist/db/index.d.mts +10 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.js +252 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/index.mjs +6 -0
- package/dist/db/index.mjs.map +1 -0
- package/dist/db/schema.d.mts +2 -0
- package/dist/db/schema.d.ts +2 -0
- package/dist/db/schema.js +186 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/schema.mjs +4 -0
- package/dist/db/schema.mjs.map +1 -0
- package/dist/schema-CgkDv4wJ.d.mts +1758 -0
- package/dist/schema-CgkDv4wJ.d.ts +1758 -0
- package/dist/sessions/queries.d.mts +34 -0
- package/dist/sessions/queries.d.ts +34 -0
- package/dist/sessions/queries.js +268 -0
- package/dist/sessions/queries.js.map +1 -0
- package/dist/sessions/queries.mjs +23 -0
- package/dist/sessions/queries.mjs.map +1 -0
- package/dist/settings/queries.d.mts +20 -0
- package/dist/settings/queries.d.ts +20 -0
- package/dist/settings/queries.js +344 -0
- package/dist/settings/queries.js.map +1 -0
- package/dist/settings/queries.mjs +7 -0
- package/dist/settings/queries.mjs.map +1 -0
- package/dist/types/auth/loginSchema.d.mts +8 -0
- package/dist/types/auth/loginSchema.d.ts +8 -0
- package/dist/types/auth/loginSchema.js +18 -0
- package/dist/types/auth/loginSchema.js.map +1 -0
- package/dist/types/auth/loginSchema.mjs +16 -0
- package/dist/types/auth/loginSchema.mjs.map +1 -0
- package/dist/types/auth/signupSchema.d.mts +9 -0
- package/dist/types/auth/signupSchema.d.ts +9 -0
- package/dist/types/auth/signupSchema.js +21 -0
- package/dist/types/auth/signupSchema.js.map +1 -0
- package/dist/types/auth/signupSchema.mjs +19 -0
- package/dist/types/auth/signupSchema.mjs.map +1 -0
- package/dist/users/queries.d.mts +71 -0
- package/dist/users/queries.d.ts +71 -0
- package/dist/users/queries.js +293 -0
- package/dist/users/queries.js.map +1 -0
- package/dist/users/queries.mjs +47 -0
- package/dist/users/queries.mjs.map +1 -0
- package/lib/auth-client.ts +58 -0
- package/lib/cookie-names.ts +13 -0
- package/lib/device-fingerprint.ts +21 -0
- package/lib/formatters.ts +53 -0
- package/lib/recalculate-columns.ts +75 -0
- package/lib/request-info.ts +78 -0
- package/lib/utils.ts +6 -0
- package/package.json +301 -0
- package/styles/theme.css +124 -0
- package/types/auth/loginSchema.ts +11 -0
- package/types/auth/signupSchema.ts +14 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { db } from '../chunk-HYKUB3A2.mjs';
|
|
2
|
+
import { activityLogs, users } from '../chunk-ENGYO4K7.mjs';
|
|
3
|
+
import '../chunk-GTPTVNY2.mjs';
|
|
4
|
+
import '../chunk-YN4436PK.mjs';
|
|
5
|
+
import 'server-only';
|
|
6
|
+
import { eq, desc, and, inArray, sql, or, like, gte, lte } from 'drizzle-orm';
|
|
7
|
+
|
|
8
|
+
async function getUserActivityLogs(userId, limit = 50) {
|
|
9
|
+
return await db.select().from(activityLogs).where(eq(activityLogs.userId, userId)).orderBy(desc(activityLogs.createdAt)).limit(limit);
|
|
10
|
+
}
|
|
11
|
+
async function getUserLoginHistory(userId, limit = 20) {
|
|
12
|
+
return await db.select().from(activityLogs).where(and(eq(activityLogs.userId, userId), eq(activityLogs.action, "login"))).orderBy(desc(activityLogs.createdAt)).limit(limit);
|
|
13
|
+
}
|
|
14
|
+
async function getAllActivityLogs(limit = 100, offset = 0) {
|
|
15
|
+
return await db.select({
|
|
16
|
+
id: activityLogs.id,
|
|
17
|
+
action: activityLogs.action,
|
|
18
|
+
description: activityLogs.description,
|
|
19
|
+
ipAddress: activityLogs.ipAddress,
|
|
20
|
+
userAgent: activityLogs.userAgent,
|
|
21
|
+
metadata: activityLogs.metadata,
|
|
22
|
+
createdAt: activityLogs.createdAt,
|
|
23
|
+
userId: activityLogs.userId,
|
|
24
|
+
userName: users.name,
|
|
25
|
+
userEmail: users.email
|
|
26
|
+
}).from(activityLogs).leftJoin(users, eq(activityLogs.userId, users.id)).orderBy(desc(activityLogs.createdAt)).limit(limit).offset(offset);
|
|
27
|
+
}
|
|
28
|
+
async function getRecentImpersonationEvents(limit = 10) {
|
|
29
|
+
return await db.select({
|
|
30
|
+
id: activityLogs.id,
|
|
31
|
+
action: activityLogs.action,
|
|
32
|
+
description: activityLogs.description,
|
|
33
|
+
createdAt: activityLogs.createdAt,
|
|
34
|
+
adminId: activityLogs.userId,
|
|
35
|
+
adminName: users.name,
|
|
36
|
+
adminEmail: users.email
|
|
37
|
+
}).from(activityLogs).leftJoin(users, eq(activityLogs.userId, users.id)).where(inArray(activityLogs.action, ["impersonation_started", "impersonation_stopped"])).orderBy(desc(activityLogs.createdAt)).limit(limit);
|
|
38
|
+
}
|
|
39
|
+
function buildActivityLogsWhere({
|
|
40
|
+
search = "",
|
|
41
|
+
action,
|
|
42
|
+
dateFrom,
|
|
43
|
+
dateTo
|
|
44
|
+
}) {
|
|
45
|
+
const conditions = [];
|
|
46
|
+
if (search.trim()) {
|
|
47
|
+
conditions.push(
|
|
48
|
+
or(
|
|
49
|
+
like(users.name, `%${search}%`),
|
|
50
|
+
like(users.email, `%${search}%`)
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
if (action) {
|
|
55
|
+
conditions.push(eq(activityLogs.action, action));
|
|
56
|
+
}
|
|
57
|
+
if (dateFrom) {
|
|
58
|
+
conditions.push(gte(activityLogs.createdAt, dateFrom));
|
|
59
|
+
}
|
|
60
|
+
if (dateTo) {
|
|
61
|
+
conditions.push(lte(activityLogs.createdAt, dateTo));
|
|
62
|
+
}
|
|
63
|
+
return conditions.length > 0 ? and(...conditions) : void 0;
|
|
64
|
+
}
|
|
65
|
+
async function getActivityLogsFiltered({
|
|
66
|
+
search = "",
|
|
67
|
+
action,
|
|
68
|
+
dateFrom,
|
|
69
|
+
dateTo,
|
|
70
|
+
page = 1,
|
|
71
|
+
limit = 20
|
|
72
|
+
}) {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
const offset = (page - 1) * limit;
|
|
75
|
+
const where = buildActivityLogsWhere({ search, action, dateFrom, dateTo });
|
|
76
|
+
const [logs, countResult] = await Promise.all([
|
|
77
|
+
db.select({
|
|
78
|
+
id: activityLogs.id,
|
|
79
|
+
action: activityLogs.action,
|
|
80
|
+
description: activityLogs.description,
|
|
81
|
+
ipAddress: activityLogs.ipAddress,
|
|
82
|
+
userAgent: activityLogs.userAgent,
|
|
83
|
+
metadata: activityLogs.metadata,
|
|
84
|
+
createdAt: activityLogs.createdAt,
|
|
85
|
+
userId: activityLogs.userId,
|
|
86
|
+
userName: users.name,
|
|
87
|
+
userEmail: users.email
|
|
88
|
+
}).from(activityLogs).leftJoin(users, eq(activityLogs.userId, users.id)).where(where).orderBy(desc(activityLogs.createdAt)).limit(limit).offset(offset),
|
|
89
|
+
db.select({ count: sql`count(*)` }).from(activityLogs).leftJoin(users, eq(activityLogs.userId, users.id)).where(where)
|
|
90
|
+
]);
|
|
91
|
+
const total = Number((_b = (_a = countResult[0]) == null ? void 0 : _a.count) != null ? _b : 0);
|
|
92
|
+
return {
|
|
93
|
+
logs,
|
|
94
|
+
total,
|
|
95
|
+
page,
|
|
96
|
+
limit,
|
|
97
|
+
pages: Math.ceil(total / limit)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
var EXPORT_ROW_LIMIT = 1e4;
|
|
101
|
+
async function getActivityLogsForExport({
|
|
102
|
+
search = "",
|
|
103
|
+
action,
|
|
104
|
+
dateFrom,
|
|
105
|
+
dateTo
|
|
106
|
+
}) {
|
|
107
|
+
const where = buildActivityLogsWhere({ search, action, dateFrom, dateTo });
|
|
108
|
+
return await db.select({
|
|
109
|
+
id: activityLogs.id,
|
|
110
|
+
action: activityLogs.action,
|
|
111
|
+
description: activityLogs.description,
|
|
112
|
+
ipAddress: activityLogs.ipAddress,
|
|
113
|
+
userAgent: activityLogs.userAgent,
|
|
114
|
+
metadata: activityLogs.metadata,
|
|
115
|
+
createdAt: activityLogs.createdAt,
|
|
116
|
+
userId: activityLogs.userId,
|
|
117
|
+
userName: users.name,
|
|
118
|
+
userEmail: users.email
|
|
119
|
+
}).from(activityLogs).leftJoin(users, eq(activityLogs.userId, users.id)).where(where).orderBy(desc(activityLogs.createdAt)).limit(EXPORT_ROW_LIMIT);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { getActivityLogsFiltered, getActivityLogsForExport, getAllActivityLogs, getRecentImpersonationEvents, getUserActivityLogs, getUserLoginHistory };
|
|
123
|
+
//# sourceMappingURL=queries.mjs.map
|
|
124
|
+
//# sourceMappingURL=queries.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../lib/activity-queries.ts"],"names":[],"mappings":"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","file":"queries.mjs","sourcesContent":["import \"server-only\"\nimport { db } from \"../server/db\"\nimport { activityLogs, users, ActivityActionEnum } from \"../server/db/schema\"\nimport { eq, desc, and, or, like, gte, lte, sql, inArray, type SQL } from \"drizzle-orm\"\n\nexport async function getUserActivityLogs(userId: string, limit = 50) {\n return await db\n .select()\n .from(activityLogs)\n .where(eq(activityLogs.userId, userId))\n .orderBy(desc(activityLogs.createdAt))\n .limit(limit)\n}\n\n// Registration + sign-in events only, with the referrer/device/geolocation\n// columns captured at login time (see server/auth.ts's session.create hook).\nexport async function getUserLoginHistory(userId: string, limit = 20) {\n return await db\n .select()\n .from(activityLogs)\n .where(and(eq(activityLogs.userId, userId), eq(activityLogs.action, 'login')))\n .orderBy(desc(activityLogs.createdAt))\n .limit(limit)\n}\n\nexport async function getAllActivityLogs(limit = 100, offset = 0) {\n return await db\n .select({\n id: activityLogs.id,\n action: activityLogs.action,\n description: activityLogs.description,\n ipAddress: activityLogs.ipAddress,\n userAgent: activityLogs.userAgent,\n metadata: activityLogs.metadata,\n createdAt: activityLogs.createdAt,\n userId: activityLogs.userId,\n userName: users.name,\n userEmail: users.email,\n })\n .from(activityLogs)\n .leftJoin(users, eq(activityLogs.userId, users.id))\n .orderBy(desc(activityLogs.createdAt))\n .limit(limit)\n .offset(offset)\n}\n\n// Narrow, purpose-built feed for the admin panel's \"Impersonation log\" card —\n// so admins have a dedicated view of who's been logging in as whom without\n// having to remember to apply the generic action filter first.\nexport async function getRecentImpersonationEvents(limit = 10) {\n return await db\n .select({\n id: activityLogs.id,\n action: activityLogs.action,\n description: activityLogs.description,\n createdAt: activityLogs.createdAt,\n adminId: activityLogs.userId,\n adminName: users.name,\n adminEmail: users.email,\n })\n .from(activityLogs)\n .leftJoin(users, eq(activityLogs.userId, users.id))\n .where(inArray(activityLogs.action, ['impersonation_started', 'impersonation_stopped']))\n .orderBy(desc(activityLogs.createdAt))\n .limit(limit)\n}\n\nexport type ActivityActionFilter = (typeof ActivityActionEnum.enumValues)[number]\n\nexport interface ActivityLogFilters {\n search?: string\n action?: ActivityActionFilter\n dateFrom?: Date\n dateTo?: Date\n page?: number\n limit?: number\n}\n\nfunction buildActivityLogsWhere({\n search = \"\",\n action,\n dateFrom,\n dateTo,\n}: Pick<ActivityLogFilters, \"search\" | \"action\" | \"dateFrom\" | \"dateTo\">): SQL | undefined {\n const conditions: SQL[] = []\n if (search.trim()) {\n conditions.push(\n or(\n like(users.name, `%${search}%`),\n like(users.email, `%${search}%`)\n ) as SQL\n )\n }\n if (action) {\n conditions.push(eq(activityLogs.action, action))\n }\n if (dateFrom) {\n conditions.push(gte(activityLogs.createdAt, dateFrom))\n }\n if (dateTo) {\n conditions.push(lte(activityLogs.createdAt, dateTo))\n }\n\n return conditions.length > 0 ? and(...conditions) : undefined\n}\n\nexport async function getActivityLogsFiltered({\n search = \"\",\n action,\n dateFrom,\n dateTo,\n page = 1,\n limit = 20,\n}: ActivityLogFilters) {\n const offset = (page - 1) * limit\n\n const where = buildActivityLogsWhere({ search, action, dateFrom, dateTo })\n\n const [logs, countResult] = await Promise.all([\n db\n .select({\n id: activityLogs.id,\n action: activityLogs.action,\n description: activityLogs.description,\n ipAddress: activityLogs.ipAddress,\n userAgent: activityLogs.userAgent,\n metadata: activityLogs.metadata,\n createdAt: activityLogs.createdAt,\n userId: activityLogs.userId,\n userName: users.name,\n userEmail: users.email,\n })\n .from(activityLogs)\n .leftJoin(users, eq(activityLogs.userId, users.id))\n .where(where)\n .orderBy(desc(activityLogs.createdAt))\n .limit(limit)\n .offset(offset),\n db\n .select({ count: sql<number>`count(*)` })\n .from(activityLogs)\n .leftJoin(users, eq(activityLogs.userId, users.id))\n .where(where),\n ])\n\n const total = Number(countResult[0]?.count ?? 0)\n\n return {\n logs,\n total,\n page,\n limit,\n pages: Math.ceil(total / limit),\n }\n}\n\nexport type ActivityLogExportFilters = Pick<ActivityLogFilters, \"search\" | \"action\" | \"dateFrom\" | \"dateTo\">\n\n// Caps export size to keep the CSV response bounded on very large tables.\nconst EXPORT_ROW_LIMIT = 10_000\n\nexport async function getActivityLogsForExport({\n search = \"\",\n action,\n dateFrom,\n dateTo,\n}: ActivityLogExportFilters) {\n const where = buildActivityLogsWhere({ search, action, dateFrom, dateTo })\n\n return await db\n .select({\n id: activityLogs.id,\n action: activityLogs.action,\n description: activityLogs.description,\n ipAddress: activityLogs.ipAddress,\n userAgent: activityLogs.userAgent,\n metadata: activityLogs.metadata,\n createdAt: activityLogs.createdAt,\n userId: activityLogs.userId,\n userName: users.name,\n userEmail: users.email,\n })\n .from(activityLogs)\n .leftJoin(users, eq(activityLogs.userId, users.id))\n .where(where)\n .orderBy(desc(activityLogs.createdAt))\n .limit(EXPORT_ROW_LIMIT)\n}\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
type DeviceType = "desktop" | "mobile" | "tablet";
|
|
2
|
+
|
|
3
|
+
declare function getAdminDashboardStats(): Promise<{
|
|
4
|
+
totalUsers: number;
|
|
5
|
+
newSignupsThisWeek: number;
|
|
6
|
+
activeSessions: number;
|
|
7
|
+
bannedCount: number;
|
|
8
|
+
}>;
|
|
9
|
+
declare function getAdminStats(): Promise<{
|
|
10
|
+
totalUsers: number;
|
|
11
|
+
activeSessions: number;
|
|
12
|
+
adminCount: number;
|
|
13
|
+
regularUsers: number;
|
|
14
|
+
}>;
|
|
15
|
+
type DeviceThrottleRow = Awaited<ReturnType<typeof getDeviceThrottleActivity>>[number];
|
|
16
|
+
declare function getDeviceThrottleActivity(limit?: number): Promise<{
|
|
17
|
+
fingerprint: string;
|
|
18
|
+
count: number;
|
|
19
|
+
windowStart: Date;
|
|
20
|
+
lastAttemptAt: Date;
|
|
21
|
+
ipAddress: string | null;
|
|
22
|
+
userAgent: string | null;
|
|
23
|
+
lastEmail: string | null;
|
|
24
|
+
lastKind: string | null;
|
|
25
|
+
os: string | null;
|
|
26
|
+
browser: string | null;
|
|
27
|
+
deviceType: DeviceType;
|
|
28
|
+
country: string | null;
|
|
29
|
+
city: string | null;
|
|
30
|
+
blocked: boolean;
|
|
31
|
+
windowActive: boolean;
|
|
32
|
+
}[]>;
|
|
33
|
+
type RecentNewDeviceRow = Awaited<ReturnType<typeof getRecentNewDevices>>[number];
|
|
34
|
+
declare function getRecentNewDevices(limit?: number): Promise<{
|
|
35
|
+
os: string | null;
|
|
36
|
+
browser: string | null;
|
|
37
|
+
deviceType: DeviceType;
|
|
38
|
+
id: string;
|
|
39
|
+
userId: string;
|
|
40
|
+
userName: string;
|
|
41
|
+
userEmail: string;
|
|
42
|
+
ipAddress: string | null;
|
|
43
|
+
userAgent: string | null;
|
|
44
|
+
country: string | null;
|
|
45
|
+
city: string | null;
|
|
46
|
+
createdAt: Date;
|
|
47
|
+
}[]>;
|
|
48
|
+
type SharedDeviceRow = Awaited<ReturnType<typeof getSharedDeviceAccounts>>[number];
|
|
49
|
+
declare function getSharedDeviceAccounts(limit?: number): Promise<{
|
|
50
|
+
os: string | null;
|
|
51
|
+
browser: string | null;
|
|
52
|
+
deviceType: DeviceType;
|
|
53
|
+
visitorId: string;
|
|
54
|
+
accountCount: number;
|
|
55
|
+
lastSeenAt: Date;
|
|
56
|
+
country: string | null;
|
|
57
|
+
city: string | null;
|
|
58
|
+
userAgent: string | null;
|
|
59
|
+
accounts: {
|
|
60
|
+
userId: string;
|
|
61
|
+
userName: string;
|
|
62
|
+
userEmail: string;
|
|
63
|
+
banned: boolean;
|
|
64
|
+
firstSeenAt: Date;
|
|
65
|
+
}[];
|
|
66
|
+
}[]>;
|
|
67
|
+
|
|
68
|
+
export { type DeviceThrottleRow, type RecentNewDeviceRow, type SharedDeviceRow, getAdminDashboardStats, getAdminStats, getDeviceThrottleActivity, getRecentNewDevices, getSharedDeviceAccounts };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
type DeviceType = "desktop" | "mobile" | "tablet";
|
|
2
|
+
|
|
3
|
+
declare function getAdminDashboardStats(): Promise<{
|
|
4
|
+
totalUsers: number;
|
|
5
|
+
newSignupsThisWeek: number;
|
|
6
|
+
activeSessions: number;
|
|
7
|
+
bannedCount: number;
|
|
8
|
+
}>;
|
|
9
|
+
declare function getAdminStats(): Promise<{
|
|
10
|
+
totalUsers: number;
|
|
11
|
+
activeSessions: number;
|
|
12
|
+
adminCount: number;
|
|
13
|
+
regularUsers: number;
|
|
14
|
+
}>;
|
|
15
|
+
type DeviceThrottleRow = Awaited<ReturnType<typeof getDeviceThrottleActivity>>[number];
|
|
16
|
+
declare function getDeviceThrottleActivity(limit?: number): Promise<{
|
|
17
|
+
fingerprint: string;
|
|
18
|
+
count: number;
|
|
19
|
+
windowStart: Date;
|
|
20
|
+
lastAttemptAt: Date;
|
|
21
|
+
ipAddress: string | null;
|
|
22
|
+
userAgent: string | null;
|
|
23
|
+
lastEmail: string | null;
|
|
24
|
+
lastKind: string | null;
|
|
25
|
+
os: string | null;
|
|
26
|
+
browser: string | null;
|
|
27
|
+
deviceType: DeviceType;
|
|
28
|
+
country: string | null;
|
|
29
|
+
city: string | null;
|
|
30
|
+
blocked: boolean;
|
|
31
|
+
windowActive: boolean;
|
|
32
|
+
}[]>;
|
|
33
|
+
type RecentNewDeviceRow = Awaited<ReturnType<typeof getRecentNewDevices>>[number];
|
|
34
|
+
declare function getRecentNewDevices(limit?: number): Promise<{
|
|
35
|
+
os: string | null;
|
|
36
|
+
browser: string | null;
|
|
37
|
+
deviceType: DeviceType;
|
|
38
|
+
id: string;
|
|
39
|
+
userId: string;
|
|
40
|
+
userName: string;
|
|
41
|
+
userEmail: string;
|
|
42
|
+
ipAddress: string | null;
|
|
43
|
+
userAgent: string | null;
|
|
44
|
+
country: string | null;
|
|
45
|
+
city: string | null;
|
|
46
|
+
createdAt: Date;
|
|
47
|
+
}[]>;
|
|
48
|
+
type SharedDeviceRow = Awaited<ReturnType<typeof getSharedDeviceAccounts>>[number];
|
|
49
|
+
declare function getSharedDeviceAccounts(limit?: number): Promise<{
|
|
50
|
+
os: string | null;
|
|
51
|
+
browser: string | null;
|
|
52
|
+
deviceType: DeviceType;
|
|
53
|
+
visitorId: string;
|
|
54
|
+
accountCount: number;
|
|
55
|
+
lastSeenAt: Date;
|
|
56
|
+
country: string | null;
|
|
57
|
+
city: string | null;
|
|
58
|
+
userAgent: string | null;
|
|
59
|
+
accounts: {
|
|
60
|
+
userId: string;
|
|
61
|
+
userName: string;
|
|
62
|
+
userEmail: string;
|
|
63
|
+
banned: boolean;
|
|
64
|
+
firstSeenAt: Date;
|
|
65
|
+
}[];
|
|
66
|
+
}[]>;
|
|
67
|
+
|
|
68
|
+
export { type DeviceThrottleRow, type RecentNewDeviceRow, type SharedDeviceRow, getAdminDashboardStats, getAdminStats, getDeviceThrottleActivity, getRecentNewDevices, getSharedDeviceAccounts };
|