I am working on an e-commerce project and I only want to allow users with admin as true to be able to create and update products in the products collection(MongoDB database), but somehow I am getting it wrong because when I use a user with admin true token as a bearer token in authorization I receive the catch error
this is my user model code
import mongoose from "mongoose";
import bcrypt from 'bcrypt'
import dotenv from 'dotenv'
dotenv.config()
const userSchema = new mongoose.Schema({
username:{
required:true,
type:String
},
email:{
type:String,
unique:true,
required:true,
},
password:{
type:String,
required:String
},
profilePic:{
type:String,
required:true,
default:'https://t3.ftcdn.net/jpg/03/46/83/96/360_F_346839683_6nAPzbhpSkIpb8pmAwufkC7c5eD7wYws.jpg'
},
admin:{
type:Boolean,
required:true,
default:false
}
}, {
timestamps: true
});
my Middleware code for the protection for product creation
import jwt from 'jsonwebtoken'
import asyncHandler from 'express-async-handler'
import userModel from '../models/user.model.js'
export const productCreationProtection = asyncHandler(async(req, res, next) => {
let authorizationToken;
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')){
try {
authorizationToken = req.headers.authorization.split(" ")[1]
// decode user id
const decode = jwt.verify(authorizationToken, process.env.PRIVATE_KEY)
// Find the userModel and we use select to exclude password for find
req.user = await userModel.findOne(decode.id).select('admin')
next();
} catch (error) {
res.sendStatus(401)
throw new Error("You're not authorized to performe this function")
}
}
if(!authorizationToken){
res.sendStatus(401)
throw new Error("Not Authourized to performe this action")
}
});
CodePudding user response:
The findOne method takes an object as parameter but you are passing a string. If you are trying to find a user with given ID, then try refactoring your code as shown below:
req.user = await userModel.findOne({ _id: decode.id }).select('admin')
// Check if admin field is true
if (!req.user.admin) {
return "Forbidden"
}
next()
This will return document where _id is equal to decode.id. Do replace _id if you are querying based on any other field.
Alternatively, you can also add admin field in query itself:
const user = await userModel.findOne({ _id: decode.id, admin: true })
if (!user) {
// User with given ID not found or is not an admin
return "Forbidden"
}
next();
