Skip to content

Commit

Permalink
Merge pull request #60 from osher-sade/realities-holder
Browse files Browse the repository at this point in the history
Realities holder
  • Loading branch information
osher-sade authored Jun 16, 2019
2 parents 859872e + d829d2e commit de2fb38
Show file tree
Hide file tree
Showing 16 changed files with 129 additions and 11 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
clearMocks : true,
clearMocks: true,
moduleFileExtensions: [
"ts",
"js",
Expand Down
4 changes: 4 additions & 0 deletions src/inversion-of-control/container-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'reflect-metadata';
import { PolarisGraphQLLogger } from '../logging/polaris-graphql-logger';
import { IrrelevantEntitiesMiddleware } from '../middlewares/irrelevant-entities-middleware';
import { PolarisMiddleware } from '../middlewares/polaris-middleware';
import { DefaultRealitiesHolder } from '../realities-holder/default-realities-holder';
import { RealitiesHolderValidator } from '../realities-holder/realities-holder-validator';
import { PolarisGraphQLServer } from '../server/graphql-server';
import { POLARIS_TYPES } from './polaris-types';

Expand All @@ -13,4 +15,6 @@ 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).to(DefaultRealitiesHolder);
polarisContainer.bind(POLARIS_TYPES.SoftDeleteConfiguration).toConstantValue({});
2 changes: 2 additions & 0 deletions src/inversion-of-control/polaris-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ export const POLARIS_TYPES = {
InjectableType: Symbol('InjectableType'),
InjectableResolver: Symbol('InjectableResolver'),
CommonEntityInterface: Symbol('CommonEntityInterface`'),
RealitiesHolder: Symbol('RealitiesHolder'),
RealitiesHolderValidator: Symbol('RealitiesHolderValidator'),
};
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export {
buildPolarisSchema,
makeExecutablePolarisSchema,
} from './schema/utils/polaris-schema-creator';
export { RealitiesHolder } from './realities-holder/realities-holder';
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ResponseMiddlewareParams } from '../middleware';

export interface MiddlewareCondition {
shouldBeReturned(params: ResponseMiddlewareParams, isSubEntity?: boolean): boolean;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PolarisRequestHeaders } from '@enigmatis/utills';
import { PolarisContext } from '../../server/polaris-context';
import { ResponseMiddlewareParams } from '../middleware';
import { MiddlewareCondition } from './filter-condition';

class FilterRealities implements MiddlewareCondition {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ResponseMiddlewareParams } from '../middleware';
import { MiddlewareCondition } from './filter-condition';

class FilterSoftDelete implements MiddlewareCondition {
Expand Down
13 changes: 13 additions & 0 deletions src/realities-holder/default-realities-holder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { injectable } from 'inversify';
import { RealitiesHolder } from './realities-holder';

@injectable()
export class DefaultRealitiesHolder extends RealitiesHolder {
getRealities(): Set<number> {
return new Set<number>();
}

isRealitySupported(reality: number): boolean {
return true;
}
}
24 changes: 24 additions & 0 deletions src/realities-holder/realities-holder-validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UserInputError } from 'apollo-server-koa';
import { inject, injectable } from 'inversify';
import { POLARIS_TYPES } from '../inversion-of-control/polaris-types';
import { RealitiesHolder } from '../main';
import { PolarisContext } from '../server/polaris-context';

@injectable()
export class RealitiesHolderValidator {
constructor(@inject(POLARIS_TYPES.RealitiesHolder) private realitiesHolder: RealitiesHolder) {}

validateRealitySupport(context: PolarisContext) {
if (context) {
const requestedReality = context.headers.realityId;
if (
requestedReality != null &&
!this.realitiesHolder.isRealitySupported(requestedReality)
) {
throw new UserInputError(
`The requested reality-id ${requestedReality} is not supported!`,
);
}
}
}
}
10 changes: 10 additions & 0 deletions src/realities-holder/realities-holder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { injectable } from 'inversify';

@injectable()
export abstract class RealitiesHolder {
abstract getRealities(): Set<number>;

isRealitySupported(reality: number): boolean {
return this.getRealities().has(reality);
}
}
18 changes: 11 additions & 7 deletions src/server/graphql-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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 { RealitiesHolderValidator } from '../realities-holder/realities-holder-validator';
import { IrrelevantEntitiesExtension } from './irrelevant-entities-extension';
import { PolarisContext } from './polaris-context';

Expand All @@ -35,22 +36,23 @@ export class PolarisGraphQLServer implements GraphQLServer {
private polarisProperties: PolarisProperties;
private customContexts: contextCreator[] = [];
private httpServer?: http.Server;
private softDeleteConfiguration?: SoftDeleteConfiguration;

constructor(
@inject(POLARIS_TYPES.GraphQLSchema) schema: GraphQLSchema,
@inject(POLARIS_TYPES.PolarisServerConfig) propertiesConfig: PolarisServerConfig,
@multiInject(POLARIS_TYPES.Middleware) middlewares: Middleware[],
@inject(POLARIS_TYPES.GraphQLLogger) private polarisLogger: PolarisGraphQLLogger,
@inject(POLARIS_TYPES.RealitiesHolderValidator)
private realitiesHolderValidator: RealitiesHolderValidator,
@inject(POLARIS_TYPES.SoftDeleteConfiguration)
softDeleteConfiguration?: SoftDeleteConfiguration,
private softDeleteConfiguration?: SoftDeleteConfiguration,
) {
const executableSchemaWithMiddleware = applyMiddleware(
schema,
...(middlewares.map(createMiddleware) as any),
);
this.polarisProperties = propertiesConfig.polarisProperties;
this.softDeleteConfiguration = softDeleteConfiguration;

const config: Config = {
schema: executableSchemaWithMiddleware,
context: (args: { ctx: Koa.Context; connection: any }) => this.getContext(args),
Expand Down Expand Up @@ -124,19 +126,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,
Expand Down
2 changes: 2 additions & 0 deletions test/integration-tests/test-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { TestLogConfig } from './config/log-config';
import { TestMiddlewaresConfig } from './config/middleware-config';
import { TestServerConfig } from './config/server-config';
import { schema } from './schema/schema';
import { TestRealitiesHolder } from './test-realities-holder';

polarisContainer.bind(POLARIS_TYPES.LoggerConfig).to(TestLogConfig);
polarisContainer.bind(POLARIS_TYPES.PolarisServerConfig).to(TestServerConfig);
polarisContainer.bind(POLARIS_TYPES.MiddlewaresConfig).to(TestMiddlewaresConfig);
polarisContainer.bind(POLARIS_TYPES.GraphQLSchema).toConstantValue(schema);
polarisContainer.rebind(POLARIS_TYPES.RealitiesHolder).to(TestRealitiesHolder);

export class TestServer {
server: GraphQLServer;
Expand Down
9 changes: 9 additions & 0 deletions test/integration-tests/test-server/test-realities-holder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { injectable } from 'inversify';
import { RealitiesHolder } from '../../../src/realities-holder/realities-holder';

@injectable()
export class TestRealitiesHolder extends RealitiesHolder {
getRealities(): Set<number> {
return new Set<number>([0, 1, 2, 3, 4, 999]);
}
}
10 changes: 9 additions & 1 deletion test/integration-tests/tests/reality.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('reality tests', () => {
test('fetch entities with invalid reality header', async () => {
const queryBook = `query{books{title}}`;
await expect(graphQLRequest(queryBook, requestRealityIdHeader('oops'))).rejects.toThrow(
'Unable to format headers',
'"reality-id" must be a number',
);
});

Expand Down Expand Up @@ -128,4 +128,12 @@ describe('reality tests', () => {
expect(book.author).toBeNull();
}
});

test('fetch entities from unsupported reality', async () => {
const queryBook = `query{books{realityId}}`;
const realityId: number = 1337;
await expect(graphQLRequest(queryBook, requestRealityIdHeader(realityId))).rejects.toThrow(
`The requested reality-id ${realityId} is not supported!`,
);
});
});
35 changes: 35 additions & 0 deletions test/realities-holder/realities-holder-validator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'reflect-metadata';
import { PolarisContext, RealitiesHolder } from '../../src/main';
import { RealitiesHolderValidator } from '../../src/realities-holder/realities-holder-validator';

describe('realities-holder-validator tests', () => {
const polarisContextMock: { [T in keyof PolarisContext]: any } = {
headers: {
realityId: jest.fn(),
},
} as any;

test('validating supported reality', () => {
const realitiesHolderMock: { [T in keyof RealitiesHolder]: any } = {
isRealitySupported: () => true,
} as any;

const realitiesHolderValidator = new RealitiesHolderValidator(realitiesHolderMock);

expect(() => {
realitiesHolderValidator.validateRealitySupport(polarisContextMock);
}).not.toThrow();
});

test('validating unsupported reality', () => {
const realitiesHolderMock: { [T in keyof RealitiesHolder]: any } = {
isRealitySupported: () => false,
} as any;

const realitiesHolderValidator = new RealitiesHolderValidator(realitiesHolderMock);

expect(() => {
realitiesHolderValidator.validateRealitySupport(polarisContextMock);
}).toThrow();
});
});
7 changes: 7 additions & 0 deletions test/server/graphql-server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ describe('graphql-server tests', () => {
polarisProperties: jest.fn(),
} as any;
const polarisMiddlewareMock: { [T in keyof PolarisMiddleware]: any } = {} as any;
const realitiesHolderValidatorMock = {} as any;

test('creating new polaris server - with arguments - graphql apply middleware have been called', () => {
const server = new PolarisGraphQLServer(
graphQLSchemaMock,
polarisServerConfigMock,
[polarisMiddlewareMock],
polarisLog,
realitiesHolderValidatorMock,
);

expect(applyMiddleware).toHaveBeenCalled();
Expand All @@ -53,6 +55,7 @@ describe('graphql-server tests', () => {
polarisServerConfigMock,
middlewares,
polarisLog,
realitiesHolderValidatorMock,
);

expect(createMiddleware).toHaveBeenCalledTimes(middlewares.length);
Expand All @@ -64,6 +67,7 @@ describe('graphql-server tests', () => {
polarisServerConfigMock,
[polarisMiddlewareMock],
polarisLog,
realitiesHolderValidatorMock,
);

expect(ApolloServer).toHaveBeenCalled();
Expand All @@ -79,6 +83,7 @@ describe('graphql-server tests', () => {
polarisServerConfigMockWithEndpoint,
[polarisMiddlewareMock],
polarisLog,
realitiesHolderValidatorMock,
);
server.start();
expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith(
Expand All @@ -103,6 +108,7 @@ describe('graphql-server tests', () => {
polarisServerConfigMockWithEndpoint,
[polarisMiddlewareMock],
polarisLog,
realitiesHolderValidatorMock,
);
server.start(app);
expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith(
Expand All @@ -126,6 +132,7 @@ describe('graphql-server tests', () => {
polarisServerConfigMockWithEndpoint,
[polarisMiddlewareMock],
polarisLog,
realitiesHolderValidatorMock,
);
server.start(app);
expect(apolloServerMock.applyMiddleware).toHaveBeenCalledWith(
Expand Down

0 comments on commit de2fb38

Please sign in to comment.