Skip to content

fix(security): surface extra_editors in dashboard/chart lists - #43392

Open
EnxDev wants to merge 1 commit into
masterfrom
enxdev/fix/dashboard-list
Open

fix(security): surface extra_editors in dashboard/chart lists#43392
EnxDev wants to merge 1 commit into
masterfrom
enxdev/fix/dashboard-list

Conversation

@EnxDev

@EnxDev EnxDev commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

SUMMARY

extra_editors — editorship a deployment grants indirectly via EXTRA_EDITORS_RESOLVER — was attached only to single-object GET responses (DashboardRestApi.get / ChartRestApi.get), never to list responses. DashboardCard, ChartCard, and the Dashboard/Chart list pages also checked editors only. Combined, a resolver-granted editor saw the Edit affordance disabled on cards/list rows even though the server's is_editor already let them save once the dashboard/chart was open — a UI-affordance gap, not an authorization bug (confirmed via raise_for_editorship/is_editor, which already union editors with the resolver output).

  • superset/security/manager.py: new get_extra_editors_by_pk batch-resolves
    extra editors for a page of rows in one query, re-querying by the primary
    keys FAB already selected (list responses only expose serialized rows to
    pre_get_list, not model instances).
  • superset/dashboards/api.py / superset/charts/api.py: a new
    pre_get_list attaches extra_editors per row, gated on
    EXTRA_EDITORS_RESOLVER being configured — zero extra cost when it isn't.
  • permissionUtils.ts's isUserEditorOrAdmin now takes an optional
    extraEditors argument; DashboardCard, ChartCard, DashboardList, and
    ChartList pass extra_editors alongside editors.
  • DatasetList is untouched — datasets never got EXTRA_EDITORS_RESOLVER
    support, so its editors-only check is already correct.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

extra_editors_before_after.mp4

TESTING INSTRUCTIONS

  • pytest tests/integration_tests/dashboards/api_tests.py -k extra_editors
    — 4 new tests: list responses omit/include extra_editors for
    dashboards and charts depending on whether EXTRA_EDITORS_RESOLVER is
    configured.
  • npm run test -- permissionUtils.test.ts — new cases for
    isUserEditorOrAdmin's extraEditors union/precedence.
  • Manually: configure EXTRA_EDITORS_RESOLVER, grant a non-editor user
    editorship on a dashboard they can view but aren't listed as an editor
    of, then confirm the dashboard list/card Edit affordance is enabled for
    them.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@dosubot dosubot Bot added authentication:access-control Rlated to access control change:backend Requires changing the backend change:frontend Requires changing the frontend labels Aug 21, 2026
@bito-code-review

bito-code-review Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6fc504

Actionable Suggestions - 0
Review Details
  • Files reviewed - 12 · Commit Range: 5aa2b45..5aa2b45
    • superset-frontend/src/dashboard/util/permissionUtils.test.ts
    • superset-frontend/src/dashboard/util/permissionUtils.ts
    • superset-frontend/src/features/charts/ChartCard.tsx
    • superset-frontend/src/features/dashboards/DashboardCard.tsx
    • superset-frontend/src/pages/ChartList/index.tsx
    • superset-frontend/src/pages/DashboardList/index.tsx
    • superset-frontend/src/types/Chart.ts
    • superset-frontend/src/views/CRUD/types.ts
    • superset/charts/api.py
    • superset/dashboards/api.py
    • superset/security/manager.py
    • tests/integration_tests/dashboards/api_tests.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@github-actions github-actions Bot added the api Related to the REST API label Aug 21, 2026
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.82%. Comparing base (05842a6) to head (5aa2b45).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #43392      +/-   ##
==========================================
- Coverage   66.84%   66.82%   -0.03%     
==========================================
  Files        2876     2876              
  Lines      164132   164257     +125     
  Branches    37875    37921      +46     
==========================================
+ Hits       109719   109764      +45     
- Misses      52238    52306      +68     
- Partials     2175     2187      +12     
Flag Coverage Δ
hive 38.09% <20.83%> (-0.05%) ⬇️
javascript 74.12% <100.00%> (-0.01%) ⬇️
mysql 57.81% <100.00%> (-0.03%) ⬇️
postgres 57.84% <100.00%> (-0.03%) ⬇️
presto 40.02% <20.83%> (-0.05%) ⬇️
python 59.27% <100.00%> (-0.03%) ⬇️
sqlite 57.53% <100.00%> (-0.03%) ⬇️
unit 100.00% <ø> (ø)

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.

Comment thread superset/charts/api.py
"""Attach ``extra_editors`` to each row, matching the single-object GET."""
super().pre_get_list(data)
ids = data.get("ids", [])
extra_editors_by_id = get_extra_editors_by_pk(Slice, ids)

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.

Suggestion: The chart list path performs one EXTRA_EDITORS_RESOLVER call for each chart returned by the page through get_extra_editors_by_pk. This multiplies resolver latency with page size and propagates any resolver exception as a list-request failure, unlike the previous list behavior. Use a bounded or batch-aware resolution strategy, or handle per-chart resolver failures without aborting the entire response. [performance]

Severity Level: Major ⚠️
- ⚠️ Configured chart lists incur resolver work per returned chart.
- ❌ Resolver failure can make chart listings return an API error.
- ⚠️ Large chart pages amplify custom resolver latency.

Use CodeAnt Skill

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/charts/api.py
**Line:** 420:420
**Comment:**
	*Performance: The chart list path performs one `EXTRA_EDITORS_RESOLVER` call for each chart returned by the page through `get_extra_editors_by_pk`. This multiplies resolver latency with page size and propagates any resolver exception as a list-request failure, unlike the previous list behavior. Use a bounded or batch-aware resolution strategy, or handle per-chart resolver failures without aborting the entire response.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

"""Attach ``extra_editors`` to each row, matching the single-object GET."""
super().pre_get_list(data)
ids = data.get("ids", [])
extra_editors_by_id = get_extra_editors_by_pk(Dashboard, ids)

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.

Suggestion: The list endpoint now invokes EXTRA_EDITORS_RESOLVER once for every dashboard in the page through get_extra_editors_by_pk. A resolver that performs I/O or is computationally expensive therefore turns a single list request into one resolver execution per row, multiplying latency and potentially causing the entire listing to fail if any resolver invocation raises. Use a bounded or batch-aware resolution strategy, or isolate resolver failures so one problematic resource does not break the whole list response. [performance]

Severity Level: Major ⚠️
- ⚠️ Configured dashboard lists incur resolver work per row.
- ❌ Resolver failure can make dashboard listings return an API error.
- ⚠️ Large dashboard pages amplify custom resolver latency.

Use CodeAnt Skill

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/dashboards/api.py
**Line:** 441:441
**Comment:**
	*Performance: The list endpoint now invokes `EXTRA_EDITORS_RESOLVER` once for every dashboard in the page through `get_extra_editors_by_pk`. A resolver that performs I/O or is computationally expensive therefore turns a single list request into one resolver execution per row, multiplying latency and potentially causing the entire listing to fail if any resolver invocation raises. Use a bounded or batch-aware resolution strategy, or isolate resolver failures so one problematic resource does not break the whole list response.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@villebro villebro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not familiar with this implementation detail, but I think I understand the logic and the fix here.

@sha174n sha174n 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.

Reviewed this as a consistency fix rather than an authorization change: server-side is_editor/raise_for_editorship already union editors with the resolver output, so this only surfaces extra_editors on list responses and unions it into the client-side edit affordance, granting no new capability. It is also not a new exposure, since the single-object GET already returns extra_editors to anyone who can GET the object and list rows are access-filtered to that same audience; get_extra_editors_by_pk scopes its re-query to the page's already-filtered ids, so skipping the visibility filter avoids double-filtering without widening the set. Whole path is gated on EXTRA_EDITORS_RESOLVER, so stock deployments are unaffected. One nit: pre_get_list pairs rows via zip(result, ids), which relies on FAB keeping those aligned; a brief comment noting that assumption would help. LGTM once rebased on master (currently conflicting only because master moved in the same files).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API authentication:access-control Rlated to access control change:backend Requires changing the backend change:frontend Requires changing the frontend size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants