rebenitez1802 commented on PR #41606:
URL: https://github.com/apache/superset/pull/41606#issuecomment-4985005483

   Request changes: strong PR — editorship authorization, input/output 
sanitization, and the zero-owner guard are all sound and well-tested. One 
should-fix before merge (the roles tool is missing the anti-enumeration no-op 
guard its sibling deliberately implements) plus polish items.
   
   🟡 **Medium — `manage_dashboard_roles` is missing the no-op short-circuit 
that `manage_dashboard_owners` has**
   `manage_dashboard_owners` deliberately short-circuits a no-op and returns an 
*empty* `owners` list (owners tool ~L345–357) so it "cannot be used as a 
disguised directory lookup," but `manage_dashboard_roles` has no equivalent 
guard: an editor calling it with an already-assigned role commits a redundant 
write and gets the **full** current `roles` list back every time (roles tool 
~L263–336), contradicting its own docstring privacy promise (L221–226). This is 
not a capability-matrix escalation — the caller is already an editor who can 
see roles in the UI, so it's out of scope as a SECURITY.md vuln — but it breaks 
the author's own stated invariant and is the one behavioral inconsistency worth 
fixing. Fix: add the guard right after `assert new_role_ids is not None` 
(~L261), mirroring the owners tool, and add a test asserting `payload["roles"] 
== []` on a no-op:
   ```python
   if set(new_role_ids) == set(current_role_ids):
       ctx.info(f"Dashboard {dashboard.id} roles unchanged; no-op request.")
       return ManageDashboardRolesResponse(
           dashboard_url=_dashboard_url(dashboard),
           viewers_enabled=viewers_enabled,
           warnings=warnings
           + ["No effective change: requested roles already match the current 
state."],
       )
   ```
   
   🟢 **Low — Owners tool commits a redundant write on a caller self-removal 
no-op**
   When a non-admin removes only themselves, `new_owner_ids` drops the caller 
so the first no-op check (~L350) misses; `_apply_owner_change` then commits, 
and `populate_subject_list(ensure_no_lockout=True)` re-adds the caller, so the 
redundant-work is only detected at the second check (~L382) *after* the DB 
write. Result is correct, but the write is wasted. Fix: hoist the detection 
ahead of the commit, or leave a comment noting the rare path.
   
   🟢 **Low — A valid role can be rejected as "does not exist"**
   `get_or_create_user_subject` auto-creates a missing USER subject, but the 
roles path uses `subjects_from_roles`, which silently skips any role lacking a 
synced `Subject` row (`superset/subjects/utils.py:144-161`); the tool then 
reports it as `"role IDs do not exist … Use list_roles"` even though 
`list_roles` would show it. Normally mitigated by the `sync_role_subject` hooks 
and the CLI backfill, so impact is low — but the error is misleading for 
pre-sync roles and asymmetric with the owners tool.
   
   🟢 **Low — `_find_and_authorize_dashboard` / `_dashboard_url` duplicated 
across four tool files**
   The ~53-line auth helper and the URL helper are copy-pasted across 
`manage_dashboard_owners`, `manage_dashboard_roles`, 
`manage_dashboard_certification`, and `update_dashboard`, so a future fix to 
the auth flow needs four edits. Fine for this PR; Fix (follow-up ok): extract 
to a shared `dashboard/tool/` utility.
   
   🟢 **Low — New schemas use `typing.List[...]` instead of `list[...]`**
   `ManageDashboard{Owners,Roles}Request/Response` and 
`ManageDashboardCertificationResponse` use 
`List[int]`/`List[SubjectInfo]`/`List[str]` (schemas.py ~L1086, 1160, 1230, 
1280, 1425), while the file already has `from __future__ import annotations` 
and uses `list[int]` internally. Fix: `List[...]` → `list[...]` to match the 
Python 3.10+ convention for new code.
   
   🟢 **Low — Test coverage gaps on the defensive branches**
   Untested (all confirmed correct by reading, just uncovered): the 
`refresh()`-fails-after-commit warning in all three tools, the nested 
`rollback()`-also-fails path, the `dashboard.viewers` lazy-load 
`SQLAlchemyError` in the roles tool, and the `SubjectsNotFoundValidationError` 
handler in the owners tool. Each is a one-line `side_effect=SQLAlchemyError` 
mock.
   
   🟢 **Low — PR description has two stale names**
   The description says the roles response reports `dashboard_rbac_enabled` 
(code: `viewers_enabled`, gated by `ENABLE_VIEWERS`) and that the tools gate on 
`raise_for_ownership` (code: `raise_for_editorship`). The code is correct and 
consistent with `update_dashboard`; just update the PR body.
   
   🟢 **Low (informational) — Reviewed & cleared: `removed_owner_ids=[]` when a 
self-removal is auto-reverted is by design**
   Flagging this because it looks like a bug at a glance: when 
`ensure_no_lockout` re-adds a non-admin caller, `removed_owner_ids` is empty. 
The delta comment (owners tool ~L371–374) intentionally reports deltas against 
the *actual* post-resolution state so a reverted removal is "never disclosed as 
a change," and a `warnings` entry already explains the revert. Since the field 
means "actually removed," `[]` is correct — no change needed.
   
   Verified clean (no action): editorship authorization is identical to 
`update_dashboard` and enforced on every path; XSS + LLM-prompt-injection 
sanitization on cert input and all disclosed labels/text; the zero-owner guard 
and ownership-transfer flow; certification `None`/`""`/value semantics with the 
sanitize-to-empty guard; the pre-commit value-capture pattern; ASF license 
headers; and alphabetical `app.py` registration.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to