msyavuz commented on code in PR #43988:
URL: https://github.com/apache/superset/pull/43988#discussion_r3959532639


##########
superset/models/slice.py:
##########
@@ -496,13 +496,36 @@ def set_related_perm(_mapper: Mapper, _connection: 
Connection, target: Slice) ->
     # pylint: disable=import-outside-toplevel
     from superset.daos.datasource import DatasourceDAO
 
-    src_class = DatasourceDAO.sources[target.datasource_type]
+    # This listener also runs on updates, so clear the derived values before
+    # attempting to resolve the datasource. Otherwise an unmapped or deleted
+    # datasource can retain permission strings copied from a previous one.
+    target.perm = None
+    target.catalog_perm = None
+    target.schema_perm = None
+
+    src_class = DatasourceDAO.sources.get(target.datasource_type)
+    if src_class is None:
+        # The chart API accepts every ``DatasourceType``, but only some of them

Review Comment:
   This isn't true since #43500: `CreateChartCommand.validate` rejects anything 
but `table` (create.py:84) and the legacy explore view hard-codes `table`, so 
no HTTP path reaches this branch or the `getattr` fallbacks. On master the SQL 
Lab save already fails with a 422 from validate, not the 500 the unit test 
docstring describes. The frontend change is the fix; is this listener change 
still needed?



##########
tests/integration_tests/charts/api_tests.py:
##########
@@ -704,6 +704,44 @@ def 
test_create_chart_from_saved_query_rejected_cleanly(self):
             db.session.delete(db.session.query(SavedQuery).get(saved_query_id))
             db.session.commit()
 
+    def test_create_chart_from_sql_lab_query_rejected_cleanly(self):

Review Comment:
   This passes on master unchanged: the 422 comes from 
`CreateChartCommand.validate` before `set_related_perm` runs, same path as 
`test_create_chart_from_saved_query_rejected_cleanly` above it.



##########
superset/models/slice.py:
##########
@@ -496,13 +496,36 @@ def set_related_perm(_mapper: Mapper, _connection: 
Connection, target: Slice) ->
     # pylint: disable=import-outside-toplevel
     from superset.daos.datasource import DatasourceDAO
 
-    src_class = DatasourceDAO.sources[target.datasource_type]
+    # This listener also runs on updates, so clear the derived values before
+    # attempting to resolve the datasource. Otherwise an unmapped or deleted
+    # datasource can retain permission strings copied from a previous one.
+    target.perm = None

Review Comment:
   Following up on the thread above with the soft-delete case: the 
`do_orm_execute` visibility filter hides a soft-deleted dataset from this 
query, so any flush of one of its charts (chart trash, since Slice is also 
`SoftDeleteMixin`) nulls the perms. When the dataset is restored the join 
passes again but the strings stay NULL, so the chart drops out of the 
permission leg of `ChartFilter` until someone re-saves it. Previously the 
still-correct strings survived.



##########
tests/unit_tests/models/slice_test.py:
##########
@@ -229,6 +229,107 @@ def test_icons_escapes_datasource_html(self):
         assert '"onmouseover' not in html
 
 
+def _run_set_related_perm(
+    datasource_type: str, *, with_existing_perms: bool = False
+) -> Slice:
+    """Run the perm-denormalizing listener against a stand-in datasource.
+
+    The stand-in is specced against the model class registered for
+    ``datasource_type``, so it exposes exactly the perm attributes that class
+    really defines -- the whole point being that they differ per type.
+    """
+    # pylint: disable=import-outside-toplevel
+    from superset.daos.datasource import DatasourceDAO
+
+    target = Slice()
+    target.datasource_type = datasource_type
+    target.datasource_id = 1
+    if with_existing_perms:
+        target.perm = "old-perm"
+        target.catalog_perm = "old-catalog-perm"
+        target.schema_perm = "old-schema-perm"
+
+    src_class = DatasourceDAO.sources.get(datasource_type)
+    datasource = MagicMock(spec=src_class) if src_class else None
+
+    with patch("superset.models.slice.db") as mock_db:
+        query = mock_db.session.query.return_value.filter_by.return_value
+        query.first.return_value = datasource
+        set_related_perm(None, None, target)
+
+    return target
+
+
[email protected]("datasource_type", ["table", "semantic_view"])

Review Comment:
   `MagicMock(spec=SemanticView)` returns a mock for `catalog_perm`, but the 
real property returns `None` (semantic_layers/models.py:684), so the 
`catalog_perm is not None` assertion for `semantic_view` is testing the mock.



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