"use server"; import { revalidatePath } from "next/cache"; import { auth } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; /** * Accept a pending friend request as the SIGNED-IN user. * * The ACCEPTER is re-read from the session via auth() and is never trusted from * the submitted FormData. Only the request id comes from the form, and the * request is only honoured when its target (user_to_id) is the session user — * so a crafted form cannot accept a request addressed to someone else. * * Arcturus/AtomCMS stores friendships as TWO directional rows in * messenger_friendships (one user_one_id→user_two_id, one the reverse). We * create both inside a transaction and delete the originating request so it no * longer shows as pending in the in-game messenger or here. */ export async function acceptFriend(formData: FormData): Promise { const session = await auth(); const meId = Number(session?.user?.id); if (!Number.isInteger(meId) || meId <= 0) return; const requestId = Number(formData.get("requestId")); if (!Number.isInteger(requestId) || requestId <= 0) return; try { // The request must exist AND be addressed to the session user. const request = await prisma.messengerFriendrequests.findUnique({ where: { id: requestId }, select: { id: true, userFromId: true, userToId: true }, }); if (!request || request.userToId !== meId) return; const friendId = request.userFromId; if (!Number.isInteger(friendId) || friendId <= 0 || friendId === meId) { // Malformed/self request — just clear it. await prisma.messengerFriendrequests.delete({ where: { id: requestId } }); return; } const friendsSince = Math.floor(Date.now() / 1000); await prisma.$transaction(async (tx) => { // Don't double-insert if a friendship already exists in either direction. const existing = await tx.messengerFriendships.findFirst({ where: { OR: [ { userOneId: meId, userTwoId: friendId }, { userOneId: friendId, userTwoId: meId }, ], }, select: { id: true }, }); if (!existing) { await tx.messengerFriendships.createMany({ data: [ { userOneId: meId, userTwoId: friendId, friendsSince }, { userOneId: friendId, userTwoId: meId, friendsSince }, ], }); } await tx.messengerFriendrequests.delete({ where: { id: requestId } }); }); } catch { // DB unavailable — fail soft; nothing to persist. return; } revalidatePath("/messages"); revalidatePath("/friends"); }