Textless query result endpoint (#3311)

* add an endpoint for running a query by its id and (optional) parameters
without having to provide the query text

* check for access to query before running it
This commit is contained in:
Omer Lachish 2019-01-23 11:10:04 +02:00 committed by GitHub
parent 7fa6665445
commit a9c514aaf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 1 deletions

View File

@ -6,7 +6,7 @@ from redash.utils import json_dumps
from redash.handlers.base import org_scoped_rule
from redash.handlers.permissions import ObjectPermissionsListResource, CheckPermissionResource
from redash.handlers.alerts import AlertResource, AlertListResource, AlertSubscriptionListResource, AlertSubscriptionResource
from redash.handlers.dashboards import DashboardListResource, DashboardResource, DashboardShareResource, PublicDashboardResource
from redash.handlers.dashboards import DashboardListResource, DashboardResource, DashboardShareResource, PublicDashboardResource
from redash.handlers.data_sources import DataSourceTypeListResource, DataSourceListResource, DataSourceSchemaResource, DataSourceResource, DataSourcePauseResource, DataSourceTestResource
from redash.handlers.events import EventsResource
from redash.handlers.queries import QueryForkResource, QueryRefreshResource, QueryListResource, QueryRecentResource, QuerySearchResource, QueryResource, MyQueriesResource
@ -92,6 +92,7 @@ api.add_org_resource(QueryResultListResource, '/api/query_results', endpoint='qu
api.add_org_resource(QueryResultResource,
'/api/query_results/<query_result_id>.<filetype>',
'/api/query_results/<query_result_id>',
'/api/queries/<query_id>/results',
'/api/queries/<query_id>/results.<filetype>',
'/api/queries/<query_id>/results/<query_result_id>.<filetype>',
endpoint='query_result')

View File

@ -154,6 +154,29 @@ class QueryResultResource(BaseResource):
return make_response("", 200, headers)
@require_permission('execute_query')
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)
parameters = params.get('parameters', {})
max_age = int(params.get('max_age', 0))
query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
if not has_access(query.data_source.groups, self.current_user, not_view_only):
return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403
else:
return run_query(query.data_source, parameters, query.query_text, query_id, max_age)
@require_permission('view_query')
def get(self, query_id=None, query_result_id=None, filetype='json'):
"""

View File

@ -128,6 +128,14 @@ class TestQueryResultAPI(BaseTestCase):
rv = self.make_request('get', '/api/query_results/{}'.format(query_result.id))
self.assertEquals(rv.status_code, 200)
def test_execute_new_query(self):
query = self.factory.create_query()
rv = self.make_request('post', '/api/queries/{}/results'.format(query.id), data={'parameters': {}})
self.assertEquals(rv.status_code, 200)
self.assertIn('job', rv.json)
def test_access_with_query_api_key(self):
ds = self.factory.create_data_source(group=self.factory.org.default_group, view_only=False)
query = self.factory.create_query()