Ejemplo n.º 1
0
    def get_datasource(cls, datasource_type: str, datasource_id: int,
                       session: Session) -> "BaseDatasource":
        """Safely get a datasource instance, raises `DatasetNotFoundError` if
        `datasource_type` is not registered or `datasource_id` does not
        exist."""
        if datasource_type not in cls.sources:
            raise DatasetNotFoundError()

        datasource = (session.query(cls.sources[datasource_type]).filter_by(
            id=datasource_id).one_or_none())

        if not datasource:
            raise DatasetNotFoundError()

        return datasource
Ejemplo n.º 2
0
    def validate(self) -> None:
        exceptions = list()
        owner_ids: Optional[List[int]] = self._properties.get("owners")
        # Validate/populate model exists
        self._model = DatasetDAO.find_by_id(self._model_id)
        if not self._model:
            raise DatasetNotFoundError()
        # Check ownership
        try:
            check_ownership(self._model)
        except SupersetSecurityException:
            raise DatasetForbiddenError()

        database_id = self._properties.get("database", None)
        table_name = self._properties.get("table_name", None)
        # Validate uniqueness
        if not DatasetDAO.validate_update_uniqueness(
                self._model.database_id, self._model_id, table_name):
            exceptions.append(DatasetExistsValidationError(table_name))
        # Validate/Populate database not allowed to change
        if database_id and database_id != self._model:
            exceptions.append(DatabaseChangeValidationError())
        # Validate/Populate owner
        try:
            owners = populate_owners(self._actor, owner_ids)
            self._properties["owners"] = owners
        except ValidationError as e:
            exceptions.append(e)
        if exceptions:
            exception = DatasetInvalidError()
            exception.add_list(exceptions)
            raise exception
def dataset_macro(
    dataset_id: int,
    include_metrics: bool = False,
    columns: Optional[List[str]] = None,
) -> str:
    """
    Given a dataset ID, return the SQL that represents it.

    The generated SQL includes all columns (including computed) by default. Optionally
    the user can also request metrics to be included, and columns to group by.
    """
    # pylint: disable=import-outside-toplevel
    from superset.datasets.dao import DatasetDAO

    dataset = DatasetDAO.find_by_id(dataset_id)
    if not dataset:
        raise DatasetNotFoundError(f"Dataset {dataset_id} not found!")

    columns = columns or [column.column_name for column in dataset.columns]
    metrics = [metric.metric_name for metric in dataset.metrics]
    query_obj = {
        "is_timeseries": False,
        "filter": [],
        "metrics": metrics if include_metrics else None,
        "columns": columns,
    }
    sqla_query = dataset.get_query_str_extended(query_obj)
    sql = sqla_query.sql
    return f"({sql}) AS dataset_{dataset_id}"
Ejemplo n.º 4
0
    def external_metadata_by_name(self, **kwargs: Any) -> FlaskResponse:
        """Gets table metadata from the source system and SQLAlchemy inspector"""
        try:
            params: ExternalMetadataParams = (ExternalMetadataSchema().load(
                kwargs.get("rison")))
        except ValidationError as err:
            return json_error_response(str(err), status=400)

        datasource = ConnectorRegistry.get_datasource_by_name(
            session=db.session,
            datasource_type=params["datasource_type"],
            database_name=params["database_name"],
            schema=params["schema_name"],
            datasource_name=params["table_name"],
        )
        try:
            if datasource is not None:
                # Get columns from Superset metadata
                external_metadata = datasource.external_metadata()
            else:
                # Use the SQLAlchemy inspector to get columns
                database = (db.session.query(Database).filter_by(
                    database_name=params["database_name"]).one())
                external_metadata = get_physical_table_metadata(
                    database=database,
                    table_name=params["table_name"],
                    schema_name=params["schema_name"],
                )
        except (NoResultFound, NoSuchTableError) as ex:
            raise DatasetNotFoundError() from ex
        return self.json_response(external_metadata)
Ejemplo n.º 5
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()
Ejemplo n.º 6
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._model = DatasetDAO.find_by_id(self._model_id)
     if not self._model:
         raise DatasetNotFoundError()
     # Check ownership
     try:
         check_ownership(self._model)
     except SupersetSecurityException:
         raise DatasetForbiddenError()
Ejemplo n.º 7
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()
Ejemplo n.º 8
0
 def validate(self) -> None:
     # Validate/populate model exists
     self._models = DatasetDAO.find_by_ids(self._model_ids)
     if not self._models or len(self._models) != len(self._model_ids):
         raise DatasetNotFoundError()
     # Check ownership
     for model in self._models:
         try:
             security_manager.raise_for_ownership(model)
         except SupersetSecurityException as ex:
             raise DatasetForbiddenError() from ex
Ejemplo n.º 9
0
    def run(self) -> Dict[str, Any]:
        self.validate()
        if not self._model:
            raise DatasetNotFoundError()

        qc_instance = QueryContextFactory().create(
            datasource={
                "type": self._model.type,
                "id": self._model.id,
            },
            queries=[{}],
            result_type=ChartDataResultType.SAMPLES,
            force=self._force,
        )
        results = qc_instance.get_payload()
        try:
            return results["queries"][0]
        except (IndexError, KeyError) as exc:
            raise DatasetSamplesFailedError from exc
Ejemplo n.º 10
0
    def validate(self) -> None:
        exceptions: List[ValidationError] = []
        owner_ids: Optional[List[int]] = self._properties.get("owners")
        # Validate/populate model exists
        self._model = DatasetDAO.find_by_id(self._model_id)
        if not self._model:
            raise DatasetNotFoundError()
        # Check ownership
        try:
            security_manager.raise_for_ownership(self._model)
        except SupersetSecurityException as ex:
            raise DatasetForbiddenError() from ex

        database_id = self._properties.get("database", None)
        table_name = self._properties.get("table_name", None)
        # Validate uniqueness
        if not DatasetDAO.validate_update_uniqueness(
                self._model.database_id, self._model_id, table_name):
            exceptions.append(DatasetExistsValidationError(table_name))
        # Validate/Populate database not allowed to change
        if database_id and database_id != self._model:
            exceptions.append(DatabaseChangeValidationError())
        # Validate/Populate owner
        try:
            owners = self.populate_owners(owner_ids)
            self._properties["owners"] = owners
        except ValidationError as ex:
            exceptions.append(ex)

        # Validate columns
        columns = self._properties.get("columns")
        if columns:
            self._validate_columns(columns, exceptions)

        # Validate metrics
        metrics = self._properties.get("metrics")
        if metrics:
            self._validate_metrics(metrics, exceptions)

        if exceptions:
            exception = DatasetInvalidError()
            exception.add_list(exceptions)
            raise exception
Ejemplo n.º 11
0
 def validate(self) -> None:
     self._models = DatasetDAO.find_by_ids(self.dataset_ids)
     if len(self._models) != len(self.dataset_ids):
         raise DatasetNotFoundError()