Migrate Social Diagram reads to secured /api/v3/individuals/info/social-data#1635
Open
JasonWildMe wants to merge 13 commits into
Open
Migrate Social Diagram reads to secured /api/v3/individuals/info/social-data#1635JasonWildMe wants to merge 13 commits into
JasonWildMe wants to merge 13 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… rel _id, partner resolution, dataTypes) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…per-companion-encounter ACL) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends MarkedIndividualInfo to handle args[2]=="social-data": - 401 for anonymous callers (statusCode now included in 401 body) - 400 for blank/missing id - 404 for unknown individual - 403 when canUserView returns false (collaborationSecurityEnabled) - 200 with empty encounters/relationships arrays for viewable individual Adds MarkedIndividualInfoTest: Testcontainers Postgres + MockedConstruction pattern with real ACL evaluation (canUserView drives real MarkedIndividual + Encounter + Collaboration data against live test DB). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Types Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each encounter row in the social-data response now includes `occurringWith`: a ", "-joined display string of co-occurring individuals' displayNames, gated per-companion-encounter through encCanView (NEVER occurrence-level auth). Adds occCache Map<String,String> to avoid repeated Occurrence loads. Two new tests drive real ACL via the Testcontainers fixture: - occurringWithExcludesNonViewableCompanion (security leak guard) - occurringWithIncludesViewableCompanion Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…compatible _id - Implement relationship assembly in getSocialData: queries all Relationships for focal individual, filters out non-viewable partners, serializes each row - Partner ACL uses canUserView with per-individual boolean cache to avoid repeated JDO traversals in a single request - _id is the numeric datastore key (before the "[OID]..." suffix) so callers can roundtrip via getObjectById(Relationship.class, id) - relationshipRow falls back to name-based partner lookup when object links are unpopulated - Tests: relationshipIdRoundTripsThroughGetObjectById verifies _id resolves; relationshipToNonViewablePartnerOmitted verifies ACL filter hides partners whose encounters are owned by a non-collaborating user - Mock Shepherd in invoke() now stubs getAllRelationshipsForMarkedIndividual to delegate to the backing real Shepherd Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…jdoql + per-partner gets
…n comment Wrap dispatch+response-write in try/finally so myShepherd.rollbackDBTransaction() and closeDBTransaction() are guaranteed even if getSocialData throws mid-traversal. The 401 early-return path remains before the try block (no double-close). Reword the relationshipDatastoreId comment to accurately describe what the test verifies: bare-key round-trip only, not the full edit/remove _id+[OID] form. Co-Authored-By: Claude Sonnet 4.6 <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
Migrates the legacy
individuals.jspSocial Diagram read paths onto a single new, access-controlled/api/v3endpoint, and rewrites the diagram's JavaScript to use it. The Social Diagram previously fetched its encounter table, relationship table, and per-partner details through the generic DataNucleus REST servlet (/api/jdoql,/api/{class}/{id}), which is unsuitable for entities with bidirectional relationships and does not apply Wildbook's collaboration/role access control. Loading the diagram for an individual could fail outright and could surface data without the usual view checks.Scope: reads only. Relationship writes (add/edit/remove) and the bubble-graph data feed intentionally remain on the existing path and are untouched.
New endpoint
GET /api/v3/individuals/info/social-data?id={individualId}— a new branch inorg.ecocean.api.MarkedIndividualInfo. Noweb.xmlchange, no OpenSearch serializer change.Access control enforced server-side:
401; individual not viewable by the caller →403.Encounter.canUserView).Response carries everything the two tables need in one round-trip (no per-partner fan-out). The relationship
_idis the same datastore-identity value the prior API emitted, so the retained (legacy) edit/remove buttons keep resolving the correct row.JavaScript
encounter-calls.js:getEncounterTableDataandgetRelationshipTableDatanow read the single new endpoint; the per-partner lookup helper is removed. Render logic and the edit/remove buttons are unchanged. (The file is CRLF in the repo and stays CRLF — the diff is the logical change only.)Tests
MarkedIndividualInfoTest(JUnit 5 + Testcontainers, real ACL): per-encounter visibility filtering, the individual-level gate, co-occurrence companion filtering, relationship partner filtering, the relationship_idround-trip,dataTypesprecedence, status codes, and a large-individual case exercising the memoized assembly paths. 12/12 green; module compiles.Stacking / sequencing
This branch is stacked on
fix/api-v3-individuals-get(PR #1633) — it relies onMarkedIndividual.canUserViewintroduced there — and is opened with that branch as its base so the diff is feature-only. Merge after #1633, or retarget tomainonce #1633 lands.Follow-ups (not in this PR)
selfRole/partnerRoleto remove a client-side identifier comparison (robustness; current behavior preserved from the prior implementation).Design + plan:
docs/superpowers/specs/2026-06-24-social-diagram-api-v3-reads-design.md,docs/superpowers/plans/2026-06-24-social-diagram-api-v3-reads.md.🤖 Generated with Claude Code