if not orm_datasource:
            return json_error_response("This datasource does not exist",
                                       status="400")
        elif not orm_datasource.data:
            return json_error_response("Error fetching datasource data.",
                                       status="500")

        return self.json_response(orm_datasource.data)

    @expose("/external_metadata/<datasource_type>/<datasource_id>/")
    @has_access_api
    def external_metadata(self, datasource_type=None, datasource_id=None):
        """Gets column info from the source system"""
        if datasource_type == "druid":
            datasource = ConnectorRegistry.get_datasource(
                datasource_type, datasource_id, db.session)
        elif datasource_type == "table":
            database = (db.session.query(Database).filter_by(
                id=request.args.get("db_id")).one())
            Table = ConnectorRegistry.sources["table"]
            datasource = Table(
                database=database,
                table_name=request.args.get("table_name"),
                schema=request.args.get("schema") or None,
            )
        external_metadata = datasource.external_metadata()
        return self.json_response(external_metadata)


appbuilder.add_view_no_menu(Datasource)
Example #2
0
                "created_by": obj.created_by_fk,
                "creator": obj.creator(),
            } for obj in charts)

        # saved queries
        if not types or "query" in types:
            saved_queries = (db.session.query(SavedQuery).join(
                TaggedObject,
                and_(
                    TaggedObject.object_id == SavedQuery.id,
                    TaggedObject.object_type == ObjectTypes.query,
                ),
            ).join(Tag,
                   TaggedObject.tag_id == Tag.id).filter(Tag.name.in_(tags)))
            results.extend({
                "id": obj.id,
                "type": ObjectTypes.query.name,
                "name": obj.label,
                "url": obj.url(),
                "changed_on": obj.changed_on,
                "created_by": obj.created_by_fk,
                "creator": obj.creator(),
            } for obj in saved_queries)

        return json_success(
            json.dumps(results, default=utils.core.json_int_dttm_ser))


app.url_map.converters["object_type"] = ObjectTypeConverter
appbuilder.add_view_no_menu(TagView)
Example #3
0
    }

    def pre_add(self, obj):
        obj.user = g.user

    def pre_update(self, obj):
        self.pre_add(obj)


class SavedQueryViewApi(SavedQueryView):
    show_columns = ['label', 'db_id', 'schema', 'description', 'sql']
    add_columns = show_columns
    edit_columns = add_columns


appbuilder.add_view_no_menu(SavedQueryViewApi)
appbuilder.add_view_no_menu(SavedQueryView)

appbuilder.add_link(__('Saved Queries'),
                    href='/sqllab/my_queries/',
                    icon='fa-save',
                    category='SQL Lab')


class SqlLab(BaseSupersetView):
    """The base views for Superset!"""
    @expose('/my_queries/')
    @has_access
    def my_queries(self):
        """Assigns a list of found users to the given role."""
        return redirect('/savedqueryview/list/?_flt_0_user={}'.format(
Example #4
0
        Keyword arguments:
        form_data -- the dictionary containing the properties for the table to be created
        database -- the database object which will be used
        csv_filename -- the name of the csv-file to be imported

        Raises:
            TableCreationException:  If the data could not be inserted into the table
        """
        try:
            database.db_engine_spec.create_and_fill_table_from_csv(
                form_data, csv_filename, database)
        except Exception as e:
            raise TableCreationException(
                f"Table {form_data.get('tableName')} could not be filled with CSV {csv_filename}. "
                "This could be an issue with the schema, a connection issue, etc.",
                e,
            )


appbuilder.add_view_no_menu(CsvImporter)

appbuilder.add_link(
    "Upload a CSV",
    label=__("Upload a CSV"),
    href="/csvimporter/csvtodatabase",
    icon="fa-upload",
    category="Sources",
    category_label=__("Sources"),
    category_icon="fa-wrench",
)
Example #5
0
from flask import g, request
from flask_appbuilder import expose
from flask_appbuilder.security.decorators import has_access_api

from superset import appbuilder, security_manager
from superset.common.query_context import QueryContext
from superset.models.core import Log
from .base import api, BaseSupersetView, data_payload_response, handle_api_exception


class Api(BaseSupersetView):
    @Log.log_this
    @api
    @handle_api_exception
    @has_access_api
    @expose('/v1/query/', methods=['POST'])
    def query(self):
        """
        Takes a query_obj constructed in the client and returns payload data response
        for the given query_obj.
        """
        query_context = QueryContext(
            **json.loads(request.form.get('query_context')))
        security_manager.assert_datasource_permission(query_context.datasource,
                                                      g.user)
        payload_json = query_context.get_data()
        return data_payload_response(payload_json)


appbuilder.add_view_no_menu(Api)
Example #6
0
    label_columns = {
        'column_name': _('Column'),
        'verbose_name': _('Verbose Name'),
        'description': _('Description'),
        'groupby': _('Groupable'),
        'filterable': _('Filterable'),
        'table': _('Table'),
        'expression': _('Expression'),
        'is_dttm': _('Is temporal'),
        'python_date_format': _('Datetime Format'),
        'database_expression': _('Database Expression'),
        'type': _('Type'),
    }


appbuilder.add_view_no_menu(TableColumnInlineView)


class SqlMetricInlineView(CompactCRUDMixin, SupersetModelView):  # noqa
    datamodel = SQLAInterface(models.SqlMetric)

    list_title = _('List Metrics')
    show_title = _('Show Metric')
    add_title = _('Add Metric')
    edit_title = _('Edit Metric')

    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type',
        'expression', 'table', 'd3format', 'is_restricted', 'warning_text']
    description_columns = {
            if 'dimension' not in dimension_spec:
                raise ValueError('Dimension Spec is missing `dimension`')
            # `outputName` should be the same as the `column_name`
            if dimension_spec['outputName'] != col.column_name:
                raise ValueError(
                    '`outputName` [{}] unequal to `column_name` [{}]'.format(
                        dimension_spec['outputName'], col.column_name))

    def post_update(self, col):
        col.refresh_metrics()

    def post_add(self, col):
        self.post_update(col)


appbuilder.add_view_no_menu(DruidColumnInlineView)


class DruidMetricInlineView(CompactCRUDMixin, SupersetModelView):  # noqa
    datamodel = SQLAInterface(models.DruidMetric)

    list_title = _('List Druid Metric')
    show_title = _('Show Druid Metric')
    add_title = _('Add Druid Metric')
    edit_title = _('Edit Druid Metric')

    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type', 'json',
        'datasource', 'd3format', 'is_restricted', 'warning_text'
    ]
Example #8
0
        'column_name': _('Column'),
        'verbose_name': _('Verbose Name'),
        'description': _('Description'),
        'groupby': _('Groupable'),
        'filterable': _('Filterable'),
        'datasource': _('Datasource'),
        # 'count_distinct': _('Count Distinct'),
        # 'sum': _('Sum'),
        # 'avg': _('Average'),
        # 'min': _('Min'),
        # 'max': _('Max'),
        'type': _('Type'),
    }


appbuilder.add_view_no_menu(PandasColumnInlineView)


class PandasMetricInlineView(CompactCRUDMixin, SupersetModelView,
                             DeleteMixin):  # noqa
    datamodel = SQLAInterface(PandasMetric)

    list_title = _('List Metrics')
    show_title = _('Show Metric')
    add_title = _('Add Metric')
    edit_title = _('Edit Metric')

    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type', 'source',
        'expression', 'datasource', 'd3format', 'is_restricted', 'warning_text'
Example #9
0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from flask import g, redirect
from flask_appbuilder import expose
from flask_appbuilder.security.decorators import has_access

from superset import appbuilder, db
from superset.models import core as models
from .base import BaseSupersetView


class Dashboard(BaseSupersetView):
    """The base views for Superset!"""
    @has_access
    @expose("/new/")
    def new(self):  # pylint: disable=no-self-use
        """Creates a new, blank dashboard and redirects to it in edit mode"""
        new_dashboard = models.Dashboard(
            dashboard_title="[ untitled dashboard ]", owners=[g.user])
        db.session.add(new_dashboard)
        db.session.commit()
        return redirect(f"/superset/dashboard/{new_dashboard.id}/?edit=true")


appbuilder.add_view_no_menu(Dashboard)
Example #10
0
            '(http://elastic.io/docs/latest/querying/dimensionspecs.html). '
            'Make sure to input valid JSON and that the '
            '`outputName` matches the `column_name` defined '
            'above.',
            True),
    }

    def post_update(self, col):
        col.generate_metrics()
        validate_json(col.json)

    def post_add(self, col):
        self.post_update(col)


appbuilder.add_view_no_menu(ElasticColumnInlineView)


class ElasticMetricInlineView(CompactCRUDMixin, SupersetModelView):  # noqa
    datamodel = SQLAInterface(models.ElasticMetric)
    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type', 'json',
        'datasource', 'd3format', 'is_restricted']
    add_columns = edit_columns
    page_size = 500
    validators_columns = {
        'json': [validate_json],
    }
    description_columns = {
        'metric_type': markdown(
Example #11
0
        datasource_type = datasource.get('type')
        orm_datasource = ConnectorRegistry.get_datasource(
            datasource_type, datasource_id, db.session)

        if not check_ownership(orm_datasource, raise_if_false=False):
            return json_error_response(
                __(
                    'You are not authorized to modify '
                    'this data source configuration'),
                status='401',
            )

        if 'owners' in datasource:
            datasource['owners'] = db.session.query(orm_datasource.owner_class).filter(
                orm_datasource.owner_class.id.in_(datasource['owners'])).all()
        orm_datasource.update_from_object(datasource)
        data = orm_datasource.data
        db.session.commit()
        return self.json_response(data)

    @expose('/external_metadata/<datasource_type>/<datasource_id>/')
    @has_access_api
    def external_metadata(self, datasource_type=None, datasource_id=None):
        """Gets column info from the source system"""
        orm_datasource = ConnectorRegistry.get_datasource(
            datasource_type, datasource_id, db.session)
        return self.json_response(orm_datasource.external_metadata())


appbuilder.add_view_no_menu(Datasource)
Example #12
0
            and_(
                TaggedObject.object_id == superset.models.core.Slice.id,
                TaggedObject.object_type == ObjectTypes.chart,
            ),
        ).outerjoin(
            SavedQuery,
            and_(
                TaggedObject.object_id == SavedQuery.id,
                TaggedObject.object_type == ObjectTypes.query,
            ),
        ).group_by(TaggedObject.object_id, TaggedObject.object_type)

        objects = [
            {
                'id': get_attribute(obj, 'id'),
                'type': obj.TaggedObject.object_type.name,
                'name': get_name(obj),
                'url': get_attribute(obj, 'url'),
                'changed_on': get_attribute(obj, 'changed_on'),
                'created_by': get_attribute(obj, 'created_by_fk'),
                'creator': get_creator(obj),
            }
            for obj in query if get_attribute(obj, 'id')
        ]

        return json_success(json.dumps(objects, default=utils.core.json_int_dttm_ser))


app.url_map.converters['object_type'] = ObjectTypeConverter
appbuilder.add_view_no_menu(TagView)
Example #13
0
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from flask import g, redirect
from flask_appbuilder import expose
from flask_appbuilder.security.decorators import has_access

from superset import appbuilder, db
from superset.models import core as models
from .base import BaseSupersetView


class Dashboard(BaseSupersetView):
    """The base views for Superset!"""

    @has_access
    @expose('/new/')
    def new(self):
        """Creates a new, blank dashboard and redirects to it in edit mode"""
        new_dashboard = models.Dashboard(
            dashboard_title='[ untitled dashboard ]',
            owners=[g.user],
        )
        db.session.add(new_dashboard)
        db.session.commit()
        return redirect(f'/superset/dashboard/{new_dashboard.id}/?edit=true')


appbuilder.add_view_no_menu(Dashboard)
    @expose("/geocoding/progress", methods=["GET"])
    def progress(self) -> Response:
        """
        Method to check the progress of the geocoding task
        :return: GeoCoding Object
        """
        return json_success(
            json.dumps(self.geocoder.progress, default=lambda x: x.__dict__))

    @api
    @has_access_api
    @expose("/geocoding/interrupt", methods=["POST"])
    def interrupt(self) -> Response:
        """ Used for interrupting the geocoding process """
        self.geocoder.interruptflag = True
        return json_success('"OK"')


appbuilder.add_view_no_menu(Geocoder)

appbuilder.add_link(
    "Geocode Addresses",
    label=__("Geocode Addresses"),
    href="/geocoder/geocoding",
    icon="fa-globe",
    category="Sources",
    category_label=__("Sources"),
    category_icon="fa-wrench",
)
appbuilder.add_separator("Sources")
Example #15
0
        "sql",
        "extra_json",
    ]
    add_columns = [
        "label", "db_id", "schema", "description", "sql", "extra_json"
    ]
    edit_columns = add_columns
    show_columns = add_columns + ["id"]

    @has_access_api
    @expose("show/<pk>")
    def show(self, pk):
        return super().show(pk)


appbuilder.add_view_no_menu(SavedQueryViewApi)
appbuilder.add_view_no_menu(SavedQueryView)


class TabStateView(BaseSupersetView):
    def _get_owner_id(self, tab_state_id):
        return db.session.query(
            TabState.user_id).filter_by(id=tab_state_id).scalar()

    @has_access_api
    @expose("/", methods=["POST"])
    def post(self):
        query_editor = json.loads(request.form["queryEditor"])
        tab_state = TabState(
            user_id=g.user.get_id(),
            label=query_editor.get("title", "Untitled Query"),
Example #16
0

class Dashboard(BaseSupersetView):
    """The base views for Superset!"""
    @has_access
    @expose("/new/")
    def new(self):  # pylint: disable=no-self-use
        """Creates a new, blank dashboard and redirects to it in edit mode"""
        new_dashboard = models.Dashboard(
            dashboard_title="[ untitled dashboard ]", owners=[g.user])
        db.session.add(new_dashboard)
        db.session.commit()
        return redirect(f"/superset/dashboard/{new_dashboard.id}/?edit=true")


appbuilder.add_view_no_menu(Dashboard)


class DashboardModelViewAsync(DashboardModelView):  # pylint: disable=too-many-ancestors
    route_base = "/dashboardasync"
    list_columns = [
        "id",
        "dashboard_link",
        "creator",
        "modified",
        "dashboard_title",
        "changed_on",
        "url",
        "changed_by_name",
    ]
    label_columns = {
        os.remove(path)
        # Go back to welcome page / splash screen
        message = _(
            'CSV file "%(csv_filename)s" uploaded to table "%(table_name)s" in '
            'database "%(db_name)s"',
            csv_filename=csv_filename,
            table_name=form.name.data,
            db_name=table.database.database_name,
        )
        flash(message, "info")
        stats_logger.incr("successful_csv_upload")
        return redirect("/tablemodelview/list/")


appbuilder.add_view_no_menu(CsvToDatabaseView)


class DatabaseTablesAsync(DatabaseView):  # pylint: disable=too-many-ancestors
    list_columns = ["id", "all_table_names_in_database", "all_schema_names"]


appbuilder.add_view_no_menu(DatabaseTablesAsync)


class DatabaseAsync(DatabaseView):  # pylint: disable=too-many-ancestors
    list_columns = [
        "id",
        "database_name",
        "expose_in_sqllab",
        "allow_ctas",
Example #18
0
            if 'dimension' not in dimension_spec:
                raise ValueError('Dimension Spec is missing `dimension`')
            # `outputName` should be the same as the `column_name`
            if dimension_spec['outputName'] != col.column_name:
                raise ValueError(
                    '`outputName` [{}] unequal to `column_name` [{}]'
                    .format(dimension_spec['outputName'], col.column_name))

    def post_update(self, col):
        col.refresh_metrics()

    def post_add(self, col):
        self.post_update(col)


appbuilder.add_view_no_menu(DruidColumnInlineView)


class DruidMetricInlineView(CompactCRUDMixin, SupersetModelView):  # noqa
    datamodel = SQLAInterface(models.DruidMetric)

    list_title = _('List Druid Metric')
    show_title = _('Show Druid Metric')
    add_title = _('Add Druid Metric')
    edit_title = _('Edit Druid Metric')

    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type', 'json',
        'datasource', 'd3format', 'is_restricted', 'warning_text']
    add_columns = edit_columns
Example #19
0
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from flask import g, redirect
from flask_appbuilder import expose
from flask_appbuilder.security.decorators import has_access

from superset import appbuilder, db
from superset.models import core as models
from .base import BaseSupersetView


class WWD(BaseSupersetView):
    @has_access
    @expose('/wwd/')
    def new(self):
        return self.render_template('superset/base.html')


appbuilder.add_view_no_menu(WWD)
Example #20
0
    }

    def pre_add(self, obj):
        obj.user = g.user

    def pre_update(self, obj):
        self.pre_add(obj)


class SavedQueryViewApi(SavedQueryView):
    show_columns = ['label', 'db_id', 'schema', 'description', 'sql']
    add_columns = show_columns
    edit_columns = add_columns


appbuilder.add_view_no_menu(SavedQueryViewApi)
appbuilder.add_view_no_menu(SavedQueryView)

appbuilder.add_link(
    __('Saved Queries'),
    href='/sqllab/my_queries/',
    icon='fa-save',
    category='SQL Lab')


class SqlLab(BaseSupersetView):
    """The base views for Superset!"""
    @expose('/my_queries/')
    def my_queries(self):
        """Assigns a list of found users to the given role."""
        return redirect(
Example #21
0
        'groupby': _("Groupable"),
        'filterable': _("Filterable"),
        'table': _("Table"),
        'count_distinct': _("Count Distinct"),
        'sum': _("Sum"),
        'min': _("Min"),
        'max': _("Max"),
        'expression': _("Expression"),
        'is_dttm': _("Is temporal"),
        'python_date_format': _("Datetime Format"),
        'database_expression': _("Database Expression"),
        'type': _('Type'),
    }


appbuilder.add_view_no_menu(TableColumnInlineView)


class SqlMetricInlineView(CompactCRUDMixin, SupersetModelView):  # noqa
    datamodel = SQLAInterface(models.SqlMetric)

    list_title = _('List Metrics')
    show_title = _('Show Metric')
    add_title = _('Add Metric')
    edit_title = _('Edit Metric')

    list_columns = ['metric_name', 'verbose_name', 'metric_type']
    edit_columns = [
        'metric_name', 'description', 'verbose_name', 'metric_type',
        'expression', 'table', 'd3format', 'is_restricted', 'warning_text'
    ]
Example #22
0
import json

from flask import g, request
from flask_appbuilder import expose
from flask_appbuilder.security.decorators import has_access_api

from superset import appbuilder, security_manager
from superset.common.query_context import QueryContext
from superset.models.core import Log
from .base import api, BaseSupersetView, data_payload_response, handle_api_exception


class Api(BaseSupersetView):
    @Log.log_this
    @api
    @handle_api_exception
    @has_access_api
    @expose('/v1/query/', methods=['POST'])
    def query(self):
        """
        Takes a query_obj constructed in the client and returns payload data response
        for the given query_obj.
        """
        query_context = QueryContext(**json.loads(request.form.get('query_context')))
        security_manager.assert_datasource_permission(query_context.datasource, g.user)
        payload_json = query_context.get_data()
        return data_payload_response(payload_json)


appbuilder.add_view_no_menu(Api)