def get(self, visualization_id):
        """
        Retrieve a visualization.

        :param visualization_id: ID of visualization to fetch

        Responds with the :ref:`visualization <visualization-response-label>` contents.
        """
        vis = get_object_or_404(models.Visualization.get_by_id,
                                visualization_id)
        require_access(vis.query_rel, self.current_user, view_only)

        result = serialize_visualization(vis, True)

        api_key = models.ApiKey.get_by_object(vis)
        if api_key:
            result['api_key'] = api_key.api_key

        result['can_edit'] = can_modify(vis, self.current_user)

        self.record_event({
            'action': 'view',
            'object_id': visualization_id,
            'object_type': 'query',
        })

        return result
예제 #2
0
    def get(self, query_id, dropdown_query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        related_queries_ids = [
            p['queryId'] for p in query.parameters if p['type'] == 'query'
        ]
        if int(dropdown_query_id) not in related_queries_ids:
            abort(403)

        return dropdown_values(dropdown_query_id, should_require_access=False)
예제 #3
0
    def post(self, alert_id):
        req = request.get_json(True)
        params = project(req, ('options', 'name', 'query_id', 'rearm'))
        alert = get_object_or_404(models.Alert.get_by_id_and_org, alert_id,
                                  self.current_org)
        require_admin_or_owner(alert.user.id)

        self.update_model(alert, params)
        models.db.session.commit()

        return serialize_alert(alert)
예제 #4
0
    def post(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org,
                                        data_source_id, self.current_org)

        req = request.get_json(True)
        if req and "folder_id" in req:
            data_source.update_folder(req['folder_id'])
        else:
            abort(400)

        return data_source.to_dict()
예제 #5
0
    def post(self, query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        req = request.get_json(True)

        if req and "folder_id" in req:
            query.update_folder(req['folder_id'])
        else:
            abort(400)

        return query.to_dict()
예제 #6
0
    def delete(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org,
                                        data_source_id, self.current_org)
        data_source.resume()

        self.record_event({
            'action': 'resume',
            'object_id': data_source.id,
            'object_type': 'datasource'
        })
        return data_source.to_dict()
예제 #7
0
    def get(self, snippet_id):
        snippet = get_object_or_404(models.QuerySnippet.get_by_id_and_org,
                                    snippet_id, self.current_org)

        self.record_event({
            'action': 'view',
            'object_id': snippet_id,
            'object_type': 'query_snippet',
        })

        return snippet.to_dict()
예제 #8
0
    def post(self, dashboard_slug):
        dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org,
                                      dashboard_slug, self.current_org)

        req = request.get_json(True)
        if req and "folder_id" in req:
            dashboard.update_folder(req['folder_id'])
        else:
            abort(400)

        return dashboard.to_dict()
    def delete(self, visualization_id):
        """
        Archives a visualization.

        :param visualization_id: ID of the visualization to archive
        """
        vis = get_object_or_404(models.Visualization.get_by_id_and_org,
                                visualization_id, self.current_org)
        require_object_modify_permission(vis.query_rel, self.current_user)
        vis.archive(self.current_user)
        models.db.session.commit()
예제 #10
0
    def get(self, dashboard_slug=None):
        """
        Retrieves a dashboard.

        :qparam string slug: Slug of dashboard to retrieve.

        .. _dashboard-response-label:

        :>json number id: Dashboard ID
        :>json string name:
        :>json string slug:
        :>json number user_id: ID of the dashboard creator
        :>json string created_at: ISO format timestamp for dashboard creation
        :>json string updated_at: ISO format timestamp for last dashboard modification
        :>json number version: Revision number of dashboard
        :>json boolean dashboard_filters_enabled: Whether filters are enabled or not
        :>json boolean is_archived: Whether this dashboard has been removed from the index or not
        :>json boolean is_draft: Whether this dashboard is a draft or not.
        :>json array layout: Array of arrays containing widget IDs, corresponding to the rows and columns the widgets are displayed in
        :>json array widgets: Array of arrays containing :ref:`widget <widget-response-label>` data

        .. _widget-response-label:

        Widget structure:

        :>json number widget.id: Widget ID
        :>json number widget.width: Widget size
        :>json object widget.options: Widget options
        :>json number widget.dashboard_id: ID of dashboard containing this widget
        :>json string widget.text: Widget contents, if this is a text-box widget
        :>json object widget.visualization: Widget contents, if this is a visualization widget
        :>json string widget.created_at: ISO format timestamp for widget creation
        :>json string widget.updated_at: ISO format timestamp for last widget modification
        """
        dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org,
                                      dashboard_slug, self.current_org)
        response = serialize_dashboard(dashboard,
                                       with_widgets=True,
                                       user=self.current_user)

        api_key = models.ApiKey.get_by_object(dashboard)
        if api_key:
            response['api_key'] = api_key.api_key

        response['can_edit'] = can_modify(dashboard, self.current_user)

        self.record_event({
            'action': 'view',
            'object_id': dashboard.id,
            'object_type': 'dashboard',
        })

        return response
예제 #11
0
    def post(self, query_id):
        """
        Execute a saved query.

        :param number query_id: The ID of the query whose results should be fetched.
        :param object parameters: The parameter values to apply to the query.
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        """
        params = request.get_json(force=True)
        parameter_values = params.get('parameters')

        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)

        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)

        # allow_executing_with_view_only_permissions = query.parameterized.is_safe

        # TODO: Workaround, always allow APIKEY user
        if self.current_user.is_api_user:
            return run_query(query.parameterized, parameter_values,
                             query.data_source, query_id, max_age)
        elif not is_admin_or_owner(query.user_id):
            if models.QueryGroup.get_by_query_groups(
                    query, query.query_groups).first() is None:
                return {
                    'job': {
                        'status':
                        4,
                        'error':
                        'You do not have permission to run queries with this data source.'
                    }
                }, 403
            else:
                logger.debug("ok to run query...")
                return run_query(query.parameterized, parameter_values,
                                 query.data_source, query_id, max_age)
        else:
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403
예제 #12
0
    def delete(self, snippet_id):
        snippet = get_object_or_404(models.QuerySnippet.get_by_id_and_org,
                                    snippet_id, self.current_org)
        require_admin_or_owner(snippet.user.id)
        models.db.session.delete(snippet)
        models.db.session.commit()

        self.record_event({
            'action': 'delete',
            'object_id': snippet.id,
            'object_type': 'query_snippet'
        })
예제 #13
0
 def delete(self, object_id):
     dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org,
                                   object_id, self.current_org)
     models.Favorite.query.filter(
         models.Favorite.object == dashboard,
         models.Favorite.user == self.current_user).delete()
     models.db.session.commit()
     self.record_event({
         'action': 'unfavorite',
         'object_id': dashboard.id,
         'object_type': 'dashboard'
     })
    def post(self, visualization_id):
        vis = get_object_or_404(models.Visualization.get_by_id_and_org,
                                visualization_id, self.current_org)

        req = request.get_json(True)
        if req and "folder_id" in req:
            vis.update_folder(req['folder_id'])
        else:
            abort(400)

        d = serialize_visualization(vis, with_query=False)
        return d
예제 #15
0
    def post(self, query_id):
        """
        Modify a query.

        :param query_id: ID of query to update
        :<json number data_source_id: The ID of the data source this query will run on
        :<json string query: Query text
        :<json string name:
        :<json string description:
        :<json string schedule: Schedule interval, in seconds, for repeated execution of this query
        :<json object options: Query options

        Responds with the updated :ref:`query <query-response-label>` object.
        """
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)

        if not is_admin_or_owner(query.user_id):
            if models.QueryGroup.get_by_query_groups(
                    query, query.query_groups).first() is None:
                abort(404)

        query_def = request.get_json(force=True)

        #require_object_modify_permission(query, self.current_user)
        require_access_to_dropdown_queries(self.current_user, query_def)

        for field in [
                'id', 'created_at', 'api_key', 'visualizations',
                'latest_query_data', 'user', 'last_modified_by', 'org'
        ]:
            query_def.pop(field, None)

        if 'query' in query_def:
            query_def['query_text'] = query_def.pop('query')

        query_def['last_modified_by'] = self.current_user
        query_def['changed_by'] = self.current_user
        # SQLAlchemy handles the case where a concurrent transaction beats us
        # to the update. But we still have to make sure that we're not starting
        # out behind.
        if 'version' in query_def and query_def['version'] != query.version:
            abort(409)

        try:
            self.update_model(query, query_def)
            models.db.session.commit()
        except StaleDataError:
            abort(409)

        return QuerySerializer(query, with_visualizations=True).serialize()
예제 #16
0
    def delete(self, query_id):
        """
        Archives a query.

        :param query_id: ID of query to archive
        """
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        if not is_admin_or_owner(query.user_id):
            if models.QueryGroup.get_by_query_groups(
                    query, query.query_groups).first() is None:
                abort(404)
        query.archive(self.current_user)
        models.db.session.commit()
    def post(self):
        kwargs = request.get_json(force=True)

        query = get_object_or_404(models.Query.get_by_id_and_org,
                                  kwargs.pop('query_id'), self.current_org)
        require_object_modify_permission(query, self.current_user)

        kwargs['options'] = json_dumps(kwargs['options'])
        kwargs['query_rel'] = query
        kwargs['user'] = self.current_user

        vis = models.Visualization(**kwargs)
        models.db.session.add(vis)
        models.db.session.commit()
        return serialize_visualization(vis, with_query=False)
    def get(self, token):
        """
        Retrieve a public visualization.

        :param token: An API key for a public visualization.
        :>json representation of the visualization
        """

        api_key = get_object_or_404(models.ApiKey.get_by_api_key, token)
        vis = api_key.object

        if vis is None:
            abort(404)

        return public_visualization(vis)
예제 #19
0
    def get(self, group_id):
        group = get_object_or_404(models.Group.get_by_id_and_org, group_id,
                                  self.current_org)

        # TOOD: move to models
        queries = (models.Query.query.join(
            models.QueryGroup).filter(models.QueryGroup.group == group))

        self.record_event({
            'action': 'list',
            'object_id': group_id,
            'object_type': 'group',
        })

        return [query.to_dict(with_permissions_for=group) for query in queries]
예제 #20
0
    def get(self, token):
        """
        Retrieve a public dashboard.

        :param token: An API key for a public dashboard.
        :>json array widgets: An array of arrays of :ref:`public widgets <public-widget-label>`, corresponding to the rows and columns the widgets are displayed in
        """

        api_key = get_object_or_404(models.ApiKey.get_by_api_key, token)
        dashboard = api_key.object

        if dashboard is None:
            abort(404)

        return serializers.public_dashboard(dashboard)
예제 #21
0
    def post(self, snippet_id):
        req = request.get_json(True)
        params = project(req, ('trigger', 'description', 'snippet'))
        snippet = get_object_or_404(models.QuerySnippet.get_by_id_and_org,
                                    snippet_id, self.current_org)
        require_admin_or_owner(snippet.user.id)

        self.update_model(snippet, params)
        models.db.session.commit()

        self.record_event({
            'action': 'edit',
            'object_id': snippet.id,
            'object_type': 'query_snippet'
        })
        return snippet.to_dict()
예제 #22
0
    def post(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org,
                                        data_source_id, self.current_org)

        self.record_event({
            'action': 'test',
            'object_id': data_source_id,
            'object_type': 'datasource',
        })

        try:
            data_source.query_runner.test_connection()
        except Exception as e:
            return {"message": text_type(e), "ok": False}
        else:
            return {"message": "success", "ok": True}
    def post(self, visualization_id):
        vis = get_object_or_404(models.Visualization.get_by_id_and_org,
                                visualization_id, self.current_org)
        require_object_modify_permission(vis.query_rel, self.current_user)

        kwargs = request.get_json(force=True)
        if 'options' in kwargs:
            kwargs['options'] = json_dumps(kwargs['options'])

        kwargs.pop('id', None)
        kwargs.pop('query_id', None)

        self.update_model(vis, kwargs)
        d = serialize_visualization(vis, with_query=False)
        models.db.session.commit()
        return d
예제 #24
0
    def delete(self, query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        require_access(query, self.current_user, view_only)

        models.Favorite.query.filter(
            models.Favorite.object_id == query_id,
            models.Favorite.object_type == u'Query',
            models.Favorite.user == self.current_user,
        ).delete()
        models.db.session.commit()

        self.record_event({
            'action': 'favorite',
            'object_id': query.id,
            'object_type': 'query'
        })
예제 #25
0
    def post(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org,
                                        data_source_id, self.current_org)
        data = request.get_json(force=True, silent=True)
        if data:
            reason = data.get('reason')
        else:
            reason = request.args.get('reason')

        data_source.pause(reason)

        self.record_event({
            'action': 'pause',
            'object_id': data_source.id,
            'object_type': 'datasource'
        })
        return data_source.to_dict()
예제 #26
0
    def get(self, dashboard_id):
        dashboard = get_object_or_404(models.Dashboard.get_by_id_and_org,
                                      dashboard_id, self.current_org)

        # TOOD: move to models
        groups = (models.Group.query.join(models.DashboardGroup).filter(
            models.DashboardGroup.dashboard == dashboard))

        self.record_event({
            'action': 'list',
            'object_id': dashboard_id,
            'object_type': 'group',
        })

        return [
            serialize_groups_with_viewonly_for_dashboard(
                g, models.DashboardGroup.get_by_dashboard_group(dashboard, g))
            for g in groups
        ]
예제 #27
0
    def get(self, query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)

        # TOOD: move to models
        groups = (models.Group.query.join(
            models.QueryGroup).filter(models.QueryGroup.query_rel == query))

        self.record_event({
            'action': 'list',
            'object_id': query_id,
            'object_type': 'group',
        })

        return [
            serialize_groups_with_viewonly_for_query(
                g, models.QueryGroup.get_by_query_group(query, g))
            for g in groups
        ]
예제 #28
0
    def post(self, object_id):
        dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org,
                                      object_id, self.current_org)
        fav = models.Favorite(org_id=self.current_org.id,
                              object=dashboard,
                              user=self.current_user)
        models.db.session.add(fav)

        try:
            models.db.session.commit()
        except IntegrityError as e:
            if 'unique_favorite' in e.message:
                models.db.session.rollback()
            else:
                raise e

        self.record_event({
            'action': 'favorite',
            'object_id': dashboard.id,
            'object_type': 'dashboard'
        })
예제 #29
0
    def post(self, query_id):
        """
        Creates a new query, copying the query text from an existing one.

        :param query_id: ID of query to fork

        Responds with created :ref:`query <query-response-label>` object.
        """
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        require_access(query.data_source, self.current_user, not_view_only)
        forked_query = query.fork(self.current_user)
        models.db.session.commit()

        self.record_event({
            'action': 'fork',
            'object_id': query_id,
            'object_type': 'query',
        })

        return QuerySerializer(forked_query,
                               with_visualizations=True).serialize()
예제 #30
0
    def post(self, query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)
        require_access(query, self.current_user, view_only)

        fav = models.Favorite(org_id=self.current_org.id,
                              object=query,
                              user=self.current_user)
        models.db.session.add(fav)

        try:
            models.db.session.commit()
        except IntegrityError as e:
            if 'unique_favorite' in e.message:
                models.db.session.rollback()
            else:
                raise e

        self.record_event({
            'action': 'favorite',
            'object_id': query.id,
            'object_type': 'query'
        })