I`m developing a MERN app. I basically did coding for CRUD operations. It perfectly works for creating a new user & signing up as existing user. But when I try to update user after logging in, it gives "Not authorized, no token" error. Updating user doesn`t work even with the admin user. When I go to the inspect section from browser, is says that there`s an internal server error with 500 status code. Please show me the part needs to be corrected if anyone knows. Thanks in advance!
Here are my codes:
1)Code for user Routes
import express from "express";
import {
createUser, loginUser, logoutCurrentUser,
getAllUsers, getCurrentUserProfile, updateCurrentUserProfile, deleteUserById,
getUserById, updateUserById
} from "../controllers/userController.js";
import { authenticate, authorizeAdmin } from "../middlewares/authMiddleware.js";
const router = express.Router();
router
.route("/")
.post(createUser)
router.get("/", authenticate, authorizeAdmin, getAllUsers);
router.post("/auth", loginUser);
router.post("/logout", logoutCurrentUser);
router.route("/profile")
.get(authenticate, getCurrentUserProfile)
.put(authenticate, updateCurrentUserProfile)
//Admin Routes
router.route("/:id")
.delete(authenticate, authorizeAdmin, deleteUserById)
.get(authenticate, authorizeAdmin, getUserById)
.put(authenticate, authorizeAdmin, updateUserById)
export default router;
2)Code for auth Middleware
import Jwt from "jsonwebtoken";
import User from "../models/userModel.js";
import asyncHandler from "./asyncHandler.js";
const authenticate = asyncHandler(async (req, res, next) => {
let token;
//Read JWT form the 'jwt' cookie
token = req.cookies.Jwt;
// token = req.headers.token;
if (token) {
try {
const decoded = Jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.userId).select("-password");
next();
} catch (error) {
res.status(401);
throw new Error("Not authorized, token failed");
}
} else {
res.status(401);
throw new Error("Not authorized, no token");
}
});
const authorizeAdmin = (req, res, next) => {
if (req.user && req.user.isAdmin) {
next();
} else {
res.status(401).send("Not authorized as an admin");
}
};
export { authenticate, authorizeAdmin };
3)Code for create Token
import Jwt from "jsonwebtoken";
const generateToken = (res, userId) => {
const token = Jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: "30d" });
// Set JWT as an HTTP-Only Cookie
res.cookie("jwt", token, {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: "strict",
maxAge: 30 * 24 * 60 * 60 * 1000
});
return token;
};
export default generateToken;
- Code for user controller
import User from "../models/userModel.js";
import asyncHandler from "../middlewares/asyncHandler.js";
import bcrypt from "bcryptjs";
import createToken from "../utils/createToken.js";
const createUser = asyncHandler(async (req, res) => {
const { username, email, password } = req.body;
if (!username || !email || !password) {
throw new Error("Please fill all the inputs");
}
const userExists = await User.findOne({ email });
if (userExists) res.status(400).send("User already exists");
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const newUser = await new User({ username, email, password: hashedPassword });
try {
await newUser.save();
createToken(res, newUser._id);
// const token_no = createToken(res, newUser._id);
res
.status(201)
.json({
_id: newUser._id,
username: newUser.username,
email: newUser.email,
isAdmin: newUser.isAdmin,
token: token_no,
});
} catch (error) {
res.status(400);
throw new Error("Invalid user data");
}
});
const loginUser = asyncHandler(async (req, res) => {
const { email, password } = req.body;
console.log(email);
console.log(password);
const existingUser = await User.findOne({ email })
if (existingUser) {
const isPasswordValid = await bcrypt.compare(password, existingUser.password)
if (isPasswordValid) {
const token_no = createToken(res, existingUser._id);
res
.status(201)
.json({
_id: existingUser._id,
username: existingUser.username,
email: existingUser.email,
isAdmin: existingUser.isAdmin,
token: token_no,
});
return;
}
}
});
const logoutCurrentUser = asyncHandler(async (req, res) => {
res.cookie("jwt", "", {
httpOnly: true,
expires: new Date(0)
});
res.status(200).json({ message: "Logged out successfully!" });
});
const getAllUsers = asyncHandler(async (req, res) => {
const users = await User.find({});
res.json(users);
});
const getCurrentUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id)
if (user) {
res.json({
_id: user._id,
username: user.username,
email: user.email
})
} else {
res.status(404);
throw new Error("User not found");
}
});
const updateCurrentUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id)
if (user) {
user.username = req.body.username || user.username
user.email = req.body.email || user.email
if (req.body.password) {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
user.password = hashedPassword;
}
const updatedUser = await user.save();
const token_no = createToken(res, updatedUser._id);
res.json({
_id: updatedUser._id,
username: updatedUser.username,
email: updatedUser.email,
isAdmin: updatedUser.isAdmin,
token: token_no,
});
} else {
res.status(404);
throw new Error("User not found");
}
});
const deleteUserById = asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id)
if (user) {
if (user.isAdmin) {
res.status(400)
throw new Error("Can not delete admin user")
}
await User.deleteOne({ _id: user._id });
res.json({ message: "User deleted!" })
} else {
res.status(404);
throw new Error("User not found");
}
});
const getUserById = asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id).select("-password")
if (user) {
res.json(user);
} else {
res.status(404);
throw new Error("User not found");
}
});
const updateUserById = asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id)
if (user) {
user.username = req.body.username || user.username
user.email = req.body.email || user.email
user.isAdmin = Boolean(req.body.isAdmin)
const updatedUser = await user.save();
const token_no = createToken(res, updatedUser._id);
res.json({
_id: updatedUser._id,
username: updatedUser.username,
email: updatedUser.email,
isAdmin: updatedUser.isAdmin,
token: token_no,
})
} else {
res.status(404);
throw new Error("User not found");
}
});
export {
createUser, loginUser, logoutCurrentUser,
getAllUsers, getCurrentUserProfile, updateCurrentUserProfile, deleteUserById,
getUserById, updateUserById
};
5)Code for profile( where users can`t be updated, even the admin user)
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { toast } from "react-toastify";
import Loader from "../../components/Loader";
import { setCredentials } from "../../redux/features/auth/authSlice";
import { Link } from "react-router-dom";
import { useProfileMutation } from "../../redux/api/usersApiSlice";
const Profile = () => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const { userInfo } = useSelector((state) => state.auth);
const [updateProfile, { isLoading: loadingUpdateProfile }] =
useProfileMutation();
useEffect(() => {
setUsername(userInfo.username);
setEmail(userInfo.email);
}, [userInfo.email, userInfo.username]);
const dispatch = useDispatch();
const submitHandler = async (e) => {
e.preventDefault();
if (password !== confirmPassword) {
toast.error("Passwords do not match");
} else {
try {
const res = await updateProfile({
_id: userInfo._id,
username,
email,
password,
}).unwrap();
dispatch(setCredentials({ ...res }));
toast.success("Profile updated successfully!");
} catch (err) {
toast.error(err?.data?.message || err.error);
}
}
};
export default Profile;
I couldn`t recognize the mistake here as there was no any syntax error showing in the VS code as well. I got the same "Not authorized, no token" error for all CRUD operations when I tried it with POST man. When the token is passed through body of the request, it worked perfectly. But the same error popped up again with the front end. Please let me know if anyone knows about this.