Skip to content

Commit

Permalink
Merge pull request #49 from microsoft/v0.4.4
Browse files Browse the repository at this point in the history
Add support for spec v0.4.4
  • Loading branch information
christianpaquin committed Apr 15, 2021
2 parents adb57c5 + 76c3a15 commit c6c000b
Show file tree
Hide file tree
Showing 9 changed files with 10,410 additions and 314 deletions.
10,403 changes: 10,111 additions & 292 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 13 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "health-cards-validation-sdk",
"version": "0.4.3",
"version": "0.4.4-1",
"description": "",
"main": "js/src/shc-validator.js",
"scripts": {
Expand All @@ -15,19 +15,18 @@
"author": "",
"license": "MIT",
"dependencies": {
"ajv": "^7.1.1",
"ajv": "^8.1.0",
"bmp-js": "^0.1.0",
"canonicalize": "^1.0.5",
"canvas": "^2.6.1",
"canvas": "^2.7.0",
"colors": "^1.4.0",
"commander": "^7.1.0",
"commander": "^7.2.0",
"execa": "^5.0.0",
"file-type": "^16.2.0",
"file-type": "^16.3.0",
"gm": "^1.23.1",
"got": "^11.8.2",
"istextorbinary": "^5.12.0",
"jimp": "^0.16.1",
"jpeg-js": "^0.4.2",
"jpeg-js": "^0.4.3",
"json-beautify": "^1.1.1",
"jsqr": "^1.3.1",
"node-jose": "^2.0.0",
Expand All @@ -39,21 +38,21 @@
"devDependencies": {
"@types/bmp-js": "^0.1.0",
"@types/gm": "^1.18.9",
"@types/jest": "^26.0.20",
"@types/node": "^14.14.31",
"@types/jest": "^26.0.22",
"@types/node": "^14.14.39",
"@types/node-jose": "^1.1.5",
"@types/pako": "^1.0.1",
"@types/pngjs": "^6.0.0",
"@types/qrcode": "^1.4.0",
"@types/semver": "^7.3.4",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"eslint": "^7.20.0",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"eslint": "^7.24.0",
"jest": "^26.6.3",
"qrcode": "^1.4.4",
"ts-jest": "^26.5.2",
"ts-jest": "^26.5.4",
"ts-node": "^9.1.1",
"typescript": "^4.2.2"
"typescript": "^4.2.4"
}
}
15 changes: 9 additions & 6 deletions src/fhirBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,24 @@ export function validate(fhirBundleText: string): ValidationResult {
const entry = fhirBundle.entry[i];
const resource = entry.resource;

validateSchema({ $ref: 'https://smarthealth.cards/schema/fhir-schema.json#/definitions/' + resource.resourceType }, resource, log);
validateSchema({ $ref: 'https://smarthealth.cards/schema/fhir-schema.json#/definitions/' + resource.resourceType }, resource, log, ['', 'entry', i.toString(), resource.resourceType].join('/'));

if (resource == null) {
log.error("Bundle.entry[" + i.toString() + "].resource missing");
continue;
}
}

if (resource.id) {
log.warn("Bundle.entry[" + i.toString() + "].resource[" + resource.resourceType + "] should not include .id elements", ErrorCode.SCHEMA_ERROR);
}
}

if (resource.meta) {
log.warn("Bundle.entry[" + i.toString() + "].resource[" + resource.resourceType + "] should not include .meta elements", ErrorCode.SCHEMA_ERROR);
}

// resource.meta.security allowed as special case, however, no other properties may be included on .meta
if (!resource.meta.security || Object.keys(resource.meta).length > 1) {
log.warn("Bundle.entry[" + i.toString() + "].resource[" + resource.resourceType + "].meta should only include .security property with an array of identity assurance codes", ErrorCode.SCHEMA_ERROR);
}
}

if (resource.text) {
log.warn("Bundle.entry[" + i.toString() + "].resource[" + resource.resourceType + "] should not include .text elements", ErrorCode.SCHEMA_ERROR);
}
Expand Down
21 changes: 20 additions & 1 deletion src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { KeySet } from './keys';
const schemaCache: Record<string, AnyValidateFunction> = {};


export function validateSchema(schema: AnySchemaObject, data: FhirBundle | JWS | JWSPayload | HealthCard | KeySet | Resource, log: Log): boolean {
export function validateSchema(schema: AnySchemaObject, data: FhirBundle | JWS | JWSPayload | HealthCard | KeySet | Resource, log: Log, pathPrefix = ''): boolean {

// by default, the validator will stop at the first failure. 'allErrors' allows it to keep going.
const schemaId = (schema as { [key: string]: string })["$id"] || (schema as { [key: string]: string })["$ref"];
Expand Down Expand Up @@ -43,6 +43,18 @@ export function validateSchema(schema: AnySchemaObject, data: FhirBundle | JWS |
.filter((err, index) => errors.indexOf(err) === index);

errors.forEach(ve => {
//"dataPath":"/meta/security/0"

// prefix 'dataPath' property with passed in pathPrefix
// because when validating sub-schemas our paths are relative and it may
// not be apparent what the full path is when referring to common properties like 'id'
const pathPart = ve.indexOf('"dataPath":"');

if (pathPart > 0 && pathPrefix.length > 0) {
const insertIndex = pathPart + '"dataPath":"'.length;
ve = ve.slice(0, insertIndex) + pathPrefix + ve.slice(insertIndex);
}

log.error('Schema: ' + ve, ErrorCode.SCHEMA_ERROR);
});

Expand All @@ -68,8 +80,15 @@ export function objPathToSchema(path: string) : string {
for (let i = 1; i < properties.length; i++) {

if (p.properties) {

p = p.properties[properties[i]];

// this property is not valid according to the schema
if (!p) {
t = "unknown";
continue;
}

// directly has a ref, then it is that type
if (p.$ref) {
t = p.$ref.slice(p.$ref.lastIndexOf('/') + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface FhirBundle {
"entry": BundleEntry[]
}

type Resource = { resourceType: string } & Record<string, unknown>;
type Resource = { resourceType: string, meta? : {security? : unknown[]} } & Record<string, unknown>;

interface BundleEntry {
id?: string,
Expand Down
84 changes: 84 additions & 0 deletions testdata/test-example-00-a-fhirBundle-bad_meta_extra_key.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"resourceType": "Bundle",
"id": "Scenario1Bundle",
"type": "collection",
"entry": [
{
"fullUrl": "resource:0",
"resource": {
"resourceType": "Patient",
"name": [
{
"family": "Anyperson",
"given": [
"John",
"B."
]
}
],
"birthDate": "1951-01-20"
}
},
{
"fullUrl": "resource:1",
"resource": {
"resourceType": "Immunization",
"meta": {
"id": "extra meta value",
"security": [{"code": "IAL1"}]
},
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx-TEMPORARY-CODE-SYSTEM",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-01-01",
"performer": [
{
"actor": {
"display": "ABC General Hospital"
}
}
],
"lotNumber": "0000001"
}
},
{
"fullUrl": "resource:2",
"resource": {
"resourceType": "Immunization",
"meta": {
"security": [{"code": "IAL1.2"}]
},
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx-TEMPORARY-CODE-SYSTEM",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-01-29",
"performer": [
{
"actor": {
"display": "ABC General Hospital"
}
}
],
"lotNumber": "0000007"
}
}
]
}
83 changes: 83 additions & 0 deletions testdata/test-example-00-a-fhirBundle-bad_meta_non_security.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"resourceType": "Bundle",
"id": "Scenario1Bundle",
"type": "collection",
"entry": [
{
"fullUrl": "resource:0",
"resource": {
"resourceType": "Patient",
"name": [
{
"family": "Anyperson",
"given": [
"John",
"B."
]
}
],
"birthDate": "1951-01-20"
}
},
{
"fullUrl": "resource:1",
"resource": {
"resourceType": "Immunization",
"meta": {
"id": "bad-meta"
},
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx-TEMPORARY-CODE-SYSTEM",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-01-01",
"performer": [
{
"actor": {
"display": "ABC General Hospital"
}
}
],
"lotNumber": "0000001"
}
},
{
"fullUrl": "resource:2",
"resource": {
"resourceType": "Immunization",
"meta": {
"security": [{"code": "IAL1.2"}]
},
"status": "completed",
"vaccineCode": {
"coding": [
{
"system": "http://hl7.org/fhir/sid/cvx-TEMPORARY-CODE-SYSTEM",
"code": "207"
}
]
},
"patient": {
"reference": "resource:0"
},
"occurrenceDateTime": "2021-01-29",
"performer": [
{
"actor": {
"display": "ABC General Hospital"
}
}
],
"lotNumber": "0000007"
}
}
]
}

0 comments on commit c6c000b

Please sign in to comment.