Skip to content

Commit

Permalink
feat: validation when op (create, update)
Browse files Browse the repository at this point in the history
- refactor, move `getValidateResult`  into `models/FHIR/fhir-validator`
- add variable to store `user.checkTokenPermission` and
using it in condition
- remove all filename logs, because log4js already log filename
  • Loading branch information
Chinlinlee committed Apr 1, 2022
1 parent 65b90db commit 97d5414
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 88 deletions.
39 changes: 3 additions & 36 deletions api/FHIRApiService/$validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ const _ = require('lodash');
const FHIR = require('fhir').Fhir;
const mongodb = require('../../models/mongodb');
const { handleError, OperationOutcome, issue} = require('../../models/FHIR/httpMessage');
const { validateByProfile, validateByMetaProfile } = require('../../models/FHIR/fhir-validator');
const { getValidateResult } = require('../../models/FHIR/fhir-validator');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

/**
*
Expand All @@ -32,40 +31,8 @@ module.exports = async function (req, res, resourceType) {
return doRes(200, operationOutcomeMessage);
} catch(e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr}]`);
let operationOutcomeError = handleError.exception(errorStr);
return doRes(500, operationOutcomeError);
}
};

/**
*
* @param {import('express').Request} req
* @param {string} resourceType
*/
async function getValidateResult(req, resourceType) {
try {
let profileUrl = _.get(req.query, "profile");
let metaProfiles = _.get(req.body, "meta.profile", false);
if (profileUrl) {
return await validateByProfile(profileUrl, req.body);
} else if (metaProfiles) {
return await validateByMetaProfile(req.body);
}
let validation = await mongodb[resourceType].validate(req.body);
} catch(e) {
let name = _.get(e, "name");
if (name === "ValidationError") {
let operationOutcomeError = new OperationOutcome([]);
for (let errorKey in e.errors) {
let error = e.errors[errorKey];
let message = _.get(error, "message", `${error} invalid`);
let errorIssue = new issue("error", "invalid", message);
_.set(errorIssue, "Location", [errorKey]);
operationOutcomeError.issue.push(errorIssue);
}
return operationOutcomeError;
}
throw e;
}
}
};
12 changes: 6 additions & 6 deletions api/FHIRApiService/condition-delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ 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 @@ -19,7 +18,7 @@ const PWD_FILENAME = path.relative(process.cwd(), __filename);
* @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}] `);
logger.info(`[Info: do condition-delete] [Resource Type: ${resourceType}] [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 @@ -28,8 +27,9 @@ 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}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "delete")
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [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 @@ -50,7 +50,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
paramsSearch[key](queryParameter);
} catch (e) {
if (key != "$and") {
logger.error(`[Error: Unknown search parameter ${key} or value ${queryParameter[key]}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [${e}]`);
logger.error(`[Error: Unknown search parameter ${key} or value ${queryParameter[key]}] [Resource Type: ${resourceType}] [${e}]`);
return doRes(400 , handleError.processing(`Unknown search parameter ${key} or value ${queryParameter[key]}`));
}
}
Expand All @@ -65,7 +65,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
return doRes(200 , info);
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}]`);
let operationOutcomeError = handleError.exception(e);
return doRes(500 , operationOutcomeError);
}
Expand Down
28 changes: 18 additions & 10 deletions api/FHIRApiService/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ const { checkReference, getNotExistReferenceList } = require('../apiService');
const FHIR = require('fhir').Fhir;
const user = require('../APIservices/user.service');
const validateContained = require('./validateContained');
const { getValidateResult } = require('../../models/FHIR/fhir-validator.js');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

const responseFunc = {
/**
Expand All @@ -27,7 +27,7 @@ const responseFunc = {
let fullAbsoluteUrl = new URL(req.originalUrl, reqBaseUrl).href;
res.set("Location", fullAbsoluteUrl);
res.append("Last-Modified", (new Date()).toUTCString());
logger.info(`[Info: create id: ${doc.id} successfully] [Resource Type: ${resourceType}] [From-file: ${PWD_FILENAME}]`);
logger.info(`[Info: create id: ${doc.id} successfully] [Resource Type: ${resourceType}]`);
return doResCallback(201 , doc);
},
/**
Expand Down Expand Up @@ -62,7 +62,7 @@ const responseFunc = {
msg : handleError.exception(err.message)
};
}
logger.error(`[Error: ${JSON.stringify(operationOutcomeMessage)}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${JSON.stringify(operationOutcomeMessage)}] [Resource Type: ${resourceType}]`);
return doResCallback(operationOutcomeMessage.code , operationOutcomeMessage.msg);
}
};
Expand All @@ -73,7 +73,7 @@ const responseFunc = {
* @returns
*/
module.exports = async function(req, res , resourceType) {
logger.info(`[Info: do create] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}]`);
logger.info(`[Info: do create] [Resource Type: ${resourceType}] [Content-Type: ${res.getHeader("content-type")}]`);
let doRes = function (code , item) {
if (res.getHeader("content-type").includes("xml")) {
let fhir = new FHIR();
Expand All @@ -82,8 +82,9 @@ module.exports = async function(req, res , resourceType) {
}
return res.status(code).send(item);
};
if (!await user.checkTokenPermission(req, resourceType, "create")) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-File: ${PWD_FILENAME}] [From-IP: ${req.socket.remoteAddress}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "create");
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-IP: ${req.socket.remoteAddress}]`);
return doRes(403,handleError.forbidden("Your token doesn't have permission with this API"));
}
try {
Expand All @@ -95,7 +96,7 @@ module.exports = async function(req, res , resourceType) {
let validation = await validateContained(resource, index);
if (!validation.status) {
let operationOutcomeError = handleError.processing(`The resource in contained error. ${validation.message}`);
logger.error(`[Error: ${JSON.stringify(operationOutcomeError)}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${JSON.stringify(operationOutcomeError)}] [Resource Type: ${resourceType}]`);
return doRes(400, operationOutcomeError);
}
}
Expand All @@ -106,15 +107,22 @@ module.exports = async function(req, res , resourceType) {
let notExistReferenceList = getNotExistReferenceList(checkReferenceRes);
let operationOutcomeError = handleError.processing(`The reference not found : ${_.map(notExistReferenceList , "value").join(",")}`);
_.set(operationOutcomeError , "issue.0.location" , _.map(notExistReferenceList , "path"));
logger.error(`[Error: ${JSON.stringify(operationOutcomeError)}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${JSON.stringify(operationOutcomeError)}] [Resource Type: ${resourceType}]`);
return doRes(400, operationOutcomeError);
}
}
if (process.env.ENABLE_VALIDATION_WHEN_OP === "true" && process.env.ENABLE_CSHARP_VALIDATOR === "true") {
let operationOutcomeMessage = await getValidateResult(req, resourceType);
let haveError = (_.get(operationOutcomeMessage, "issue")) ? operationOutcomeMessage.issue.find(v=> v.severity === "error") : false;
if (haveError) {
return doRes(412, operationOutcomeMessage);
}
}
let [status, doc] = await doInsertData(insertData, resourceType);
return responseFunc[status](doc, req, res, resourceType, doRes);
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr})}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr})}] [Resource Type: ${resourceType}]`);
let operationOutcomeError = handleError.exception(e);
return doRes(500 , operationOutcomeError);
}
Expand All @@ -130,7 +138,7 @@ async function doInsertData(insertData , resourceType) {
return [true, doc.getFHIRField()];
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}]`);
return [false , e];
}
}
10 changes: 5 additions & 5 deletions api/FHIRApiService/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const FHIR = require('fhir').Fhir;
const user = require('../APIservices/user.service');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

const responseFunc = {
/**
Expand Down Expand Up @@ -55,7 +54,7 @@ const responseFunc = {
* @returns
*/
module.exports = async function (req, res, resourceType) {
logger.info(`[Info: do delete by id, id: ${req.params.id}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}]`);
logger.info(`[Info: do delete by id, id: ${req.params.id}] [Resource Type: ${resourceType}] [Content-Type: ${res.getHeader("content-type")}]`);
let doRes = function (code, item) {
if (res.getHeader("content-type").includes("xml")) {
let fhir = new FHIR();
Expand All @@ -64,8 +63,9 @@ module.exports = async function (req, res, resourceType) {
}
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}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "delete");
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-IP: ${req.socket.remoteAddress}]`);
return doRes(403,handleError.forbidden("Your token doesn't have permission with this API"));
}
let [status, doc] = await doDeleteData(req, resourceType);
Expand All @@ -80,7 +80,7 @@ async function doDeleteData(req, resourceType) {
}, (err, doc) => {
if (err) {
let errorStr = JSON.stringify(err, Object.getOwnPropertyNames(err));
logger.error(`[Error ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error ${errorStr}] [Resource Type: ${resourceType}]`);
return resolve([false, err]);
}
return resolve([true, doc]);
Expand Down
10 changes: 5 additions & 5 deletions api/FHIRApiService/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const { handleError } = require('../../models/FHIR/httpMessage');
const user = require('../APIservices/user.service');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

/**
* @param {import("express").Request} req
Expand All @@ -17,7 +16,7 @@ const PWD_FILENAME = path.relative(process.cwd(), __filename);
* @returns
*/
module.exports = async function(req, res, resourceType) {
logger.info(`[Info: do history-instance by id, id: ${req.params.id}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}] [Url-SearchParam: ${req.url}] `);
logger.info(`[Info: do history-instance by id, id: ${req.params.id}] [Resource Type: ${resourceType}] [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 @@ -26,8 +25,9 @@ module.exports = async function(req, res, resourceType) {
}
return res.status(code).send(item);
};
if (!await user.checkTokenPermission(req, resourceType, "history")) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-File: ${PWD_FILENAME}] [From-IP: ${req.socket.remoteAddress}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "history");
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [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 Down Expand Up @@ -65,7 +65,7 @@ module.exports = async function(req, res, resourceType) {
return doRes(200, bundle);
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr})}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr})}] [Resource Type: ${resourceType}]`);
let operationOutcomeError = handleError.exception(e);
return doRes(500, operationOutcomeError);
}
Expand Down
10 changes: 5 additions & 5 deletions api/FHIRApiService/read.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const FHIR = require('fhir').Fhir;
const user = require('../APIservices/user.service');
const { logger } = require('../../utils/log');
const path = require('path');
const PWD_FILENAME = path.relative(process.cwd(), __filename);

/**
* @param {import("express").Request} req
Expand All @@ -15,7 +14,7 @@ const PWD_FILENAME = path.relative(process.cwd(), __filename);
* @returns
*/
module.exports = async function (req , res , resourceType) {
logger.info(`[Info: do create] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}]`);
logger.info(`[Info: do create] [Resource Type: ${resourceType}] [Content-Type: ${res.getHeader("content-type")}]`);
let doRes = function (code, item) {
if (res.getHeader("content-type").includes("xml")) {
let fhir = new FHIR();
Expand All @@ -24,8 +23,9 @@ module.exports = async function (req , res , resourceType) {
}
return res.status(code).send(item);
};
if (!await user.checkTokenPermission(req, resourceType, "read")) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-File: ${PWD_FILENAME}] [From-IP: ${req.socket.remoteAddress}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "read");
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-IP: ${req.socket.remoteAddress}]`);
return doRes(403,handleError.forbidden("Your token doesn't have permission with this API"));
}
let id = req.params.id;
Expand All @@ -44,7 +44,7 @@ module.exports = async function (req , res , resourceType) {
return doRes(404, operationOutcomeError);
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}]`);
let operationOutcomeError = handleError.exception(e);
return doRes(500, operationOutcomeError);
}
Expand Down
12 changes: 6 additions & 6 deletions api/FHIRApiService/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ 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 @@ -24,7 +23,7 @@ const PWD_FILENAME = path.relative(process.cwd(), __filename);
* @returns
*/
module.exports = async function(req, res, resourceType, paramsSearch) {
logger.info(`[Info: do search] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [Content-Type: ${res.getHeader("content-type")}] [Url-SearchParam: ${req.url}]`);
logger.info(`[Info: do search] [Resource Type: ${resourceType}] [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 @@ -33,8 +32,9 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
}
return res.status(code).send(item);
};
if (!await user.checkTokenPermission(req, resourceType, "search-type")) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-File: ${PWD_FILENAME}] [From-IP: ${req.socket.remoteAddress}]`);
let hasPermission = await user.checkTokenPermission(req, resourceType, "search-type");
if (!hasPermission) {
logger.warn(`[Warn: Request token doesn't have permission with this API] [From-IP: ${req.socket.remoteAddress}]`);
return doRes(403,handleError.forbidden("token doesn't have permission with this API"));
}
let queryParameter = _.cloneDeep(req.query);
Expand All @@ -55,7 +55,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
paramsSearch[key](queryParameter);
} catch (e) {
if (key != "$and") {
logger.error(`[Error: Unknown search parameter ${key} or value ${queryParameter[key]}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}] [${e}]`);
logger.error(`[Error: Unknown search parameter ${key} or value ${queryParameter[key]}] [Resource Type: ${resourceType}] [${e}]`);
return doRes(400 , handleError.processing(`Unknown search parameter ${key} or value ${queryParameter[key]}`));
}
}
Expand Down Expand Up @@ -88,7 +88,7 @@ module.exports = async function(req, res, resourceType, paramsSearch) {
return doRes(200 , bundle);
} catch (e) {
let errorStr = JSON.stringify(e, Object.getOwnPropertyNames(e));
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}] [From-File: ${PWD_FILENAME}]`);
logger.error(`[Error: ${errorStr}] [Resource Type: ${resourceType}]`);
if (_.get(e, "code")) {
return doRes(e.code , e.operationOutcome);
}
Expand Down
Loading

0 comments on commit 97d5414

Please sign in to comment.