Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
# Conflicts:
#	package-lock.json
  • Loading branch information
Chinlinlee committed Mar 7, 2022
2 parents a476423 + ff6c2b7 commit ac4fbf5
Show file tree
Hide file tree
Showing 85 changed files with 919 additions and 11,105 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"comma-dangle": ["error", "never"],
"no-unused-vars": "off",
"no-console": 0 ,
"no-useless-escape": "off"
"no-useless-escape": "off",
"no-useless-catch": "off"
},
"ignorePatterns": ["public/**", "temp/**", "models/FHIR/fhir/**", "docs/**"]
}
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ models/mongodb/FHIRDataTypesSchema-New
config/config.js

#ignore apidoc comment files
docs/apidoc/apidoc-sources
docs/apidoc/apidoc-sources

#ignore log files
/log
/pm2log
11 changes: 5 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
FROM keymetrics/pm2:latest-alpine


WORKDIR /
RUN mkdir -p /nodejs/fhir-burni/
WORKDIR /nodejs/fhir-burni/
# Bundle APP files
COPY package*.json /nodejs/fhir-burni/
COPY . /nodejs/fhir-burni/
COPY --chown=node:node package*.json /nodejs/fhir-burni/
COPY --chown=node:node . /nodejs/fhir-burni/

# Install app dependencies
ENV NPM_CONFIG_LOGLEVEL warn
RUN npm install
RUN npm rebuild
ENV NODE_ENV production
RUN npm ci --only=production

# Show current folder structure in logs
#RUN ls -al -R

USER node
CMD [ "pm2-runtime", "start", "ecosystem.config.js" ]
4 changes: 2 additions & 2 deletions api/FHIR/Patient/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const joi = require('joi');
const {
FHIRValidateParams
} = require('api/validator');
const FHIR = require('../../../models/FHIR/fhir/fhir').Fhir;
const FHIR = require('fhir').Fhir;
const {
handleError
} = require('../../../models/FHIR/httpMessage');
Expand Down Expand Up @@ -82,7 +82,7 @@ if (_.get(config, "Patient.interaction.create", true)) {
router.post('/', require('./controller/postPatient'));
}

//router.post('/([\$])validate', require('./controller/postPatientValidate'));
router.post('/([\$])validate', require('./controller/postPatientValidate'));

if (_.get(config, "Patient.interaction.update", true)) {
router.put('/:id', require("./controller/putPatient"));
Expand Down
123 changes: 23 additions & 100 deletions api/FHIRApiService/$validate.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
const _ = require('lodash');
const fetch = require('node-fetch');
const FHIR = require('../../models/FHIR/fhir/fhir').Fhir;
const fhirVersions = require('../../models/FHIR/fhir/fhir').Versions;
const ParseConformance = require('../../models/FHIR/fhir/parseConformance').ParseConformance;
const { handleError, issue, OperationOutcome } = require('../../models/FHIR/httpMessage');
const { getDeepKeys } = require('../apiService');
const FHIR = require('fhir').Fhir;
const { handleError } = require('../../models/FHIR/httpMessage');
const { validateByProfile, validateByMetaProfile } = require('../../models/FHIR/fhir-validator');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

/**
*
* @param {import('express').Request} req
Expand All @@ -21,101 +22,23 @@ module.exports = async function (req, res, resourceType) {
}
return res.status(code).send(item);
};
let operationOutcomeMessage;
let query = req.query;
let resourceBody = req.body;
let profile = _.get(query, "profile");
if (profile) {
try {
let fetchProfileRes = await fetch(profile, {
headers: {
"accept": "application/fhir+json"
}
});
let profileJson = await fetchProfileRes.json();
_.set(profileJson, "id", resourceType);
let parser = new ParseConformance(true, fhirVersions.R4);

let valueSetKeys =
getDeepKeys(profileJson)
.filter(v =>
v.includes("binding.valueSet") //&&
//v.includes("snapshot")
);
let parsedValueSetsKeys = Object.keys(parser.parsedValueSets);
for (let key of valueSetKeys) {
let valueSetUri = _.get(profileJson, key);
if (!parsedValueSetsKeys.includes(valueSetUri)) {
console.log(`Get valueSet from "${valueSetUri}"`);
let valueSetRes = await fetch(valueSetUri, {
headers: {
"accept": "application/fhir+json"
}
});
let valueSetJson = await valueSetRes.json();
console.log(`Load valueSet "${valueSetJson.id}"`);
parser.parseValueSet(valueSetJson);
console.log(`Success parse valuset "${valueSetJson.id}"`);
}
}

parser.parseStructureDefinition(profileJson);
console.log(parser.parsedStructureDefinitions[resourceType]);
let fhir = new FHIR(parser);
let validation = fhir.validate(resourceBody);
if (validation.messages.length > 0) {
let issueList = [];
for (let message of validation.messages) {
let issueObj = new issue(message.severity, "processing", message.message);
_.set(issueObj, "location", [message.location]);
issueList.push(issueObj);
}
let operationOutcomeError = new OperationOutcome(issueList);
if (validation.messages.find(v => v.severity == "error")) {
operationOutcomeMessage = {
code: 412,
msg: operationOutcomeError
};
} else {
operationOutcomeMessage = {
code: 200,
msg: operationOutcomeError
};
}
} else {
let operationOutcomeInfo = handleError.informational("No issues detected during validation");
operationOutcomeMessage = {
code: 200,
msg: operationOutcomeInfo
};
}
} catch (e) {
console.error(e);
operationOutcomeMessage = {
code: 500,
msg: handleError.exception(e)
};
}
} else {
let fhir = new FHIR();
let validation = fhir.validate(resourceBody);
if (validation.messages.length > 0) {
for (let message of validation.messages) {
let issueObj = new issue(message.severity, "processing", message.message);
_.set(issueObj, "Location", [message.location]);
let operationOutcomeError = new OperationOutcome(issueObj);
operationOutcomeMessage = {
code: 412,
msg: operationOutcomeError
};
}
try {
let operationOutcomeMessage;
let profileUrl = _.get(req.query, "profile");
if (profileUrl) {
operationOutcomeMessage = await validateByProfile(profileUrl, req.body);
} else {
let operationOutcomeInfo = handleError.informational("No issues detected during validation");
operationOutcomeMessage = {
code: 200,
msg: operationOutcomeInfo
};
operationOutcomeMessage = await validateByMetaProfile(req.body);
}
let haveError = (_.get(operationOutcomeMessage, "issue")) ? operationOutcomeMessage.issue.find(v=> v.severity === "error") : false;
if (haveError) {
return doRes(412, operationOutcomeMessage);
}
return doRes(200, operationOutcomeMessage);
} catch(e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [From-File: ${PWD_FILENAME}]`);
let operationOutcomeError = handleError.exception(errorStr);
return doRes(500, operationOutcomeError);
}
return doRes(operationOutcomeMessage.code, operationOutcomeMessage.msg);
};
12 changes: 9 additions & 3 deletions api/FHIRApiService/condition-delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ const mongodb = require('models/mongodb');
const {
handleError
} = require('../../models/FHIR/httpMessage');
const FHIR = require('../../models/FHIR/fhir/fhir').Fhir;
const FHIR = require('fhir').Fhir;
const { isRealObject } = require('../apiService');
const user = require('../APIservices/user.service');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

/**
*
Expand All @@ -16,6 +19,7 @@ const user = require('../APIservices/user.service');
* @returns
*/
module.exports = async function(req, res, resourceType, paramsSearch) {
logger.info(`[Info: do condition-delete] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}] [Url-SearchParam: ${req.url}] `);
let doRes = function (code , item) {
if (res.getHeader("content-type").includes("xml")) {
let fhir = new FHIR();
Expand All @@ -25,6 +29,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
return res.status(code).send(item);
};
if (!await user.checkTokenPermission(req, resourceType, "delete")) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-File: ${PWD_FILENAME}] [From-IP: ${req.socket.remoteAddress}]`);
return doRes(403,handleError.forbidden("Your token doesn't have permission with this API"));
}
let queryParameter = _.cloneDeep(req.query);
Expand All @@ -45,7 +50,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
paramsSearch[key](queryParameter);
} catch (e) {
if (key != "$and") {
console.error(e);
logger.error(`[Error: Unknown search parameter ${key} or value ${queryParameter[key]}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [${e}]`);
return doRes(400 , handleError.processing(`Unknown search parameter ${key} or value ${queryParameter[key]}`));
}
}
Expand All @@ -59,7 +64,8 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
let info = handleError.informational(`delete successfully, deleted count : ${deletion.deletedCount}`);
return doRes(200 , info);
} catch (e) {
console.log(`api ${process.env.FHIRSERVER_APIPATH}/${resourceType}/ has error, `, e);
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
let operationOutcomeError = handleError.exception(e);
return doRes(500 , operationOutcomeError);
}
Expand Down
Loading

0 comments on commit ac4fbf5

Please sign in to comment.