Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw an error when a patch attempts to modify resourceType or Id #4360

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gusIreland
Copy link

This PR addresses #3888

When a resource is PATCHed and the field attempted to be updated is either id or resourceType, an error is thrown

@gusIreland gusIreland requested a review from a team as a code owner April 11, 2024 21:20
Copy link

vercel bot commented Apr 11, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
medplum-provider ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 23, 2024 0:18am
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
medplum-app ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2024 0:18am
medplum-storybook ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2024 0:18am
medplum-www ⬜️ Ignored (Inspect) Visit Preview Apr 23, 2024 0:18am

Copy link

vercel bot commented Apr 11, 2024

@gusIreland is attempting to deploy a commit to the Medplum Team on Vercel.

A member of the Team first needs to authorize it.

},
]);

expect(result.id).toEqual(patient.id);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this spec to wrap my head around the patchResource function - I copied the spec from this spec. I'm a little unclear as I thought the patch would modify the resource in place, instead of having to use and check the result object

@reshmakh reshmakh added the fhir-datastore Related to the FHIR datastore, includes API and FHIR operations label Apr 13, 2024
Comment on lines +1022 to +1027
if (patch.find((operation) => operation.path === '/resourceType')) {
throw new OperationOutcomeError(badRequest('Incorrect Resource Type'));
}
if (patch.find((operation) => operation.path === '/id')) {
throw new OperationOutcomeError(badRequest('Incorrect Id'));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer for these checks to live in updateResourceImpl(), which several different Repository methods call into, so that this issue can be prevented in depth for the future. @gusIreland If you don't mind making that change I'd appreciate it, but I'm also happy to handle it if you're short on time — let me know either way!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense! I'll update it and ping you when it's ready

if (patch.find((operation) => operation.path === '/id')) {
throw new OperationOutcomeError(badRequest('Incorrect Id'));
}

try {
const patchResult = applyPatch(resource, patch).filter(Boolean);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattwiller I moved the checks to updateResourceImpl(), but my new spec fails with a validation error(Invalid additional property) from the applyPatch function, which gets called before updateResourceImpl().

Would it make sense to have checks at both levels? One to check that the patch call is valid, and another at the updateResourceImpl to prevent the issue in depth

Comment on lines +512 to +517
if (resource.resourceType !== resourceType) {
throw new OperationOutcomeError(badRequest('Incorrect resource type'));
}
if (resource.id !== id) {
throw new OperationOutcomeError(badRequest('Incorrect ID'));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks can never fail:

const { resourceType, id } = resource; // <-- resourceType and id come from resource
// ...
if (resource.resourceType !== resourceType) { // <-- comparing back to resource must succeed
  throw new OperationOutcomeError(badRequest('Incorrect resource type'));
}
if (resource.id !== id) { // <-- same here
  throw new OperationOutcomeError(badRequest('Incorrect ID'));
}

In order to make this work correctly, the updated resourceType and id should be compared against the existing ones in a stored resource to ensure they will not be changed in the update. This might require some deeper refactoring; I can take a look in the next day or two to evaluate

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, I was trying to add some specs for that change and running into that problem - I'll start poking at it on my end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fhir-datastore Related to the FHIR datastore, includes API and FHIR operations
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

None yet

3 participants