aminghadersohi commented on code in PR #44126:
URL: https://github.com/apache/superset/pull/44126#discussion_r4270433227


##########
docs/admin_docs/configuration/configuring-superset.mdx:
##########
@@ -606,6 +606,52 @@ def FLASK_APP_MUTATOR(app: Flask) -> None:
     app.before_request_funcs.setdefault(None, 
[]).append(make_session_permanent)
 ```
 
+## Reacting to chart and dashboard creation
+
+`AFTER_ASSET_CREATE` is an optional hook that runs after a chart or dashboard
+is created, letting deployments react to new assets without forking the
+creation commands or views — for example to auto-categorize the asset, write
+an audit log entry, or fire a notification.
+
+The hook receives the model instance and the asset type string (`"chart"` or
+`"dashboard"`):
+
+```python
+# superset_config.py
+from superset import db
+
+
+def _after_asset_create(model, asset_type):
+    # The model is pending in the session but may not be flushed yet, so
+    # flush first if you need database-assigned fields like ``id``.
+    db.session.flush()
+    audit_log.write(f"{asset_type} {model.id} created by {model.created_by}")
+
+
+AFTER_ASSET_CREATE = _after_asset_create
+```
+
+It defaults to `None`, which is a no-op: with nothing configured, chart and
+dashboard creation behaves exactly as it did before this hook existed.
+
+The hook runs before the surrounding database transaction commits, so an
+exception raised inside it aborts the chart or dashboard creation. Keep it
+fast and side-effect-light, and avoid raising unless you intend to cancel
+the creation. On the REST API path the model has been added to the session
+but not flushed when the hook is called, so `id`, `created_by`, and other
+database-assigned fields are still `None` unless the hook flushes the
+session itself, as in the example above.

Review Comment:
   On master `CreateDashboardCommand.run` flushes before the hook 
(`commands/dashboard/create.py:58`), so "not flushed" is wrong for dashboards 
once this merges; only the chart path is unflushed. Writes outside the session 
also survive a later rollback, which this never says.
   
   ```suggestion
   The hook runs before the surrounding database transaction commits, so an
   exception raised inside it aborts the chart or dashboard creation, while work
   it does outside the session (an external audit write, a notification) is not
   undone if the transaction later rolls back. Keep it fast and
   side-effect-light, and avoid raising unless you intend to cancel the
   creation. The model may not be flushed when the hook is called (the chart
   create command never flushes first), so `id`, `created_by`, and other
   database-assigned fields can still be `None` unless the hook flushes the
   session itself, as in the example above.
   ```



##########
docs/admin_docs/configuration/configuring-superset.mdx:
##########
@@ -606,6 +606,52 @@ def FLASK_APP_MUTATOR(app: Flask) -> None:
     app.before_request_funcs.setdefault(None, 
[]).append(make_session_permanent)
 ```
 
+## Reacting to chart and dashboard creation
+
+`AFTER_ASSET_CREATE` is an optional hook that runs after a chart or dashboard
+is created, letting deployments react to new assets without forking the
+creation commands or views — for example to auto-categorize the asset, write
+an audit log entry, or fire a notification.
+
+The hook receives the model instance and the asset type string (`"chart"` or
+`"dashboard"`):
+
+```python
+# superset_config.py
+from superset import db
+
+
+def _after_asset_create(model, asset_type):
+    # The model is pending in the session but may not be flushed yet, so
+    # flush first if you need database-assigned fields like ``id``.
+    db.session.flush()
+    audit_log.write(f"{asset_type} {model.id} created by {model.created_by}")
+
+
+AFTER_ASSET_CREATE = _after_asset_create
+```
+
+It defaults to `None`, which is a no-op: with nothing configured, chart and
+dashboard creation behaves exactly as it did before this hook existed.
+
+The hook runs before the surrounding database transaction commits, so an
+exception raised inside it aborts the chart or dashboard creation. Keep it
+fast and side-effect-light, and avoid raising unless you intend to cancel
+the creation. On the REST API path the model has been added to the session
+but not flushed when the hook is called, so `id`, `created_by`, and other
+database-assigned fields are still `None` unless the hook flushes the
+session itself, as in the example above.
+
+The hook fires for any chart or dashboard created through the REST API
+(including Explore's Save As) and for blank dashboards created from the UI's
+"+ New dashboard" button. MCP-generated charts go through the same path, but
+MCP-generated dashboards currently build the dashboard directly and skip the
+hook. The dashboard copy endpoint (`POST /api/v1/dashboard/<id>/copy/`) also
+bypasses it, since it clones the dashboard directly rather than going through
+the create command. The chart and dashboard import endpoints
+(`POST /api/v1/chart/import/` and `POST /api/v1/dashboard/import/`) create
+assets via `import_from_dict` and skip the hook as well.

Review Comment:
   `POST /api/v1/assets/import/` (`importexport/api.py:92`) also creates charts 
and dashboards via `import_charts`/`import_dashboard` and `import_from_dict` 
with no hook call, so line 645's "any ... through the REST API" is still too 
broad.
   
   ```suggestion
   the create command. The chart, dashboard, and bulk asset import endpoints
   (`POST /api/v1/chart/import/`, `POST /api/v1/dashboard/import/`, and
   `POST /api/v1/assets/import/`) create assets via `import_from_dict` and skip
   the hook as well.
   ```



-- 
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