Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
feat: Add support for GetSearchFilterBasedOnIdentity (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyen102 authored Dec 21, 2020
1 parent c6a974d commit ce1a489
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
"dependencies": {
"axios": "^0.20.0",
"fhir-works-on-aws-interface": "^4.0.0",
"fhir-works-on-aws-interface": "^6.0.0",
"jsonwebtoken": "^8.5.1"
},
"devDependencies": {
Expand Down
65 changes: 65 additions & 0 deletions src/smartHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
AllowedResourceTypesForOperationRequest,
BASE_R4_RESOURCES,
AuthorizationBundleRequest,
GetSearchFilterBasedOnIdentityRequest,
} from 'fhir-works-on-aws-interface';
import { decode } from 'jsonwebtoken';
import { SMARTHandler } from './smartHandler';
Expand Down Expand Up @@ -1002,3 +1003,67 @@ describe('getAllowedResourceTypesForOperation', () => {
);
});
});

describe('getSearchFilterBasedOnIdentity', () => {
const authZHandler: SMARTHandler = new SMARTHandler(authZConfig, apiUrl, '4.0.1');
test('Patient identity', async () => {
// BUILD
const userIdentity = clone(patientIdentityWithoutScopes);
const request: GetSearchFilterBasedOnIdentityRequest = {
userIdentity,
operation: 'search-type',
};

// OPERATE, CHECK
const expectedFilter = [
{
key: '_reference',
logicalOperator: 'OR',
comparisonOperator: '==',
value: [patientId, `${apiUrl}${patientId}`],
},
];
await expect(authZHandler.getSearchFilterBasedOnIdentity(request)).resolves.toEqual(expectedFilter);
});

test('Patient identity; fhirUser hostname does not match server hostname', async () => {
// BUILD
const authZHandlerWithFakeApiUrl: SMARTHandler = new SMARTHandler(
authZConfig,
'https://fhir.server-2.com/dev/',
'4.0.1',
);

const userIdentity = clone(patientIdentityWithoutScopes);
const request: GetSearchFilterBasedOnIdentityRequest = {
userIdentity,
operation: 'search-type',
};

// OPERATE, CHECK
const expectedFilter = [
{
key: '_reference',
logicalOperator: 'OR',
comparisonOperator: '==',
value: [`${apiUrl}${patientId}`],
},
];
await expect(authZHandlerWithFakeApiUrl.getSearchFilterBasedOnIdentity(request)).resolves.toEqual(
expectedFilter,
);
});

test('Practitioner identity', async () => {
// BUILD
const userIdentity = clone(practitionerIdentityWithoutScopes);
const request: GetSearchFilterBasedOnIdentityRequest = {
userIdentity,
operation: 'search-type',
};

// OPERATE, CHECK
const expectedFilter: [] = [];
await expect(authZHandler.getSearchFilterBasedOnIdentity(request)).resolves.toEqual(expectedFilter);
});
});
23 changes: 23 additions & 0 deletions src/smartHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
FhirVersion,
BASE_STU3_RESOURCES,
BulkDataAuth,
GetSearchFilterBasedOnIdentityRequest,
SearchFilter,
} from 'fhir-works-on-aws-interface';
import axios from 'axios';
import {
Expand Down Expand Up @@ -143,6 +145,27 @@ export class SMARTHandler implements Authorization {
}
}

async getSearchFilterBasedOnIdentity(request: GetSearchFilterBasedOnIdentityRequest): Promise<SearchFilter[]> {
const fhirUser = this.getFhirUser(request.userIdentity);
const { hostname, resourceType, id } = fhirUser;

// Create a SearchFilter to limit access to only resources that are referring to the requesting user
if (resourceType !== 'Practitioner') {
const searchFilter: SearchFilter = {
key: '_reference',
value: [`${hostname}${resourceType}/${id}`],
comparisonOperator: '==',
logicalOperator: 'OR', // logicalOperator can be either 'AND' or 'OR' since value is an array of one string
};
if (hostname === this.apiUrl) {
searchFilter.value = [`${resourceType}/${id}`, `${hostname}${resourceType}/${id}`];
}
return [searchFilter];
}

return [];
}

async isBundleRequestAuthorized(request: AuthorizationBundleRequest): Promise<void> {
const { scopes } = request.userIdentity;
request.requests.forEach((req: BatchReadWriteRequest) => {
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1745,10 +1745,10 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"

fhir-works-on-aws-interface@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fhir-works-on-aws-interface/-/fhir-works-on-aws-interface-4.0.0.tgz#4d857dc62a867fba596a02fd481034a94ca93ac0"
integrity sha512-7onyEoHuwd+xQoMl6OlugCSahhtrYDNgmy4tYgcsGzTpnbDhQKpDbJUizW1vrpH9t/mPstSYxsBSc1WQ0rl2EA==
fhir-works-on-aws-interface@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/fhir-works-on-aws-interface/-/fhir-works-on-aws-interface-6.0.0.tgz#e1edcd2013b4669986a22716109421bd8361fb68"
integrity sha512-TZNpvk6M8wOoLufVCJgLUFKRx83L1cx1u/7Hh2mc+zVudz/+H4EMCAIaLfXjMhdZVYK02hM2CbmcE1vBdwbudw==

figures@^3.0.0:
version "3.2.0"
Expand Down

0 comments on commit ce1a489

Please sign in to comment.