Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(api): populate dashboard_id and slice_id in audit logs for mutation endpoints #38187#38347

Open
vikash7485 wants to merge 2 commits intoapache:masterfrom
vikash7485:fix/issue-38187-audit-log-ids
Open

fix(api): populate dashboard_id and slice_id in audit logs for mutation endpoints #38187#38347
vikash7485 wants to merge 2 commits intoapache:masterfrom
vikash7485:fix/issue-38187-audit-log-ids

Conversation

@vikash7485
Copy link

Description

Fixes #38187

dashboard_id and slice_id columns in the logs table were always
NULL for every REST API mutation endpoint (POST, PUT, DELETE). This
made audit logs useless for filtering by dashboard or chart.

Root Cause

log_with_context() in utils/log.py reads IDs from the merged HTTP
payload:

dashboard_id = to_int(payload.get("dashboard_id"))  # always None
slice_id     = to_int(payload.get("slice_id"))       # always None

collect_request_payload() only reads request.form, request.args,
and request.json body. URL path params (e.g. /api/v1/dashboard/42)
are never included, so the IDs were never captured.

Fix

Used the existing allow_extra_payload=True mechanism — already
proven working in DashboardRestApi.get — to explicitly inject
dashboard_id / slice_id into the log payload after each operation.

11 endpoints fixed across 2 files:

superset/dashboards/api.py (7 endpoints):

  • postadd_extra_log_payload(dashboard_id=new_model.id)
  • putadd_extra_log_payload(dashboard_id=changed_model.id)
  • put_filtersadd_extra_log_payload(dashboard_id=pk)
  • put_chart_customizationsadd_extra_log_payload(dashboard_id=pk)
  • put_colorsadd_extra_log_payload(dashboard_id=pk)
  • deleteadd_extra_log_payload(dashboard_id=pk) called before
    DeleteDashboardCommand.run() so the ID is captured before the row
    is gone
  • bulk_deleteadd_extra_log_payload(dashboard_ids=item_ids) stores
    the list in the json column (cannot fit multiple IDs in a single
    integer column — this is intentional)

superset/charts/api.py (4 endpoints):

  • postadd_extra_log_payload(slice_id=new_model.id)
  • putadd_extra_log_payload(slice_id=changed_model.id)
  • deleteadd_extra_log_payload(slice_id=pk) called before deletion
  • bulk_deleteadd_extra_log_payload(slice_ids=item_ids)

Also added missing Callable to the from typing import line in
charts/api.py.

Testing

Unit teststests/integration_tests/event_logger_tests.py

Added TestMutationEndpointAuditIds with 6 regression tests that mock
DBEventLogger.log and assert the correct ID is passed as a kwarg:

Test Asserts
test_dashboard_put_logs_dashboard_id dashboard_id == 42
test_dashboard_delete_logs_dashboard_id dashboard_id == 42
test_dashboard_post_logs_dashboard_id dashboard_id == 42
test_chart_put_logs_slice_id slice_id == 42
test_chart_delete_logs_slice_id slice_id == 42
test_chart_post_logs_slice_id slice_id == 42

Integration teststests/integration_tests/dashboards/api_tests.py
and tests/integration_tests/charts/api_tests.py

Added DB-level assertions that query the Log model directly after
each mutation and confirm the ID column is non-NULL:

  • test_update_dashboard → asserts log.dashboard_id == dashboard_id
  • test_delete_dashboard → asserts log.dashboard_id == dashboard_id
  • test_update_chart → asserts log.slice_id == chart_id
  • test_delete_chart → asserts log.slice_id == chart_id

SQL verification query (run after deployment):

SELECT id, action, dashboard_id, slice_id, dttm
FROM logs
ORDER BY dttm DESC
LIMIT 20;

After this fix, dashboard_id will be non-NULL for all
DashboardRestApi.* actions and slice_id will be non-NULL for all
ChartRestApi.* actions.

Checklist

  • Added unit tests
  • Added integration tests with DB-level assertions
  • Tested delete captures ID before row deletion
  • bulk_delete stores ID list in json column (documented above)
  • Callable import fix in charts/api.py
  • AST syntax check passed on all changed files
  • Full test suite run pending (requires Flask-capable environment)

@github-actions github-actions bot added the api Related to the REST API label Mar 2, 2026
Copy link
Contributor

@bito-code-review bito-code-review bot left a comment

Choose a reason for hiding this comment

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

Code Review Agent Run #5af5a8

Actionable Suggestions - 2
  • tests/integration_tests/charts/api_tests.py - 2
Review Details
  • Files reviewed - 5 · Commit Range: 186a3ad..c4aeaff
    • superset/charts/api.py
    • superset/dashboards/api.py
    • tests/integration_tests/charts/api_tests.py
    • tests/integration_tests/dashboards/api_tests.py
    • tests/integration_tests/event_logger_tests.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - 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 [email protected].

Documentation & Help

AI Code Review powered by Bito Logo

# Verify audit log
log = (
db.session.query(Log)
.filter_by(action="delete", slice_id=chart_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

Mismatched audit log action assertion

The test assertion checks for action="delete", but the @event_logger.log_this_with_context decorator on the delete method sets action to "ChartRestApi.delete" via the lambda. This mismatch will cause the assertion to fail. Either update the test to expect "ChartRestApi.delete" or change the decorator's action to "delete" for consistency with other tests.

Code suggestion
Check the AI-generated fix before applying
 --- superset/charts/api.py
 +++ superset/charts/api.py
 @@ -473,7 +473,7 @@
      @event_logger.log_this_with_context(
 -        action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.delete",
 +        action="delete",
          log_to_statsd=False,
          allow_extra_payload=True,
      )

Code Review Run #5af5a8


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

# Verify audit log
log = (
db.session.query(Log)
.filter_by(action="put", slice_id=chart_id)
Copy link
Contributor

Choose a reason for hiding this comment

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

Mismatched audit log action assertion

Similar to the delete test, the put test assertion checks for action="put", but the logging decorator sets action to "ChartRestApi.put". This will cause the test to fail. Update the decorator's action to "put" for consistency.

Code suggestion
Check the AI-generated fix before applying
 --- superset/charts/api.py
 +++ superset/charts/api.py
 @@ -389,7 +389,7 @@
      @event_logger.log_this_with_context(
 -        action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.put",
 +        action="put",
          log_to_statsd=False,
          allow_extra_payload=True,
      )

Code Review Run #5af5a8


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

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 size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User-Level Audit: Dashboard_id And Slice_id Not Populated In Logs

1 participant