Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broken NestJs middleware #20

Open
jgr3go opened this issue Jun 13, 2021 · 4 comments
Open

Broken NestJs middleware #20

jgr3go opened this issue Jun 13, 2021 · 4 comments

Comments

@jgr3go
Copy link

jgr3go commented Jun 13, 2021

Using NestJs Middleware Consumers is broken with this module. I'm trying to globally add middleware to the admin module with something like:

@Module({
   imports: [
     // whatever
     AdminModule.createAdmin({ 
       adminBroOptions: {
         rootPath: 'admin',
         // etc
       }
     })
  ]
})
export class AppModule implements NestModule {
  confgure(consumer: MiddlewareConsumer) {
     consumer.apply(passport.authenticate('jwt').forRoutes({path: 'admin*', method: RequestMethod.ALL});
  }
}

But the middleware is never executed. I'm reasonably sure this is due to the middleware reordering in express.loader.ts because when I comment it out, the middleware is executed as expected.

@burgalon
Copy link

anyone? @wojtek-krysiak ?

@burgalon
Copy link

burgalon commented Jul 12, 2021

My solution for now is to initialize in App.module.js with:

    AdminModule.createAdminAsync({
      customLoader: CustomAdminJsCustomLoader,
      useFactory: () => ({
        adminJsOptions: {
          rootPath: '/admin',
        },
      }),
    }),

and then in CustomAdminJsCustomLoader copy ExpressLoader without the reordering

@siddisking
Copy link

My solution for now is to initialize in App.module.js with:

    AdminModule.createAdminAsync({
      customLoader: CustomAdminJsCustomLoader,
      useFactory: () => ({
        adminJsOptions: {
          rootPath: '/admin',
        },
      }),
    }),

and then in CustomAdminJsCustomLoader copy ExpressLoader without the reordering

Hi,

I am looking for a similar solution but as soon as I did that this error happened:

{"message":"\n You probably used old body-parser middleware, which is not compatible\n with @adminjs/express. In order to make it work you will have to\n 1. move body-parser invocation after the AdminJS setup like this:\n \n const adminJs = new AdminJS()\n const router = new buildRouter(adminJs)\n app.use(adminJs.options.rootPath, router)\n \n // body parser goes after the AdminJS router\n app.use(bodyParser())\n \n 2. Upgrade body-parser to the latest version and use it like this:\n app.use(bodyParser.json())\n "}

I was looking for a way to add a middleware for mitigating session fixation...

Any inputs of how I can get add a middleware to the adminjs nestjs setup ?

@rckrdstrgrd
Copy link

rckrdstrgrd commented Jan 19, 2024

Here's a modified version that inserts adminjs after any middleware applied to the rootPath. I have not tested it much but it seems to be working with nestjs applied middleware.

private reorderRoutes(app, rootPath: string) {
    let jsonParser = [];
    let urlencodedParser = [];
    let admin = [];

    // Nestjs uses bodyParser under the hood which is in conflict with adminjs setup.
    // Due to adminjs-expressjs usage of formidable we have to move body parser in layer tree after adminjs init.
    // Notice! This is not documented feature of express, so this may change in the future. We have to keep an eye on it.
    if (app && app._router && app._router.stack) {
      const jsonParserIndex = app._router.stack.findIndex(
        (layer: { name: string }) => layer.name === 'jsonParser',
      );
      if (jsonParserIndex >= 0) {
        jsonParser = app._router.stack.splice(jsonParserIndex, 1);
      }

      const urlencodedParserIndex = app._router.stack.findIndex(
        (layer: { name: string }) => layer.name === 'urlencodedParser',
      );
      if (urlencodedParserIndex >= 0) {
        urlencodedParser = app._router.stack.splice(urlencodedParserIndex, 1);
      }

      const adminIndex = app._router.stack.findIndex(
        (layer: { name: string }) => layer.name === 'admin',
      );
      if (adminIndex >= 0) {
        admin = app._router.stack.splice(adminIndex, 1);
      }

      // if adminjs-nestjs didn't reorder the middleware
      // the body parser would have come after corsMiddleware
      const corsIndex = app._router.stack.findIndex(
        (layer: { name: string }) => layer.name === 'corsMiddleware',
      );

      // in other case if there is no corsIndex we go after expressInit, because right after that
      // there are nest endpoints.
      const expressInitIndex = app._router.stack.findIndex(
        (layer: { name: string }) => layer.name === 'expressInit',
      );

      // in case there are other middleware on the rootPath
      // the adminjs should go after those
      let rootPathMiddlewareIndex = -1;

      const matches = app._router.stack
        .map((s, i) => {
          return { stackIndex: i, ...s };
        })
        .filter((s: { regexp: RegExp; name: string }) => {
          if (['query', 'corsMiddleware', 'expressInit'].includes(s.name)) {
            return false;
          }
          return s.regexp.test(rootPath);
        });

      if (matches.length > 0) {
        rootPathMiddlewareIndex = matches[0].stackIndex + matches.length;
      }

      const initIndex =
        rootPathMiddlewareIndex >= 0
          ? rootPathMiddlewareIndex
          : (corsIndex >= 0 ? corsIndex : expressInitIndex) + 1;

      app._router.stack.splice(
        initIndex,
        0,
        ...admin,
        ...jsonParser,
        ...urlencodedParser,
      );
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants