Skip to content

feat: add post-create resource authorship edit endpoint (DEV-6669)#4158

Open
danielasubotic wants to merge 5 commits into
feature/dev-6662-per-resource-authorshipfrom
feature/dev-6669-resource-authorship-edit
Open

feat: add post-create resource authorship edit endpoint (DEV-6669)#4158
danielasubotic wants to merge 5 commits into
feature/dev-6662-per-resource-authorshipfrom
feature/dev-6669-resource-authorship-edit

Conversation

@danielasubotic

Copy link
Copy Markdown
Contributor

Fixes DEV-6669

Stacked on #4157 (api-2, DEV-6662) — base branch is feature/dev-6662-per-resource-authorship, not main. Review/merge #4157 first, then rebase this onto main.

Motivation

api-2 (#4157) added the knora-base:hasResourceAuthorship property with read + write-on-create. This PR (api-2b) adds the post-create edit path so a resource's authorship can be changed after creation — needed by dsp-app app-3's inline authorship edit (DEV-6667). It was split out of api-2 because it has no FileValue precedent and warranted a focused, design-first PR (spec §4.B).

Summary

A new Modify-gated endpoint PUT /v2/resources/authorship that replaces a resource's authorship (an empty list clears it). Modeled end-to-end on the existing updateResourceMetadataV2 chain.

Key Changes

  • Messages (ResourceMessagesV2): UpdateResourceAuthorshipRequestV2 + UpdateResourceAuthorshipResponseV2 (with toJsonLDDocument emitting knora-api:hasResourceAuthorship + the new lastModificationDate).
  • Parser (ApiComplexV2JsonLdRequestParser): updateResourceAuthorshipRequestV2 (reuses the resourceAuthorship accessor added in api-2).
  • SPARQL (ChangeResourceAuthorshipQuery, new): mirrors ChangeResourceMetadataQuery — DELETE the old hasResourceAuthorship triples + last-mod-date, INSERT the new authorship (one triple per author) + new last-mod-date, with the same optimistic-lock lastModificationDate WHERE handling.
  • Responder (ResourcesResponderV2.updateResourceAuthorshipV2): IriLocker, class check, ensureNoConflictingChange, checkResourcePermission(_, Permission.ObjectAccess.Modify, _), run the update, verify the new last-mod-date.
  • Endpoint + wiring: putResourcesAuthorship in ResourcesEndpoints, wired through ResourcesServerEndpoints and ResourcesRestService.

Challenges and Decisions

  • Replace semantics. The endpoint sets authorship to exactly the submitted list; an empty list clears it (viewer then shows the labeled "no authorship recorded" fallback). The multi-valued DELETE binds existing values via an OPTIONAL ?oldAuthorship and re-inserts the new set.
  • Permission. Gated by Modify object-access on the resource (server-side, via the shared ResourceUtilV2.checkResourcePermission) — a non-Modify user gets 403, matching WB-2.

Gotchas

  • Inherits api-2's R2R-fixture caveat (regenerate knoraApiOntologyWithValueObjects.jsonld with the stack) since it builds on that branch.
  • This is stacked — its CI reflects api-2 + api-2b together.

Test Plan

  • Unit: ApiComplexV2JsonLdRequestParserSpecupdateResourceAuthorshipRequestV2 parses the resource IRI and the new authorship.
  • webapi/compile and webapi/Test/compile green; sbt fmt applied.
  • Follow-up (needs the Docker stack): e2e edit round-trip + non-Modify 403.

🤖 Generated with Claude Code

Adds PUT /v2/resources/authorship to replace a resource's data-side authorship after
creation, gated by Modify object-access permission. Modelled on updateResourceMetadataV2,
with a new ChangeResourceAuthorshipQuery SPARQL update. Stacked on the api-2 branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 21, 2026

Copy link
Copy Markdown

DEV-6669

@danielasubotic

Copy link
Copy Markdown
Contributor Author

Related PRs — resource-side legal metadata (R5-SC-04 / DEV-6475)

This is one of three coordinated dsp-api PRs for the feature (project fields → #4156, per-resource authorship property → #4157, edit endpoint → #4158). Downstream consumer PRs:

The api PRs deploy together; dsp-app regenerates its OpenAPI client from the deployed api and dsp-tools calls the JSON API directly. For local end-to-end testing, all three dsp-api PRs are combined on the feature/legal-metadata-resource-side-integration branch (see the LOCAL_TESTING guide).

danielasubotic and others added 2 commits June 23, 2026 15:08
The updateResourceAuthorshipRequestV2 parse test compared authorship as an
ordered Seq, but authorship is a plain multi-valued datatype property
(no rdf:List, no ORDER BY on read), so order does not round-trip through the
triplestore. Compare as an unordered set, matching the createResourceRequestV2
test fixed on the base branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 34.65347% with 66 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.80%. Comparing base (e118fa2) to head (4762925).
⚠️ Report is 1 commits behind head on feature/dev-6662-per-resource-authorship.

Files with missing lines Patch % Lines
...ra/webapi/responders/v2/ResourcesResponderV2.scala 0.00% 35 Missing ⚠️
...esponder/resourcemessages/ResourceMessagesV2.scala 0.00% 22 Missing ⚠️
.../slice/api/v2/resources/ResourcesRestService.scala 0.00% 6 Missing ⚠️
...resources/repo/ChangeResourceAuthorshipQuery.scala 88.46% 3 Missing ⚠️
Additional details and impacted files
@@                             Coverage Diff                              @@
##           feature/dev-6662-per-resource-authorship    #4158      +/-   ##
============================================================================
- Coverage                                     86.00%   85.80%   -0.21%     
============================================================================
  Files                                           539      540       +1     
  Lines                                         30539    30656     +117     
  Branches                                       3558     3554       -4     
============================================================================
+ Hits                                          26265    26304      +39     
- Misses                                         4274     4352      +78     
Flag Coverage Δ
e2e 85.80% <34.65%> (-0.21%) ⬇️
integration 85.80% <34.65%> (-0.21%) ⬇️
unit 85.80% <34.65%> (-0.21%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

danielasubotic and others added 2 commits June 25, 2026 09:50
…rsisted (DEV-6669)

The resource authorship and metadata update queries scoped the named project
graph onto only the DELETE/INSERT templates (via .from/.into) and left the WHERE
clause ungraphed. That makes the update depend on the triplestore's
union-default-graph being enabled for the WHERE to match the resource; on a
triplestore without it, the WHERE matches nothing and the whole update silently
no-ops. Use `WITH <graph>` so the named project graph applies to DELETE, INSERT
and WHERE alike, independent of the union-default-graph setting.

Also verify in the responder that the authorship was actually persisted — not
only that the lastModificationDate advanced — and fail with
UpdateNotPerformedException otherwise, so a no-op surfaces as an error instead of
a misleading 200.

Add ChangeResourceAuthorshipQuerySpec and update ChangeResourceMetadataQuerySpec
to assert the WITH form (no GRAPH wrapper).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace a double-arrow (U+21D2) and two em-dashes (U+2014) introduced in earlier
comments with `=>` and `--`, per the ASCII-only convention for src/main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant