Skip to content

fix(resource, computing-unit): keep owners' full access to their datasets, models and computing units - #8890

Merged
kunwp1 merged 10 commits into
apache:mainfrom
tanishqgandhi1908:fix/owner-access-guard
Oct 27, 2026
Merged

kunwp1 merged 10 commits into
apache:mainfrom
tanishqgandhi1908:fix/owner-access-guard

Conversation

@tanishqgandhi1908

@tanishqgandhi1908 tanishqgandhi1908 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Datasets, models and computing units each record their owner, plus a separate access list. Two problems:

Any WRITE collaborator could change or remove the owner’s own access entry.
Several places decided what a user sees from the access list alone, so a changed or missing entry hid the resource from its owner or gave them read-only controls.

This PR:

  1. Refuses to change or revoke the owner’s access (403, the same message workflows use), for datasets, models and computing units.
  2. Treats the owner as WRITE wherever access is read, whatever their access entry says:
  • ResourceAccess.privilegeOf, used by the dataset and model detail pages.

  • listVisible (Datasets and Models lists) and ownerEmailsVisibleTo (owner filter).

  • Unified search: its filter and VersionedResourceTables.hydrate.

  • getComputingUnitInfo. A planted READ row could disable Run for the owner.

  • Hub and search cards: entryLink sends the owner to the private page even without an access row.

Owners whose entry was already damaged are fixed by this, with no migration.

  1. Hides a leftover owner row from the computing-unit access list, and refuses that list (403) to a user who can't see the unit.
  2. Hub top cards (fetchDashboardVersionedResourcesByIds) now carry only the viewer's own privilege, not another user's.

The owner rule and the "can't change the owner" guard live in one helper, OwnerAccess in common/auth; its granted argument is by-name, so the owner skips the access-row query.

Workflows are out of scope: their sharing already refuses to change the owner's row, and moving their read paths to the same owner rule is tracked in #9150.

Before: a WRITE collaborator shares the dataset with the owner as READ, and the owner loses the Settings tab, delete button and upload panel:

before-2-collab-shares-owner-read before-4-owner-after

After: the same share is refused, and the owner's page is unchanged:

after-1-share-refused after-2-owner-keeps-access

Any related issues, documentation, discussions?

Closes #8889

How was this PR tested?

New ResourceAccessSpec in common/resource, covering the owner’s privilege, lists, owner filter, and the grant/revoke guard. The module gets DAO % "test->test" and a test-only jersey-common dependency for this.
New OwnerAccessSpec in common/auth, and new cases in DatasetSearchQueryBuilderSpec, HubResourceSpec, ComputingUnitAccessResourceSpec, ComputingUnitManagingResourceSpec and the frontend resource-registry.service.spec.ts.
All new tests fail without the change.
DatasetResourceSpec’s orphan-dataset test now uses another user’s public dataset, so it still exercises the public-list path.

sbt "Auth/testOnly *OwnerAccessSpec" "Resource/test" \
    "ComputingUnitManagingService/testOnly *ComputingUnitAccessResourceSpec *ComputingUnitManagingResourceSpec" \
    "FileService/testOnly *DatasetAccessResourceSpec *ModelAccessResourceSpec *DatasetResourceSpec" \
    "WorkflowExecutionService/testOnly *DatasetSearchQueryBuilderSpec *HubResourceSpec"
cd frontend && yarn ng test --watch=false --include='**/resource-registry.service.spec.ts'

Also checked against a local stack: sharing a dataset with its owner as READ is refused, and DELETE /api/access/dataset/revoke/{did}/{ownerEmail} returns 403.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 5.5)

@github-actions github-actions Bot added fix common platform Non-amber Scala service paths labels Oct 7, 2026
@Yicong-Huang Yicong-Huang added release/v1.3 back porting to release/v1.3 release/v1.2 back porting to release/v1.2 labels Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @aglinxinyuan, @Ma77Ball, @eugenegujing
    You can notify them by mentioning @aglinxinyuan, @Ma77Ball, @eugenegujing in a comment.

@github-actions
github-actions Bot requested review from mengw15 and xuang7 October 7, 2026 03:59
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Backport auto-label report

This fix: PR was checked against each actively-supported release branch. A release/* label nominates a backport target; the branch's release manager approving this PR is what sends the fix there. The required Backport Approvals check stays red until every label below is approved, so each manager either approves or removes their own label — which is why the labels left on a merged PR are exactly the branches it reached.

Release branch Analysis
✅ release/v1.3 Already labeled — this fix is queued to backport here. @mengw15 decides: approving sends the fix here, removing this label declines it. The merge waits on one or the other.
✅ release/v1.2 Already labeled — this fix is queued to backport here. @xuang7 decides: approving sends the fix here, removing this label declines it. The merge waits on one or the other.

Auto-label run.

@codecov-commenter

codecov-commenter commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.94%. Comparing base (d70fc72) to head (4000f74).

Files with missing lines Patch % Lines
...pache/texera/service/resource/ResourceAccess.scala 81.81% 0 Missing and 2 partials ⚠️
...b/resource/dashboard/VersionedResourceTables.scala 66.66% 0 Missing and 1 partial ⚠️
...exera/web/resource/dashboard/hub/HubResource.scala 75.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8890      +/-   ##
============================================
+ Coverage     91.74%   91.94%   +0.20%     
- Complexity     5078     5081       +3     
============================================
  Files          1279     1280       +1     
  Lines         55638    55563      -75     
  Branches       7051     7048       -3     
============================================
+ Hits          51044    51088      +44     
+ Misses         2855     2733     -122     
- Partials       1739     1742       +3     
Flag Coverage Δ *Carryforward flag
access-control-service 77.44% <ø> (ø)
agent-service 99.14% <ø> (-0.02%) ⬇️ Carriedforward from 3b8e43e
amber 86.36% <85.71%> (+0.57%) ⬆️
computing-unit-managing-service 61.81% <100.00%> (-0.03%) ⬇️
config-service 87.50% <ø> (ø)
file-service 82.29% <ø> (ø)
frontend 96.52% <100.00%> (+<0.01%) ⬆️
notebook-migration-service 83.77% <ø> (ø)
pyamber 98.54% <ø> (ø) Carriedforward from 3b8e43e
workflow-compiling-service 74.25% <ø> (ø)

*This pull request uses carry forward flags. 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:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 0 better · 🔴 8 worse · ⚪ 7 noise (<±5%) · 0 without baseline

Compared against main d70fc72 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 336 0.205 30,651/38,108/38,108 us 🔴 +33.5% / 🔴 +211.7%
🔴 bs=100 sw=10 sl=64 812 0.496 122,971/145,136/145,136 us 🔴 +5.4% / 🔴 +66.5%
🔴 bs=1000 sw=10 sl=64 939 0.573 1,055,870/1,258,152/1,258,152 us 🔴 +14.7% / 🔴 +53.8%
Baseline details

Latest main d70fc72 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 336 tuples/sec 393 tuples/sec 1,019 tuples/sec -14.5% -67.0%
bs=10 sw=10 sl=64 MB/s 0.205 MB/s 0.24 MB/s 0.622 MB/s -14.6% -67.0%
bs=10 sw=10 sl=64 p50 30,651 us 22,952 us 10,144 us +33.5% +202.1%
bs=10 sw=10 sl=64 p95 38,108 us 35,489 us 12,225 us +7.4% +211.7%
bs=10 sw=10 sl=64 p99 38,108 us 35,489 us 15,527 us +7.4% +145.4%
bs=100 sw=10 sl=64 throughput 812 tuples/sec 842 tuples/sec 1,371 tuples/sec -3.6% -40.8%
bs=100 sw=10 sl=64 MB/s 0.496 MB/s 0.514 MB/s 0.837 MB/s -3.5% -40.7%
bs=100 sw=10 sl=64 p50 122,971 us 116,692 us 79,910 us +5.4% +53.9%
bs=100 sw=10 sl=64 p95 145,136 us 139,983 us 87,155 us +3.7% +66.5%
bs=100 sw=10 sl=64 p99 145,136 us 139,983 us 106,643 us +3.7% +36.1%
bs=1000 sw=10 sl=64 throughput 939 tuples/sec 953 tuples/sec 1,415 tuples/sec -1.5% -33.7%
bs=1000 sw=10 sl=64 MB/s 0.573 MB/s 0.582 MB/s 0.864 MB/s -1.5% -33.7%
bs=1000 sw=10 sl=64 p50 1,055,870 us 1,053,678 us 780,407 us +0.2% +35.3%
bs=1000 sw=10 sl=64 p95 1,258,152 us 1,096,595 us 817,814 us +14.7% +53.8%
bs=1000 sw=10 sl=64 p99 1,258,152 us 1,096,595 us 848,683 us +14.7% +48.2%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,594.88,200,128000,336,0.205,30650.65,38108.05,38108.05
1,100,10,64,20,2463.49,2000,1280000,812,0.496,122971.14,145136.23,145136.23
2,1000,10,64,20,21306.67,20000,12800000,939,0.573,1055869.90,1258152.30,1258152.30

@tanishqgandhi1908

Copy link
Copy Markdown
Contributor Author

@xuang7 or @mengw15, Can you please review the PR when possible? Thanks!

@chenlica
chenlica requested a review from kunwp1 October 12, 2026 06:00
@chenlica

Copy link
Copy Markdown
Contributor

@kunwp1 Please review this PR.

@kunwp1 kunwp1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you address the comments? Also,

  1. Can you add more test cases to make the code coverage 100%?
  2. Can you check if computing unit also has a similar issue?

@github-actions github-actions Bot added engine dependencies Pull requests that update a dependency file labels Oct 15, 2026
@tanishqgandhi1908

tanishqgandhi1908 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Can you address the comments? Also,

  1. Can you add more test cases to make the code coverage 100%?
  2. Can you check if computing unit also has a similar issue?

Thanks for the review! Addressed in 1019982:

Coverage: Codecov only counts common/resource’s own tests for this code, so I added ResourceAccessSpec there, plus tests in the search and computing-unit specs. They all fail without the change.
Computing units had the same issue. The owner’s access can no longer be changed, the unit info treats the owner as WRITE, and the access list hides a leftover owner row.

Also updated the PR description

@tanishqgandhi1908 tanishqgandhi1908 changed the title fix(resource): refuse changing or revoking the owner's access to a dataset or model fix(resource, computing-unit): keep owners' full access to their datasets, models and computing units Oct 15, 2026

@kunwp1 kunwp1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the update. My earlier points are addressed. The comments below are mostly smaller follow-ups.

…ard, and check access before listing a unit's collaborators
@tanishqgandhi1908

Copy link
Copy Markdown
Contributor Author

Thanks for the update. My earlier points are addressed. The comments below are mostly smaller follow-ups.

Thanks, Have worked on the follow ups.

@chenlica

Copy link
Copy Markdown
Contributor

@kunwp1 Can you review it again.

@kunwp1 kunwp1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the update.

  • /hub/user-access returns only the uids found in the access table, and the frontend's entryLink uses that list to choose between the private page and the hub page. An owner whose row was already removed is therefore still sent to the hub page. Including the owner's uid there or having entryLink also check entry.isOwner, would close it.
  • fetchDashboardVersionedResourcesByIds still joins every user's access row so a non-owner can be shown another user's privilege including the owner's WRITE.
  • Workflows still read privilege from the row alone.

Could these be fixed here or tracked as issues with the description narrowed to match?

Comment thread common/auth/src/main/scala/org/apache/texera/auth/util/OwnerAccess.scala Outdated
… to their own page, and scope hub cards to the viewer
@github-actions github-actions Bot added the frontend Changes related to the frontend GUI label Oct 26, 2026
@tanishqgandhi1908

Copy link
Copy Markdown
Contributor Author

Thanks for the update.

  • /hub/user-access returns only the uids found in the access table, and the frontend's entryLink uses that list to choose between the private page and the hub page. An owner whose row was already removed is therefore still sent to the hub page. Including the owner's uid there or having entryLink also check entry.isOwner, would close it.
  • fetchDashboardVersionedResourcesByIds still joins every user's access row so a non-owner can be shown another user's privilege including the owner's WRITE.
  • Workflows still read privilege from the row alone.

Could these be fixed here or tracked as issues with the description narrowed to match?

Thanks! Have fixed the current points and updated the description

  1. entryLink now also treats the entry’s owner (ownerId) as able to reach the private page.
  2. fetchDashboardVersionedResourcesByIds now limits the access join to the viewer, as search does, so a card only carries the viewer’s own privilege.
  3. Workflows: their sharing already refuses to change or remove the owner’s row, so the app can’t damage it. Moving their read paths to the same owner rule touches workflow search and access code, so I have filed Workflow privilege is read from the owner’s access row instead of ownership #9150

@kunwp1 kunwp1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks LGTM with a small comment below.

@mengw15 mengw15 removed release/v1.2 back porting to release/v1.2 release/v1.3 back porting to release/v1.3 labels Oct 26, 2026
@kunwp1
kunwp1 enabled auto-merge October 26, 2026 19:55
@kunwp1
kunwp1 added this pull request to the merge queue Oct 27, 2026
Merged via the queue into apache:main with commit bc4f3c8 Oct 27, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

common dependencies Pull requests that update a dependency file engine fix frontend Changes related to the frontend GUI platform Non-amber Scala service paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A WRITE collaborator can downgrade or remove the owner's access to a dataset or model

6 participants