I'm building a MERN project i.e. a Teacher's forum application where teachers can create their own classroom & give access to particular students through OTP service. But while I'm building a route for student user which "leave" means under every classroom there is a leave button which when clicked student should leave a classroom.
The code through which you'll get an idea:
// route for leave classroom
router.delete('/leave/:classid', authTokenHandler, async (req, res) => {
const { classid } = req.params;
console.log("From classroom: ", classid);
const userEmail = req.user?.email; // Get the authenticated user's email
console.log("Email: ", userEmail);
try {
// Find and delete the student's entry from the classroomJoin collection
const classroomEntry = await ClassroomJoin.findOneAndDelete({
classroomId: classid,
studentEmail: userEmail
});
if (!classroomEntry) {
return res.status(400).json({ message: 'You are not part of this classroom' });
}
return res.status(200).json({ message: 'Successfully left the classroom' });
} catch (err) {
return res.status(500).json({ message: 'Internal server error', error: err });
}
});
My database Schema is as follows:
classroomModel - classrooms created by teachers stored here
const mongoose = require('mongoose');
const ClassroomSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Reference to the User model
required: true
},
description: {
type: String,
trim: true
},
students: [String],
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
}, {timestamps: true});
const Classroom = mongoose.model('Classroom', ClassroomSchema);
module.exports = Classroom;
// classroomJoinModel - Students who join the classroom will be stored here
const mongoose = require('mongoose');
const classroomJoinSchema = new mongoose.Schema({
classroomId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Classroom', // Reference to the Classroom model
required: true
},
studentEmail: {
type: String,
required: true
},
code: {
type: String,
required: true
},
classOwnerEmail: {
type: String,
required: true
}
}, { timestamps: true });
const ClassroomJoin = mongoose.model('ClassroomJoin', classroomJoinSchema);
module.exports = ClassroomJoin;
In the route I mentioned, I'm getting classroomId but not getting user email. Instead of this if we fetched & delete the object created in ClassroomJoinModel classroom collection will be updated & student will be left.
Console Output:
classroomId: 679bafd26f16f2790e992e3b
email: undefined
But I'm not understanding how to get data from classroomJoinModel, I need help with this.
I'm building a MERN project i.e. a Teacher's forum application where teachers can create their own classroom & give access to particular students through OTP service. But while I'm building a route for student user which "leave" means under every classroom there is a leave button which when clicked student should leave a classroom.
The code through which you'll get an idea:
// route for leave classroom
router.delete('/leave/:classid', authTokenHandler, async (req, res) => {
const { classid } = req.params;
console.log("From classroom: ", classid);
const userEmail = req.user?.email; // Get the authenticated user's email
console.log("Email: ", userEmail);
try {
// Find and delete the student's entry from the classroomJoin collection
const classroomEntry = await ClassroomJoin.findOneAndDelete({
classroomId: classid,
studentEmail: userEmail
});
if (!classroomEntry) {
return res.status(400).json({ message: 'You are not part of this classroom' });
}
return res.status(200).json({ message: 'Successfully left the classroom' });
} catch (err) {
return res.status(500).json({ message: 'Internal server error', error: err });
}
});
My database Schema is as follows:
classroomModel - classrooms created by teachers stored here
const mongoose = require('mongoose');
const ClassroomSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Reference to the User model
required: true
},
description: {
type: String,
trim: true
},
students: [String],
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
}, {timestamps: true});
const Classroom = mongoose.model('Classroom', ClassroomSchema);
module.exports = Classroom;
// classroomJoinModel - Students who join the classroom will be stored here
const mongoose = require('mongoose');
const classroomJoinSchema = new mongoose.Schema({
classroomId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Classroom', // Reference to the Classroom model
required: true
},
studentEmail: {
type: String,
required: true
},
code: {
type: String,
required: true
},
classOwnerEmail: {
type: String,
required: true
}
}, { timestamps: true });
const ClassroomJoin = mongoose.model('ClassroomJoin', classroomJoinSchema);
module.exports = ClassroomJoin;
In the route I mentioned, I'm getting classroomId but not getting user email. Instead of this if we fetched & delete the object created in ClassroomJoinModel classroom collection will be updated & student will be left.
Console Output:
classroomId: 679bafd26f16f2790e992e3b
email: undefined
But I'm not understanding how to get data from classroomJoinModel, I need help with this.
Share Improve this question edited Feb 9 at 18:19 halfer 20.3k19 gold badges109 silver badges202 bronze badges asked Feb 2 at 14:04 Shubham MerguShubham Mergu 31 bronze badge1 Answer
Reset to default 0Your authTokenHandler should decode the authentication token and set req.user
. If it's missing or incorrectly implemented, req.user?.email
will be undefined.
const jwt = require('jsonwebtoken');
const User = require('../models/userModel');
const authTokenHandler = async (req, res, next) => {
const token = req.header('Authorization')?.split(' ')[1]; // Extract token from header
if (!token) {
return res.status(401).json({ message: 'Access denied, no token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id).select('-password'); // Fetch user excluding password
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
req.user = user; // Attach user to request
next();
} catch (err) {
return res.status(401).json({ message: 'Invalid token' });
}
};
module.exports = authTokenHandler;
Also you can ensure req.user
contains the authenticated user's details.
If req.user
is undefined, debug by logging inside authTokenHandler.
Now, you can fix the route updating the Classroom collection to remove the student from the students array.
router.delete('/leave/:classid', authTokenHandler, async (req, res) => {
const { classid } = req.params;
const userEmail = req.user?.email; // Get the authenticated user's email
if (!userEmail) {
return res.status(401).json({ message: 'Unauthorized, user email not found' });
}
try {
// Find the student's entry in ClassroomJoin and delete it
const classroomEntry = await ClassroomJoin.findOneAndDelete({
classroomId: classid,
studentEmail: userEmail
});
if (!classroomEntry) {
return res.status(400).json({ message: 'You are not part of this classroom' });
}
// Update Classroom model to remove student email from students array
await Classroom.findByIdAndUpdate(
classid,
{ $pull: { students: userEmail } },
{ new: true }
);
return res.status(200).json({ message: 'Successfully left the classroom' });
} catch (err) {
return res.status(500).json({ message: 'Internal server error', error: err });
}
});
My authtokenHandler in code! can you help me with this?
const jwt = require("jsonwebtoken");
function checkAuth(req, res, next) {
const authToken = req.cookies.authToken;
const refreshToken = req.cookies.refreshToken;
if (!authToken || !refreshToken) {
return res.status(401).json({ message: "Unauthorized" });
}
jwt.verify(authToken, process.env.JWT_SECRET_KEY, (err, decoded) => {
if (!err) {
req.userId = decoded.userId;
req.ok = true;
req.message = "Authentication successful";
next();
} else {
jwt.verify(
refreshToken,
process.env.JWT_REFRESH_SECRET_KEY,
(refreshErr, refreshDecoded) => {
if (refreshErr) {
return res.status(401).json({ message: "Unauthorized" });
}
const newAuthToken = jwt.sign(
{ userId: refreshDecoded.userId },
process.env.JWT_SECRET_KEY,
{ expiresIn: "1d" }
);
const newRefreshToken = jwt.sign(
{ userId: refreshDecoded.userId },
process.env.JWT_REFRESH_SECRET_KEY,
{ expiresIn: "10d" }
);
res.cookie("authToken", newAuthToken, {
sameSite: "none",
httpOnly: true,
secure: true,
});
res.cookie("refreshToken", newRefreshToken, {
sameSite: "none",
httpOnly: true,
secure: true,
});
req.userId = refreshDecoded.userId;
req.ok = true;
req.message = "Authentication successful";
next();
}
);
}
});
}
module.exports = checkAuth;