from flask import request from redash import statsd_client from redash.wsgi import api from redash.handlers.base import BaseResource class EventAPI(BaseResource): def post(self): events_list = request.get_json(force=True) for event in events_list: self.record_event(event) api.add_org_resource(EventAPI, '/api/events', endpoint='events') class MetricsAPI(BaseResource): def post(self): for stat_line in request.data.split(): stat, value = stat_line.split(':') statsd_client._send_stat('client.{}'.format(stat), value, 1) return "OK." api.add_resource(MetricsAPI, '/api/metrics/v1/send', endpoint='metrics')
new_row = False else: layout.append([widget.id]) else: layout.append([widget.id]) widget.dashboard.layout = json.dumps(layout) widget.dashboard.save() return { 'widget': widget.to_dict(), 'layout': layout, 'new_row': new_row } class WidgetAPI(BaseResource): @require_permission('edit_dashboard') def delete(self, widget_id): widget = models.Widget.get_by_id_and_org(widget_id, self.current_org) require_admin_or_owner(widget.dashboard.user_id) widget.delete_instance() return {'layout': widget.dashboard.layout} api.add_org_resource(WidgetListAPI, '/api/widgets', endpoint='widgets') api.add_org_resource(WidgetAPI, '/api/widgets/<int:widget_id>', endpoint='widget')
def get(self, alert_id): alert = models.Alert.get_by_id_and_org(alert_id, self.current_org) require_access(alert.groups, self.current_user, view_only) subscriptions = models.AlertSubscription.all(alert_id) return [s.to_dict() for s in subscriptions] class AlertSubscriptionResource(BaseResource): def delete(self, alert_id, subscriber_id): models.AlertSubscription.unsubscribe(alert_id, subscriber_id) require_admin_or_owner(subscriber_id) self.record_event({ 'action': 'unsubscribe', 'timestamp': int(time.time()), 'object_id': alert_id, 'object_type': 'alert' }) api.add_org_resource(AlertResource, '/api/alerts/<alert_id>', endpoint='alert') api.add_org_resource(AlertSubscriptionListResource, '/api/alerts/<alert_id>/subscriptions', endpoint='alert_subscriptions') api.add_org_resource(AlertSubscriptionResource, '/api/alerts/<alert_id>/subscriptions/<subscriber_id>', endpoint='alert_subscription') api.add_org_resource(AlertListResource, '/api/alerts', endpoint='alerts')
def post(self, dashboard_slug): dashboard_properties = request.get_json(force=True) # TODO: either convert all requests to use slugs or ids dashboard = models.Dashboard.get_by_id_and_org(dashboard_slug, self.current_org) dashboard.layout = dashboard_properties['layout'] dashboard.name = dashboard_properties['name'] dashboard.save() return dashboard.to_dict(with_widgets=True, user=self.current_user) @require_permission('edit_dashboard') def delete(self, dashboard_slug): dashboard = models.Dashboard.get_by_slug_and_org( dashboard_slug, self.current_org) dashboard.is_archived = True dashboard.save() return dashboard.to_dict(with_widgets=True, user=self.current_user) api.add_org_resource(DashboardListAPI, '/api/dashboards', endpoint='dashboards') api.add_org_resource(DashboardRecentAPI, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_org_resource(DashboardAPI, '/api/dashboards/<dashboard_slug>', endpoint='dashboard')
from redash import models from redash.wsgi import api from redash.permissions import require_admin from redash.query_runner import query_runners, validate_configuration from redash.handlers.base import BaseResource, get_object_or_404 class DataSourceTypeListAPI(BaseResource): @require_admin def get(self): return [q.to_dict() for q in query_runners.values()] api.add_org_resource(DataSourceTypeListAPI, '/api/data_sources/types', endpoint='data_source_types') class DataSourceAPI(BaseResource): @require_admin def get(self, data_source_id): data_source = models.DataSource.get_by_id_and_org( data_source_id, self.current_org) return data_source.to_dict(all=True) @require_admin def post(self, data_source_id): data_source = models.DataSource.get_by_id_and_org( data_source_id, self.current_org) req = request.get_json(True)
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.") # TODO: move to resource of its own? (POST /queries/{id}/archive) 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() class QueryRefreshResource(BaseResource): 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) api.add_org_resource(QuerySearchAPI, '/api/queries/search', endpoint='queries_search') api.add_org_resource(QueryRecentAPI, '/api/queries/recent', endpoint='recent_queries') api.add_org_resource(QueryListAPI, '/api/queries', endpoint='queries') api.add_org_resource(QueryRefreshResource, '/api/queries/<query_id>/refresh', endpoint='query_refresh') api.add_org_resource(QueryAPI, '/api/queries/<query_id>', endpoint='query')
'object_id': group_id, 'object_type': 'group', 'member_id': data_source.id, 'view_only': view_only }) return data_source.to_dict(with_permissions=True) @require_admin def delete(self, group_id, data_source_id): data_source = models.DataSource.get_by_id_and_org(data_source_id, self.current_org) group = models.Group.get_by_id_and_org(group_id, self.current_org) data_source.remove_group(group) self.record_event({ 'action': 'remove_data_source', 'timestamp': int(time.time()), 'object_id': group_id, 'object_type': 'group', 'member_id': data_source.id }) api.add_org_resource(GroupListResource, '/api/groups', endpoint='groups') api.add_org_resource(GroupResource, '/api/groups/<group_id>', endpoint='group') api.add_org_resource(GroupMemberListResource, '/api/groups/<group_id>/members', endpoint='group_members') api.add_org_resource(GroupMemberResource, '/api/groups/<group_id>/members/<user_id>', endpoint='group_member') api.add_org_resource(GroupDataSourceListResource, '/api/groups/<group_id>/data_sources', endpoint='group_data_sources') api.add_org_resource(GroupDataSourceResource, '/api/groups/<group_id>/data_sources/<data_source_id>', endpoint='group_data_source')
'object_id': alert_id, 'object_type': 'alert' }) return subscription.to_dict() def get(self, alert_id): alert = models.Alert.get_by_id_and_org(alert_id, self.current_org) require_access(alert.groups, self.current_user, view_only) subscriptions = models.AlertSubscription.all(alert_id) return [s.to_dict() for s in subscriptions] class AlertSubscriptionResource(BaseResource): def delete(self, alert_id, subscriber_id): models.AlertSubscription.unsubscribe(alert_id, subscriber_id) require_admin_or_owner(subscriber_id) self.record_event({ 'action': 'unsubscribe', 'timestamp': int(time.time()), 'object_id': alert_id, 'object_type': 'alert' }) api.add_org_resource(AlertResource, '/api/alerts/<alert_id>', endpoint='alert') api.add_org_resource(AlertSubscriptionListResource, '/api/alerts/<alert_id>/subscriptions', endpoint='alert_subscriptions') api.add_org_resource(AlertSubscriptionResource, '/api/alerts/<alert_id>/subscriptions/<subscriber_id>', endpoint='alert_subscription') api.add_org_resource(AlertListResource, '/api/alerts', endpoint='alerts')
params.pop('old_password') if 'groups' in params and not self.current_user.has_permission('admin'): abort(403, message="Must be admin to change groups membership.") try: user.update_instance(**params) except IntegrityError as e: if "email" in e.message: message = "Email already taken." else: message = "Error updating record" abort(400, message=message) self.record_event({ 'action': 'edit', 'timestamp': int(time.time()), 'object_id': user.id, 'object_type': 'user', 'updated_fields': params.keys() }) return user.to_dict(with_api_key=is_admin_or_owner(user_id)) api.add_org_resource(UserListResource, '/api/users', endpoint='users') api.add_org_resource(UserResource, '/api/users/<user_id>', endpoint='user')
def delete(self, group_id, data_source_id): data_source = models.DataSource.get_by_id_and_org( data_source_id, self.current_org) group = models.Group.get_by_id_and_org(group_id, self.current_org) data_source.remove_group(group) self.record_event({ 'action': 'remove_data_source', 'timestamp': int(time.time()), 'object_id': group_id, 'object_type': 'group', 'member_id': data_source.id }) api.add_org_resource(GroupListResource, '/api/groups', endpoint='groups') api.add_org_resource(GroupResource, '/api/groups/<group_id>', endpoint='group') api.add_org_resource(GroupMemberListResource, '/api/groups/<group_id>/members', endpoint='group_members') api.add_org_resource(GroupMemberResource, '/api/groups/<group_id>/members/<user_id>', endpoint='group_member') api.add_org_resource(GroupDataSourceListResource, '/api/groups/<group_id>/data_sources', endpoint='group_data_sources') api.add_org_resource(GroupDataSourceResource, '/api/groups/<group_id>/data_sources/<data_source_id>', endpoint='group_data_source')
public_url = url_for('public_dashboard', token=api_key.api_key, org_slug=self.current_org.slug, _external=True) return {'public_url': public_url, 'api_key': api_key.api_key} def delete(self, dashboard_id): dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org) require_admin_or_owner(dashboard.user_id) api_key = models.ApiKey.get_by_object(dashboard) if api_key: api_key.active = False api_key.save() api.add_org_resource(DashboardListResource, '/api/dashboards', endpoint='dashboards') api.add_org_resource(RecentDashboardsResource, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_org_resource(DashboardResource, '/api/dashboards/<dashboard_slug>', endpoint='dashboard') api.add_org_resource(DashboardShareResource, '/api/dashboards/<dashboard_id>/share', endpoint='dashboard_share')
vis = get_object_or_404(models.Visualization.get_by_id_and_org, visualization_id, self.current_org) require_admin_or_owner(vis.query.user_id) 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) vis.update_instance(**kwargs) return vis.to_dict(with_query=False) @require_permission('edit_query') 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.user_id) vis.delete_instance() api.add_org_resource(VisualizationListResource, '/api/visualizations', endpoint='visualizations') api.add_org_resource(VisualizationResource, '/api/visualizations/<visualization_id>', endpoint='visualization')
return 'failed' dashboard = models.Dashboard.get_by_id(dashboard_id) if not dashboard.groups: dashboard.groups = [group_id] elif not group_id in dashboard.groups: dashboard.groups.append(group_id) dashboard.save() group = models.Group.get_by_id(group_id) return {'name':group.name,'id':str(group.id)} class DashboardDelGroupAPI(BaseResource): @require_permission('edit_dashboard') def post(self): args = request.get_json(force=True) dashboard_id = args['dashboard_id'] group_id = args['group_id'] dashboard = models.Dashboard.get_by_id(dashboard_id) groups = set(dashboard.groups) groups = groups - set([group_id]) dashboard.groups = list(groups) dashboard.save() return {'group_id':group_id} api.add_org_resource(DashboardListAPI, '/api/dashboards', endpoint='dashboards') api.add_org_resource(DashboardRecentAPI, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_org_resource(DashboardAPI, '/api/dashboards/<dashboard_slug>', endpoint='dashboard') api.add_org_resource(DashboardGroupAPI, '/api/dashboards/group', endpoint='dashboard_group') api.add_org_resource(DashboardDelGroupAPI, '/api/dashboards/delgroup', endpoint='dashboard_del_group')
from flask.ext.restful import abort from funcy import project from redash import models from redash.wsgi import api from redash.permissions import require_admin from redash.query_runner import query_runners, validate_configuration from redash.handlers.base import BaseResource, get_object_or_404 class DataSourceTypeListAPI(BaseResource): @require_admin def get(self): return [q.to_dict() for q in query_runners.values()] api.add_org_resource(DataSourceTypeListAPI, '/api/data_sources/types', endpoint='data_source_types') class DataSourceAPI(BaseResource): @require_admin def get(self, data_source_id): data_source = models.DataSource.get_by_id_and_org(data_source_id, self.current_org) return data_source.to_dict(all=True) @require_admin def post(self, data_source_id): data_source = models.DataSource.get_by_id_and_org(data_source_id, self.current_org) req = request.get_json(True) data_source.replace_secret_placeholders(req['options'])
class DashboardAPI(BaseResource): def get(self, dashboard_slug=None): dashboard = get_object_or_404(models.Dashboard.get_by_slug_and_org, dashboard_slug, self.current_org) return dashboard.to_dict(with_widgets=True, user=self.current_user) @require_permission('edit_dashboard') def post(self, dashboard_slug): dashboard_properties = request.get_json(force=True) # TODO: either convert all requests to use slugs or ids dashboard = models.Dashboard.get_by_id_and_org(dashboard_slug, self.current_org) dashboard.layout = dashboard_properties['layout'] dashboard.name = dashboard_properties['name'] dashboard.save() return dashboard.to_dict(with_widgets=True, user=self.current_user) @require_permission('edit_dashboard') def delete(self, dashboard_slug): dashboard = models.Dashboard.get_by_slug_and_org(dashboard_slug, self.current_org) dashboard.is_archived = True dashboard.save() return dashboard.to_dict(with_widgets=True, user=self.current_user) api.add_org_resource(DashboardListAPI, '/api/dashboards', endpoint='dashboards') api.add_org_resource(DashboardRecentAPI, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_org_resource(DashboardAPI, '/api/dashboards/<dashboard_slug>', endpoint='dashboard')
return vis.to_dict(with_query=False) class VisualizationResource(BaseResource): @require_permission('edit_query') def post(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.user_id) 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) vis.update_instance(**kwargs) return vis.to_dict(with_query=False) @require_permission('edit_query') 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.user_id) vis.delete_instance() api.add_org_resource(VisualizationListResource, '/api/visualizations', endpoint='visualizations') api.add_org_resource(VisualizationResource, '/api/visualizations/<visualization_id>', endpoint='visualization')
@staticmethod def make_csv_response(query_result): s = cStringIO.StringIO() query_data = json.loads(query_result.data) writer = csv.DictWriter(s, fieldnames=[col['name'] for col in query_data['columns']]) writer.writer = utils.UnicodeWriter(s) writer.writeheader() for row in query_data['rows']: writer.writerow(row) headers = {'Content-Type': "text/csv; charset=UTF-8"} return make_response(s.getvalue(), 200, headers) api.add_org_resource(QueryResultListAPI, '/api/query_results', endpoint='query_results') api.add_org_resource(QueryResultAPI, '/api/query_results/<query_result_id>', '/api/queries/<query_id>/results.<filetype>', '/api/queries/<query_id>/results/<query_result_id>.<filetype>', endpoint='query_result') class JobAPI(BaseResource): def get(self, job_id): # TODO: if finished, include the query result job = QueryTask(job_id=job_id) return {'job': job.to_dict()} def delete(self, job_id): job = QueryTask(job_id=job_id)
if len(layout) == 0 or widget.width == 2: layout.append([widget.id]) elif len(layout[-1]) == 1: neighbour_widget = models.Widget.get(models.Widget.id == layout[-1][0]) if neighbour_widget.width == 1: layout[-1].append(widget.id) new_row = False else: layout.append([widget.id]) else: layout.append([widget.id]) widget.dashboard.layout = json.dumps(layout) widget.dashboard.save() return {'widget': widget.to_dict(), 'layout': layout, 'new_row': new_row} class WidgetAPI(BaseResource): @require_permission('edit_dashboard') def delete(self, widget_id): widget = models.Widget.get_by_id_and_org(widget_id, self.current_org) require_admin_or_owner(widget.dashboard.user_id) widget.delete_instance() return {'layout': widget.dashboard.layout} api.add_org_resource(WidgetListAPI, '/api/widgets', endpoint='widgets') api.add_org_resource(WidgetAPI, '/api/widgets/<int:widget_id>', endpoint='widget')
q = get_object_or_404(models.Query.get_by_hash, query_hash) #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.") # TODO: move to resource of its own? (POST /queries/{id}/archive) 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() class QueryRefreshResource(BaseResource): 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) api.add_org_resource(QuerySearchAPI, '/api/queries/search', endpoint='queries_search') api.add_org_resource(QueryRecentAPI, '/api/queries/recent', endpoint='recent_queries') api.add_org_resource(QueryListAPI, '/api/queries', endpoint='queries') api.add_org_resource(QueryRefreshResource, '/api/queries/<query_id>/refresh', endpoint='query_refresh') api.add_org_resource(QueryAPI, '/api/queries/<query_id>', endpoint='query')
column_names = [] for (c, col) in enumerate(query_data['columns']): sheet.write(0, c, col['name']) column_names.append(col['name']) for (r, row) in enumerate(query_data['rows']): for (c, name) in enumerate(column_names): sheet.write(r+1, c, row[name]) book.close() headers = {'Content-Type': "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"} return make_response(s.getvalue(), 200, headers) api.add_org_resource(QueryResultListAPI, '/api/query_results', endpoint='query_results') api.add_org_resource(QueryResultAPI, '/api/query_results/<query_result_id>', '/api/queries/<query_id>/results.<filetype>', '/api/queries/<query_id>/results/<query_result_id>.<filetype>', endpoint='query_result') class JobAPI(BaseResource): def get(self, job_id): # TODO: if finished, include the query result job = QueryTask(job_id=job_id) return {'job': job.to_dict()} def delete(self, job_id): job = QueryTask(job_id=job_id)
dashboard = models.Dashboard.get_by_slug_and_org(dashboard_slug, self.current_org) dashboard.is_archived = True dashboard.save() return dashboard.to_dict(with_widgets=True, user=self.current_user) class DashboardShareResource(BaseResource): def post(self, dashboard_id): dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org) require_admin_or_owner(dashboard.user_id) api_key = models.ApiKey.create_for_object(dashboard, self.current_user) public_url = url_for('public_dashboard', token=api_key.api_key, org_slug=self.current_org.slug, _external=True) return {'public_url': public_url, 'api_key': api_key.api_key} def delete(self, dashboard_id): dashboard = models.Dashboard.get_by_id_and_org(dashboard_id, self.current_org) require_admin_or_owner(dashboard.user_id) api_key = models.ApiKey.get_by_object(dashboard) if api_key: api_key.active = False api_key.save() api.add_org_resource(DashboardListResource, '/api/dashboards', endpoint='dashboards') api.add_org_resource(RecentDashboardsResource, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_org_resource(DashboardResource, '/api/dashboards/<dashboard_slug>', endpoint='dashboard') api.add_org_resource(DashboardShareResource, '/api/dashboards/<dashboard_id>/share', endpoint='dashboard_share')