forked from finos/architecture-as-code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidation-route.ts
More file actions
78 lines (68 loc) · 2.95 KB
/
validation-route.ts
File metadata and controls
78 lines (68 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { SchemaDirectory, validate } from '@finos/calm-shared';
import { Router, Request, Response } from 'express';
import { ValidationOutcome } from '@finos/calm-shared';
import rateLimit from 'express-rate-limit';
import { initLogger, Logger } from '@finos/calm-shared/dist/logger';
export class ValidationRouter {
private schemaDirectory: SchemaDirectory;
private logger: Logger;
constructor(router: Router, schemaDirectory: SchemaDirectory, debug: boolean = false) {
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
});
this.schemaDirectory = schemaDirectory;
this.logger = initLogger(debug, 'calm-server');
router.use(limiter);
this.initializeRoutes(router);
}
private initializeRoutes(router: Router) {
router.post('/', this.validateSchema);
}
private validateSchema = async (req: Request<ValidationRequest>, res: Response<ValidationOutcome | ErrorResponse>) => {
let architecture;
try {
architecture = JSON.parse(req.body.architecture);
} catch (error) {
this.logger.error('Invalid JSON format for architecture ' + error);
return res.status(400).type('json').send(new ErrorResponse('Invalid JSON format for architecture'));
}
const schema = architecture['$schema'];
if (!schema) {
return res.status(400).type('json').send(new ErrorResponse('The "$schema" field is missing from the request body'));
}
try {
await this.schemaDirectory.loadSchemas();
} catch (error) {
this.logger.error('Failed to load schemas: ' + error);
return res.status(500).type('json').send(new ErrorResponse('Failed to load schemas'));
}
let foundSchema;
try {
foundSchema = await this.schemaDirectory.getSchema(schema);
if (!foundSchema) {
this.logger.error('Schema with $id ' + schema + ' not found');
return res.status(400).type('json').send(new ErrorResponse('The "$schema" field referenced is not available to the server'));
}
} catch (err) {
this.logger.error('Failed to load schema: ' + err);
return res.status(500).type('json').send(new ErrorResponse('Failed to load schema: ' + err));
}
try {
const outcome = await validate(architecture, foundSchema, undefined, this.schemaDirectory, true);
return res.status(201).type('json').send(outcome);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return res.status(500).type('json').send(new ErrorResponse(message));
}
};
}
class ErrorResponse {
error: string;
constructor(error: string) {
this.error = error;
}
};
interface ValidationRequest {
architecture: string;
}