Include required "user" after middleware in Express with Typescript and Passport setup

I find myself constantly having to include code like

if (!req.user) return res.status(401).send()

The first solution that comes to mind is creating an express middleware for this. However, even though I can prevent non-logged in users from accessing the route, I am struggling to properly type the express req.

When I try to override the "req" parameter, the router raises errors because the user key in "Express.User" is considered optional.

I don't think modifying the global override so that "user" is required is a good idea since it should only be required after passing through the middleware validation. How can I solve this issue?

Here's a snippet of relevant code to provide more context.

Global Express Override

declare global {
  namespace Express {
    interface User extends TUser {
      _id: ObjectId
    }
  }
}

Desired Outcome

// Router
router.post('/', sessionMiddleware, controller)

// Middleware
const sessionMiddleware = (req: Request, res: Response, next: NextFunction) => {
if (!req.user) return res.status(401).send()
next()
}

// Controller
const controller = (req: RequestWithRequiredUser, res: Response) => {
  // user here can't possibly be typed undefined
  const user = req.user
  ...
}

Current Workaround:

const controller = (req: Request, res: Response) => {
  if (!req.user) return res.status(401).send()

  ...doSomethingElse
}

Answer №1

This solution utilizes middlewares to avoid redundant logic, offering a workaround for the issue at hand.

sessionBuilder.ts

/** Ensure specified keys are required */
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

type Controller<T extends Request> = (req: WithRequired<T, 'user'>, res: Response) => unknown

export const sessionBuilder =
  <T extends Request>(controller: Controller<T>) =>
  (req: Request, res: Response) => {
    if (!req.user) return res.status(401).send()

    // A temporary workaround is necessary due to a type mismatch issue
    // Using Omit instead of WithRequired didn't resolve it
    const request = req as WithRequired<T, 'user'>

    return controller(request, res)
  }

specificController.ts

export const customExpressController = 
  sessionBuilder((req, res) => {
  
    // It's guaranteed that user will always have a value here
    const { user } = req

    return res.json(user)
  })

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Solving the problem of cookieParser implementation in NestJS

Greetings! I have a question for you. Currently, I am working on developing a backend using NestJS, a Node.js framework. Everything is functioning smoothly except for some issues when it comes to hosting. I have created a new NestJS project and made some ...

Error Message: Angular 5 - Unable to bind to 'ngModel' as it is not recognized as a valid property of 'input'

I am currently working on an Angular 5 online tutorial using Visual Studio Code and have the following versions: Angular CLI: 7.0.6 Node: 10.7.0 Angular: 7.0.4, Despite not encountering any errors in Visual Studio Code, I am receiving an error in ...

Error: The selected module is not a valid top-level option

I am facing an issue while using the babel-loader. I have removed all irrelevant code and just kept the error-related portion. What could be causing this problem? module.exports = merge(baseWebpackConfig, { ... module: { rules: [ ...

Tips for creating more organized express routers while incorporating helper functions

When it comes to organizing controllers in separate files and utilizing OOP, one common question arises: how should helper functions be separated? Specifically, I'm referring to those functions created to enhance code cleanliness that are only used on ...

Learn the process of transferring a complete JSON object into another object using Angular

I'm having trouble inserting one object into another. My JSON object is multidimensional, like this: { "item1":{ "key":"Value", "key":"Value" }, "item2":{ "key ...

Learn the steps to establish a one-to-many relational record with the help of Node.js and Sequelize-Typescript

Currently, I am working on Nodejs with sequelize-typescript to develop a CRUD system for a one-to-many relationship. Unfortunately, I have encountered an issue with my code that I cannot seem to pinpoint. While I am able to retrieve records successfully us ...

I developed a compact application utilizing Node.js in tandem with Express framework

There is an issue with the GPA calculator app built using Node.js and Express. It works fine for a single user, but when multiple users try to use it simultaneously, the scores are being combined, resulting in incorrect values. I need to create an app that ...

What is the best way to ensure that messages stay saved in my app for an extended

I am looking for a way to store messages sent through my small messaging app in a persistent manner. Currently, the messages are transferred from the front-end to a Node, Socket.io, and Express back-end. A friend recommended using Enmaps (), but unfortuna ...

Can a node server be set up using only git-tracked files in Express?

My goal is to only run my Express app with files that are currently tracked in Git. Here's the current status of Git when I run git status: On branch master Untracked files: (use "git add <file>..." to include in what will be committed) b ...

"Encountering errors when running a query involving integer values

As I set up my Express server to generate MongoDB endpoints, I referred to this helpful guide: https://devcenter.heroku.com/articles/mean-apps-restful-api When it comes to defining query strings, I implemented the following function: app.get("/contacts", ...

Can you explain to me the syntax used in Javascript?

I'm a bit puzzled by the syntax used in this react HOC - specifically the use of two fat arrows like Component => props =>. Can someone explain why this works? const withLogging = Component => props => { useEffect(() => { fetch(`/ ...

Encountering an Issue with Vue 3 and Vue Router 4: Uncaught TypeError - Trying to Access Undefined Properties (specifically 'push')

I'm currently working with Vue 3, Vue Router 4, and TypeScript in my project. However, I've encountered an issue while trying to utilize router.push(). Every time I attempt this, I receive a console error stating: Uncaught (in promise) TypeError: ...

Utilizing Angular.js to Retrieve JSON Data Using the HTTP Response Interceptor

When it comes to handling HTTP requests and responses, I have a setup that involves sending requests with a 404 status code while also intercepting them in an Angular Service. res.status(404).send({message: 'O Captain! My Captain!'}); In my Ang ...

Mongoose updates only the values that have been modified

I have a PUT route set up to update values. I am making requests to this route from two different places. One is sending information regarding details, while the other is providing data on completed. The issue arises when Mongoose updates both fields, even ...

Creating encoded objects for a content-type of `application/x-www-form-urlencoded`

Upgrading AngularJS Code to Angular 2+ - Http Issue I am in the process of converting some legacy AngularJS code (specifically Ionic 1) to the latest version of Angular (Ionic 4), and I've encountered a troubling issue. Previously, in every HTTP POS ...

Exploring the possibilities of connecting Facebook with the power of Node.js

I have a great idea, but I am facing some challenges... How can I connect Facebook users to my Node app using socket.io? I have already created a socket.io chat, but now I want to allow Facebook users to join the chat and create something similar to a Fac ...

Eliminating the parent property name from the validation message of a nested object

When using @ValidateNested() with the class-validator library, I encountered a formatting issue when validating a nested object: // Object Schema: export class CreateServerSettingsDTO { @IsNotEmpty({ message: 'Username is required' }) usernam ...

A guide to accessing an ngModel element within a reusable component

I have a specific ngModel component inside a reusable component that is not part of a form. I need to access it in order to make some changes, but when I try to do so using the code below, it returns undefined during OnInit. Can you advise me on how to pro ...

jade, express, as well as findings from mysql

My goal is to display the results of an SQL query in Jade, which pulls data from a table of banners. Each banner has a unique id and falls under one of three types. Here is my current code : express : connection.query("SELECT * FROM banner_idx ORDER BY ...

Solving the Cache Busting Problem in ReactJS and Express

Is there a way to prevent cache busting by incorporating version numbers in the index.html file name (like index.hash.html) generated with html-webpack-plugin? I'm facing the issue where the browser continues to retrieve the old cached index.html file ...