This is an automated email from the ASF dual-hosted git repository. amitmiran pushed a commit to branch feat/dashboard_extra_jwt in repository https://gitbox.apache.org/repos/asf/superset.git
commit 38c678da61f35a8c8b74473375d250d164468c8e Author: amitmiran137 <[email protected]> AuthorDate: Thu Mar 18 13:20:35 2021 +0200 start of dashboard jwt manager --- superset/app.py | 7 ++++++- superset/extensions.py | 2 ++ superset/utils/dashboard_jwt_manager.py | 36 +++++++++++++++++++++++++++++++++ superset/views/core.py | 15 +++++++++++++- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/superset/app.py b/superset/app.py index 432d3fb..38d499f 100644 --- a/superset/app.py +++ b/superset/app.py @@ -40,7 +40,7 @@ from superset.extensions import ( manifest_processor, migrate, results_backend_manager, - talisman, + talisman, dashboard_jwt_manager, ) from superset.security import SupersetSecurityManager from superset.typing import FlaskResponse @@ -530,6 +530,7 @@ class SupersetAppInitializer: self.configure_data_sources() self.configure_auth_provider() self.configure_async_queries() + self.configure_dashboard_jwt() # Hook that provides administrators a handle on the Flask APP # after initialization @@ -694,3 +695,7 @@ class SupersetAppInitializer: def setup_bundle_manifest(self) -> None: manifest_processor.init_app(self.flask_app) + + def configure_dashboard_jwt(self): + if feature_flag_manager.is_feature_enabled("DASHBOARD_RBAC"): + dashboard_jwt_manager.init_app(self.flask_app) diff --git a/superset/extensions.py b/superset/extensions.py index 8f5bc6d..098471f 100644 --- a/superset/extensions.py +++ b/superset/extensions.py @@ -29,6 +29,7 @@ from werkzeug.local import LocalProxy from superset.utils.async_query_manager import AsyncQueryManager from superset.utils.cache_manager import CacheManager +from superset.utils.dashboard_jwt_manager import DashboardJwtManager from superset.utils.feature_flag_manager import FeatureFlagManager from superset.utils.machine_auth import MachineAuthProviderFactory @@ -100,6 +101,7 @@ APP_DIR = os.path.dirname(__file__) appbuilder = AppBuilder(update_perms=False) async_query_manager = AsyncQueryManager() cache_manager = CacheManager() +dashboard_jwt_manager = DashboardJwtManager() celery_app = celery.Celery() csrf = CSRFProtect() db = SQLA() diff --git a/superset/utils/dashboard_jwt_manager.py b/superset/utils/dashboard_jwt_manager.py new file mode 100644 index 0000000..8a629e7 --- /dev/null +++ b/superset/utils/dashboard_jwt_manager.py @@ -0,0 +1,36 @@ +import json +from typing import Dict, Any + +import jwt +from flask import Flask + + +class DashboardJwtDataObject: + id_or_slug: int + dataset_ids: [int] + + def __init__(self, id: int, dataset_ids: [int]) -> None: + super().__init__() + self.id_or_slug = id + self.dataset_ids = dataset_ids + + +class DashboardJwtManager: + + def __init__(self) -> None: + super().__init__() + self._jwt_secret: str + + def init_app(self, app: Flask) -> None: + config = app.config + + self._jwt_secret = config["DASHBOARD_JWT_SECRET"] + + def generate_jwt(self, data: DashboardJwtDataObject) -> str: + encoded_jwt = jwt.encode(data.__dict__, self._jwt_secret, algorithm="HS256") + return encoded_jwt.decode("utf-8") + + def parse_jwt(self, token: str) -> Dict[str, Any]: + data = jwt.decode(token, self._jwt_secret, algorithms=["HS256"]) + #todo validate data + return data diff --git a/superset/views/core.py b/superset/views/core.py index 2c390c4..aa561f9 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -84,7 +84,8 @@ from superset.exceptions import ( SupersetTemplateParamsErrorException, SupersetTimeoutException, ) -from superset.extensions import async_query_manager, cache_manager +from superset.extensions import async_query_manager, cache_manager, \ + dashboard_jwt_manager from superset.jinja_context import get_template_processor from superset.models.core import Database, FavStar, Log from superset.models.dashboard import Dashboard @@ -102,6 +103,8 @@ from superset.utils import core as utils from superset.utils.async_query_manager import AsyncQueryTokenException from superset.utils.cache import etag_cache from superset.utils.core import ReservedUrlParameters +from superset.utils.dashboard_jwt_manager import DashboardJwtManager, \ + DashboardJwtDataObject from superset.utils.dates import now_as_float from superset.utils.decorators import check_dashboard_access from superset.views.base import ( @@ -1866,6 +1869,8 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods if key not in [param.value for param in utils.ReservedUrlParameters] } + + bootstrap_data = { "user_id": g.user.get_id(), "common": common_bootstrap_payload(), @@ -1880,6 +1885,14 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods "superset_can_csv": superset_can_csv, "slice_can_edit": slice_can_edit, }, + "extra_jwt": dashboard_jwt_manager + .generate_jwt(DashboardJwtDataObject(dashboard.id, + list( + map( + lambda + datasource: datasource.id, + dashboard.datasources)) + )), "datasources": data["datasources"], }
