示例#1
0
 def run(self):
     self.validate()
     try:
         dashboard = DashboardDAO.create(self._properties)
     except DAOCreateFailedError as e:
         logger.exception(e.exception)
         raise DashboardCreateFailedError()
     return dashboard
示例#2
0
 def run(self) -> Model:
     self.validate()
     try:
         dashboard = DashboardDAO.delete(self._model)
     except DAODeleteFailedError as e:
         logger.exception(e.exception)
         raise DashboardDeleteFailedError()
     return dashboard
示例#3
0
 def wraps(self: BaseSupersetModelRestApi, id_or_slug: str) -> Response:
     try:
         dash = DashboardDAO.get_by_id_or_slug(id_or_slug)
         return f(self, dash)
     except DashboardAccessDeniedError:
         return self.response_403()
     except DashboardNotFoundError:
         return self.response_404()
示例#4
0
    def test_get_dashboard_changed_on(self):
        session = db.session()
        dashboard = session.query(Dashboard).filter_by(
            slug="world_health").first()

        assert dashboard.changed_on == DashboardDAO.get_dashboard_changed_on(
            dashboard)
        assert dashboard.changed_on == DashboardDAO.get_dashboard_changed_on(
            "world_health")

        old_changed_on = dashboard.changed_on

        # freezegun doesn't work for some reason, so we need to sleep here :(
        time.sleep(1)
        data = dashboard.data
        positions = data["position_json"]
        data.update({"positions": positions})
        original_data = copy.deepcopy(data)

        data.update({"foo": "bar"})
        DashboardDAO.set_dash_metadata(dashboard, data)
        session.merge(dashboard)
        session.commit()
        assert old_changed_on < DashboardDAO.get_dashboard_changed_on(
            dashboard)

        DashboardDAO.set_dash_metadata(dashboard, original_data)
        session.merge(dashboard)
        session.commit()
示例#5
0
    def validate(self) -> None:
        exceptions: List[ValidationError] = []
        owners_ids: Optional[List[int]] = self._properties.get("owners")
        roles_ids: Optional[List[int]] = self._properties.get("roles")
        slug: Optional[str] = self._properties.get("slug")

        # Validate/populate model exists
        self._model = DashboardDAO.find_by_id(self._model_id)
        if not self._model:
            raise DashboardNotFoundError()
        # Check ownership
        try:
            security_manager.raise_for_ownership(self._model)
        except SupersetSecurityException as ex:
            raise DashboardForbiddenError() from ex

        # Validate slug uniqueness
        if not DashboardDAO.validate_update_slug_uniqueness(self._model_id, slug):
            exceptions.append(DashboardSlugExistsValidationError())

        # Validate/Populate owner
        if owners_ids is None:
            owners_ids = [owner.id for owner in self._model.owners]
        try:
            owners = self.populate_owners(owners_ids)
            self._properties["owners"] = owners
        except ValidationError as ex:
            exceptions.append(ex)
        if exceptions:
            exception = DashboardInvalidError()
            exception.add_list(exceptions)
            raise exception

        # Validate/Populate role
        if roles_ids is None:
            roles_ids = [role.id for role in self._model.roles]
        try:
            roles = populate_roles(roles_ids)
            self._properties["roles"] = roles
        except ValidationError as ex:
            exceptions.append(ex)
        if exceptions:
            exception = DashboardInvalidError()
            exception.add_list(exceptions)
            raise exception
示例#6
0
 def get(self, resource_id: int, key: str,
         refresh_timeout: bool) -> Optional[str]:
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard:
         entry: Entry = cache_manager.filter_state_cache.get(
             cache_key(resource_id, key))
         if refresh_timeout:
             cache_manager.filter_state_cache.set(key, entry)
         return entry["value"]
     return None
示例#7
0
 def create(self, cmd_params: CommandParameters) -> bool:
     resource_id = cmd_params.resource_id
     actor = cmd_params.actor
     key = cache_key(resource_id, cmd_params.key)
     value = cmd_params.value
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard and value:
         entry: Entry = {"owner": actor.get_user_id(), "value": value}
         return cache_manager.filter_state_cache.set(key, entry)
     return False
示例#8
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._model = DashboardDAO.find_by_id(self._model_id)
     if not self._model:
         raise DashboardNotFoundError()
     # Check ownership
     try:
         check_ownership(self._model)
     except SupersetSecurityException:
         raise DashboardForbiddenError()
示例#9
0
 def run(self) -> Optional[DashboardPermalinkValue]:
     self.validate()
     try:
         key = decode_permalink_id(self.key, salt=self.salt)
         command = GetKeyValueCommand(resource=self.resource, key=key)
         value: Optional[DashboardPermalinkValue] = command.run()
         if value:
             DashboardDAO.get_by_id_or_slug(value["dashboardId"])
             return value
         return None
     except (
             DashboardNotFoundError,
             KeyValueGetFailedError,
             KeyValueParseKeyError,
     ) as ex:
         raise DashboardPermalinkGetFailedError(message=ex.message) from ex
     except SQLAlchemyError as ex:
         logger.exception("Error running get command")
         raise DashboardPermalinkGetFailedError() from ex
示例#10
0
 def run(self) -> str:
     self.validate()
     try:
         DashboardDAO.get_by_id_or_slug(self.dashboard_id)
         value = {
             "dashboardId": self.dashboard_id,
             "state": self.state,
         }
         key = CreateKeyValueCommand(
             actor=self.actor,
             resource=self.resource,
             value=value,
         ).run()
         if key.id is None:
             raise DashboardPermalinkCreateFailedError("Unexpected missing key id")
         return encode_permalink_key(key=key.id, salt=self.salt)
     except SQLAlchemyError as ex:
         logger.exception("Error running create command")
         raise DashboardPermalinkCreateFailedError() from ex
示例#11
0
 def run(self) -> str:
     self.validate()
     try:
         DashboardDAO.get_by_id_or_slug(self.dashboard_id)
         value = {
             "dashboardId": self.dashboard_id,
             "state": self.state,
         }
         user_id = get_user_id()
         key = UpsertKeyValueCommand(
             resource=self.resource,
             key=get_deterministic_uuid(self.salt, (user_id, value)),
             value=value,
         ).run()
         assert key.id  # for type checks
         return encode_permalink_key(key=key.id, salt=self.salt)
     except SQLAlchemyError as ex:
         logger.exception("Error running create command")
         raise DashboardPermalinkCreateFailedError() from ex
示例#12
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._models = DashboardDAO.find_by_ids(self._model_ids)
     if not self._models or len(self._models) != len(self._model_ids):
         raise DashboardNotFoundError()
     # Check ownership
     for model in self._models:
         try:
             check_ownership(model)
         except SupersetSecurityException:
             raise DashboardForbiddenError()
示例#13
0
 def run(self) -> Model:
     self.validate()
     try:
         dashboard = DashboardDAO.update(self._model,
                                         self._properties,
                                         commit=False)
         dashboard = DashboardDAO.update_charts_owners(dashboard,
                                                       commit=False)
         if self._properties.get("json_metadata"):
             dashboard = DashboardDAO.set_dash_metadata(
                 dashboard,
                 data=json.loads(self._properties.get(
                     "json_metadata", "{}")),
                 commit=False,
             )
         db.session.commit()
     except DAOUpdateFailedError as ex:
         logger.exception(ex.exception)
         raise DashboardUpdateFailedError() from ex
     return dashboard
示例#14
0
 def favorite_status(self, **kwargs: Any) -> Response:
     """Favorite Stars for Dashboards
     ---
     get:
       description: >-
         Check favorited dashboards for current user
       parameters:
       - in: query
         name: q
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/get_fav_star_ids_schema'
       responses:
         200:
           description:
           content:
             application/json:
               schema:
                 $ref: "#/components/schemas/GetFavStarIdsSchema"
         400:
           $ref: '#/components/responses/400'
         401:
           $ref: '#/components/responses/401'
         404:
           $ref: '#/components/responses/404'
         500:
           $ref: '#/components/responses/500'
     """
     requested_ids = kwargs["rison"]
     dashboards = DashboardDAO.find_by_ids(requested_ids)
     if not dashboards:
         return self.response_404()
     favorited_dashboard_ids = DashboardDAO.favorited_ids(
         dashboards, g.user.get_id()
     )
     res = [
         {"id": request_id, "value": request_id in favorited_dashboard_ids}
         for request_id in requested_ids
     ]
     return self.response(200, result=res)
示例#15
0
    def get_charts(self, id_or_slug: str) -> Response:
        """Gets the chart definitions for a given dashboard
        ---
        get:
          description: >-
            Get the chart definitions for a given dashboard
          parameters:
          - in: path
            schema:
              type: string
            name: id_or_slug
          responses:
            200:
              description: Dashboard chart definitions
              content:
                application/json:
                  schema:
                    type: object
                    properties:
                      result:
                        type: array
                        items:
                          $ref: '#/components/schemas/ChartEntityResponseSchema'
            302:
              description: Redirects to the current digest
            400:
              $ref: '#/components/responses/400'
            401:
              $ref: '#/components/responses/401'
            403:
              $ref: '#/components/responses/403'
            404:
              $ref: '#/components/responses/404'
        """
        try:
            charts = DashboardDAO.get_charts_for_dashboard(id_or_slug)
            result = [
                self.chart_entity_response_schema.dump(chart)
                for chart in charts
            ]

            if is_feature_enabled("REMOVE_SLICE_LEVEL_LABEL_COLORS"):
                # dashboard metadata has dashboard-level label_colors,
                # so remove slice-level label_colors from its form_data
                for chart in result:
                    form_data = chart.get("form_data")
                    form_data.pop("label_colors", None)

            return self.response(200, result=result)
        except DashboardAccessDeniedError:
            return self.response_403()
        except DashboardNotFoundError:
            return self.response_404()
示例#16
0
 def delete(self, cmd_params: CommandParameters) -> bool:
     resource_id = cmd_params.resource_id
     actor = cmd_params.actor
     key = cache_key(resource_id, cmd_params.key)
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard:
         entry: Entry = cache_manager.filter_state_cache.get(key)
         if entry:
             if entry["owner"] != actor.get_user_id():
                 raise KeyValueAccessDeniedError()
             return cache_manager.filter_state_cache.delete(key)
     return False
示例#17
0
 def delete(self, actor: User, resource_id: int,
            key: str) -> Optional[bool]:
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard:
         entry: Entry = cache_manager.filter_state_cache.get(
             cache_key(resource_id, key))
         if entry:
             if entry["owner"] != actor.get_user_id():
                 raise KeyValueAccessDeniedError()
             return cache_manager.filter_state_cache.delete(
                 cache_key(resource_id, key))
     return False
示例#18
0
    def validate(self) -> None:
        exceptions: List[ValidationError] = []
        dashboard_ids = self._properties.get("dashboards")
        owner_ids: Optional[List[int]] = self._properties.get("owners")

        # Validate if datasource_id is provided datasource_type is required
        datasource_id = self._properties.get("datasource_id")
        if datasource_id is not None:
            datasource_type = self._properties.get("datasource_type", "")
            if not datasource_type:
                exceptions.append(
                    DatasourceTypeUpdateRequiredValidationError())

        # Validate/populate model exists
        self._model = ChartDAO.find_by_id(self._model_id)
        if not self._model:
            raise ChartNotFoundError()

        # Check and update ownership; when only updating query context we ignore
        # ownership so the update can be performed by report workers
        if not is_query_context_update(self._properties):
            try:
                check_ownership(self._model)
                owners = self.populate_owners(self._actor, owner_ids)
                self._properties["owners"] = owners
            except SupersetSecurityException as ex:
                raise ChartForbiddenError() from ex
            except ValidationError as ex:
                exceptions.append(ex)

        # Validate/Populate datasource
        if datasource_id is not None:
            try:
                datasource = get_datasource_by_id(datasource_id,
                                                  datasource_type)
                self._properties["datasource_name"] = datasource.name
            except ValidationError as ex:
                exceptions.append(ex)

        # Validate/Populate dashboards only if it's a list
        if dashboard_ids is not None:
            dashboards = DashboardDAO.find_by_ids(dashboard_ids)
            if len(dashboards) != len(dashboard_ids):
                exceptions.append(DashboardsNotFoundValidationError())
            self._properties["dashboards"] = dashboards

        if exceptions:
            exception = ChartInvalidError()
            exception.add_list(exceptions)
            raise exception
示例#19
0
 def get_datasets(self, id_or_slug: str) -> Response:
     """Gets a dashboard's datasets
     ---
     get:
       description: >-
         Returns a list of a dashboard's datasets. Each dataset includes only
         the information necessary to render the dashboard's charts.
       parameters:
       - in: path
         schema:
           type: string
         name: id_or_slug
         description: Either the id of the dashboard, or its slug
       responses:
         200:
           description: Dashboard dataset definitions
           content:
             application/json:
               schema:
                 type: object
                 properties:
                   result:
                     type: array
                     items:
                       $ref: '#/components/schemas/DashboardDatasetSchema'
         400:
           $ref: '#/components/responses/400'
         401:
           $ref: '#/components/responses/401'
         403:
           $ref: '#/components/responses/403'
         404:
           $ref: '#/components/responses/404'
     """
     try:
         datasets = DashboardDAO.get_datasets_for_dashboard(id_or_slug)
         result = [
             self.dashboard_dataset_schema.dump(dataset)
             for dataset in datasets
         ]
         return self.response(200, result=result)
     except (TypeError, ValueError) as err:
         return self.response_400(message=gettext(
             "Dataset schema is invalid, caused by: %(error)s",
             error=str(err)))
     except DashboardAccessDeniedError:
         return self.response_403()
     except DashboardNotFoundError:
         return self.response_404()
示例#20
0
    def validate(self) -> None:
        exceptions: List[ValidationError] = list()
        dashboard_ids = self._properties.get("dashboards")
        owner_ids: Optional[List[int]] = self._properties.get("owners")

        # Validate if datasource_id is provided datasource_type is required
        datasource_id = self._properties.get("datasource_id")
        if datasource_id is not None:
            datasource_type = self._properties.get("datasource_type", "")
            if not datasource_type:
                exceptions.append(
                    DatasourceTypeUpdateRequiredValidationError())

        # Validate/populate model exists
        self._model = ChartDAO.find_by_id(self._model_id)
        if not self._model:
            raise ChartNotFoundError()
        # Check ownership
        try:
            check_ownership(self._model)
        except SupersetSecurityException:
            raise ChartForbiddenError()

        # Validate/Populate datasource
        if datasource_id is not None:
            try:
                datasource = get_datasource_by_id(datasource_id,
                                                  datasource_type)
                self._properties["datasource_name"] = datasource.name
            except ValidationError as ex:
                exceptions.append(ex)

        # Validate/Populate dashboards only if it's a list
        if dashboard_ids is not None:
            dashboards = DashboardDAO.find_by_ids(dashboard_ids)
            if len(dashboards) != len(dashboard_ids):
                exceptions.append(DashboardsNotFoundValidationError())
            self._properties["dashboards"] = dashboards

        # Validate/Populate owner
        try:
            owners = populate_owners(self._actor, owner_ids)
            self._properties["owners"] = owners
        except ValidationError as ex:
            exceptions.append(ex)
        if exceptions:
            exception = ChartInvalidError()
            exception.add_list(exceptions)
            raise exception
示例#21
0
 def create(self, cmd_params: CommandParameters) -> str:
     resource_id = cmd_params.resource_id
     actor = cmd_params.actor
     tab_id = cmd_params.tab_id
     contextual_key = cache_key(session.get("_id"), tab_id, resource_id)
     key = cache_manager.filter_state_cache.get(contextual_key)
     if not key or not tab_id:
         key = random_key()
     value = cmd_params.value
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard and value:
         entry: Entry = {"owner": actor.get_user_id(), "value": value}
         cache_manager.filter_state_cache.set(cache_key(resource_id, key), entry)
         cache_manager.filter_state_cache.set(contextual_key, key)
     return key
示例#22
0
 def delete(self, cmd_params: CommandParameters) -> bool:
     resource_id = cmd_params.resource_id
     actor = cmd_params.actor
     key = cache_key(resource_id, cmd_params.key)
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard:
         entry: Entry = cache_manager.filter_state_cache.get(key)
         if entry:
             if entry["owner"] != actor.get_user_id():
                 raise TemporaryCacheAccessDeniedError()
             tab_id = cmd_params.tab_id
             contextual_key = cache_key(session.get("_id"), tab_id,
                                        resource_id)
             cache_manager.filter_state_cache.delete(contextual_key)
             return cache_manager.filter_state_cache.delete(key)
     return False
示例#23
0
 def update(self, actor: User, resource_id: int, key: str,
            value: str) -> Optional[bool]:
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard:
         entry: Entry = cache_manager.filter_state_cache.get(
             cache_key(resource_id, key))
         if entry:
             user_id = actor.get_user_id()
             if entry["owner"] != user_id:
                 raise KeyValueAccessDeniedError()
             new_entry: Entry = {
                 "owner": actor.get_user_id(),
                 "value": value
             }
             return cache_manager.filter_state_cache.set(
                 cache_key(resource_id, key), new_entry)
     return False
示例#24
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._model = DashboardDAO.find_by_id(self._model_id)
     if not self._model:
         raise DashboardNotFoundError()
     # Check there are no associated ReportSchedules
     reports = ReportScheduleDAO.find_by_dashboard_id(self._model_id)
     if reports:
         report_names = [report.name for report in reports]
         raise DashboardDeleteFailedReportsExistError(
             _("There are associated alerts or reports: %s" %
               ",".join(report_names)))
     # Check ownership
     try:
         check_ownership(self._model)
     except SupersetSecurityException as ex:
         raise DashboardForbiddenError() from ex
示例#25
0
 def update(self, cmd_params: CommandParameters) -> bool:
     resource_id = cmd_params.resource_id
     actor = cmd_params.actor
     key = cache_key(resource_id, cmd_params.key)
     value = cmd_params.value
     dashboard = DashboardDAO.get_by_id_or_slug(str(resource_id))
     if dashboard and value:
         entry: Entry = cache_manager.filter_state_cache.get(key)
         if entry:
             user_id = actor.get_user_id()
             if entry["owner"] != user_id:
                 raise KeyValueAccessDeniedError()
             new_entry: Entry = {
                 "owner": actor.get_user_id(),
                 "value": value
             }
             return cache_manager.filter_state_cache.set(key, new_entry)
     return False
示例#26
0
    def test_set_dash_metadata(self):
        dash: Dashboard = (
            db.session.query(Dashboard).filter_by(slug="world_health").first()
        )
        data = dash.data
        positions = data["position_json"]
        data.update({"positions": positions})
        original_data = copy.deepcopy(data)

        # add filter scopes
        filter_slice = next(slc for slc in dash.slices if slc.viz_type == "filter_box")
        immune_slices = [slc for slc in dash.slices if slc != filter_slice]
        filter_scopes = {
            str(filter_slice.id): {
                "region": {
                    "scope": ["ROOT_ID"],
                    "immune": [slc.id for slc in immune_slices],
                }
            }
        }
        data.update({"filter_scopes": json.dumps(filter_scopes)})
        DashboardDAO.set_dash_metadata(dash, data)
        updated_metadata = json.loads(dash.json_metadata)
        self.assertEqual(updated_metadata["filter_scopes"], filter_scopes)

        # remove a slice and change slice ids (as copy slices)
        removed_slice = immune_slices.pop()
        removed_components = [
            key
            for (key, value) in positions.items()
            if isinstance(value, dict)
            and value.get("type") == "CHART"
            and value["meta"]["chartId"] == removed_slice.id
        ]
        for component_id in removed_components:
            del positions[component_id]

        data.update({"positions": positions})
        DashboardDAO.set_dash_metadata(dash, data)
        updated_metadata = json.loads(dash.json_metadata)
        expected_filter_scopes = {
            str(filter_slice.id): {
                "region": {
                    "scope": ["ROOT_ID"],
                    "immune": [slc.id for slc in immune_slices],
                }
            }
        }
        self.assertEqual(updated_metadata["filter_scopes"], expected_filter_scopes)

        # reset dash to original data
        DashboardDAO.set_dash_metadata(dash, original_data)
示例#27
0
    def validate(self) -> None:
        exceptions = list()
        owner_ids: Optional[List[int]] = self._properties.get("owners")
        slug: str = self._properties.get("slug", "")

        # Validate slug uniqueness
        if not DashboardDAO.validate_slug_uniqueness(slug):
            exceptions.append(DashboardSlugExistsValidationError())

        try:
            owners = populate_owners(self._actor, owner_ids)
            self._properties["owners"] = owners
        except ValidationError as ex:
            exceptions.append(ex)
        if exceptions:
            exception = DashboardInvalidError()
            exception.add_list(exceptions)
            raise exception
示例#28
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._models = DashboardDAO.find_by_ids(self._model_ids)
     if not self._models or len(self._models) != len(self._model_ids):
         raise DashboardNotFoundError()
     # Check there are no associated ReportSchedules
     reports = ReportScheduleDAO.find_by_dashboard_ids(self._model_ids)
     if reports:
         report_names = [report.name for report in reports]
         raise DashboardBulkDeleteFailedReportsExistError(
             _("There are associated alerts or reports: %s" % ",".join(report_names))
         )
     # Check ownership
     for model in self._models:
         try:
             security_manager.raise_for_ownership(model)
         except SupersetSecurityException as ex:
             raise DashboardForbiddenError() from ex
示例#29
0
文件: api.py 项目: ws1993/superset
 def get_datasets(self, id_or_slug: str) -> Response:
     """Gets a dashboard's datasets
     ---
     get:
       description: >-
         Returns a list of a dashboard's datasets. Each dataset includes only
         the information necessary to render the dashboard's charts.
       parameters:
       - in: path
         schema:
           type: string
         name: id_or_slug
         description: Either the id of the dashboard, or its slug
       responses:
         200:
           description: Dashboard dataset definitions
           content:
             application/json:
               schema:
                 type: object
                 properties:
                   result:
                     type: array
                     items:
                       $ref: '#/components/schemas/DashboardDatasetSchema'
         302:
           description: Redirects to the current digest
         400:
           $ref: '#/components/responses/400'
         401:
           $ref: '#/components/responses/401'
         404:
           $ref: '#/components/responses/404'
     """
     try:
         datasets = DashboardDAO.get_datasets_for_dashboard(id_or_slug)
         result = [
             self.dashboard_dataset_schema.dump(dataset)
             for dataset in datasets
         ]
         return self.response(200, result=result)
     except DashboardNotFoundError:
         return self.response_404()
示例#30
0
 def get(self, id_or_slug: str) -> Response:
     """Gets a dashboard
     ---
     get:
       description: >-
         Get a dashboard
       parameters:
       - in: path
         schema:
           type: string
         name: id_or_slug
         description: Either the id of the dashboard, or its slug
       responses:
         200:
           description: Dashboard
           content:
             application/json:
               schema:
                 type: object
                 properties:
                   result:
                     $ref: '#/components/schemas/DashboardGetResponseSchema'
         302:
           description: Redirects to the current digest
         400:
           $ref: '#/components/responses/400'
         401:
           $ref: '#/components/responses/401'
         403:
           $ref: '#/components/responses/403'
         404:
           $ref: '#/components/responses/404'
     """
     # pylint: disable=arguments-differ
     try:
         dash = DashboardDAO.get_by_id_or_slug(id_or_slug)
         result = self.dashboard_get_response_schema.dump(dash)
         return self.response(200, result=result)
     except DashboardAccessDeniedError:
         return self.response_403()
     except DashboardNotFoundError:
         return self.response_404()