import { UserModel } from '../db/mongo'; import { FriendRequestModel } from '../models/friend'; import { logger } from '../utils/logger'; /** * Check if two users are friends. Used before allowing signaling to prevent * stranger signaling attacks — only friends can initiate WebRTC offers. */ export async function areFriends(uidA: string, uidB: string): Promise { const user = await UserModel.findOne({ uid: uidA, friends: uidB }, '_id').lean(); return !!user; } /** Send a friend request (fromUid → toUid). Idempotent. */ export async function sendFriendRequest(fromUid: string, toUid: string): Promise { await FriendRequestModel.findOneAndUpdate( { fromUid, toUid }, { status: 'pending' }, { upsert: true, new: true } ); } /** Accept a friend request. Adds each user to the other's friends list. */ export async function acceptFriendRequest(fromUid: string, toUid: string): Promise { const req = await FriendRequestModel.findOneAndUpdate( { fromUid, toUid, status: 'pending' }, { status: 'accepted' } ); if (!req) return false; // Add to both users' friend lists atomically await Promise.all([ UserModel.updateOne({ uid: toUid }, { $addToSet: { friends: fromUid } }), UserModel.updateOne({ uid: fromUid }, { $addToSet: { friends: toUid } }), ]); return true; } /** Reject a friend request. */ export async function rejectFriendRequest(fromUid: string, toUid: string): Promise { await FriendRequestModel.findOneAndUpdate( { fromUid, toUid, status: 'pending' }, { status: 'rejected' } ); } /** Remove a friend (unfriend). Removes from both sides. */ export async function removeFriend(uidA: string, uidB: string): Promise { await Promise.all([ UserModel.updateOne({ uid: uidA }, { $pull: { friends: uidB } }), UserModel.updateOne({ uid: uidB }, { $pull: { friends: uidA } }), ]); logger.info('Friendship removed', { uidA, uidB }); } /** Get a user's friend list. Returns array of UIDs. */ export async function getFriendList(uid: string): Promise { const user = await UserModel.findOne({ uid }, 'friends').lean(); return (user?.friends as string[]) ?? []; }