Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboard_rbac): provide data access based on dashboard access #13992

Merged
merged 18 commits into from
Apr 13, 2021
30 changes: 27 additions & 3 deletions superset/security/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from flask import current_app, g
from flask_appbuilder import Model
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.security.sqla.manager import SecurityManager
from flask_appbuilder.security.sqla.models import (
assoc_permissionview_role,
Expand Down Expand Up @@ -60,7 +61,7 @@
from superset.models.sql_lab import Query
from superset.sql_parse import Table
from superset.viz import BaseViz

from superset.models.slice import Slice

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -293,7 +294,7 @@ def can_access_schema(self, datasource: "BaseDatasource") -> bool:

return (
self.can_access_all_datasources()
or self.can_access_database(datasource.database)
or self.can_access_database(datasource.canrdatabase)
or self.can_access("schema_access", datasource.schema_perm or "")
)

Expand Down Expand Up @@ -994,8 +995,14 @@ def raise_for_access( # pylint: disable=too-many-arguments,too-many-branches

assert datasource

from superset import is_feature_enabled

if not (
self.can_access_schema(datasource)
(
is_feature_enabled("DASHBOARD_RBAC")
and self.can_access_based_on_dashboard(datasource)
)
or self.can_access_schema(datasource)
or self.can_access("datasource_access", datasource.perm or "")
):
raise SupersetSecurityException(
Expand Down Expand Up @@ -1125,3 +1132,20 @@ def raise_for_dashboard_access(self, dashboard: "Dashboard") -> None:

if not can_access:
raise DashboardAccessDeniedError()

# pylint: disable=no-self-use
def can_access_based_on_dashboard(self, datasource: "BaseDatasource"):
from superset import db
from superset.dashboards.filters import DashboardFilter
from superset.models.slice import Slice
from superset.models.dashboard import Dashboard

TBL = ConnectorRegistry.sources["table"]
query = db.session.query(TBL).join(Slice.table).filter(TBL.id == datasource.id)

query = DashboardFilter("id", SQLAInterface(Dashboard, db.session)).apply(
query, None
)

exists = db.session.query(query.exists()).scalar()
return exists