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:
Ville Brofeldt
2020-09-22 08:54:10 +03:00
committed by GitHub
parent 3be8bdad9a
commit 448a41a4e7
8 changed files with 395 additions and 83 deletions

View File

@@ -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 []