From 37de9f459db72aa87c52e90e4cd15de71b0ae6f7 Mon Sep 17 00:00:00 2001 From: Gautier Darchen Date: Mon, 10 Jun 2024 10:04:48 +0200 Subject: [PATCH] fix(cookies): Apply split cookie session middleware per route (#2880) --- packages/core/src/app.module.ts | 29 ++++++++++++++++++++++++++++- packages/core/src/bootstrap.ts | 14 ++++---------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/packages/core/src/app.module.ts b/packages/core/src/app.module.ts index d463a4062c..fdb0a69537 100644 --- a/packages/core/src/app.module.ts +++ b/packages/core/src/app.module.ts @@ -1,4 +1,5 @@ import { MiddlewareConsumer, Module, NestModule, OnApplicationShutdown } from '@nestjs/common'; +import cookieSession from 'cookie-session'; import { ApiModule } from './api/api.module'; import { Middleware, MiddlewareHandler } from './common'; @@ -26,18 +27,44 @@ import { ServiceModule } from './service/service.module'; ], }) export class AppModule implements NestModule, OnApplicationShutdown { - constructor(private configService: ConfigService, private i18nService: I18nService) {} + constructor( + private configService: ConfigService, + private i18nService: I18nService, + ) {} configure(consumer: MiddlewareConsumer) { const { adminApiPath, shopApiPath, middleware } = this.configService.apiOptions; + const { cookieOptions } = this.configService.authOptions; + const i18nextHandler = this.i18nService.handle(); const defaultMiddleware: Middleware[] = [ { handler: i18nextHandler, route: adminApiPath }, { handler: i18nextHandler, route: shopApiPath }, ]; + const allMiddleware = defaultMiddleware.concat(middleware); + + // If the Admin API and Shop API should have specific cookies names, we need to create separate cookie sessions + if (typeof cookieOptions?.name === 'object') { + const shopApiCookieName = cookieOptions.name.shop; + const adminApiCookieName = cookieOptions.name.admin; + allMiddleware.push({ + handler: cookieSession({ ...cookieOptions, name: adminApiCookieName }), + route: adminApiPath, + }); + allMiddleware.push({ + handler: cookieSession({ ...cookieOptions, name: shopApiCookieName }), + route: shopApiPath, + }); + allMiddleware.push({ + handler: cookieSession({ ...cookieOptions, name: shopApiCookieName }), + route: '/', + }); + } + const consumableMiddlewares = allMiddleware.filter(mid => !mid.beforeListen); const middlewareByRoute = this.groupMiddlewareByRoute(consumableMiddlewares); + for (const [route, handlers] of Object.entries(middlewareByRoute)) { consumer.apply(...handlers).forRoutes(route); } diff --git a/packages/core/src/bootstrap.ts b/packages/core/src/bootstrap.ts index a18c89d7f5..9824100b6a 100644 --- a/packages/core/src/bootstrap.ts +++ b/packages/core/src/bootstrap.ts @@ -250,7 +250,7 @@ function checkPluginCompatibility(config: RuntimeVendureConfig): void { if (!satisfies(VENDURE_VERSION, compatibility, { loose: true, includePrerelease: true })) { Logger.error( `Plugin "${pluginName}" is not compatible with this version of Vendure. ` + - `It specifies a semver range of "${compatibility}" but the current version is "${VENDURE_VERSION}".`, + `It specifies a semver range of "${compatibility}" but the current version is "${VENDURE_VERSION}".`, ); throw new InternalServerError( `Plugin "${pluginName}" is not compatible with this version of Vendure.`, @@ -411,15 +411,9 @@ export function configureSessionCookies( ): void { const { cookieOptions } = userConfig.authOptions; - // If the Admin API and Shop API should have specific cookies names - if (typeof cookieOptions?.name === 'object') { - const shopApiCookieName = cookieOptions.name.shop; - const adminApiCookieName = cookieOptions.name.admin; - const { shopApiPath, adminApiPath } = userConfig.apiOptions; - app.use(cookieSession({...cookieOptions, name: shopApiCookieName})); - app.use(`/${shopApiPath}`, cookieSession({ ...cookieOptions, name: shopApiCookieName })); - app.use(`/${adminApiPath}`, cookieSession({ ...cookieOptions, name: adminApiCookieName })); - } else { + // If the Admin API and Shop API should have the same cookie name + // Else, the specific cookie middlewares are handled in the 'AppModule#configure' method + if (typeof cookieOptions?.name === 'string') { app.use( cookieSession({ ...cookieOptions,