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
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)
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)
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()
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()
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()
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()
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()
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
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
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' })
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
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()
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)
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]
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)
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()
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
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' })
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()
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 ]
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 ]
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' })
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()
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' })