'Property 'admin' does not exist on type 'User'.ts(2339)

I have the following function to specify a request has sent by a regular or admin user:

export function verifyAdmin(req: Request, res: Response, next: NextFunction) {
    if(req?.user?.admin){
        return next();
    }
    else{
        let err = new Error('Only Admin can access to this web page or resources!');
        err.status = 403;
        return next(err);
    }
};

But I get errors like following:

Property 'admin' does not exist on type 'User'.ts(2339)

At:

if(req?.user?.admin){

And the following error:

Property 'status' does not exist on type 'Error'.ts(2339)

At:

err.status = 403;

My models/user.ts file looks like as below:

import mongoose , {Schema } from 'mongoose';
import passportLocalMongoose from 'passport-local-mongoose';

export interface digitalWalletDocument extends mongoose.Document{
    currencyName: string;
    value: number;

}

const digitalWalletSchema = new Schema<digitalWalletDocument>({
    currencyName : {
        type : String
    },
    value : {
        type : Number
    }
});


export interface UserDocument extends mongoose.Document{
    username :  string;
    firstName : string;
    lastName : string;
    email : string;
    telNumber : number;
    nationalCode : number;
    admin : boolean;
    image :  string;
    wallet : number;
    rate : number;
    shabaCode :number;
    cardNumber : number;
    birthDay : string;
    status : string;
    address : string;
    documnetPath : string;
    description : string;
    purchased : string;
    digitalWallet : digitalWalletDocument;
}

export const userSchema = new Schema<UserDocument>({
    username : {
        type : String,
        sparse : true ,
        unique : true
    },
    firstName : {
        type: String
    },
    lastName : {
        type : String
    },
    email : {
        type : String,
        unique : true
    },
    telNumber : {
        type : Number
    },
    nationalCode : {
        type : Number,
        sparse : true,
        unique : true
    },
    admin : {
        type:Boolean,
        default : false
    },
    image : {
        type : String
    },
    wallet: {
        type : Number,
        default : 0
    },
    rate : {
        type : Number,
        default : 0
    },
    shabaCode : {
        type : Number
    },
    cardNumber : {
        type : Number
    },
    birthDay : {
        type : String
    },
    status : {
        type : String
    },
    address : {
        type : String
    },
    documnetPath : {
        type : String
    },
    description : {
        type: String
    },
    purchased : [String],
    digitalWallet : [digitalWalletSchema]
}, {timestamps : true});

export interface UserModel extends mongoose.PassportLocalModel<UserDocument>{};

userSchema.plugin(passportLocalMongoose,{usernameField : 'email'});

export default mongoose.model<UserDocument,UserModel>('User' , userSchema);

I don't know why this happens? I think maybe there is a name conflict between User that I have defined and User preserved name in Mongoose or Express or somewhere else?

This code was originally written in JS and when I tried to convert it to TS this problem happended.



Solution 1:[1]

I have faced this problem, after investigating it, I came up with to result that in every request, req.user object is modified by the passport. I can't find any other explanation for that, because in a current request if you set any parameter to req.user object, it will work, for instance:

app.get('/blog',(req,res)=>{
 req.user.admin = "foo";
console.log(req.user.admin) //foo
}
)

app.get('/blog/1',(req,res)=>{
conole.log(req.user.admin) //undefined
})

But if you try to access admin property from other endpoints, you will get an undefined result, because req.user has no admin property.

I fixed this problem by saving my property on the session object,

app.get('/blog',(req,res)=>{
 req.session.admin = "foo";
})

app.get('/blog/1',(req,res)=>{
conole.log(req.session.admin) //foo
})

req.session.admin worked for me on all requests.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1