Esempio n. 1
0
    def post(self, data_source_id):

        req = request.get_json(True)

        if req:
            if not req.has_key("type"):
                abort(400)

            if req["type"] == "column":
                data_source = get_object_or_404(models.DataSourceColumn.get_by_id, data_source_id)
            elif req["type"] == "table":
                data_source = get_object_or_404(models.DataSourceTable.get_by_id, data_source_id)
            else:
                abort(400)

            if req["type"] == "column" and req.has_key("joins"):
                data_source.joins = req["joins"]
            if req.has_key("description"):
                data_source.description = req["description"]
            if req.has_key("tags"):
                data_source.tags = req["tags"]

            data_source.save()

            return data_source.to_dict(all=True)
        else:
            abort(400)
Esempio n. 2
0
    def get(self, query_id=None, query_result_id=None, filetype='json'):
        # TODO:
        # This method handles two cases: retrieving result by id & retrieving result by query id.
        # They need to be split, as they have different logic (for example, retrieving by query id
        # should check for query parameters and shouldn't cache the result).
        should_cache = query_result_id is not None
        if query_result_id is None and query_id is not None:
            query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
            if query:
                query_result_id = query._data['latest_query_data']

        if query_result_id:
            query_result = get_object_or_404(models.QueryResult.get_by_id_and_org, query_result_id, self.current_org)
        else:
            query_result = None

        if query_result:
            require_access(query_result.data_source.groups, self.current_user, view_only)

            if isinstance(self.current_user, models.ApiUser):
                event = {
                    'user_id': None,
                    'org_id': self.current_org.id,
                    'action': 'api_get',
                    'timestamp': int(time.time()),
                    'api_key': self.current_user.name,
                    'file_type': filetype,
                    'user_agent': request.user_agent.string,
                    'ip': request.remote_addr
                }

                if query_id:
                    event['object_type'] = 'query'
                    event['object_id'] = query_id
                else:
                    event['object_type'] = 'query_result'
                    event['object_id'] = query_result_id

                record_event.delay(event)

            if filetype == 'json':
                response = self.make_json_response(query_result)
            elif filetype == 'xlsx':
                response = self.make_excel_response(query_result)
            else:
                response = self.make_csv_response(query_result)

            if len(settings.ACCESS_CONTROL_ALLOW_ORIGIN) > 0:
                self.add_cors_headers(response.headers)

            if should_cache:
                response.headers.add_header('Cache-Control', 'max-age=%d' % ONE_YEAR)

            return response

        else:
            abort(404, message='No cached result found for this query.')
Esempio n. 3
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)
        require_access(query, current_user, view_only)

        related_queries_ids = [p['queryId'] for p in query.parameters if p['type'] == 'query']
        if int(dropdown_query_id) not in related_queries_ids:
            dropdown_query = get_object_or_404(models.Query.get_by_id_and_org, dropdown_query_id, self.current_org)
            require_access(dropdown_query.data_source, current_user, view_only)

        return dropdown_values(dropdown_query_id)
Esempio n. 4
0
    def post(self, object_type, object_id):
        model = get_model_from_type(object_type)
        obj = get_object_or_404(model.get_by_id_and_org, object_id, self.current_org)

        require_admin_or_owner(obj.user_id)

        req = request.get_json(True)

        access_type = req['access_type']

        if access_type not in ACCESS_TYPES:
            abort(400, message='Unknown access type.')

        try:
            grantee = User.get_by_id_and_org(req['user_id'], self.current_org)
        except User.DoesNotExist:
            abort(400, message='User not found.')

        permission = AccessPermission.grant(obj, access_type, grantee, self.current_user)

        self.record_event({
            'action': 'grant_permission',
            'object_id': object_id,
            'object_type': object_type,
            'access_type': access_type,
            'grantee': grantee.id
        })

        return permission.to_dict()
Esempio n. 5
0
    def post(self, query_id):
        query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
        query_def = request.get_json(force=True)

        require_object_modify_permission(query, self.current_user)

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

        if 'latest_query_data_id' in query_def:
            query_def['latest_query_data'] = query_def.pop('latest_query_data_id')

        if 'data_source_id' in query_def:
            query_def['data_source'] = query_def.pop('data_source_id')

        query_def['last_modified_by'] = self.current_user
        query_def['changed_by'] = self.current_user

        try:
            query.update_instance(**query_def)
        except models.ConflictDetectedError:
            abort(409)

        # old_query = copy.deepcopy(query.to_dict())
        # new_change = query.update_instance_tracked(changing_user=self.current_user, old_object=old_query, **query_def)
        # abort(409) # HTTP 'Conflict' status code

        result = query.to_dict(with_visualizations=True)
        return result
Esempio n. 6
0
def public_dashboard(token, org_slug=None):
    # TODO: verify object is a dashboard?
    if not isinstance(current_user, models.ApiUser):
        api_key = get_object_or_404(models.ApiKey.get_by_api_key, token)
        dashboard = api_key.object
    else:
        dashboard = current_user.object

    user = {
        'permissions': [],
        'apiKey': current_user.id
    }

    headers = {
        'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate'
    }

    record_event(current_org, current_user, {
        'action': 'view',
        'object_id': dashboard.id,
        'object_type': 'dashboard',
        'public': True,
        'headless': 'embed' in request.args,
        'referer': request.headers.get('Referer')
    })

    response = render_template("public.html",
                               headless='embed' in request.args,
                               user=json.dumps(user),
                               seed_data=json_dumps({
                                 'dashboard': serializers.public_dashboard(dashboard)
                               }),
                               client_config=json.dumps(settings.COMMON_CLIENT_CONFIG))

    return response, 200, headers
Esempio n. 7
0
    def get(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org, data_source_id, self.current_org)
        require_access(data_source.groups, self.current_user, view_only)
        refresh = request.args.get('refresh') is not None
        schema = data_source.get_schema(refresh)

        return schema
Esempio n. 8
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

        if has_access(query, self.current_user, allow_executing_with_view_only_permissions):
            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
Esempio n. 9
0
    def get(self, object_type, object_id, access_type):
        model = get_model_from_type(object_type)
        obj = get_object_or_404(model.get_by_id_and_org, object_id, self.current_org)

        has_access = AccessPermission.exists(obj, access_type, self.current_user)

        return {'response': has_access}
Esempio n. 10
0
    def get(self, query_id):
        q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
        require_access(q.groups, self.current_user, view_only)

        result = q.to_dict(with_visualizations=True)
        result['can_edit'] = can_modify(q, self.current_user)
        return result
Esempio n. 11
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.groups, self.current_user, not_view_only)

        parameter_values = collect_parameters_from_request(request.args)

        return run_query(query.data_source, parameter_values, query.query, query.id)
Esempio n. 12
0
    def get(self, query_id=None, query_result_id=None, filetype='json'):
        should_cache = query_result_id is not None
        if query_result_id is None and query_id is not None:
            query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
            if query:
                query_result_id = query._data['latest_query_data']

        if query_result_id:
            query_result = get_object_or_404(models.QueryResult.get_by_id_and_org, query_result_id, self.current_org)

        if query_result:
            if isinstance(self.current_user, models.ApiUser):
                event = {
                    'user_id': None,
                    'org_id': self.current_org.id,
                    'action': 'api_get',
                    'timestamp': int(time.time()),
                    'api_key': self.current_user.id,
                    'file_type': filetype
                }

                if query_id:
                    event['object_type'] = 'query'
                    event['object_id'] = query_id
                else:
                    event['object_type'] = 'query_result'
                    event['object_id'] = query_result_id

                record_event.delay(event)

            if filetype == 'json':
                response = self.make_json_response(query_result)
            elif filetype == 'xlsx':
                response = self.make_excel_response(query_result)
            else:
                response = self.make_csv_response(query_result)

            if len(settings.ACCESS_CONTROL_ALLOW_ORIGIN) > 0:
                self.add_cors_headers(response.headers)

            if should_cache:
                response.headers.add_header('Cache-Control', 'max-age=%d' % ONE_YEAR)

            return response

        else:
            abort(404)
Esempio n. 13
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)
Esempio n. 14
0
    def get(self, query_id):
        q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
        require_access(q.groups, self.current_user, view_only)

        if q:
            return q.to_dict(with_visualizations=True)
        else:
            abort(404, message="Query not found.")
Esempio n. 15
0
    def post(self, join_id):
        join = get_object_or_404(models.DataSourceJoin.get_by_id, join_id)

        kwargs = request.get_json(True)

        join.update_instance(**kwargs)

        return join.to_dict(all=True)
Esempio n. 16
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
        data_sources = models.DataSource.select(models.DataSource, models.DataSourceGroup.view_only)\
            .join(models.DataSourceGroup)\
            .where(models.DataSourceGroup.group == group)

        return [ds.to_dict(with_permissions=True) for ds in data_sources]
Esempio n. 17
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'
     })
Esempio n. 18
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)

        try:
            data_source.query_runner.test_connection()
        except Exception as e:
            return {"message": unicode(e), "ok": False}
        else:
            return {"message": "success", "ok": True}
Esempio n. 19
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)
        snippet.delete_instance()

        self.record_event({
            'action': 'delete',
            'object_id': snippet.id,
            'object_type': 'query_snippet'
        })
Esempio n. 20
0
 def delete(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)
     self.record_event({
         'action': 'delete',
         'object_id': visualization_id,
         'object_type': 'Visualization'
     })
     models.db.session.delete(vis)
     models.db.session.commit()
Esempio n. 21
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()
Esempio n. 22
0
    def get(self, dashboard_slug=None):
        dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org, dashboard_slug, self.current_org)
        response = dashboard.to_dict(with_widgets=True, user=self.current_user)

        api_key = models.ApiKey.get_by_object(dashboard)
        if api_key:
            response['public_url'] = url_for('redash.public_dashboard', token=api_key.api_key, org_slug=self.current_org.slug, _external=True)
            response['api_key'] = api_key.api_key

        return response
Esempio n. 23
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
        data_sources = (models.DataSource.query
                        .join(models.DataSourceGroup)
                        .filter(models.DataSourceGroup.group == group))

        return [ds.to_dict(with_permissions_for=group) for ds in data_sources]
Esempio n. 24
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)
        require_admin_or_owner(query.user_id)
        query.archive(self.current_user)
        models.db.session.commit()
Esempio n. 25
0
    def get(self, user_id):
        require_permission_or_owner('list_users', user_id)
        user = get_object_or_404(models.User.get_by_id_and_org, user_id, self.current_org)

        self.record_event({
            'action': 'view',
            'object_id': user_id,
            'object_type': 'user',
        })

        return user.to_dict(with_api_key=is_admin_or_owner(user_id))
Esempio n. 26
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()
Esempio n. 27
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)
        forked_query = query.fork(self.current_user)
        models.db.session.commit()
        return forked_query.to_dict(with_visualizations=True)
Esempio n. 28
0
    def delete(self, alert_id, subscriber_id):
        
        subscription = get_object_or_404(models.AlertSubscription.get_by_id, subscriber_id)
        require_admin_or_owner(subscription.user.id)
        subscription.delete_instance()

        self.record_event({
            'action': 'unsubscribe',
            'timestamp': int(time.time()),
            'object_id': alert_id,
            'object_type': 'alert'
        })
Esempio n. 29
0
    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_admin_or_owner(query.user_id)

        kwargs['options'] = json.dumps(kwargs['options'])
        kwargs['query'] = query

        vis = models.Visualization.create(**kwargs)

        return vis.to_dict(with_query=False)
Esempio n. 30
0
    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

        vis = models.Visualization(**kwargs)
        models.db.session.add(vis)
        models.db.session.commit()
        return serialize_visualization(vis, with_query=False)
Esempio n. 31
0
    def get(self, dashboard_id=None):
        """
        Retrieves a dashboard.

        :qparam number id: Id 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
        """
        if request.args.get("legacy") is not None:
            fn = models.Dashboard.get_by_slug_and_org
        else:
            fn = models.Dashboard.get_by_id_and_org

        dashboard = get_object_or_404(fn, dashboard_id, self.current_org)
        response = DashboardSerializer(
            dashboard, with_widgets=True, user=self.current_user
        ).serialize()

        api_key = models.ApiKey.get_by_object(dashboard)
        if api_key:
            response["public_url"] = url_for(
                "redash.public_dashboard",
                token=api_key.api_key,
                org_slug=self.current_org.slug,
                _external=True,
            )
            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
Esempio n. 32
0
 def delete(self, visualization_id):
     vis = get_object_or_404(models.Visualization.get_by_id_and_org,
                             visualization_id, self.current_org)
     require_admin_or_owner(vis.query_rel.user_id)
     models.db.session.delete(vis)
     models.db.session.commit()
Esempio n. 33
0
    def post(self):
        """
        Create a new query.

        :<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

        .. _query-response-label:

        :>json number id: Query ID
        :>json number latest_query_data_id: ID for latest output data from this query
        :>json string name:
        :>json string description:
        :>json string query: Query text
        :>json string query_hash: Hash of query text
        :>json string schedule: Schedule interval, in seconds, for repeated execution of this query
        :>json string api_key: Key for public access to this query's results.
        :>json boolean is_archived: Whether this query is displayed in indexes and search results or not.
        :>json boolean is_draft: Whether this query is a draft or not
        :>json string updated_at: Time of last modification, in ISO format
        :>json string created_at: Time of creation, in ISO format
        :>json number data_source_id: ID of the data source this query will run on
        :>json object options: Query options
        :>json number version: Revision version (for update conflict avoidance)
        :>json number user_id: ID of query creator
        :>json number last_modified_by_id: ID of user who last modified this query
        :>json string retrieved_at: Time when query results were last retrieved, in ISO format (may be null)
        :>json number runtime: Runtime of last query execution, in seconds (may be null)
        """
        query_def = request.get_json(force=True)
        LOG.info('** receive queries create param: %s' % query_def)
        group = query_def.pop('group')
        group_ref = models.Group.query\
                .filter(models.Group.name == group)\
                .first()

        query_obj = None
        query_id = query_def.pop('query_id', None)
        if query_id:
            query_obj = get_object_or_404(models.Query.get_by_id_and_org,
                                          query_id, self.current_org)

        data_source = models.DataSource.get_by_id_and_org(
            query_def.pop("data_source_id"), self.current_org)
        require_access(data_source, self.current_user, not_view_only)
        require_access_to_dropdown_queries(self.current_user, query_def)

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

        if query_obj:
            for field in ["user", "org"]:
                query_def.pop(field, None)
            if "query" in query_def:
                query_def["query_text"] = query_def.pop("query")

            if "tags" in query_def:
                query_def["tags"] = [tag for tag in query_def["tags"] if tag]
            query_def["last_modified_by"] = self.current_user
            query_def["changed_by"] = self.current_user
            if "version" in query_def and query_def[
                    "version"] != query_obj.version:
                abort(409)

            try:
                self.update_model(query_obj, query_def)
                query_obj.group_id = group_ref.id
                models.db.session.commit()
            except StaleDataError:
                abort(409)
            query = query_obj

        else:
            query_def["query_text"] = query_def.pop("query")
            query_def["user"] = self.current_user
            query_def["data_source"] = data_source
            query_def["org"] = self.current_org
            query_def["is_draft"] = True
            query_def["group_id"] = group_ref.id
            LOG.info('** handle queries query ref data: %s' % query_def)
            query = models.Query.create(**query_def)
            models.db.session.add(query)
            models.db.session.commit()

            self.record_event({
                "action": "create",
                "object_id": query.id,
                "object_type": "query"
            })

        return QuerySerializer(query, with_visualizations=True).serialize()
Esempio n. 34
0
 def delete(self, alert_id):
     alert = get_object_or_404(models.Alert.get_by_id_and_org, alert_id,
                               self.current_org)
     require_admin_or_owner(alert.user_id)
     models.db.session.delete(alert)
     models.db.session.commit()
Esempio n. 35
0
    def get(self, user_id):
        require_permission_or_owner('list_users', user_id)
        user = get_object_or_404(models.User.get_by_id_and_org, user_id, self.current_org)

        return user.to_dict(with_api_key=is_admin_or_owner(user_id))
Esempio n. 36
0
    def get(self, query_id=None, query_result_id=None, filetype='json'):
        """
        Retrieve query results.

        :param number query_id: The ID of the query whose results should be fetched
        :param number query_result_id: the ID of the query result to fetch
        :param string filetype: Format to return. One of 'json', 'xlsx', or 'csv'. Defaults to 'json'.

        :<json number id: Query result ID
        :<json string query: Query that produced this result
        :<json string query_hash: Hash code for query text
        :<json object data: Query output
        :<json number data_source_id: ID of data source that produced this result
        :<json number runtime: Length of execution time in seconds
        :<json string retrieved_at: Query retrieval date/time, in ISO format
        """
        # TODO:
        # This method handles two cases: retrieving result by id & retrieving result by query id.
        # They need to be split, as they have different logic (for example, retrieving by query id
        # should check for query parameters and shouldn't cache the result).
        should_cache = query_result_id is not None

        parameter_values = collect_parameters_from_request(request.args)
        max_age = int(request.args.get('maxAge', 0))

        query_result = None
        query = None

        if query_result_id:
            query_result = get_object_or_404(
                models.QueryResult.get_by_id_and_org, query_result_id,
                self.current_org)

        if query_id is not None:
            query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                      self.current_org)

            if query_result is None and query is not None and query.latest_query_data_id is not None:
                query_result = get_object_or_404(
                    models.QueryResult.get_by_id_and_org,
                    query.latest_query_data_id, self.current_org)

            if query is not None and query_result is not None and self.current_user.is_api_user(
            ):
                if query.query_hash != query_result.query_hash:
                    abort(404,
                          message='No cached result found for this query.')

        if query_result:
            require_access(query_result.data_source, self.current_user,
                           view_only)

            if isinstance(self.current_user, models.ApiUser):
                event = {
                    'user_id': None,
                    'org_id': self.current_org.id,
                    'action': 'api_get',
                    'api_key': self.current_user.name,
                    'file_type': filetype,
                    'user_agent': request.user_agent.string,
                    'ip': request.remote_addr
                }

                if query_id:
                    event['object_type'] = 'query'
                    event['object_id'] = query_id
                else:
                    event['object_type'] = 'query_result'
                    event['object_id'] = query_result_id

                self.record_event(event)

            if filetype == 'json':
                response = self.make_json_response(query_result)
            elif filetype == 'xlsx':
                response = self.make_excel_response(query_result)
            else:
                response = self.make_csv_response(query_result)

            if len(settings.ACCESS_CONTROL_ALLOW_ORIGIN) > 0:
                self.add_cors_headers(response.headers)

            if should_cache:
                response.headers.add_header('Cache-Control',
                                            'private,max-age=%d' % ONE_YEAR)

            filename = get_download_filename(query_result, query, filetype)

            response.headers.add_header(
                "Content-Disposition",
                'attachment; filename="{}"'.format(filename.encode("utf-8")))

            return response

        else:
            abort(404, message='No cached result found for this query.')
Esempio n. 37
0
    def get(self, data_source_id):
        data_source = get_object_or_404(models.DataSource.get_by_id_and_org,
                                        data_source_id, self.current_org)
        schema = data_source.get_schema()

        return schema
Esempio n. 38
0
 def get(self, alert_id):
     alert = get_object_or_404(models.Alert.get_by_id_and_org, alert_id,
                               self.current_org)
     require_access(alert.groups, self.current_user, view_only)
     return alert.to_dict()
Esempio n. 39
0
 def get(self, snippet_id):
     snippet = get_object_or_404(models.QuerySnippet.get_by_id_and_org,
                                 snippet_id, self.current_org)
     return snippet.to_dict()
Esempio n. 40
0
    def get(self, query_id=None, query_result_id=None, filetype="json"):
        """
        Retrieve query results.

        :param number query_id: The ID of the query whose results should be fetched
        :param number query_result_id: the ID of the query result to fetch
        :param string filetype: Format to return. One of 'json', 'xlsx', or 'csv'. Defaults to 'json'.

        :<json number id: Query result ID
        :<json string query: Query that produced this result
        :<json string query_hash: Hash code for query text
        :<json object data: Query output
        :<json number data_source_id: ID of data source that produced this result
        :<json number runtime: Length of execution time in seconds
        :<json string retrieved_at: Query retrieval date/time, in ISO format
        """
        # TODO:
        # This method handles two cases: retrieving result by id & retrieving result by query id.
        # They need to be split, as they have different logic (for example, retrieving by query id
        # should check for query parameters and shouldn't cache the result).
        should_cache = query_result_id is not None

        query_result = None
        query = None

        if query_result_id:
            query_result = get_object_or_404(
                models.QueryResult.get_by_id_and_org, query_result_id,
                self.current_org)

        if query_id is not None:
            query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                      self.current_org)

            if (query_result is None and query is not None
                    and query.latest_query_data_id is not None):
                query_result = get_object_or_404(
                    models.QueryResult.get_by_id_and_org,
                    query.latest_query_data_id,
                    self.current_org,
                )

            if (query is not None and query_result is not None
                    and self.current_user.is_api_user()):
                if query.query_hash != query_result.query_hash:
                    abort(404,
                          message="No cached result found for this query.")

        if query_result:
            require_access(query_result.data_source, self.current_user,
                           view_only)

            if isinstance(self.current_user, models.ApiUser):
                event = {
                    "user_id": None,
                    "org_id": self.current_org.id,
                    "action": "api_get",
                    "api_key": self.current_user.name,
                    "file_type": filetype,
                    "user_agent": request.user_agent.string,
                    "ip": request.remote_addr,
                }

                if query_id:
                    event["object_type"] = "query"
                    event["object_id"] = query_id
                else:
                    event["object_type"] = "query_result"
                    event["object_id"] = query_result_id

                self.record_event(event)

            response_builders = {
                "json": self.make_json_response,
                "xlsx": self.make_excel_response,
                "csv": self.make_csv_response,
                "tsv": self.make_tsv_response,
            }
            response = response_builders[filetype](query_result)

            if len(settings.ACCESS_CONTROL_ALLOW_ORIGIN) > 0:
                self.add_cors_headers(response.headers)

            if should_cache:
                response.headers.add_header("Cache-Control",
                                            "private,max-age=%d" % ONE_YEAR)

            filename = get_download_filename(query_result, query, filetype)

            filenames = content_disposition_filenames(filename)
            response.headers.add("Content-Disposition", "attachment",
                                 **filenames)

            return response

        else:
            abort(404, message="No cached result found for this query.")
Esempio n. 41
0
 def delete(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)
     models.db.session.delete(vis)
     models.db.session.commit()
Esempio n. 42
0
 def delete(self, query_id):
     query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                               self.current_org)
     require_admin_or_owner(query.user_id)
     query.archive(self.current_user)