Enable GET /api/v3/individuals/{id} with proper view ACL#1633
Open
JasonWildMe wants to merge 1 commit into
Open
Enable GET /api/v3/individuals/{id} with proper view ACL#1633JasonWildMe wants to merge 1 commit into
JasonWildMe wants to merge 1 commit into
Conversation
The /api/v3/individuals/* path was already mapped to the BaseObject servlet and MarkedIndividual already overrode getById(), but the endpoint never worked: - Base.getByClassnameAndId() (the dispatch used by processGet) handled only encounters and annotations, so an individual GET fell through to return null -> 404. - MarkedIndividual did not override canUserView(User, Shepherd), so Base.jsonForApiGet()'s ACL gate used the Base default (false) and would have returned 401 for every caller even once the object resolved. Add the individuals dispatch case, add a MarkedIndividual.canUserView() that grants access to admins or users who can view at least one of the individual's encounters (no view grant for an encounter-less individual), and guard processGet against a missing id segment so /api/v3/individuals returns 404 rather than a generic 500. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Enables
GET /api/v3/individuals/{individualID}to actually resolve and return aMarkedIndividual. The URL pattern was already mapped to theBaseObjectservlet inweb.xml, andMarkedIndividualalready overridesBase.getById(...), but two pieces were missing, so the endpoint returned404(and would have returned401even once found):Base.getByClassnameAndId(...)— the dispatch switch used byBaseObject.processGet(...)— handled onlyencountersandannotations, so an individual GET fell through toreturn null→404 not found.MarkedIndividualdid not overridecanUserView(User, Shepherd).Base.jsonForApiGet(...)gates oncanUserView(...), and theBasedefault returnsfalse, so the endpoint would have returned401for every caller even after the object resolved.Why
The supported way to fetch a single individual as JSON via the modern API is this
/api/v3endpoint, which returns the sanitized OpenSearch-document representation and enforcescanUserView(...). With the wiring incomplete, there was no working/api/v3route to retrieve an individual by itsindividualID, leaving only the generic DataNucleus REST endpoint — which recursively serializes the full object graph and is unsuitable for entities with bidirectional relationships.Changes
Base.getByClassnameAndId— add theindividualscase:MarkedIndividual.canUserView(User, Shepherd)— new override. A user may view an individual if they are an admin or can view at least one of its encounters. An individual with no encounters grants no view access (it is not made visible to any logged-in user). This mirrorsEncounter.canUserView(...)and the per-encounter access loop already used for occurrences.BaseObject.processGet— require a non-empty id segment before lookup, so/api/v3/individuals(no id) returns the existing404path rather than throwing and falling through to a generic500.Behavior
MarkedIndividual.getById()→Shepherd.getMarkedIndividual(id)resolves by theindividualIDprimary key. The response flows throughBase.jsonForApiGet(...):statusCode 200statusCode 401statusCode 404Scope note
/api/v3/occurrences/*is also mapped-but-unresolved by the same switch, but is intentionally not enabled here: the occurrence view path (Collaboration.canUserViewOccurrence) currently treats a zero-encounter occurrence as viewable by any authenticated user, which warrants its own review before that route is exposed.Testing
mvn compile— clean.🤖 Generated with Claude Code