Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add server-side parameter handling for embeds #1014

Merged
merged 1 commit into from
May 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions redash/handlers/embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,35 @@

from redash import models, settings
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.base import org_scoped_rule, record_event
from redash.permissions import require_access, view_only
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'])
@login_required
Expand All @@ -22,10 +45,23 @@ def embed(query_id, visualization_id, org_slug=None):
vis = query.visualizations.where(models.Visualization.id == visualization_id).first()
qr = {}

parameter_values = collect_parameters_from_request(request.args)

if vis is not None:
vis = vis.to_dict()
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")
else:
qr = qr.to_dict()
Expand Down Expand Up @@ -54,6 +90,7 @@ def embed(query_id, visualization_id, org_slug=None):
query_result=json_dumps(qr))



@routes.route(org_scoped_rule('/public/dashboards/<token>'), methods=['GET'])
@login_required
def public_dashboard(token, org_slug=None):
Expand Down
4 changes: 4 additions & 0 deletions redash/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ def all_settings():
# Enhance schema fetching
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 = {
'allowScriptsInUserInput': ALLOW_SCRIPTS_IN_USER_INPUT,
Expand Down