Create Request Models
Create a subdirectory in src/models named requests. Inside src/models/requests add the following models.
Request.js
import { model, Schema } from 'mongoose'
const requestSchema = new Schema({
sender: {
username: {
type: String,
required: true
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User'
}
},
receiver: {
username: {
type: String,
required: true
},
userId: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
},
{
timestamps: true ,
discriminatorKey: 'kind'
})
const Request = model('Request', requestSchema)
export default Request
FriendRequest.js
import { Schema } from "mongoose";
import Request from "./Request.js";
const friendRequestSchema = new Schema({ })
const FriendRequest = Request.discriminator('FriendRequest', friendRequestSchema)
export default FriendRequest
ChatInvite.js
import { Schema } from "mongoose";
import Request from "./Request.js";
const chatInviteSchema = new Schema({
chat: {
name: {
type: String,
required: true
},
chatId: {
type: Schema.Types.ObjectId,
ref: 'Chat',
required: true
}
}
})
const ChatInvite = Request.discriminator('ChatInvite', chatInviteSchema)
export default ChatInvite
Update the User Model
Add the following properties to your User schema.
...
// Import new Models
import Request from './requests/Request.js'
import FriendRequest from './requests/FriendRequest.js'
import ChatInvite from './requests/ChatInvite.js'
const userSchema = new Schema({
...
/* add new fields
requests: [ Request.schema ],
friends: [
{
username: {
type: String,
required: true
},
userId: {
type: Schema.Types.ObjectId,
required: true
}
}
]
})
...
/* Set up requests array to allow different type elements */
userSchema.path('requests').discriminator('FriendRequest', FriendRequest.schema)
userSchema.path('requests').discriminator('ChatInvite', ChatInvite.schema)
const User = model('User', userSchema)
export default User
Create Friends Router
Create a file named friends.js in src/routers and add the following code to the file.
import Router from 'express'
import User from '../models/User.js'
import FriendRequest from '../models/requests/FriendRequest.js'
import { auth } from '../middleware/auth.js'
const router = new Router()
router.post('/friend-request/:id', auth, async (req, res) => {
let sender = req.user
let receiver = await User.findById(req.params.id)
if (!receiver) {
return res.status(404).send('User not found')
}
const request = new FriendRequest({
sender: {
username: sender.username,
userId: sender._id
},
receiver: {
username: receiver.username,
userId: receiver._id
}
})
receiver.requests.push(request)
try {
await receiver.save()
res.send()
}
catch (err) {
console.log(err)
res.status(500).send()
}
})
router.patch('/friend-request/:id', auth, async (req, res) => {
const user = req.user
const index = user.requests.findIndex(item => item._id.equals(req.params.id));
if (index === -1) {
return res.status(404).send()
}
const arr = user.requests.splice(index, 1); // remove 1 element at index
const request = arr[0]
if (!req.query || !Object.hasOwn(req.query, 'accept')) {
return res.status(400).send()
}
if (req.query.accept === 'false') {
try {
await user.save()
return res.send(user.requests)
}
catch (err) {
return res.status(500).send()
}
}
const sender = await User.findById(request.sender.userId)
if (sender) {
try {
if (!user.friends.some(item => item.userId.equals(sender._id))) {
user.friends.push({ username: sender.username, userId: sender._id })
await user.save()
}
if (!sender.friends.some(item => item.userId.equals(user._id))) {
sender.friends.push({ username: user.username, userId: user._id })
await sender.save()
}
}
catch (err) {
return res.status(500).send()
}
}
res.send(user.requests)
})
router.get('/friend-requests', auth, async (req, res) => {
const friendRequests = req.user.requests.filter(item => item.kind === 'FriendRequest')
res.send(friendRequests)
})
router.delete('/friend/:userId', auth, async (req, res) => {
const user = req.user
// TODO: remove user from target's friends list
user.friends = user.friends.filter(item => !item.userId.equals(req.params.userId))
try {
await user.save()
res.send(user.friends)
}
catch (err) {
console.log(err)
res.status(500).send()
}
})
export default router
Add Friends Router to app.js
Add the following code to app.js so that express uses the friends router.
... import friendRouter from './routers/friends.js' ... app.use(friendRouter) ...
Test the Friends Endpoints
Stop your API server, drop your database, and restart your API server.
In Postman create a folder named Friends and inside the folder create requests to test the new endpoints.
Push to GitHub
Git add, commit, and push.