This is an automated email from the ASF dual-hosted git repository.

beto pushed a commit to branch new-dar
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 902509b1f06302f1adb7e559fe2f1f22f3842275
Author: Beto Dealmeida <[email protected]>
AuthorDate: Wed Dec 17 17:29:18 2025 -0500

    Explore working
---
 superset/data_access_rules/utils.py | 57 +++++++++++++++++++++++++++++++++++++
 superset/security/manager.py        | 23 +++++++++++++++
 superset/utils/filters.py           | 47 +++++++++++++++++++++++++++++-
 3 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/superset/data_access_rules/utils.py 
b/superset/data_access_rules/utils.py
index 90582b7291..c56d9268f2 100644
--- a/superset/data_access_rules/utils.py
+++ b/superset/data_access_rules/utils.py
@@ -732,6 +732,63 @@ def get_allowed_databases() -> set[str]:
     return database_names
 
 
+@dataclass
+class AllowedTable:
+    """A table allowed by DAR with database context."""
+
+    database: str
+    table: str
+    schema: str | None = None
+    catalog: str | None = None
+
+
+def get_all_allowed_tables() -> list[AllowedTable]:
+    """
+    Get all tables that the current user has access to via Data Access Rules
+    across all databases.
+
+    This function is used for dataset filtering where we need to know all
+    specific tables the user can access.
+
+    Returns:
+        List of AllowedTable objects representing allowed tables.
+    """
+    if not is_feature_enabled("DATA_ACCESS_RULES"):
+        return []
+
+    rules = get_user_rules()
+    if not rules:
+        return []
+
+    allowed_tables: list[AllowedTable] = []
+
+    for rule in rules:
+        rule_dict = rule.rule_dict
+
+        # Collect tables from allowed entries
+        for entry in rule_dict.get("allowed", []):
+            database = entry.get("database")
+            if not database:
+                continue
+
+            table_name = entry.get("table")
+            if not table_name:
+                # Skip database-level or schema-level access for now
+                # as we can't enumerate all tables without querying the DB
+                continue
+
+            allowed_tables.append(
+                AllowedTable(
+                    database=database,
+                    table=table_name,
+                    schema=entry.get("schema"),
+                    catalog=entry.get("catalog"),
+                )
+            )
+
+    return allowed_tables
+
+
 def get_all_group_keys(
     database_name: str | None = None,
     table: Table | None = None,
diff --git a/superset/security/manager.py b/superset/security/manager.py
index f377832194..5c48064db6 100644
--- a/superset/security/manager.py
+++ b/superset/security/manager.py
@@ -2489,10 +2489,33 @@ class SupersetSecurityManager(  # pylint: 
disable=too-many-public-methods
 
             assert datasource
 
+            # Check DAR access for datasource
+            dar_allowed = False
+            if is_feature_enabled("DATA_ACCESS_RULES") and hasattr(
+                datasource, "database"
+            ):
+                from superset.data_access_rules.utils import (
+                    AccessCheckResult,
+                    check_table_access,
+                )
+                from superset.sql.parse import Table
+
+                dar_table = Table(
+                    table=datasource.table_name,
+                    schema=datasource.schema,
+                    catalog=getattr(datasource, "catalog", None),
+                )
+                dar_access_info = check_table_access(
+                    database_name=datasource.database.database_name,
+                    table=dar_table,
+                )
+                dar_allowed = dar_access_info.access == 
AccessCheckResult.ALLOWED
+
             if not (
                 self.can_access_schema(datasource)
                 or self.can_access("datasource_access", datasource.perm or "")
                 or self.is_owner(datasource)
+                or dar_allowed
                 or (
                     # Grant access to the datasource only if dashboard RBAC is 
enabled
                     # or the user is an embedded guest user with access to the 
dashboard
diff --git a/superset/utils/filters.py b/superset/utils/filters.py
index 8c4a079949..fb90dc7c7d 100644
--- a/superset/utils/filters.py
+++ b/superset/utils/filters.py
@@ -17,10 +17,51 @@
 from typing import Any
 
 from flask_appbuilder import Model
-from sqlalchemy import or_
+from sqlalchemy import and_, or_
 from sqlalchemy.sql.elements import BooleanClauseList
 
 
+def get_dar_dataset_filters(base_model: type[Model]) -> list[Any]:
+    """Get SQLAlchemy filters for DAR-allowed tables."""
+    # pylint: disable=import-outside-toplevel
+    import logging
+
+    from superset import is_feature_enabled
+    from superset.connectors.sqla.models import Database
+
+    if not is_feature_enabled("DATA_ACCESS_RULES"):
+        return []
+
+    try:
+        from superset.data_access_rules.utils import get_all_allowed_tables
+
+        allowed_tables = get_all_allowed_tables()
+        if not allowed_tables:
+            return []
+
+        # Build OR filters for each allowed table
+        table_filters = []
+        for table in allowed_tables:
+            table_filter = and_(
+                Database.database_name == table.database,
+                base_model.table_name == table.table,
+            )
+            # Add schema filter if specified
+            if table.schema:
+                table_filter = and_(
+                    table_filter,
+                    base_model.schema == table.schema,
+                )
+            table_filters.append(table_filter)
+
+        return table_filters
+    except Exception as ex:
+        logging.getLogger(__name__).warning(
+            "Error getting DAR dataset filters: %s", ex
+        )
+        return []
+
+
 def get_dataset_access_filters(
     base_model: type[Model],
     *args: Any,
@@ -34,10 +75,14 @@ def get_dataset_access_filters(
     schema_perms = security_manager.user_view_menu_names("schema_access")
     catalog_perms = security_manager.user_view_menu_names("catalog_access")
 
+    # Get DAR-based table filters
+    dar_filters = get_dar_dataset_filters(base_model)
+
     return or_(
         Database.id.in_(database_ids),
         base_model.perm.in_(perms),
         base_model.catalog_perm.in_(catalog_perms),
         base_model.schema_perm.in_(schema_perms),
+        *dar_filters,
         *args,
     )

Reply via email to