Home > Blockchain >  Express middleware undefined type
Express middleware undefined type

Time:02-16

I am trying to create an authentication middleware for my express server and I get no Type errors in my IDE but when I try to complile I am getting TypeError: Cannot read properties of undefined (reading protect). The route works fine without the middleware and the middleware has no detectable linting issues. I am also using socket.io so I tried io.use(wrap(middleware)) on the off chance it would work and it didn't but that was a shot in the dark anyway, the problem seems unrelated. I've also tried replacing ALL relevant type declarations with any and got the same problem.

userController:

export const getMe = asyncHandler(async (req: IGetUserAuthInfoRequest, res: Response): Promise<void> => {
  res.status(200).json(req.user)
})

RoutesController:

public static protect = asyncHandler(async (req: IGetUserAuthInfoRequest, res: Response, next: NextFunction): Promise<void> => {
    let token: string

    if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
      try {
        token = req.headers.authorization.split(' ')[1]

        const decoded: JwtPayload = jwt.verify(token, process.env.JWT_SECRET, { complete: true })
        req.user = await UserModel.findById(decoded.id).select('-password')
        next()
      } catch (err) {
        res.status(401)
        throw new Error('Not authorised')
      }
    }
    if (!token) {
      res.status(401)
      throw new Error('Not a valid token')
    }
  })

Extended express Request interface:

export interface IGetUserAuthInfoRequest extends Request {
  user: any
}

userRouter:

userRouter.route('/me').get(RoutesController.protect, userController.getMe)

The error:

TypeError: Cannot read properties of undefined (reading 'protect')
    at Object.<anonymous> (C:\Users\liams\dev\my-rest-server\src\routes\user.router.ts:8:46)
    at Module._compile (node:internal/modules/cjs/loader:1097:14)
    at Module._compile (C:\Users\liams\dev\my-rest-server\node_modules\source-map-support\source-map-support.js:568:25)
    at Module.m._compile (C:\Users\liams\AppData\Local\Temp\ts-node-dev-hook-8639111545614118.js:69:33)
    at Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
    at require.extensions.<computed> (C:\Users\liams\AppData\Local\Temp\ts-node-dev-hook-8639111545614118.js:71:20)
    at Object.nodeDevHook [as .ts] (C:\Users\liams\dev\my-rest-server\node_modules\ts-node-dev\lib\hook.js:63:13)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:999:19)
[ERROR] 20:08:00 TypeError: Cannot read properties of undefined (reading 'protect')

Any ideas what I'm missing?

EDIT: rather than posting everyline of my code here you can see it in the repo: https://github.com/dotDone/my-rest-server/tree/auth

CodePudding user response:

Your RouteController is not defined yet when you use it in the user controller. ( Your architecture can be improved, but I will try to only answer your question, just know that there is a better way to organize all this ) Try the following

Turn UserRoutes to a class

import { Router } from 'express'
import * as userController from '../controllers/user.controller'

class UserRoutes {
constructor(routesController) {
this.userRouter: Router = Router();
this.routesController = routesController;
this.initRoutes();
}

initRoutes() {
userRouter.route('/').get(userController.getUsers).post(userController.createUser).put(userController.editUser).delete(userController.deleteUser)
userRouter.route('/me').get(this.routesController.protect, userController.getMe)
} 

}

Then in your server.ts, create another function, call it initRoutes for example where you do something like this

constructor() {
    this.startServer().then(() => this.startControllers()).then(() => this.initRoutes()).catch(err => console.log(err))
}

...

initRoutes() {
  this.userRoutes = new UserRoutes(this.routesController);
}
  • Related