Spaces:
Runtime error
Runtime error
| "use server"; | |
| import { db } from "@/lib/db"; | |
| import { | |
| detectedObjects, | |
| adminModeration, | |
| marketplaceMatches, | |
| } from "@/lib/db/schema"; | |
| import { eq, and } from "drizzle-orm"; | |
| import { getAdminSession } from "@/lib/admin"; | |
| import { revalidatePath } from "next/cache"; | |
| import * as Sentry from "@sentry/nextjs"; | |
| export interface AdminCorrectionData { | |
| objectName?: string; | |
| category?: string; | |
| marketplaceLinkOverrides?: { matchId: string; affiliateUrl: string }[]; | |
| } | |
| export async function adminCorrectDetection( | |
| detectionId: string, | |
| data: AdminCorrectionData | |
| ) { | |
| try { | |
| const session = await getAdminSession(); | |
| if (!session) { | |
| return { success: false, error: "Unauthorized: admin access required" }; | |
| } | |
| // 1. Fetch current detection for audit snapshot | |
| const current = await db.query.detectedObjects.findFirst({ | |
| where: eq(detectedObjects.id, detectionId), | |
| }); | |
| if (!current) { | |
| return { success: false, error: "Detection not found" }; | |
| } | |
| // Fetch current marketplace matches for complete audit snapshot | |
| const currentMatches = await db | |
| .select({ | |
| id: marketplaceMatches.id, | |
| affiliateUrl: marketplaceMatches.affiliateUrl, | |
| marketplace: marketplaceMatches.marketplace, | |
| }) | |
| .from(marketplaceMatches) | |
| .where(eq(marketplaceMatches.objectId, detectionId)); | |
| const originalValues = { | |
| objectName: current.objectName, | |
| category: current.category, | |
| status: current.status, | |
| marketplaceMatches: currentMatches.map(m => ({ | |
| id: m.id, | |
| affiliateUrl: m.affiliateUrl, | |
| marketplace: m.marketplace, | |
| })), | |
| }; | |
| // 2. Start transaction for atomicity | |
| return await db.transaction(async (tx) => { | |
| // 3. Update detected_objects | |
| await tx | |
| .update(detectedObjects) | |
| .set({ | |
| objectName: data.objectName ?? current.objectName, | |
| category: (data.category as any) ?? current.category, | |
| status: "pending_review", // Moves to creator queue | |
| updatedAt: new Date(), | |
| }) | |
| .where(eq(detectedObjects.id, detectionId)); | |
| // 4. Update marketplace links if provided | |
| if (data.marketplaceLinkOverrides && data.marketplaceLinkOverrides.length > 0) { | |
| for (const override of data.marketplaceLinkOverrides) { | |
| await tx | |
| .update(marketplaceMatches) | |
| .set({ | |
| affiliateUrl: override.affiliateUrl, | |
| updatedAt: new Date() | |
| }) | |
| .where( | |
| and( | |
| eq(marketplaceMatches.id, override.matchId), | |
| eq(marketplaceMatches.objectId, detectionId) | |
| ) | |
| ); | |
| } | |
| } | |
| // 5. Insert audit log | |
| await tx.insert(adminModeration).values({ | |
| id: crypto.randomUUID(), | |
| detectionId, | |
| adminId: session.user.id, | |
| action: "corrected", | |
| originalValues, | |
| correctedValues: { | |
| ...data, | |
| correctedAt: new Date().toISOString(), | |
| }, | |
| trainAiFlag: true, | |
| }); | |
| revalidatePath("/admin/moderation"); | |
| revalidatePath("/dashboard/moderation"); | |
| return { success: true }; | |
| }); | |
| } catch (error) { | |
| Sentry.captureException(error, { | |
| tags: { action: "admin-correct-detection", detection_id: detectionId }, | |
| }); | |
| console.error("Admin correction failed:", error); | |
| return { success: false, error: "Failed to apply admin correction" }; | |
| } | |
| } | |