diff --git a/src/inversion-of-control/container-manager.ts b/src/inversion-of-control/container-manager.ts index c2c0cd3..887c85f 100644 --- a/src/inversion-of-control/container-manager.ts +++ b/src/inversion-of-control/container-manager.ts @@ -5,6 +5,7 @@ import { PolarisGraphQLLogger } from '../logging/polaris-graphql-logger'; import { IrrelevantEntitiesMiddleware } from '../middlewares/irrelevant-entities-middleware'; import { PolarisMiddleware } from '../middlewares/polaris-middleware'; import { PolarisGraphQLServer } from '../server/graphql-server'; +import { RealitiesHolderValidator } from '../server/realities-holder-validator'; import { POLARIS_TYPES } from './polaris-types'; decorate(injectable(), PolarisLogger); @@ -13,4 +14,5 @@ polarisContainer.bind(POLARIS_TYPES.GraphQLServer).to(PolarisGraphQLServer); polarisContainer.bind(POLARIS_TYPES.GraphQLLogger).to(PolarisGraphQLLogger); polarisContainer.bind(POLARIS_TYPES.Middleware).to(PolarisMiddleware); polarisContainer.bind(POLARIS_TYPES.Middleware).to(IrrelevantEntitiesMiddleware); +polarisContainer.bind(POLARIS_TYPES.RealitiesHolderValidator).to(RealitiesHolderValidator); polarisContainer.bind(POLARIS_TYPES.RealitiesHolder).toConstantValue({}); diff --git a/src/inversion-of-control/polaris-types.ts b/src/inversion-of-control/polaris-types.ts index cccefcf..72d77ee 100644 --- a/src/inversion-of-control/polaris-types.ts +++ b/src/inversion-of-control/polaris-types.ts @@ -19,4 +19,5 @@ export const POLARIS_TYPES = { InjectableResolver: Symbol('InjectableResolver'), CommonEntityInterface: Symbol('CommonEntityInterface`'), RealitiesHolder: Symbol('RealitiesHolder'), + RealitiesHolderValidator: Symbol('RealitiesHolderValidator'), }; diff --git a/src/server/graphql-server.ts b/src/server/graphql-server.ts index 58f76f9..4f89294 100644 --- a/src/server/graphql-server.ts +++ b/src/server/graphql-server.ts @@ -13,10 +13,9 @@ import { PolarisGraphQLLogger } from '../logging/polaris-graphql-logger'; import { Middleware } from '../middlewares/middleware'; import { createMiddleware } from '../middlewares/polaris-middleware-creator'; import { PolarisProperties } from '../properties/polaris-properties'; -import { RealitiesHolder } from '../realities-holder/realities-holder'; import { IrrelevantEntitiesExtension } from './irrelevant-entities-extension'; import { PolarisContext } from './polaris-context'; -import { RealitiesHolderChecker } from './realities-holder-checker'; +import { RealitiesHolderValidator } from './realities-holder-validator'; export interface GraphQLServer { server: ApolloServer; @@ -41,7 +40,8 @@ export class PolarisGraphQLServer implements GraphQLServer { @inject(POLARIS_TYPES.PolarisServerConfig) propertiesConfig: PolarisServerConfig, @multiInject(POLARIS_TYPES.Middleware) middlewares: Middleware[], @inject(POLARIS_TYPES.GraphQLLogger) private polarisLogger: PolarisGraphQLLogger, - @inject(POLARIS_TYPES.RealitiesHolder) private realitiesHolder: RealitiesHolder, + @inject(POLARIS_TYPES.RealitiesHolderValidator) + private realitiesHolderValidator: RealitiesHolderValidator, ) { const executableSchemaWithMiddleware = applyMiddleware( schema, @@ -54,10 +54,7 @@ export class PolarisGraphQLServer implements GraphQLServer { context: (args: { ctx: Koa.Context; connection: any }) => this.getContext(args), formatError: (error: any) => this.formatError(error), formatResponse: (response: any) => this.formatResponse(response), - extensions: [ - () => new IrrelevantEntitiesExtension(), - () => new RealitiesHolderChecker(realitiesHolder), - ], + extensions: [() => new IrrelevantEntitiesExtension()], }; this.server = new ApolloServer(config); this.app = new Koa(); @@ -122,19 +119,21 @@ export class PolarisGraphQLServer implements GraphQLServer { private getContext({ ctx, connection }: { ctx: Koa.Context; connection: any }): PolarisContext { try { if (!connection) { - return this.getHttpContext(ctx); + const context: PolarisContext = this.getHttpContext(ctx); + this.realitiesHolderValidator.validateRealitySupport(context); + return context; } else { return { body: {}, pubSub: new PubSub() } as any; } } catch (e) { - this.polarisLogger.error('Headers error', { + this.polarisLogger.error('Context error', { polarisLogProperties: { throwable: e }, }); - throw new Error('Unable to format headers'); + throw new Error(e.message); } } - private getHttpContext(ctx: Koa.Context) { + private getHttpContext(ctx: Koa.Context): PolarisContext { const headers = getHeaders(ctx.request.headers); const context: PolarisContext = { headers, diff --git a/src/server/realities-holder-checker.ts b/src/server/realities-holder-checker.ts deleted file mode 100644 index 4ed714b..0000000 --- a/src/server/realities-holder-checker.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { GraphQLExtension } from 'graphql-extensions'; -import { RealitiesHolder } from '../realities-holder/realities-holder'; -import { PolarisContext } from './polaris-context'; - -export class RealitiesHolderChecker extends GraphQLExtension { - constructor(private realitiesHolder: any) { - super(); - } - - requestDidStart(responseContext: { context: PolarisContext }) { - const requestedReality = responseContext.context.headers.realityId; - - const realityIsNotSupported: boolean = - requestedReality && - this.realitiesHolder && - this.realitiesHolder instanceof RealitiesHolder && - !this.realitiesHolder.isRealitySupported(requestedReality); - - if (realityIsNotSupported) { - throw new Error( - `The requested reality-id is not supported!\nConsider support that reality-id with the class that extends RealitiesHolder`, - ); - } - } -} diff --git a/src/server/realities-holder-validator.ts b/src/server/realities-holder-validator.ts new file mode 100644 index 0000000..7acddff --- /dev/null +++ b/src/server/realities-holder-validator.ts @@ -0,0 +1,25 @@ +import { UserInputError } from 'apollo-server-koa'; +import { inject, injectable } from 'inversify'; +import { POLARIS_TYPES } from '../inversion-of-control/polaris-types'; +import { RealitiesHolder } from '../realities-holder/realities-holder'; +import { PolarisContext } from './polaris-context'; + +@injectable() +export class RealitiesHolderValidator { + constructor(@inject(POLARIS_TYPES.RealitiesHolder) private realitiesHolder: any) {} + + validateRealitySupport(context: PolarisContext) { + if (context) { + const requestedReality = context.headers.realityId; + if ( + requestedReality != null && + this.realitiesHolder instanceof RealitiesHolder && + !this.realitiesHolder.isRealitySupported(requestedReality) + ) { + throw new UserInputError( + `The requested reality-id ${requestedReality} is not supported!`, + ); + } + } + } +} diff --git a/test/integration-tests/test-server/test-realities-holder.ts b/test/integration-tests/test-server/test-realities-holder.ts index e4a39ac..7e4a3fc 100644 --- a/test/integration-tests/test-server/test-realities-holder.ts +++ b/test/integration-tests/test-server/test-realities-holder.ts @@ -4,6 +4,6 @@ import { RealitiesHolder } from '../../../src/realities-holder/realities-holder' @injectable() export class TestRealitiesHolder extends RealitiesHolder { getRealities(): Set { - return new Set([0, 2]); + return new Set([0, 1, 2]); } } diff --git a/test/server/graphql-server.test.ts b/test/server/graphql-server.test.ts index 23a86ff..cab382c 100644 --- a/test/server/graphql-server.test.ts +++ b/test/server/graphql-server.test.ts @@ -5,7 +5,6 @@ import 'reflect-metadata'; import { PolarisServerConfig } from '../../src/common/injectable-interfaces'; import { PolarisMiddleware } from '../../src/middlewares/polaris-middleware'; import { createMiddleware } from '../../src/middlewares/polaris-middleware-creator'; -import { RealitiesHolder } from '../../src/realities-holder/realities-holder'; import { PolarisGraphQLServer } from '../../src/server/graphql-server'; const apolloServerMock: { [T in keyof ApolloServer]: any } = { @@ -35,7 +34,7 @@ describe('graphql-server tests', () => { polarisProperties: jest.fn(), } as any; const polarisMiddlewareMock: { [T in keyof PolarisMiddleware]: any } = {} as any; - const realitiesHolderMock: { [T in keyof RealitiesHolder]: any } = {} as any; + const realitiesHolderValidatorMock = {} as any; test('creating new polaris server - with arguments - graphql apply middleware have been called', () => { const server = new PolarisGraphQLServer( @@ -43,7 +42,7 @@ describe('graphql-server tests', () => { polarisServerConfigMock, [polarisMiddlewareMock], polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); expect(applyMiddleware).toHaveBeenCalled(); @@ -56,7 +55,7 @@ describe('graphql-server tests', () => { polarisServerConfigMock, middlewares, polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); expect(createMiddleware).toHaveBeenCalledTimes(middlewares.length); @@ -68,7 +67,7 @@ describe('graphql-server tests', () => { polarisServerConfigMock, [polarisMiddlewareMock], polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); expect(ApolloServer).toHaveBeenCalled(); @@ -84,7 +83,7 @@ describe('graphql-server tests', () => { polarisServerConfigMockWithEndpoint, [polarisMiddlewareMock], polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); server.start(); expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith( @@ -109,7 +108,7 @@ describe('graphql-server tests', () => { polarisServerConfigMockWithEndpoint, [polarisMiddlewareMock], polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); server.start(app); expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith( @@ -133,7 +132,7 @@ describe('graphql-server tests', () => { polarisServerConfigMockWithEndpoint, [polarisMiddlewareMock], polarisLog, - realitiesHolderMock, + realitiesHolderValidatorMock, ); server.start(app); expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith(