mirror of
https://github.com/getredash/redash.git
synced 2025-12-19 17:37:19 -05:00
Merge pull request #1014 from whummer/feat/params_on_embeds
Add server-side parameter handling for embeds
This commit is contained in:
@@ -7,12 +7,35 @@ from flask_restful import abort
|
|||||||
|
|
||||||
from redash import models, settings
|
from redash import models, settings
|
||||||
from redash import serializers
|
from redash import serializers
|
||||||
from redash.utils import json_dumps
|
from redash.utils import json_dumps, collect_parameters_from_request
|
||||||
from redash.handlers import routes
|
from redash.handlers import routes
|
||||||
from redash.handlers.base import org_scoped_rule, record_event
|
from redash.handlers.base import org_scoped_rule, record_event
|
||||||
from redash.permissions import require_access, view_only
|
from redash.permissions import require_access, view_only
|
||||||
from authentication import current_org
|
from authentication import current_org
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run a parameterized query synchronously and return the result
|
||||||
|
# DISCLAIMER: Temporary solution to support parameters in queries. Should be
|
||||||
|
# removed once we refactor the query results API endpoints and handling
|
||||||
|
# on the client side. Please don't reuse in other API handlers.
|
||||||
|
#
|
||||||
|
def run_query_sync(data_source, parameter_values, query_text):
|
||||||
|
query_parameters = set(collect_query_parameters(query_text))
|
||||||
|
missing_params = set(query_parameters) - set(parameter_values.keys())
|
||||||
|
if missing_params:
|
||||||
|
raise Exception('Missing parameter value for: {}'.format(", ".join(missing_params)))
|
||||||
|
|
||||||
|
if query_parameters:
|
||||||
|
query_text = pystache.render(query_text, parameter_values)
|
||||||
|
|
||||||
|
try:
|
||||||
|
data, error = data_source.query_runner.run_query(query_text)
|
||||||
|
if error:
|
||||||
|
return None
|
||||||
|
return data
|
||||||
|
except Exception, e:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@routes.route(org_scoped_rule('/embed/query/<query_id>/visualization/<visualization_id>'), methods=['GET'])
|
@routes.route(org_scoped_rule('/embed/query/<query_id>/visualization/<visualization_id>'), methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@@ -22,10 +45,23 @@ def embed(query_id, visualization_id, org_slug=None):
|
|||||||
vis = query.visualizations.where(models.Visualization.id == visualization_id).first()
|
vis = query.visualizations.where(models.Visualization.id == visualization_id).first()
|
||||||
qr = {}
|
qr = {}
|
||||||
|
|
||||||
|
parameter_values = collect_parameters_from_request(request.args)
|
||||||
|
|
||||||
if vis is not None:
|
if vis is not None:
|
||||||
vis = vis.to_dict()
|
vis = vis.to_dict()
|
||||||
qr = query.latest_query_data
|
qr = query.latest_query_data
|
||||||
if qr is None:
|
if settings.ALLOW_PARAMETERS_IN_EMBEDS == True and len(parameter_values) > 0:
|
||||||
|
# run parameterized query
|
||||||
|
#
|
||||||
|
# WARNING: Note that the external query parameters
|
||||||
|
# are a potential risk of SQL injections.
|
||||||
|
#
|
||||||
|
results = run_query_sync(query.data_source, parameter_values, query.query)
|
||||||
|
if results is None:
|
||||||
|
abort(400, message="Unable to get results for this query")
|
||||||
|
else:
|
||||||
|
qr = {"data": json.loads(results)}
|
||||||
|
elif qr is None:
|
||||||
abort(400, message="No Results for this query")
|
abort(400, message="No Results for this query")
|
||||||
else:
|
else:
|
||||||
qr = qr.to_dict()
|
qr = qr.to_dict()
|
||||||
@@ -54,6 +90,7 @@ def embed(query_id, visualization_id, org_slug=None):
|
|||||||
query_result=json_dumps(qr))
|
query_result=json_dumps(qr))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@routes.route(org_scoped_rule('/public/dashboards/<token>'), methods=['GET'])
|
@routes.route(org_scoped_rule('/public/dashboards/<token>'), methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def public_dashboard(token, org_slug=None):
|
def public_dashboard(token, org_slug=None):
|
||||||
|
|||||||
@@ -203,6 +203,10 @@ BIGQUERY_HTTP_TIMEOUT = int(os.environ.get("REDASH_BIGQUERY_HTTP_TIMEOUT", "600"
|
|||||||
# Enhance schema fetching
|
# Enhance schema fetching
|
||||||
SCHEMA_RUN_TABLE_SIZE_CALCULATIONS = parse_boolean(os.environ.get("REDASH_SCHEMA_RUN_TABLE_SIZE_CALCULATIONS", "false"))
|
SCHEMA_RUN_TABLE_SIZE_CALCULATIONS = parse_boolean(os.environ.get("REDASH_SCHEMA_RUN_TABLE_SIZE_CALCULATIONS", "false"))
|
||||||
|
|
||||||
|
# Allow Parameters in Embeds
|
||||||
|
# WARNING: With this option enabled, Redash reads query parameters from the request URL (risk of SQL injection!)
|
||||||
|
ALLOW_PARAMETERS_IN_EMBEDS = parse_boolean(os.environ.get("REDASH_ALLOW_PARAMETERS_IN_EMBEDS", "false"))
|
||||||
|
|
||||||
### Common Client config
|
### Common Client config
|
||||||
COMMON_CLIENT_CONFIG = {
|
COMMON_CLIENT_CONFIG = {
|
||||||
'allowScriptsInUserInput': ALLOW_SCRIPTS_IN_USER_INPUT,
|
'allowScriptsInUserInput': ALLOW_SCRIPTS_IN_USER_INPUT,
|
||||||
|
|||||||
Reference in New Issue
Block a user