File size: 2,200 Bytes
87cb242 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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<boolean> {
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<void> {
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<boolean> {
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<void> {
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<void> {
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<string[]> {
const user = await UserModel.findOne({ uid }, 'friends').lean();
return (user?.friends as string[]) ?? [];
}
|