"use server"; import { getServerSession } from "next-auth"; import { revalidatePath } from "next/cache"; import { authOptions } from "@/lib/auth"; import { isAdminEmail } from "@/lib/admin"; import { userService } from "@/server/services/user.service"; import { auditLog } from "@/server/services/audit-log.service"; import { emailService } from "@/lib/email/send"; import { userRepo } from "@/server/repositories/user.repo"; export async function suspendUserAction(userId: string, reason: string) { const session = await getServerSession(authOptions); if (!session?.user) { return { error: "Kamu harus login terlebih dahulu" }; } if (!isAdminEmail(session.user.email)) { return { error: "Hanya admin yang bisa melakukan aksi ini" }; } try { await userService.suspendUser({ userId, adminId: session.user.id, reason, }); await auditLog.record({ admin: { id: session.user.id, email: session.user.email }, action: "USER_SUSPEND", entityType: "User", entityId: userId, payload: { reason: reason.trim() }, }); // Notif email user — due process: kasih tahu alasan + cara appeal. void notifySuspended(userId, reason.trim()); revalidatePath("/admin/users"); revalidatePath(`/admin/users/${userId}`); return { success: true as const }; } catch (err) { return { error: (err as Error).message }; } } async function notifySuspended(userId: string, reason: string) { const target = await userRepo.findById(userId); if (!target) return; await emailService.send({ to: target.email, // Suspend bisa di-trigger berulang — sertakan timestamp supaya tiap suspend // baru dapat email baru. idempotencyKey: `account_suspended-${userId}-${Date.now()}`, template: { template: "account_suspended", data: { userName: target.name, reason }, }, }); } export async function unsuspendUserAction(userId: string) { const session = await getServerSession(authOptions); if (!session?.user) { return { error: "Kamu harus login terlebih dahulu" }; } if (!isAdminEmail(session.user.email)) { return { error: "Hanya admin yang bisa melakukan aksi ini" }; } try { await userService.unsuspendUser({ userId, adminId: session.user.id }); await auditLog.record({ admin: { id: session.user.id, email: session.user.email }, action: "USER_UNSUSPEND", entityType: "User", entityId: userId, }); revalidatePath("/admin/users"); revalidatePath(`/admin/users/${userId}`); return { success: true as const }; } catch (err) { return { error: (err as Error).message }; } }