Files
Epicnabbo-Catalogus-Updated…/src/actions/multi-account-detect.ts
T
SimoandCursor 0e89d03940 Finish fine-grained ACL across remaining admin pages and actions.
Replace leftover requireStaff gates with module PERMS, drop hardcoded room rank thresholds, and expand contract tests so admin mutations cannot regress to dashboard-only checks.

Co-authored-by: Cursor <[email protected]>
2026-07-15 20:15:22 +02:00

59 lines
1.3 KiB
TypeScript

"use server";
import { requirePermission } from "@/lib/admin/guard";
import { PERMS } from "@/lib/permissions";
import { prisma } from "@/lib/prisma";
export interface MultiAccountCluster {
key: string;
label: string;
accountCount: number;
accounts: Array<{
id: number;
username: string;
rank: number;
online: string;
}>;
}
export async function detectMultiAccounts({
minAccounts,
limit,
}: {
minAccounts: number;
limit: number;
}) {
await requirePermission(PERMS.USERS_VIEW);
const clusters: MultiAccountCluster[] = [];
const ipGroups = await prisma.user.groupBy({
by: ["ipCurrent"],
where: { ipCurrent: { not: "" } },
_count: { id: true },
having: { id: { _count: { gte: minAccounts } } },
orderBy: { _count: { id: "desc" } },
take: limit,
});
for (const group of ipGroups) {
const users = await prisma.user.findMany({
where: { ipCurrent: group.ipCurrent },
select: { id: true, username: true, rank: true, online: true },
orderBy: { id: "asc" },
});
clusters.push({
key: group.ipCurrent,
label: `IP: ${group.ipCurrent}`,
accountCount: group._count.id,
accounts: users.map((u) => ({
id: u.id,
username: u.username,
rank: u.rank,
online: u.online,
})),
});
}
return { ok: true as const, data: { clusters } };
}