mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
feat(row-level-security): add base filter type and filter grouping (#10946)
* feat(row-level-security): add filter type and group key * simplify tests and add custom list widget * address comments * use enum value to ensure case sensitive value is used
This commit is contained in:
@@ -36,7 +36,7 @@ from flask_appbuilder.security.views import (
|
||||
ViewMenuModelView,
|
||||
)
|
||||
from flask_appbuilder.widgets import ListWidget
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy import and_, or_
|
||||
from sqlalchemy.engine.base import Connection
|
||||
from sqlalchemy.orm.mapper import Mapper
|
||||
from sqlalchemy.orm.query import Query as SqlaQuery
|
||||
@@ -46,7 +46,7 @@ from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.constants import RouteMethod
|
||||
from superset.errors import ErrorLevel, SupersetError, SupersetErrorType
|
||||
from superset.exceptions import SupersetSecurityException
|
||||
from superset.utils.core import DatasourceName
|
||||
from superset.utils.core import DatasourceName, RowLevelSecurityFilterType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset.common.query_context import QueryContext
|
||||
@@ -62,7 +62,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class SupersetSecurityListWidget(ListWidget):
|
||||
"""
|
||||
Redeclaring to avoid circular imports
|
||||
Redeclaring to avoid circular imports
|
||||
"""
|
||||
|
||||
template = "superset/fab_overrides/list.html"
|
||||
@@ -70,8 +70,8 @@ class SupersetSecurityListWidget(ListWidget):
|
||||
|
||||
class SupersetRoleListWidget(ListWidget):
|
||||
"""
|
||||
Role model view from FAB already uses a custom list widget override
|
||||
So we override the override
|
||||
Role model view from FAB already uses a custom list widget override
|
||||
So we override the override
|
||||
"""
|
||||
|
||||
template = "superset/fab_overrides/list_role.html"
|
||||
@@ -1012,8 +1012,23 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods
|
||||
.filter(assoc_user_role.c.user_id == g.user.id)
|
||||
.subquery()
|
||||
)
|
||||
filter_roles = (
|
||||
regular_filter_roles = (
|
||||
self.get_session.query(RLSFilterRoles.c.rls_filter_id)
|
||||
.join(RowLevelSecurityFilter)
|
||||
.filter(
|
||||
RowLevelSecurityFilter.filter_type
|
||||
== RowLevelSecurityFilterType.REGULAR
|
||||
)
|
||||
.filter(RLSFilterRoles.c.role_id.in_(user_roles))
|
||||
.subquery()
|
||||
)
|
||||
base_filter_roles = (
|
||||
self.get_session.query(RLSFilterRoles.c.rls_filter_id)
|
||||
.join(RowLevelSecurityFilter)
|
||||
.filter(
|
||||
RowLevelSecurityFilter.filter_type
|
||||
== RowLevelSecurityFilterType.BASE
|
||||
)
|
||||
.filter(RLSFilterRoles.c.role_id.in_(user_roles))
|
||||
.subquery()
|
||||
)
|
||||
@@ -1024,10 +1039,25 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods
|
||||
)
|
||||
query = (
|
||||
self.get_session.query(
|
||||
RowLevelSecurityFilter.id, RowLevelSecurityFilter.clause
|
||||
RowLevelSecurityFilter.id,
|
||||
RowLevelSecurityFilter.group_key,
|
||||
RowLevelSecurityFilter.clause,
|
||||
)
|
||||
.filter(RowLevelSecurityFilter.id.in_(filter_tables))
|
||||
.filter(RowLevelSecurityFilter.id.in_(filter_roles))
|
||||
.filter(
|
||||
or_(
|
||||
and_(
|
||||
RowLevelSecurityFilter.filter_type
|
||||
== RowLevelSecurityFilterType.REGULAR,
|
||||
RowLevelSecurityFilter.id.in_(regular_filter_roles),
|
||||
),
|
||||
and_(
|
||||
RowLevelSecurityFilter.filter_type
|
||||
== RowLevelSecurityFilterType.BASE,
|
||||
RowLevelSecurityFilter.id.notin_(base_filter_roles),
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
return query.all()
|
||||
return []
|
||||
|
||||
Reference in New Issue
Block a user