feat(dashboard_rbac): dashboard_view access enforcement (#12875)

* test: dashboard_view_test failing

* test: tests works first time

* fix: pre-commit and  some refactoring

* fix:  after CR

* fix:  replace not_published with draft

* fix:  after CR

* fix: pre-commit fixes

* fix: pre-commit and lint fixes

* fix: remove unused

* fix: remove unused import

* fix: wrap the decorator to not block others

* chore: reuse dashboard from decorator into function
This commit is contained in:
Amit Miran
2021-02-04 20:23:53 +02:00
committed by GitHub
parent 9982fdebd8
commit b472d1841c
6 changed files with 299 additions and 114 deletions

View File

@@ -15,11 +15,16 @@
# specific language governing permissions and limitations
# under the License.
import time
from functools import wraps
from typing import Any, Callable, Dict, Iterator, Union
from contextlib2 import contextmanager
from flask import Response
from superset import is_feature_enabled
from superset.dashboards.commands.exceptions import DashboardAccessDeniedError
from superset.stats_logger import BaseStatsLogger
from superset.utils import core as utils
from superset.utils.dates import now_as_float
@@ -69,3 +74,35 @@ def debounce(duration: Union[float, int] = 0.1) -> Callable[..., Any]:
return wrapped
return decorate
def on_security_exception(self: Any, ex: Exception) -> Response:
return self.response(403, **{"message": utils.error_msg_from_exception(ex)})
# noinspection PyPackageRequirements
def check_dashboard_access(
on_error: Callable[..., Any] = on_security_exception
) -> Callable[..., Any]:
def decorator(f: Callable[..., Any]) -> Callable[..., Any]:
@wraps(f)
def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
from superset.models.dashboard import (
Dashboard,
raise_for_dashboard_access,
)
dashboard = Dashboard.get(str(kwargs["dashboard_id_or_slug"]))
if is_feature_enabled("DASHBOARD_RBAC"):
try:
raise_for_dashboard_access(dashboard)
except DashboardAccessDeniedError as ex:
return on_error(self, ex)
except Exception as exception:
raise exception
return f(self, *args, dashboard=dashboard, **kwargs)
return wrapper
return decorator