From 8d4a54de4a5a92ef9dbc88383065b80f88848a2a Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 21 Feb 2026 02:44:58 +0800 Subject: [PATCH] fix(users): allow deleting guest users with dependent records --- lib/db/queries.ts | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/db/queries.ts b/lib/db/queries.ts index 554727ea8..258485880 100644 --- a/lib/db/queries.ts +++ b/lib/db/queries.ts @@ -50,6 +50,8 @@ import { loginToken, generatedImage, pointsLedger, + tutorialVideos, + messageDeprecated, } from "./schema"; import { generateHashedPassword } from "./utils"; import { @@ -107,7 +109,7 @@ export async function createGuestUser() { const password = generateHashedPassword(generateUUID()); try { - return await db.insert(user).values({ email, password }).returning({ + return await db.insert(user).values({ email, password, role: "guest" }).returning({ id: user.id, email: user.email, }); @@ -909,7 +911,39 @@ export async function updateUser({ export async function deleteUserById({ id }: { id: string }) { try { - return await db.delete(user).where(eq(user.id, id)).returning(); + return await db.transaction(async (tx) => { + const userChats = await tx + .select({ id: chat.id }) + .from(chat) + .where(eq(chat.userId, id)); + const chatIds = userChats.map((row) => row.id); + + if (chatIds.length > 0) { + await tx.delete(vote).where(inArray(vote.chatId, chatIds)); + await tx.delete(message).where(inArray(message.chatId, chatIds)); + await tx.delete(messageDeprecated).where(inArray(messageDeprecated.chatId, chatIds)); + await tx.delete(stream).where(inArray(stream.chatId, chatIds)); + } + + await tx.delete(chat).where(eq(chat.userId, id)); + await tx.delete(suggestion).where(eq(suggestion.userId, id)); + await tx.delete(document).where(eq(document.userId, id)); + await tx.delete(generatedImage).where(eq(generatedImage.userId, id)); + + // 清理“操作人/更新人”外键引用,避免删除被阻塞 + await tx.update(pointsLedger).set({ createdBy: null }).where(eq(pointsLedger.createdBy, id)); + await tx.update(generatedImage).set({ featuredBy: null }).where(eq(generatedImage.featuredBy, id)); + await tx.update(aiProvider).set({ updatedBy: null }).where(eq(aiProvider.updatedBy, id)); + await tx.update(storageConfig).set({ updatedBy: null }).where(eq(storageConfig.updatedBy, id)); + await tx.update(systemSettings).set({ updatedBy: null }).where(eq(systemSettings.updatedBy, id)); + await tx.update(toolConfig).set({ updatedBy: null }).where(eq(toolConfig.updatedBy, id)); + await tx.update(siteSettings).set({ updatedBy: null }).where(eq(siteSettings.updatedBy, id)); + await tx.update(authSettings).set({ updatedBy: null }).where(eq(authSettings.updatedBy, id)); + await tx.update(navLinks).set({ createdBy: null }).where(eq(navLinks.createdBy, id)); + await tx.update(tutorialVideos).set({ createdBy: null }).where(eq(tutorialVideos.createdBy, id)); + + return await tx.delete(user).where(eq(user.id, id)).returning(); + }); } catch (_error) { throw new ChatSDKError("bad_request:database", "Failed to delete user"); }