Skip to content

Commit

Permalink
Merge pull request #48 from zeevosec/feat/return-404-for-no-resources
Browse files Browse the repository at this point in the history
feat: return a 404 when no resource is found
  • Loading branch information
zeevo committed Sep 1, 2020
2 parents bbbfb63 + 7b6a939 commit 2a65af1
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 90 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# System/IDE files
.DS_Store
.idea
.vscode

# Dependencies
node_modules
Expand Down
23 changes: 9 additions & 14 deletions packages/fhir-qb-sql/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ let formDateComparison = function(comparator, date, colName = 'value') {
/**
* Takes in a list of queries and wraps them in an $and block
*/
let buildAndQuery = function(queries) {
const buildAndQuery = function(queries) {
return { [Op.and]: queries };
};

/**
* Takes in a list of queries and wraps them in an $or block
*/
let buildOrQuery = function({ queries, invert = false }) {
const buildOrQuery = function({ queries, invert = false }) {
if (invert) {
return { [Op.not]: { [Op.or]: queries } };
} else {
Expand All @@ -68,7 +68,7 @@ let buildOrQuery = function({ queries, invert = false }) {
* Builds query to get records where the value of the field equal to the value.
* Setting invert to true will get records that are NOT equal instead.
*/
let buildEqualToQuery = function({
const buildEqualToQuery = function({
field,
value,
invert = false,
Expand All @@ -87,7 +87,7 @@ let buildEqualToQuery = function({
/**
* Builds query to get records where the value of the field is [<,<=,>,>=,!=] to the value.
*/
let buildComparatorQuery = function({
const buildComparatorQuery = function({
field,
value,
comparator,
Expand Down Expand Up @@ -116,7 +116,7 @@ let buildComparatorQuery = function({
* Builds query to get records where the value of the field is in the specified range
* Setting invert to true will get records that are NOT in the specified range.
*/
let buildInRangeQuery = function({
const buildInRangeQuery = function({
field,
lowerBound,
upperBound,
Expand Down Expand Up @@ -155,15 +155,15 @@ let buildInRangeQuery = function({
* Builds query to retrieve records where the field exists (or not).
*/
// TODO: Need to figure out how to do exist check.
let buildExistsQuery = function({ field, exists }) {
const buildExistsQuery = function(/* { field, exists } */) {
return 'NOT IMPLEMENTED';
};

/**
* Builds query to get records where the value of the field contains the value.
* Setting caseSensitive to true will cause the regex to be case insensitive
*/
let buildContainsQuery = function({ field, value, caseSensitive = false }) {
const buildContainsQuery = function({ field, value, caseSensitive = false }) {
// TODO: contains is not working as expected, like is for string matching - doublecheck this
if (caseSensitive) {
return { name: field, value: { [Op.like]: value } };
Expand All @@ -176,7 +176,7 @@ let buildContainsQuery = function({ field, value, caseSensitive = false }) {
* Builds query to get records where the value of the field starts with the value.
* Setting caseSensitive to true will cause the regex to be case insensitive
*/
let buildStartsWithQuery = function({ field, value, caseSensitive = false }) {
const buildStartsWithQuery = function({ field, value, caseSensitive = false }) {
if (caseSensitive) {
return { name: field, value: { [Op.startsWith]: value } };
} else {
Expand All @@ -188,7 +188,7 @@ let buildStartsWithQuery = function({ field, value, caseSensitive = false }) {
* Builds query to get records where the value of the field ends with the value.
* Setting caseSensitive to true will cause the regex to be case insensitive
*/
let buildEndsWithQuery = function({ field, value, caseSensitive = false }) {
const buildEndsWithQuery = function({ field, value, caseSensitive = false }) {
if (caseSensitive) {
return { name: field, value: { [Op.endsWith]: value } };
} else {
Expand Down Expand Up @@ -266,17 +266,12 @@ let applySearchResultTransformations = function({
* @returns {Array}
*/
let assembleSearchQuery = function({
joinsToPerform,
matchesToPerform,
tokenMatches,
searchResultTransformations,
implementationParameters,
includeArchived,
pageNumber,
resultsPerPage,
}) {
let query = {};
let toSuppress = {};

// Check that the necessary implementation parameters were passed through
let { archivedParamPath } = implementationParameters;
Expand Down
59 changes: 3 additions & 56 deletions packages/fhir-qb/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,6 @@ array-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=

array-uniq@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=

array-unique@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
Expand Down Expand Up @@ -712,7 +707,7 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=

chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2:
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
Expand Down Expand Up @@ -853,11 +848,6 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"

cssfilter@0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=

cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
version "0.3.8"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
Expand Down Expand Up @@ -1011,21 +1001,6 @@ domexception@^1.0.1:
dependencies:
webidl-conversions "^4.0.2"

domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
dependencies:
domelementtype "1"

domutils@^1.5.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
dependencies:
dom-serializer "0"
domelementtype "1"

dottie@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.1.tgz#697ad9d72004db7574d21f892466a3c285893659"
Expand Down Expand Up @@ -1471,18 +1446,6 @@ html-encoding-sniffer@^1.0.2:
dependencies:
whatwg-encoding "^1.0.1"

htmlparser2@^3.10.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
dependencies:
domelementtype "^1.3.1"
domhandler "^2.3.0"
domutils "^1.5.1"
entities "^1.1.1"
inherits "^2.0.1"
readable-stream "^3.1.1"

http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
Expand Down Expand Up @@ -3137,22 +3100,6 @@ sane@^4.0.3:
minimist "^1.1.1"
walker "~1.0.5"

sanitize-html@^1.20.0:
version "1.20.1"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.1.tgz#f6effdf55dd398807171215a62bfc21811bacf85"
integrity sha512-txnH8TQjaQvg2Q0HY06G6CDJLVYCpbnxrdO0WN8gjCKaU5J0KbyGYhZxx5QJg3WLZ1lB7XU9kDkfrCXUozqptA==
dependencies:
chalk "^2.4.1"
htmlparser2 "^3.10.0"
lodash.clonedeep "^4.5.0"
lodash.escaperegexp "^4.1.2"
lodash.isplainobject "^4.0.6"
lodash.isstring "^4.0.1"
lodash.mergewith "^4.6.1"
postcss "^7.0.5"
srcset "^1.0.0"
xtend "^4.0.1"

sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
Expand Down Expand Up @@ -3671,7 +3618,7 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==

util-deprecate@^1.0.1, util-deprecate@~1.0.1:
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
Expand All @@ -3697,7 +3644,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"

validator@^10.11.0, validator@^10.8.0:
validator@^10.11.0:
version "10.11.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
Expand Down
17 changes: 11 additions & 6 deletions packages/fhir-response-util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,23 @@ function read(req, res, json) {
* @description Used when you are returning a single resource of any type
* @param {Express.req} req - Express request object
* @param {Express.res} res - Express response object
* @param {Object} json - json to send to client
* @param {Object} resource - resource to send to client
*/
function readOne(req, res, json) {
function readOne(req, res, resource) {
let fhirVersion = req.params.base_version;

if (json && json.meta) {
res.set('Last-Modified', json.meta.lastUpdated);
res.set('ETag', `W/"${json.meta.versionId}"`);
if (resource && resource.meta) {
res.set('Last-Modified', resource.meta.lastUpdated);
res.set('ETag', `W/"${resource.meta.versionId}"`);
}

res.type(getContentType(fhirVersion));
res.status(200).json(json);

if (!resource) {
res.sendStatus(404);
} else {
res.status(200).json(resource);
}
}

/**
Expand Down
43 changes: 29 additions & 14 deletions packages/fhir-response-util/index.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const handler = require('./index.js');

let req = {
const req = {
protocol: 'https',
get: _prop => 'localhost:3000',
params: {
Expand All @@ -21,6 +21,10 @@ describe('FHIR Response Utility', () => {
end: end,
json: json,
})),
sendStatus: jest.fn(() => ({
end: end,
json: json,
})),
};
});

Expand All @@ -35,7 +39,7 @@ describe('FHIR Response Utility', () => {

describe('read', () => {
test('should set the correct status code', () => {
let results = { results: 'GOLD' };
const results = { results: 'GOLD' };
handler.read(req, res, results);

expect(res.type.mock.calls).toHaveLength(1);
Expand All @@ -46,7 +50,7 @@ describe('FHIR Response Utility', () => {
});

test('should invoke status().json with the results', () => {
let results = { results: 'GOLD' };
const results = { results: 'GOLD' };
handler.read(req, res, results);

expect(res.status.mock.calls).toHaveLength(1);
Expand All @@ -59,7 +63,7 @@ describe('FHIR Response Utility', () => {

describe('readOne', () => {
test('should set the correct status code', () => {
let results = { results: 'GOLD' };
const results = { results: 'GOLD' };
handler.readOne(req, res, results);

expect(res.type.mock.calls).toHaveLength(1);
Expand All @@ -69,8 +73,19 @@ describe('FHIR Response Utility', () => {
expect(res.status.mock.calls[0][0]).toBe(200);
});

test('should respond with a 404 when there is no resource', () => {
const results = undefined;
handler.readOne(req, res, results);

expect(res.type.mock.calls).toHaveLength(1);
expect(res.type.mock.calls[0][0]).toBe('application/fhir+json');

expect(res.sendStatus.mock.calls).toHaveLength(1);
expect(res.sendStatus.mock.calls[0][0]).toBe(404);
});

test('should set the E-Tag and Last-Modified headers with metadata', () => {
let results = {
const results = {
results: 'GOLD',
meta: {
lastUpdated: 'now',
Expand All @@ -96,7 +111,7 @@ describe('FHIR Response Utility', () => {

describe('create', () => {
test('should set the correct status code', () => {
let results = { id: 'foo' };
const results = { id: 'foo' };
handler.create(req, res, results, { type: 'Patient' });

expect(res.status.mock.calls).toHaveLength(1);
Expand All @@ -106,7 +121,7 @@ describe('FHIR Response Utility', () => {
});

test('should set the E-Tag and Content-Location headers with version', () => {
let results = { id: 'foo', resource_version: '1' };
const results = { id: 'foo', resource_version: '1' };
handler.create(req, res, results, { type: 'Patient' });

let expectedContentLocation =
Expand All @@ -127,7 +142,7 @@ describe('FHIR Response Utility', () => {
});

test('should set the Location header with resource location', () => {
let results = { id: 'foo' };
const results = { id: 'foo' };
handler.create(req, res, results, { type: 'Patient' });

expect(res.set.mock.calls).toHaveLength(1);
Expand All @@ -143,8 +158,8 @@ describe('FHIR Response Utility', () => {

describe('update', () => {
test('should set the correct status code', () => {
let update = { id: 'foo', created: false };
let created = { id: 'foo', created: true };
const update = { id: 'foo', created: false };
const created = { id: 'foo', created: true };
handler.update(req, res, update, { type: 'Patient' });
handler.update(req, res, created, { type: 'Patient' });

Expand All @@ -159,7 +174,7 @@ describe('FHIR Response Utility', () => {
});

test('should set the correct response headers with version', () => {
let results = { id: 'foo', resource_version: '1', created: true };
const results = { id: 'foo', resource_version: '1', created: true };
handler.update(req, res, results, { type: 'Patient' });

let expectedContentLocation =
Expand All @@ -178,7 +193,7 @@ describe('FHIR Response Utility', () => {
});

test('should set the correct Location and Last-modified headers always', () => {
let results = { id: 'foo' };
const results = { id: 'foo' };
let expectedDate = new Date().getTime();
// Number of milliseconds tolerance we want to allow
let tolerance = 60 * 1000;
Expand Down Expand Up @@ -236,7 +251,7 @@ describe('FHIR Response Utility', () => {

describe('history', () => {
test('should set the correct status code', () => {
let results = { results: 'GOLD' };
const results = { results: 'GOLD' };
handler.history(req, res, results);

expect(res.type.mock.calls).toHaveLength(1);
Expand All @@ -247,7 +262,7 @@ describe('FHIR Response Utility', () => {
});

test('should invoke status().json with the results', () => {
let results = { results: 'GOLD' };
const results = { results: 'GOLD' };
handler.history(req, res, results);

expect(res.status.mock.calls).toHaveLength(1);
Expand Down
Loading

0 comments on commit 2a65af1

Please sign in to comment.