def test_can_access_datasource(self, mock_raise_for_access):
        datasource = self.get_datasource_mock()

        mock_raise_for_access.return_value = None
        self.assertTrue(security_manager.can_access_datasource(datasource=datasource))

        mock_raise_for_access.side_effect = SupersetSecurityException(
            SupersetError(
                "dummy",
                SupersetErrorType.DATASOURCE_SECURITY_ACCESS_ERROR,
                ErrorLevel.ERROR,
            )
        )

        self.assertFalse(security_manager.can_access_datasource(datasource=datasource))
Beispiel #2
0
def check_dataset_access(dataset_id: int) -> Optional[bool]:
    if dataset_id:
        dataset = DatasetDAO.find_by_id(dataset_id)
        if dataset:
            can_access_datasource = security_manager.can_access_datasource(dataset)
            if can_access_datasource:
                return True
            raise DatasetAccessDeniedError()
    raise DatasetNotFoundError()
Beispiel #3
0
def check_dataset_access(dataset_id: int) -> Optional[bool]:
    if dataset_id:
        # Access checks below, no need to validate them twice as they can be expensive.
        dataset = DatasetDAO.find_by_id(dataset_id, skip_base_filter=True)
        if dataset:
            can_access_datasource = security_manager.can_access_datasource(dataset)
            if can_access_datasource:
                return True
            raise DatasetAccessDeniedError()
    raise DatasetNotFoundError()
Beispiel #4
0
def check_dashboard_perms(_self: Any, dashboard_id_or_slug: str) -> None:
    """
    Check if user can access a cached response from explore_json.

    This function takes `self` since it must have the same signature as the
    the decorated method.
    """

    dash = get_dashboard(dashboard_id_or_slug)
    datasources = list(dash.datasources)
    if app.config["ENABLE_ACCESS_REQUEST"]:
        for datasource in datasources:
            if datasource and not security_manager.can_access_datasource(datasource):
                flash(
                    __(security_manager.get_datasource_access_error_msg(datasource)),
                    "danger",
                )
                redirect("superset/request_access/?" f"dashboard_id={dash.id}&")
Beispiel #5
0
    def run(self) -> Optional[Dict[str, Any]]:
        initial_form_data = {}

        if self._permalink_key is not None:
            command = GetExplorePermalinkCommand(self._permalink_key)
            permalink_value = command.run()
            if not permalink_value:
                raise ExplorePermalinkGetFailedError()
            state = permalink_value["state"]
            initial_form_data = state["formData"]
            url_params = state.get("urlParams")
            if url_params:
                initial_form_data["url_params"] = dict(url_params)
        elif self._form_data_key:
            parameters = FormDataCommandParameters(key=self._form_data_key)
            value = GetFormDataCommand(parameters).run()
            initial_form_data = json.loads(value) if value else {}

        message = None

        if not initial_form_data:
            if self._slice_id:
                initial_form_data["slice_id"] = self._slice_id
                if self._form_data_key:
                    message = _(
                        "Form data not found in cache, reverting to chart metadata."
                    )
            elif self._dataset_id:
                initial_form_data[
                    "datasource"
                ] = f"{self._dataset_id}__{self._dataset_type}"
                if self._form_data_key:
                    message = _(
                        "Form data not found in cache, reverting to dataset metadata."
                    )

        form_data, slc = get_form_data(
            use_slice_data=True, initial_form_data=initial_form_data
        )
        try:
            self._dataset_id, self._dataset_type = get_datasource_info(
                self._dataset_id, self._dataset_type, form_data
            )
        except SupersetException:
            self._dataset_id = None
            # fallback unkonw datasource to table type
            self._dataset_type = SqlaTable.type

        dataset: Optional[BaseDatasource] = None
        if self._dataset_id is not None:
            try:
                dataset = DatasourceDAO.get_datasource(
                    db.session, cast(str, self._dataset_type), self._dataset_id
                )
            except DatasetNotFoundError:
                pass
        dataset_name = dataset.name if dataset else _("[Missing Dataset]")

        if dataset:
            if app.config["ENABLE_ACCESS_REQUEST"] and (
                not security_manager.can_access_datasource(dataset)
            ):
                message = __(security_manager.get_datasource_access_error_msg(dataset))
                raise DatasetAccessDeniedError(
                    message=message,
                    dataset_type=self._dataset_type,
                    dataset_id=self._dataset_id,
                )

        viz_type = form_data.get("viz_type")
        if not viz_type and dataset and dataset.default_endpoint:
            raise WrongEndpointError(redirect=dataset.default_endpoint)

        form_data["datasource"] = (
            str(self._dataset_id) + "__" + cast(str, self._dataset_type)
        )

        # On explore, merge legacy and extra filters into the form data
        utils.convert_legacy_filters_into_adhoc(form_data)
        utils.merge_extra_filters(form_data)

        dummy_dataset_data: Dict[str, Any] = {
            "type": self._dataset_type,
            "name": dataset_name,
            "columns": [],
            "metrics": [],
            "database": {"id": 0, "backend": ""},
        }
        try:
            dataset_data = dataset.data if dataset else dummy_dataset_data
        except (SupersetException, SQLAlchemyError):
            dataset_data = dummy_dataset_data

        return {
            "dataset": sanitize_datasource_data(dataset_data),
            "form_data": form_data,
            "slice": slc.data if slc else None,
            "message": message,
        }