refactor(db): migrate app pages and APIs from Prisma facade to Drizzle (4)
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
580972c0a0
commit
9aa4f331bf
40 files changed
+1259
-927
No files matched your search
@@ -1,6 +1,15 @@
|
||||
import { and, desc, eq, inArray, or } from "drizzle-orm";
|
||||
import { isBanActive, unixNow } from "@/lib/bans";
|
||||
import {
|
||||
AdminAuditLog,
|
||||
Ban,
|
||||
db,
|
||||
StaffActivities,
|
||||
SupportTickets,
|
||||
User,
|
||||
UsersSettings,
|
||||
} from "@/lib/db";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export type SanctionEvent = {
|
||||
id: string;
|
||||
@@ -37,84 +46,89 @@ export async function loadUserSanctions(
|
||||
const now = unixNow();
|
||||
const events: SanctionEvent[] = [];
|
||||
|
||||
const [bans, audits, staffActs, cfh, settings] = await Promise.all([
|
||||
prisma.ban
|
||||
.findMany({
|
||||
where: { userId },
|
||||
orderBy: { timestamp: "desc" },
|
||||
take: 40,
|
||||
select: {
|
||||
id: true,
|
||||
banReason: true,
|
||||
type: true,
|
||||
timestamp: true,
|
||||
banExpire: true,
|
||||
userStaffId: true,
|
||||
},
|
||||
const [bans, audits, staffActs, cfh, settingsRows] = await Promise.all([
|
||||
db
|
||||
.select({
|
||||
id: Ban.id,
|
||||
banReason: Ban.banReason,
|
||||
type: Ban.type,
|
||||
timestamp: Ban.timestamp,
|
||||
banExpire: Ban.banExpire,
|
||||
userStaffId: Ban.userStaffId,
|
||||
})
|
||||
.from(Ban)
|
||||
.where(eq(Ban.userId, userId))
|
||||
.orderBy(desc(Ban.timestamp))
|
||||
.limit(40)
|
||||
.catch(() => []),
|
||||
prisma.adminAuditLog
|
||||
.findMany({
|
||||
where: {
|
||||
target: "User",
|
||||
targetId: userId,
|
||||
action: { in: [...AUDIT_ACTIONS] },
|
||||
},
|
||||
orderBy: { id: "desc" },
|
||||
take: 40,
|
||||
select: {
|
||||
id: true,
|
||||
action: true,
|
||||
details: true,
|
||||
createdAt: true,
|
||||
userId: true,
|
||||
user: { select: { username: true } },
|
||||
},
|
||||
db
|
||||
.select({
|
||||
id: AdminAuditLog.id,
|
||||
action: AdminAuditLog.action,
|
||||
details: AdminAuditLog.details,
|
||||
createdAt: AdminAuditLog.createdAt,
|
||||
userId: AdminAuditLog.userId,
|
||||
actorUsername: User.username,
|
||||
})
|
||||
.from(AdminAuditLog)
|
||||
.leftJoin(User, eq(AdminAuditLog.userId, User.id))
|
||||
.where(
|
||||
and(
|
||||
eq(AdminAuditLog.target, "User"),
|
||||
eq(AdminAuditLog.targetId, userId),
|
||||
inArray(AdminAuditLog.action, [...AUDIT_ACTIONS]),
|
||||
),
|
||||
)
|
||||
.orderBy(desc(AdminAuditLog.id))
|
||||
.limit(40)
|
||||
.catch(() => []),
|
||||
prisma.staffActivities
|
||||
.findMany({
|
||||
where: {
|
||||
targetType: "user",
|
||||
targetId: BigInt(userId),
|
||||
},
|
||||
orderBy: { id: "desc" },
|
||||
take: 40,
|
||||
select: {
|
||||
id: true,
|
||||
action: true,
|
||||
description: true,
|
||||
createdAt: true,
|
||||
userId: true,
|
||||
},
|
||||
db
|
||||
.select({
|
||||
id: StaffActivities.id,
|
||||
action: StaffActivities.action,
|
||||
description: StaffActivities.description,
|
||||
createdAt: StaffActivities.createdAt,
|
||||
userId: StaffActivities.userId,
|
||||
})
|
||||
.from(StaffActivities)
|
||||
.where(
|
||||
and(
|
||||
eq(StaffActivities.targetType, "user"),
|
||||
eq(StaffActivities.targetId, BigInt(userId)),
|
||||
),
|
||||
)
|
||||
.orderBy(desc(StaffActivities.id))
|
||||
.limit(40)
|
||||
.catch(() => []),
|
||||
prisma.supportTickets
|
||||
.findMany({
|
||||
where: {
|
||||
OR: [{ reportedId: userId }, { senderId: userId }],
|
||||
},
|
||||
orderBy: { id: "desc" },
|
||||
take: 20,
|
||||
select: {
|
||||
id: true,
|
||||
issue: true,
|
||||
state: true,
|
||||
timestamp: true,
|
||||
senderId: true,
|
||||
reportedId: true,
|
||||
modId: true,
|
||||
},
|
||||
db
|
||||
.select({
|
||||
id: SupportTickets.id,
|
||||
issue: SupportTickets.issue,
|
||||
state: SupportTickets.state,
|
||||
timestamp: SupportTickets.timestamp,
|
||||
senderId: SupportTickets.senderId,
|
||||
reportedId: SupportTickets.reportedId,
|
||||
modId: SupportTickets.modId,
|
||||
})
|
||||
.from(SupportTickets)
|
||||
.where(
|
||||
or(
|
||||
eq(SupportTickets.reportedId, userId),
|
||||
eq(SupportTickets.senderId, userId),
|
||||
),
|
||||
)
|
||||
.orderBy(desc(SupportTickets.id))
|
||||
.limit(20)
|
||||
.catch(() => []),
|
||||
db
|
||||
.select({ muteEndTimestamp: UsersSettings.muteEndTimestamp })
|
||||
.from(UsersSettings)
|
||||
.where(eq(UsersSettings.userId, userId))
|
||||
.limit(1)
|
||||
.catch(() => []),
|
||||
prisma.usersSettings
|
||||
.findUnique({
|
||||
where: { userId },
|
||||
select: { muteEndTimestamp: true },
|
||||
})
|
||||
.catch(() => null),
|
||||
]);
|
||||
|
||||
const settings = settingsRows[0] ?? null;
|
||||
const muteUntil = settings?.muteEndTimestamp ?? 0;
|
||||
if (muteUntil > now) {
|
||||
events.push({
|
||||
@@ -134,11 +148,10 @@ export async function loadUserSanctions(
|
||||
];
|
||||
const staffUsers =
|
||||
staffIds.length > 0
|
||||
? await prisma.user
|
||||
.findMany({
|
||||
where: { id: { in: staffIds } },
|
||||
select: { id: true, username: true },
|
||||
})
|
||||
? await db
|
||||
.select({ id: User.id, username: User.username })
|
||||
.from(User)
|
||||
.where(inArray(User.id, staffIds))
|
||||
.catch(() => [])
|
||||
: [];
|
||||
const staffName = new Map(staffUsers.map((u) => [u.id, u.username]));
|
||||
@@ -172,7 +185,7 @@ export async function loadUserSanctions(
|
||||
kind,
|
||||
label: a.action,
|
||||
detail: a.details?.slice(0, 200) || "—",
|
||||
actor: a.user?.username,
|
||||
actor: a.actorUsername ?? undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { asc, count, desc, eq, or, sql } from "drizzle-orm";
|
||||
import { notFound } from "next/navigation";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
db,
|
||||
Rooms,
|
||||
RoomTradeLog,
|
||||
User,
|
||||
UsersBadges,
|
||||
UsersCurrency,
|
||||
} from "@/lib/db";
|
||||
|
||||
async function rawRows<T>(query: ReturnType<typeof sql>): Promise<T[]> {
|
||||
const [rows] = (await db.execute(query)) as unknown as [T[], unknown];
|
||||
return rows ?? [];
|
||||
}
|
||||
|
||||
export async function loadUserById(id: string) {
|
||||
const numericId = Number(id);
|
||||
@@ -7,9 +20,11 @@ export async function loadUserById(id: string) {
|
||||
Number.isSafeInteger(numericId) &&
|
||||
numericId > 0 &&
|
||||
String(numericId) === id;
|
||||
const user = await prisma.user.findUnique({
|
||||
where: isNumeric ? { id: numericId } : { username: id },
|
||||
});
|
||||
const [user] = await db
|
||||
.select()
|
||||
.from(User)
|
||||
.where(isNumeric ? eq(User.id, numericId) : eq(User.username, id))
|
||||
.limit(1);
|
||||
if (!user) notFound();
|
||||
|
||||
const [
|
||||
@@ -17,67 +32,76 @@ export async function loadUserById(id: string) {
|
||||
badges,
|
||||
bansReceived,
|
||||
permissionRows,
|
||||
roomCount,
|
||||
tradeCount,
|
||||
roomCountRows,
|
||||
tradeCountRows,
|
||||
userRooms,
|
||||
chatLogs,
|
||||
commandLogs,
|
||||
] = await Promise.all([
|
||||
prisma.usersCurrency.findMany({ where: { userId: user.id } }),
|
||||
prisma.usersBadges.findMany({
|
||||
where: { userId: user.id },
|
||||
orderBy: { slotId: "asc" },
|
||||
}),
|
||||
prisma.$queryRaw<
|
||||
Array<{
|
||||
id: number;
|
||||
banReason: string;
|
||||
type: string;
|
||||
timestamp: number;
|
||||
banExpire: number;
|
||||
staffName: string;
|
||||
}>
|
||||
>`
|
||||
db.select().from(UsersCurrency).where(eq(UsersCurrency.userId, user.id)),
|
||||
db
|
||||
.select()
|
||||
.from(UsersBadges)
|
||||
.where(eq(UsersBadges.userId, user.id))
|
||||
.orderBy(asc(UsersBadges.slotId)),
|
||||
rawRows<{
|
||||
id: number;
|
||||
banReason: string;
|
||||
type: string;
|
||||
timestamp: number;
|
||||
banExpire: number;
|
||||
staffName: string;
|
||||
}>(sql`
|
||||
SELECT b.id, b.ban_reason AS banReason, b.type, b.timestamp, b.ban_expire AS banExpire,
|
||||
COALESCE(s.username, 'Unknown') AS staffName
|
||||
FROM bans b LEFT JOIN users s ON s.id = b.user_staff_id
|
||||
WHERE b.user_id = ${user.id} ORDER BY b.id DESC LIMIT 5`,
|
||||
prisma.$queryRaw<Array<{ rankName: string }>>`
|
||||
SELECT COALESCE(rank_name, CONCAT('Rank ', id)) AS rankName FROM permissions WHERE id = ${user.rank} LIMIT 1`,
|
||||
prisma.rooms.count({ where: { ownerId: user.id } }),
|
||||
prisma.roomTradeLog.count({
|
||||
where: { OR: [{ userOneId: user.id }, { userTwoId: user.id }] },
|
||||
}),
|
||||
prisma.rooms.findMany({
|
||||
where: { ownerId: user.id },
|
||||
orderBy: { users: "desc" },
|
||||
take: 20,
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
state: true,
|
||||
users: true,
|
||||
usersMax: true,
|
||||
},
|
||||
}),
|
||||
prisma.$queryRaw<
|
||||
Array<{ id: number; roomId: number; timestamp: number; message: string }>
|
||||
>`
|
||||
WHERE b.user_id = ${user.id} ORDER BY b.id DESC LIMIT 5`),
|
||||
rawRows<{ rankName: string }>(sql`
|
||||
SELECT COALESCE(rank_name, CONCAT('Rank ', id)) AS rankName FROM permissions WHERE id = ${user.rank} LIMIT 1`),
|
||||
db.select({ total: count() }).from(Rooms).where(eq(Rooms.ownerId, user.id)),
|
||||
db
|
||||
.select({ total: count() })
|
||||
.from(RoomTradeLog)
|
||||
.where(
|
||||
or(
|
||||
eq(RoomTradeLog.userOneId, user.id),
|
||||
eq(RoomTradeLog.userTwoId, user.id),
|
||||
),
|
||||
),
|
||||
db
|
||||
.select({
|
||||
id: Rooms.id,
|
||||
name: Rooms.name,
|
||||
state: Rooms.state,
|
||||
users: Rooms.users,
|
||||
usersMax: Rooms.usersMax,
|
||||
})
|
||||
.from(Rooms)
|
||||
.where(eq(Rooms.ownerId, user.id))
|
||||
.orderBy(desc(Rooms.users))
|
||||
.limit(20),
|
||||
rawRows<{
|
||||
id: number;
|
||||
roomId: number;
|
||||
timestamp: number;
|
||||
message: string;
|
||||
}>(sql`
|
||||
SELECT ROW_NUMBER() OVER (ORDER BY timestamp DESC) AS id, room_id AS roomId, timestamp, message
|
||||
FROM chatlogs_room WHERE user_from_id = ${user.id} ORDER BY timestamp DESC LIMIT 20`,
|
||||
prisma.$queryRaw<
|
||||
Array<{
|
||||
id: number;
|
||||
timestamp: number;
|
||||
command: string;
|
||||
params: string;
|
||||
succes: string;
|
||||
}>
|
||||
>`
|
||||
FROM chatlogs_room WHERE user_from_id = ${user.id} ORDER BY timestamp DESC LIMIT 20`),
|
||||
rawRows<{
|
||||
id: number;
|
||||
timestamp: number;
|
||||
command: string;
|
||||
params: string;
|
||||
succes: string;
|
||||
}>(sql`
|
||||
SELECT ROW_NUMBER() OVER (ORDER BY timestamp DESC) AS id, timestamp, command, params, succes
|
||||
FROM commandlogs WHERE user_id = ${user.id} ORDER BY timestamp DESC LIMIT 10`,
|
||||
FROM commandlogs WHERE user_id = ${user.id} ORDER BY timestamp DESC LIMIT 10`),
|
||||
]);
|
||||
|
||||
const roomCount = Number(roomCountRows[0]?.total ?? 0);
|
||||
const tradeCount = Number(tradeCountRows[0]?.total ?? 0);
|
||||
|
||||
const diamonds =
|
||||
currencies.find((currency) => currency.type === 5)?.amount ?? 0;
|
||||
const duckets =
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { redirect } from "next/navigation";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { db } from "@/lib/db";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { Prisma, prisma } from "@/lib/prisma";
|
||||
import { getWatchedUserIds } from "@/lib/services/watch";
|
||||
import { UserAccountInfo } from "../../_components/user-account-info";
|
||||
import { UserHero } from "../../_components/user-hero";
|
||||
@@ -28,10 +29,10 @@ export default async function UserEditPage({
|
||||
const watched = await getWatchedUserIds(session.user.id);
|
||||
|
||||
// Fetch rank list from permissions table for the rank dropdown
|
||||
const rawRanks: { id: number; rank_name: string }[] = await prisma.$queryRaw(
|
||||
Prisma.sql`SELECT id, rank_name FROM permissions ORDER BY id ASC`,
|
||||
);
|
||||
const ranks = rawRanks.map((r) => ({
|
||||
const [rawRanks] = (await db.execute(
|
||||
sql`SELECT id, rank_name FROM permissions ORDER BY id ASC`,
|
||||
)) as unknown as [{ id: number; rank_name: string }[], unknown];
|
||||
const ranks = (rawRanks ?? []).map((r) => ({
|
||||
id: Number(r.id),
|
||||
name: String(r.rank_name || `Rank ${r.id}`),
|
||||
}));
|
||||
|
||||
Reference in new issue
Block a user