Skip to content

Commit

Permalink
fix(overige-objecten-api): fix type parameter value
Browse files Browse the repository at this point in the history
  • Loading branch information
AliKdhim87 authored and Robbert committed Nov 14, 2024
1 parent cf72776 commit bbeadfb
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 11 deletions.
18 changes: 18 additions & 0 deletions apps/overige-objecten-api/src/controllers/openapi/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import request from 'supertest';
import { OpenAPI } from './types';
import app from '../../server';

describe('openAPIController', () => {
Expand All @@ -15,4 +16,21 @@ describe('openAPIController', () => {
expect(response.text).toEqual(JSON.stringify({ message: 'An unexpected error occurred.' }));
spy.mockRestore();
});
it('GET api/v2/openapi.json return 200 and json with updated type parameter schema enum contains the correct URLs', async () => {
const spy = jest
.spyOn(require('../../utils/getTheServerURL'), 'getTheServerURL')
.mockImplementation(() => 'https://example.com/');
const response = await request(app).get('/api/v2/openapi.json');
const body = response.body as OpenAPI;
expect(response.status).toBe(200);
expect(body).toBeDefined();
expect(body.paths['/objects'].get.parameters).toBeDefined();
const typeParameter = body.paths['/objects'].get.parameters.find((parameter) => parameter.name === 'type');
expect(typeParameter).toBeDefined();
expect(typeParameter?.schema.enum).toEqual([
'https://example.com/api/v2/objecttypes/kennisartikel',
'https://example.com/api/v2/objecttypes/vac',
]);
spy.mockRestore();
});
});
29 changes: 18 additions & 11 deletions apps/overige-objecten-api/src/controllers/openapi/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
/* eslint-disable no-undef */
import type { RequestHandler } from 'express';
import yaml from 'js-yaml';
import path from 'node:path';
import type { OpenAPI } from './types';
import { getTheServerURL, readFile } from '../../utils';

type Server = {
url: string;
description: string;
};

export const openAPIController: RequestHandler = async (req, res, next) => {
try {
// eslint-disable-next-line no-undef
const openapiYAML = readFile(path.join(__dirname, '../../docs/openapi.yaml'));
const url = new URL('api/v2', getTheServerURL(req)).href;
const OBJECT_TYPE_ENUM = [`${url}/objecttypes/kennisartikel`, `${url}/objecttypes/vac`];
const OPEN_API_YAML = readFile(path.join(__dirname, '../../docs/openapi.yaml'));

if (!openapiYAML) throw new Error('openapi.yaml file not found');
if (!OPEN_API_YAML) throw new Error('openapi.yaml file not found');

const openAPIDocument: any = yaml.load(openapiYAML);
const openapiServers = openAPIDocument.servers.map((server: Server) => ({
url: new URL('api/v2', getTheServerURL(req)),
const openAPIDocument = yaml.load(OPEN_API_YAML) as OpenAPI;
// Update server URLs
const openapiServers = (openAPIDocument.servers || []).map((server) => ({
url,
description: server.description,
}));
// Update enum for specific endpoint parameter
const typeParameter = openAPIDocument.paths['/objects']?.get?.parameters?.find(
(parameter) => parameter.name === 'type',
);
if (typeParameter?.schema) {
typeParameter.schema.enum = OBJECT_TYPE_ENUM;
}

res.setHeader('Content-Type', 'application/json');
res.setHeader('Access-Control-Allow-Origin', '*');
res.status(200);
Expand Down
240 changes: 240 additions & 0 deletions apps/overige-objecten-api/src/controllers/openapi/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
export interface APIInfo {
title: string;
description: string;
version: string;
}

export interface Server {
url: string;
description: string;
}

export interface OpenAPI {
openapi: string;
info: APIInfo;
servers: Server[];
paths: Paths;
components: Components;
}
export interface Paths {
'/objects': ObjectsEndpoint;
'/objects/{uuid}': ObjectByIdEndpoint;
}

export interface ObjectsEndpoint {
get: GetObjectsOperation;
}

export interface ObjectByIdEndpoint {
get: GetObjectByIdOperation;
}

export interface GetObjectsOperation {
security: Array<{ TokenAuth: any[] }>;
summary: string;
operationId: string;
parameters: Array<ParameterQuery>;
responses: {
200: ResponseListObjects;
};
}

export interface GetObjectByIdOperation {
security: Array<{ TokenAuth: any[] }>;
summary: string;
operationId: string;
parameters: Array<ParameterPath>;
responses: {
200: ResponseObjectById;
403: ErrorResponse;
404: ErrorResponse;
500: ErrorResponse;
};
}
export interface ParameterQuery {
in: 'query';
name: string;
required: boolean;
schema: { type: string; format?: string; enum?: string[] };
description: string;
}

export interface ParameterPath {
in: 'path';
name: string;
required: boolean;
schema: { type: string };
description: string;
}

export interface ResponseListObjects {
description: string;
content: {
'application/json': {
schema: ListObjectsSchema;
example: ListObjectsExample;
};
};
}

export interface ResponseObjectById {
description: string;
content: {
'application/json': {
schema: { oneOf: [{ $ref: string }, { $ref: string }] };
example: ObjectExample;
};
};
}

export interface ErrorResponse {
description: string;
content: {
'application/json': {
schema: ErrorSchema;
};
};
}

export interface ListObjectsSchema {
type: 'object';
properties: {
count: { type: 'integer'; example: number };
next: { type: 'string'; format: 'uri'; nullable: true; example: string };
previous: { type: 'string'; format: 'uri'; nullable: true; example: string | null };
results: { type: 'array'; items: { $ref: string } };
};
}

export interface ListObjectsExample {
count: number;
next: string | null;
previous: string | null;
results: ObjectData[];
}

export interface ObjectExample {
url: string;
uuid: string;
type: string;
record: ObjectRecord;
}

export interface ErrorSchema {
type: 'object';
properties: {
error: { type: 'string'; example: string };
};
}
export interface Components {
securitySchemes: {
TokenAuth: SecurityScheme;
};
schemas: {
ObjectData: ObjectData;
kennisartikel: KennisArtikel;
vac: VAC;
GeoJSONGeometry: GeoJSONGeometry;
};
}

export interface SecurityScheme {
type: 'apiKey';
in: 'header';
name: string;
}

export interface ObjectData {
url: string;
uuid: string;
type: string;
record: ObjectRecord;
}

export interface ObjectRecord {
index: number;
typeVersion: number;
data: KennisArtikel | VAC;
geometry: GeoJSONGeometry | null;
startAt: string;
endAt: string | null;
registrationAt: string;
correctionFor?: number;
correctedBy?: number;
}
export interface KennisArtikel {
url: string;
uuid: string;
upnUri: string;
publicatieDatum: string | null;
productAanwezig: boolean | null;
productValtOnder: string | null;
verantwoordelijkeOrganisatie: VerantwoordelijkeOrganisatie;
locaties?: string[] | null;
doelgroep: 'eu-burger' | 'eu-bedrijf';
afdelingen: Afdeling[];
vertalingen: Vertaling[];
beschikbareTalen: string[];
}

export interface VerantwoordelijkeOrganisatie {
url: string;
owmsIdentifier: string;
owmsPrefLabel?: string;
owmsEndDate: string;
}

export interface Afdeling {
afdelingId?: string;
afdelingNaam: string;
}

export interface Vertaling {
taal: 'nl' | 'en';
titel?: string;
tekst?: string;
procedureBeschrijving?: string;
vereisten?: string;
bezwaarEnBeroep?: string;
kostenEnBetaalmethoden?: string;
uitersteTermijn?: string;
wtdBijGeenReactie?: string;
notice?: string;
contact?: string;
deskMemo?: string;
trefwoorden?: Trefwoord[];
datumWijziging: string;
}

export interface Trefwoord {
trefwoord: string;
}

export interface VAC {
url?: string;
vraag: string;
status: 'actief' | 'non-actief' | 'te-verwijderen';
antwoord: string;
doelgroep: 'eu-burger' | 'eu-bedrijf' | 'eu-burger-bedrijf';
afdelingen: Afdeling[];
toelichting?: string;
trefwoorden?: Trefwoord[];
gerelateerdeVACs?: RelatedVAC[];
gerelateerdeProducten?: RelatedProduct[];
}

export interface RelatedVAC {
VAC: string;
}

export interface RelatedProduct {
product: string;
productNaam: string;
}

export interface GeoJSONGeometry {
type: string;
coordinates: Point2D[] | Point2D[][] | Point2D[][][];
}

export type Point2D = [number, number];

0 comments on commit bbeadfb

Please sign in to comment.