From f551ff3084dd0507a6219a5c14ddd377f9868ad3 Mon Sep 17 00:00:00 2001 From: Gianmarco Pettinato Date: Sun, 26 Sep 2021 20:00:33 +0200 Subject: [PATCH] standardizide the response --- README.md | 14 +- apigreen.json | 245 ++++++++++++++++++++ src/Services/dgcVerifier/VaccineVerifier.ts | 27 ++- src/Services/dgcVerifier/Verifier.ts | 33 ++- 4 files changed, 291 insertions(+), 28 deletions(-) create mode 100644 apigreen.json diff --git a/README.md b/README.md index 6608ee7..86b8817 100644 --- a/README.md +++ b/README.md @@ -24,18 +24,18 @@ When the request is complete, the server returns a JSON object with this structu { "signature": { - "valid": true, + "valid": true }, "valid": { - "valid": true, - "message": "Certificate is valid" + "valid": true, + "message": "Certificate is valid" }, "info": { "identity": { - "fnt": "ROSSI", - "fn": "ROSSI", - "gnt": "MARIO", - "gn": "MARIO" + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" }, "dob": "1973-06-22" } diff --git a/apigreen.json b/apigreen.json new file mode 100644 index 0000000..ac169e0 --- /dev/null +++ b/apigreen.json @@ -0,0 +1,245 @@ +{ + "openapi": "3.0.0", + "info": { + "contact": { + "name": "Gianmarco Pettianto", + "email": "gianmarco@pettinato.eu", + "url": "jatus.tech" + }, + "description": "Endpoint for DGC server", + "title": "green", + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost:3000" + } + ], + "paths": { + "/api/green": { + "post": { + "tags": [], + "summary": "Sends a request of testing", + "operationId": "post-certificate", + "description": "Checks the greenpass raw data", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Valid-response" + }, + "examples": { + "Valid certificate response": { + "value": { + "signature": { + "valid": true + }, + "valid": { + "valid": true, + "message": "Certificate is valid" + }, + "info": { + "identity": { + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" + }, + "dob": "1973-06-22" + } + } + }, + "expired certificate": { + "value": { + "signature": { + "valid": true + }, + "valid": { + "valid": false, + "message": "Certificate is not valid" + }, + "info": { + "identity": { + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" + }, + "dob": "1973-06-22" + } + } + }, + "Certificate not yet valid": { + "value": { + "signature": { + "valid": true + }, + "valid": { + "valid": false, + "message": "Certificate is not valid yet" + }, + "info": { + "identity": { + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" + }, + "dob": "1973-06-22" + } + } + }, + "Invalid signature": { + "value": { + "signature": { + "valid": false + }, + "valid": { + "valid": false, + "message": "Certificate is not valid yet" + }, + "info": { + "identity": { + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" + }, + "dob": "1973-06-22" + } + } + }, + "Invalid certificate": { + "value": { + "signature": { + "valid": false + }, + "valid": { + "valid": false, + "message": "" + }, + "info": { + "identity": { + "fnt": "", + "fn": "", + "gnt": "", + "gn": "" + }, + "dob": "" + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Valid-response": { + "description": "", + "type": "object", + "x-examples": { + "example-1": { + "signature": { + "valid": true + }, + "valid": { + "valid": true, + "message": "Certificate is valid" + }, + "info": { + "identity": { + "fnt": "ROSSI", + "fn": "ROSSI", + "gnt": "MARIO", + "gn": "MARIO" + }, + "dob": "1973-06-22" + } + } + }, + "properties": { + "signature": { + "type": "object", + "required": [ + "valid" + ], + "properties": { + "valid": { + "type": "boolean" + } + } + }, + "valid": { + "type": "object", + "required": [ + "valid", + "message" + ], + "properties": { + "valid": { + "type": "boolean" + }, + "message": { + "type": "string", + "minLength": 1 + } + } + }, + "info": { + "type": "object", + "required": [ + "identity", + "dob" + ], + "properties": { + "identity": { + "type": "object", + "required": [ + "fnt", + "fn", + "gnt", + "gn" + ], + "properties": { + "fnt": { + "type": "string", + "minLength": 1 + }, + "fn": { + "type": "string", + "minLength": 1 + }, + "gnt": { + "type": "string", + "minLength": 1 + }, + "gn": { + "type": "string", + "minLength": 1 + } + } + }, + "dob": { + "type": "string", + "minLength": 1 + } + } + } + }, + "required": [ + "signature", + "valid", + "info" + ] + } + } + } +} \ No newline at end of file diff --git a/src/Services/dgcVerifier/VaccineVerifier.ts b/src/Services/dgcVerifier/VaccineVerifier.ts index 176cbba..7fe9582 100644 --- a/src/Services/dgcVerifier/VaccineVerifier.ts +++ b/src/Services/dgcVerifier/VaccineVerifier.ts @@ -2,7 +2,7 @@ import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; -interface checkResult { +export interface CheckResult { valid: boolean; message: string; } @@ -26,7 +26,7 @@ export class VaccineVerifier { settings=[]; certTypes=['r','v','t',] - private checkVaccine = (payload:any):checkResult => { + private checkVaccine = (payload:any):CheckResult => { const inoculationDate = dayjs(payload.dt); const validRulesSet = this.getRulesSet(payload.mp); const vaccineDiff = payload.sd - payload.dn; @@ -40,17 +40,17 @@ export class VaccineVerifier { } } - private checkRecovery = (payload:any):checkResult => { + private checkRecovery = (payload:any):CheckResult => { const now = dayjs(); const dateFrom = dayjs(payload.df); const dateEnd = dayjs(payload.du); if(now.isAfter(dateFrom) && now.isBefore(dateEnd)){ return{valid:true, message:'Certificate is valid'}; } - return {valid:false, message:'toimplement'}; + return {valid:false, message:'Certificate is not valid'}; } - private checkTest = (payload:any):checkResult => { + private checkTest = (payload:any):CheckResult => { const validRulesSet = this.getRulesSet('GENERIC'); const testType = payload.tt; if(payload.tr === this.positiveTest) @@ -77,10 +77,9 @@ export class VaccineVerifier { this.settings = settings; } - public checkCertifcate(pass:unknown):checkResult { - console.log(pass); + public checkCertifcate(pass:unknown):CheckResult { const certificateDataAndType = this.getCertificateData(pass); - const result: checkResult = this.functionSelector[certificateDataAndType.key](certificateDataAndType.certificateData); + const result: CheckResult = this.functionSelector[certificateDataAndType.key](certificateDataAndType.certificateData); return result; } @@ -103,25 +102,25 @@ export class VaccineVerifier { }); } - private getLogicValidityDays(validRulesSet:unknown[],startKey:string, endKey:string, inoculationDate: dayjs.Dayjs): checkResult { + private getLogicValidityDays(validRulesSet:unknown[],startKey:string, endKey:string, inoculationDate: dayjs.Dayjs): CheckResult { const now = dayjs(); const ruleStart = validRulesSet.find((elem:any)=>{return elem.name == startKey;}); const ruleEnd = validRulesSet.find((elem:any)=>{return elem.name == endKey;}); const startValidity = inoculationDate.add(parseInt(ruleStart['value']),'days'); const endValidity = inoculationDate.add(parseInt(ruleEnd['value']),'days'); - if(startValidity.isAfter(now)) return {valid:false, message:'Certificate not yet valid'}; - if(now.isAfter(endValidity)) return {valid:false, message:'Certificate not more valid'}; + if(startValidity.isAfter(now)) return {valid:false, message:'Certificate is not valid yet'}; + if(now.isAfter(endValidity)) return {valid:false, message:'Certificate is not valid'}; return {valid:true, message:'Certificate is valid'}; } - private getLogicValidityHours(validRulesSet:unknown[],startKey:string, endKey:string, inoculationDate: dayjs.Dayjs): checkResult { + private getLogicValidityHours(validRulesSet:unknown[],startKey:string, endKey:string, inoculationDate: dayjs.Dayjs): CheckResult { const now = dayjs(); const ruleStart = validRulesSet.find((elem:any)=>{return elem.name == startKey;}); const ruleEnd = validRulesSet.find((elem:any)=>{return elem.name == endKey;}); const startValidity = inoculationDate.add(parseInt(ruleStart['value']),'hours'); const endValidity = inoculationDate.add(parseInt(ruleEnd['value']),'hours'); - if(startValidity.isAfter(now)) return {valid:false, message:'Certificate not yet valid'}; - if(now.isAfter(endValidity)) return {valid:false, message:'Certificate not more valid'}; + if(startValidity.isAfter(now)) return {valid:false, message:'Certificate is not valid yet'}; + if(now.isAfter(endValidity)) return {valid:false, message:'Certificate is not valid'}; return {valid:true, message:'Certificate is valid'}; } diff --git a/src/Services/dgcVerifier/Verifier.ts b/src/Services/dgcVerifier/Verifier.ts index 811e8c1..60a2ddf 100644 --- a/src/Services/dgcVerifier/Verifier.ts +++ b/src/Services/dgcVerifier/Verifier.ts @@ -1,8 +1,23 @@ import { CertificateDownloader } from '../SettingsDownloader/CertificateDownloader'; import { RuleDownloader } from '../SettingsDownloader/RuleDownloader'; -import { VaccineVerifier } from './VaccineVerifier'; +import { CheckResult, VaccineVerifier } from './VaccineVerifier'; import {DCC} from 'dcc-utils'; import jsrsasign from 'jsrsasign'; +interface certificateResponse { + signature:{ + valid: boolean + }, + valid:CheckResult, + info:{ + identity:{ + fnt:string, + fn:string, + gnt:string, + gn:string + }, + dob:string + } +} export default class Verifier { static instance: Verifier|undefined = undefined; private certDownloader: CertificateDownloader; @@ -22,12 +37,16 @@ export default class Verifier { return Verifier.instance; } - async checkCertificate(certificate:string): Promise{ - const dcc = await DCC.fromRaw(certificate); - let result:unknown = {}; - result = await (await this.checkKey(dcc)).valid; - const vaccineVerifier = new VaccineVerifier(await this.ruleDownloader.getRules()); - result = {signature: result, valid: vaccineVerifier.checkCertifcate(dcc.payload), info:{identity:dcc.payload.nam,dob:dcc.payload.dob}}; + async checkCertificate(certificate:string): Promise{ + let result:certificateResponse = {signature:{valid: false}, valid:{valid:false, message:''}, info:{identity:{fnt:'',fn:'',gnt:'',gn:''},dob:''}}; + try { + const dcc = await DCC.fromRaw(certificate); + const signatureValidity = (await this.checkKey(dcc)).valid; + const vaccineVerifier = new VaccineVerifier(await this.ruleDownloader.getRules()); + result = {signature:{valid: signatureValidity}, valid: vaccineVerifier.checkCertifcate(dcc.payload), info:{identity:dcc.payload.nam,dob:dcc.payload.dob}}; + } catch (error) { + console.log(error); + } return result; }