geido opened a new pull request, #44392:
URL: https://github.com/apache/superset/pull/44392

   ### SUMMARY
   
   Deleting a database connection opens a confirmation modal that enumerates 
the objects the delete will affect. That preview counted charts, dashboards and 
SQL Lab tabs — but not **datasets**, because `GET 
/api/v1/database/<id>/related_objects/` never returned them.
   
   That is the one dependency class the delete actually refuses on. 
`DeleteDatabaseCommand.validate()` raises 
`DatabaseDeleteDatasetsExistFailedError` (HTTP 422) while any `SqlaTable` row 
references the database, so for a connection whose only dependents are datasets 
the modal read:
   
   > The database **qa_warehouse** is linked to 0 charts that appear on 0 
dashboards and users have 0 SQL Lab tabs using this database open. **Are you 
sure you want to continue?** Deleting the database will break those objects.
   
   …which asserts nothing will break, and gates a confirmation that cannot 
succeed. The user types `DELETE`, confirms, and gets `There was an issue 
deleting qa_warehouse: Cannot delete a database that has datasets attached` — 
with the same misleading modal still on screen.
   
   This adds datasets to the preview and rewords the confirmation when they are 
present:
   
   - `DatabaseDAO.get_related_objects` returns the `SqlaTable` rows referencing 
the database. It queries them under `skip_visibility_filter`, exactly as 
`DeleteDatabaseCommand.validate()` does — `Database.tables` hides soft-deleted 
datasets, which would otherwise let the preview report zero dependents for a 
database the delete still refuses.
   - `related_objects` gains a `datasets` block (`count`, `result[{id, 
table_name, schema}]`) and `DatabaseRelatedObjectsResponse` documents it.
   - The modal names the datasets under **Affected Datasets** and states the 
connection cannot be deleted until they are removed, instead of asking the user 
to confirm.
   
   **Design decision worth reviewing:** dataset *names* are access-filtered 
with `security_manager.can_access_datasource`, the same way chart and dashboard 
names already are. The *count* is deliberately left unfiltered. This route only 
requires `can_read` on `Database`, and `DatabaseFilter` admits a caller holding 
`datasource_access` on a single dataset in that database — returning every name 
would let them enumerate datasets they hold no permission on. The count has to 
stay unfiltered because it is what explains the delete being blocked, and a 
bare number discloses far less than a name and schema. Both halves are pinned 
by tests.
   
   The frontend tolerates a backend that predates the `datasets` block 
(`json.datasets ?? { count: 0, result: [] }`), so a version-skewed deployment 
degrades to the previous copy rather than throwing.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   Verified in a running instance against a connection (`qa_warehouse`) whose 
only dependents are two datasets — no charts, no dashboards, no SQL Lab tabs. 
Exact modal text, captured from the app in both states:
   
   **Before** — the preview reports nothing attached, and invites the delete:
   
   > **Delete Data connection?**
   > The data connection **qa_warehouse** is linked to 0 charts that appear on 
0 dashboards and users have 0 SQL Lab tabs using this database open. Are you 
sure you want to continue? Deleting the database will break those objects.
   
   Typing `DELETE` and confirming then fails, because the backend refuses it:
   
   > There was an issue deleting qa_warehouse: Cannot delete a database that 
has datasets attached
   
   **After** — the preview names what is actually blocking the delete:
   
   > **Delete Data connection?**
   > The data connection **qa_warehouse** cannot be deleted because 2 datasets 
are still attached to it. Delete or move those datasets first.
   >
   > **Affected Datasets**
   > • birth_names
   > • cleaned_sales_data
   
   A connection with no datasets is byte-identical to before — the ordinary 
"Are you sure you want to continue?" confirmation is untouched.
   
   **Scope note for reviewers:** this changes the copy and names the datasets; 
it does not disable the `Type "DELETE" to confirm` affordance in the blocked 
state, so a user can still submit a request the backend will refuse. Worth 
deciding whether the primary action should also be disabled when 
`datasets.count >= 1`.
   
   ### TESTING INSTRUCTIONS
   
   Automated:
   
   ```bash
   # backend
   pytest tests/unit_tests/databases/dao/related_objects_test.py
   pytest tests/unit_tests/databases/api_test.py -k related_objects
   
   # frontend
   cd superset-frontend && npx jest src/pages/DatabaseList
   ```
   
   Manual:
   
   1. Add a database connection.
   2. Create a dataset on it (Datasets → **+ Dataset**), and no charts.
   3. Go to **Settings → Database Connections**, hover the connection, click 
the trash icon.
   4. The modal names the dataset under **Affected Datasets** and says the 
connection cannot be deleted until it is removed. Before this change it 
reported `0 charts / 0 dashboards / 0 SQL Lab tabs` and offered to continue.
   5. Remove the dataset and reopen the modal — the ordinary "Are you sure you 
want to continue?" confirmation is unchanged.
   
   To check the access-filtering: as a user holding `datasource_access` on only 
one of several datasets in the connection, the modal counts them all but names 
only the accessible one.
   
   ### ADDITIONAL INFORMATION
   
   - [ ] Has associated issue:
   - [ ] Required feature flags:
   - [x] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] 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
   


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