We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add time zone support
Right now re:dash assumes that all timestamps are in the local time zone. However, Redshift (and many other databases, depending on the configuration) default to UTC, and thus re:dash parses the data incorrectly. What's confusing is that in Highcharts also formats the data in local time, leading to this awkward display:

![image](https://cloud.githubusercontent.com/assets/963826/7282512/4c9a1d38-e8e5-11e4-9bbf-eb52707d71ff.png)

Notice how the data is highlighted at the beginning of April 23 (which hasn't happened yet in GMT), but the date is showing April 22 4:00 pm (which hasn't happened yet in Pacific Standard Time).

I temporarily worked around this by patching ng_highchart.js:

``` diff
         if (moment.isMoment(this.x)) {
-          var s = '<b>' + this.x.toDate().toLocaleString() + '</b>',
+          var s = '<b>' + this.x.toDate().toISOString() + '</b>',
               pointsCount = this.points.length;
```

resources.js:

``` diff
             if (angular.isNumber(v)) {
               columnTypes[k] = 'float';
             } else if (_.isString(v) && v.match(/^\d{4}-\d{2}-\d{2}T/)) {
-              row[k] = moment(v);
+              row[k] = moment.utc(v);
               columnTypes[k] = 'datetime';
             } else if (_.isString(v) && v.match(/^\d{4}-\d{2}-\d{2}/)) {
-              row[k] = moment(v);
+              row[k] = moment.utc(v);
               columnTypes[k] = 'date';
             } else if (typeof(v) == 'object' && v !== null) {
               row[k] = JSON.stringify(v);
```

I'd imagine there will be cases where some users have their database configured to output a specific standard time and others will use UTC. What's the best way to support this feature? Options:
1. Store the UTC offset in the `query_result` (so moment will parse the right value)
2. Allow configuration option in re:dash for time zone (e.g. UTC, America/Los_Angeles) 

What do you think, @arikfr?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `redash/handlers/static.py`
Content:
```
1 import hashlib
2 import json
3 
4 from flask import render_template, send_from_directory, current_app
5 from flask_login import current_user, login_required
6 
7 from redash import settings
8 from redash.wsgi import app
9 
10 
11 @app.route('/admin/<anything>/<whatever>')
12 @app.route('/admin/<anything>')
13 @app.route('/dashboard/<anything>')
14 @app.route('/alerts')
15 @app.route('/alerts/<pk>')
16 @app.route('/queries')
17 @app.route('/data_sources')
18 @app.route('/data_sources/<pk>')
19 @app.route('/users')
20 @app.route('/users/<pk>')
21 @app.route('/queries/<query_id>')
22 @app.route('/queries/<query_id>/<anything>')
23 @app.route('/personal')
24 @app.route('/')
25 @login_required
26 def index(**kwargs):
27     email_md5 = hashlib.md5(current_user.email.lower()).hexdigest()
28     gravatar_url = "https://www.gravatar.com/avatar/%s?s=40" % email_md5
29 
30     user = {
31         'gravatar_url': gravatar_url,
32         'id': current_user.id,
33         'name': current_user.name,
34         'email': current_user.email,
35         'groups': current_user.groups,
36         'permissions': current_user.permissions
37     }
38 
39     features = {
40         'clientSideMetrics': settings.CLIENT_SIDE_METRICS,
41         'allowScriptsInUserInput': settings.ALLOW_SCRIPTS_IN_USER_INPUT,
42         'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD
43     }
44 
45     return render_template("index.html", user=json.dumps(user), name=settings.NAME,
46                            features=json.dumps(features),
47                            analytics=settings.ANALYTICS)
48 
49 
50 @app.route('/<path:filename>')
51 def send_static(filename):
52     if current_app.debug:
53         cache_timeout = 0
54     else:
55         cache_timeout = None
56 
57     return send_from_directory(settings.STATIC_ASSETS_PATH, filename, cache_timeout=cache_timeout)
58
```

Path: `redash/settings.py`
Content:
```
1 import json
2 import os
3 import urlparse
4 from funcy import distinct
5 
6 
7 def parse_db_url(url):
8     url_parts = urlparse.urlparse(url)
9     connection = {'threadlocals': True}
10 
11     if url_parts.hostname and not url_parts.path:
12         connection['name'] = url_parts.hostname
13     else:
14         connection['name'] = url_parts.path[1:]
15         connection['host'] = url_parts.hostname
16         connection['port'] = url_parts.port
17         connection['user'] = url_parts.username
18         connection['password'] = url_parts.password
19 
20     return connection
21 
22 
23 def fix_assets_path(path):
24     fullpath = os.path.join(os.path.dirname(__file__), path)
25     return fullpath
26 
27 
28 def array_from_string(str):
29     array = str.split(',')
30     if "" in array:
31         array.remove("")
32 
33     return array
34 
35 
36 def set_from_string(str):
37     return set(array_from_string(str))
38 
39 
40 def parse_boolean(str):
41     return json.loads(str.lower())
42 
43 
44 def all_settings():
45     from types import ModuleType
46 
47     settings = {}
48     for name, item in globals().iteritems():
49         if not callable(item) and not name.startswith("__") and not isinstance(item, ModuleType):
50             settings[name] = item
51 
52     return settings
53 
54 
55 NAME = os.environ.get('REDASH_NAME', 're:dash')
56 
57 REDIS_URL = os.environ.get('REDASH_REDIS_URL', "redis://localhost:6379/0")
58 
59 STATSD_HOST = os.environ.get('REDASH_STATSD_HOST', "127.0.0.1")
60 STATSD_PORT = int(os.environ.get('REDASH_STATSD_PORT', "8125"))
61 STATSD_PREFIX = os.environ.get('REDASH_STATSD_PREFIX', "redash")
62 
63 # Connection settings for re:dash's own database (where we store the queries, results, etc)
64 DATABASE_CONFIG = parse_db_url(os.environ.get("REDASH_DATABASE_URL", "postgresql://postgres"))
65 
66 # Celery related settings
67 CELERY_BROKER = os.environ.get("REDASH_CELERY_BROKER", REDIS_URL)
68 CELERY_BACKEND = os.environ.get("REDASH_CELERY_BACKEND", CELERY_BROKER)
69 
70 # The following enables periodic job (every 5 minutes) of removing unused query results.
71 QUERY_RESULTS_CLEANUP_ENABLED = parse_boolean(os.environ.get("REDASH_QUERY_RESULTS_CLEANUP_ENABLED", "true"))
72 
73 AUTH_TYPE = os.environ.get("REDASH_AUTH_TYPE", "api_key")
74 PASSWORD_LOGIN_ENABLED = parse_boolean(os.environ.get("REDASH_PASSWORD_LOGIN_ENABLED", "true"))
75 
76 # Google Apps domain to allow access from; any user with email in this Google Apps will be allowed
77 # access
78 GOOGLE_APPS_DOMAIN = set_from_string(os.environ.get("REDASH_GOOGLE_APPS_DOMAIN", ""))
79 
80 GOOGLE_CLIENT_ID = os.environ.get("REDASH_GOOGLE_CLIENT_ID", "")
81 GOOGLE_CLIENT_SECRET = os.environ.get("REDASH_GOOGLE_CLIENT_SECRET", "")
82 GOOGLE_OAUTH_ENABLED = GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
83 
84 SAML_METADATA_URL = os.environ.get("REDASH_SAML_METADATA_URL", "")
85 SAML_LOGIN_ENABLED = SAML_METADATA_URL != ""
86 SAML_CALLBACK_SERVER_NAME = os.environ.get("REDASH_SAML_CALLBACK_SERVER_NAME", "")
87 
88 STATIC_ASSETS_PATH = fix_assets_path(os.environ.get("REDASH_STATIC_ASSETS_PATH", "../rd_ui/app/"))
89 JOB_EXPIRY_TIME = int(os.environ.get("REDASH_JOB_EXPIRY_TIME", 3600 * 6))
90 COOKIE_SECRET = os.environ.get("REDASH_COOKIE_SECRET", "c292a0a3aa32397cdb050e233733900f")
91 LOG_LEVEL = os.environ.get("REDASH_LOG_LEVEL", "INFO")
92 ANALYTICS = os.environ.get("REDASH_ANALYTICS", "")
93 
94 # Mail settings:
95 MAIL_SERVER = os.environ.get('REDASH_MAIL_SERVER', 'localhost')
96 MAIL_PORT = int(os.environ.get('REDASH_MAIL_PORT', 25))
97 MAIL_USE_TLS = parse_boolean(os.environ.get('REDASH_MAIL_USE_TLS', 'false'))
98 MAIL_USE_SSL = parse_boolean(os.environ.get('REDASH_MAIL_USE_SSL', 'false'))
99 MAIL_USERNAME = os.environ.get('REDASH_MAIL_USERNAME', None)
100 MAIL_PASSWORD = os.environ.get('REDASH_MAIL_PASSWORD', None)
101 MAIL_DEFAULT_SENDER = os.environ.get('REDASH_MAIL_DEFAULT_SENDER', None)
102 MAIL_MAX_EMAILS = os.environ.get('REDASH_MAIL_MAX_EMAILS', None)
103 MAIL_ASCII_ATTACHMENTS = parse_boolean(os.environ.get('REDASH_MAIL_ASCII_ATTACHMENTS', 'false'))
104 
105 HOST = os.environ.get('REDASH_HOST', '')
106 
107 # CORS settings for the Query Result API (and possbily future external APIs).
108 # In most cases all you need to do is set REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN
109 # to the calling domain (or domains in a comma separated list).
110 ACCESS_CONTROL_ALLOW_ORIGIN = set_from_string(os.environ.get("REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN", ""))
111 ACCESS_CONTROL_ALLOW_CREDENTIALS = parse_boolean(os.environ.get("REDASH_CORS_ACCESS_CONTROL_ALLOW_CREDENTIALS", "false"))
112 ACCESS_CONTROL_REQUEST_METHOD = os.environ.get("REDASH_CORS_ACCESS_CONTROL_REQUEST_METHOD", "GET, POST, PUT")
113 ACCESS_CONTROL_ALLOW_HEADERS = os.environ.get("REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS", "Content-Type")
114 
115 # Query Runners
116 default_query_runners = [
117     'redash.query_runner.big_query',
118     'redash.query_runner.google_spreadsheets',
119     'redash.query_runner.graphite',
120     'redash.query_runner.mongodb',
121     'redash.query_runner.mysql',
122     'redash.query_runner.pg',
123     'redash.query_runner.url',
124     'redash.query_runner.influx_db',
125     'redash.query_runner.elasticsearch',
126     'redash.query_runner.presto',
127     'redash.query_runner.hive_ds',
128     'redash.query_runner.impala_ds',
129     'redash.query_runner.vertica',
130     'redash.query_runner.treasuredata'
131 ]
132 
133 enabled_query_runners = array_from_string(os.environ.get("REDASH_ENABLED_QUERY_RUNNERS", ",".join(default_query_runners)))
134 additional_query_runners = array_from_string(os.environ.get("REDASH_ADDITIONAL_QUERY_RUNNERS", ""))
135 
136 QUERY_RUNNERS = distinct(enabled_query_runners + additional_query_runners)
137 
138 # Support for Sentry (http://getsentry.com/). Just set your Sentry DSN to enable it:
139 SENTRY_DSN = os.environ.get("REDASH_SENTRY_DSN", "")
140 
141 # Client side toggles:
142 ALLOW_SCRIPTS_IN_USER_INPUT = parse_boolean(os.environ.get("REDASH_ALLOW_SCRIPTS_IN_USER_INPUT", "false"))
143 CLIENT_SIDE_METRICS = parse_boolean(os.environ.get("REDASH_CLIENT_SIDE_METRICS", "false"))
144 # http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold
145 HIGHCHARTS_TURBO_THRESHOLD = int(os.environ.get("REDASH_HIGHCHARTS_TURBO_THRESHOLD", "1000"))
146 
147 # Features:
148 FEATURE_ALLOW_ALL_TO_EDIT_QUERIES = parse_boolean(os.environ.get("REDASH_FEATURE_ALLOW_ALL_TO_EDIT", "true"))
149 FEATURE_TABLES_PERMISSIONS = parse_boolean(os.environ.get("REDASH_FEATURE_TABLES_PERMISSIONS", "false"))
150 
151 # BigQuery
152 BIGQUERY_HTTP_TIMEOUT = int(os.environ.get("REDASH_BIGQUERY_HTTP_TIMEOUT", "600"))
153
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/redash/handlers/static.py b/redash/handlers/static.py
--- a/redash/handlers/static.py
+++ b/redash/handlers/static.py
@@ -36,14 +36,16 @@
         'permissions': current_user.permissions
     }
 
-    features = {
+    client_config = {
         'clientSideMetrics': settings.CLIENT_SIDE_METRICS,
         'allowScriptsInUserInput': settings.ALLOW_SCRIPTS_IN_USER_INPUT,
-        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD
+        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD,
+        'dateFormat': settings.DATE_FORMAT,
+        'dateTimeFormat': "{0} HH:mm".format(settings.DATE_FORMAT)
     }
 
     return render_template("index.html", user=json.dumps(user), name=settings.NAME,
-                           features=json.dumps(features),
+                           client_config=json.dumps(client_config),
                            analytics=settings.ANALYTICS)
 
 
diff --git a/redash/settings.py b/redash/settings.py
--- a/redash/settings.py
+++ b/redash/settings.py
@@ -143,6 +143,7 @@
 CLIENT_SIDE_METRICS = parse_boolean(os.environ.get("REDASH_CLIENT_SIDE_METRICS", "false"))
 # http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold
 HIGHCHARTS_TURBO_THRESHOLD = int(os.environ.get("REDASH_HIGHCHARTS_TURBO_THRESHOLD", "1000"))
+DATE_FORMAT = os.environ.get("REDASH_DATE_FORMAT", "DD/MM/YY")
 
 # Features:
 FEATURE_ALLOW_ALL_TO_EDIT_QUERIES = parse_boolean(os.environ.get("REDASH_FEATURE_ALLOW_ALL_TO_EDIT", "true"))

{"golden_diff": "diff --git a/redash/handlers/static.py b/redash/handlers/static.py\n--- a/redash/handlers/static.py\n+++ b/redash/handlers/static.py\n@@ -36,14 +36,16 @@\n         'permissions': current_user.permissions\n     }\n \n-    features = {\n+    client_config = {\n         'clientSideMetrics': settings.CLIENT_SIDE_METRICS,\n         'allowScriptsInUserInput': settings.ALLOW_SCRIPTS_IN_USER_INPUT,\n-        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD\n+        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD,\n+        'dateFormat': settings.DATE_FORMAT,\n+        'dateTimeFormat': \"{0} HH:mm\".format(settings.DATE_FORMAT)\n     }\n \n     return render_template(\"index.html\", user=json.dumps(user), name=settings.NAME,\n-                           features=json.dumps(features),\n+                           client_config=json.dumps(client_config),\n                            analytics=settings.ANALYTICS)\n \n \ndiff --git a/redash/settings.py b/redash/settings.py\n--- a/redash/settings.py\n+++ b/redash/settings.py\n@@ -143,6 +143,7 @@\n CLIENT_SIDE_METRICS = parse_boolean(os.environ.get(\"REDASH_CLIENT_SIDE_METRICS\", \"false\"))\n # http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold\n HIGHCHARTS_TURBO_THRESHOLD = int(os.environ.get(\"REDASH_HIGHCHARTS_TURBO_THRESHOLD\", \"1000\"))\n+DATE_FORMAT = os.environ.get(\"REDASH_DATE_FORMAT\", \"DD/MM/YY\")\n \n # Features:\n FEATURE_ALLOW_ALL_TO_EDIT_QUERIES = parse_boolean(os.environ.get(\"REDASH_FEATURE_ALLOW_ALL_TO_EDIT\", \"true\"))\n", "issue": "Add time zone support\nRight now re:dash assumes that all timestamps are in the local time zone. However, Redshift (and many other databases, depending on the configuration) default to UTC, and thus re:dash parses the data incorrectly. What's confusing is that in Highcharts also formats the data in local time, leading to this awkward display:\n\n![image](https://cloud.githubusercontent.com/assets/963826/7282512/4c9a1d38-e8e5-11e4-9bbf-eb52707d71ff.png)\n\nNotice how the data is highlighted at the beginning of April 23 (which hasn't happened yet in GMT), but the date is showing April 22 4:00 pm (which hasn't happened yet in Pacific Standard Time).\n\nI temporarily worked around this by patching ng_highchart.js:\n\n``` diff\n         if (moment.isMoment(this.x)) {\n-          var s = '<b>' + this.x.toDate().toLocaleString() + '</b>',\n+          var s = '<b>' + this.x.toDate().toISOString() + '</b>',\n               pointsCount = this.points.length;\n```\n\nresources.js:\n\n``` diff\n             if (angular.isNumber(v)) {\n               columnTypes[k] = 'float';\n             } else if (_.isString(v) && v.match(/^\\d{4}-\\d{2}-\\d{2}T/)) {\n-              row[k] = moment(v);\n+              row[k] = moment.utc(v);\n               columnTypes[k] = 'datetime';\n             } else if (_.isString(v) && v.match(/^\\d{4}-\\d{2}-\\d{2}/)) {\n-              row[k] = moment(v);\n+              row[k] = moment.utc(v);\n               columnTypes[k] = 'date';\n             } else if (typeof(v) == 'object' && v !== null) {\n               row[k] = JSON.stringify(v);\n```\n\nI'd imagine there will be cases where some users have their database configured to output a specific standard time and others will use UTC. What's the best way to support this feature? Options:\n1. Store the UTC offset in the `query_result` (so moment will parse the right value)\n2. Allow configuration option in re:dash for time zone (e.g. UTC, America/Los_Angeles) \n\nWhat do you think, @arikfr?\n\n", "before_files": [{"content": "import hashlib\nimport json\n\nfrom flask import render_template, send_from_directory, current_app\nfrom flask_login import current_user, login_required\n\nfrom redash import settings\nfrom redash.wsgi import app\n\n\n@app.route('/admin/<anything>/<whatever>')\n@app.route('/admin/<anything>')\n@app.route('/dashboard/<anything>')\n@app.route('/alerts')\n@app.route('/alerts/<pk>')\n@app.route('/queries')\n@app.route('/data_sources')\n@app.route('/data_sources/<pk>')\n@app.route('/users')\n@app.route('/users/<pk>')\n@app.route('/queries/<query_id>')\n@app.route('/queries/<query_id>/<anything>')\n@app.route('/personal')\n@app.route('/')\n@login_required\ndef index(**kwargs):\n    email_md5 = hashlib.md5(current_user.email.lower()).hexdigest()\n    gravatar_url = \"https://www.gravatar.com/avatar/%s?s=40\" % email_md5\n\n    user = {\n        'gravatar_url': gravatar_url,\n        'id': current_user.id,\n        'name': current_user.name,\n        'email': current_user.email,\n        'groups': current_user.groups,\n        'permissions': current_user.permissions\n    }\n\n    features = {\n        'clientSideMetrics': settings.CLIENT_SIDE_METRICS,\n        'allowScriptsInUserInput': settings.ALLOW_SCRIPTS_IN_USER_INPUT,\n        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD\n    }\n\n    return render_template(\"index.html\", user=json.dumps(user), name=settings.NAME,\n                           features=json.dumps(features),\n                           analytics=settings.ANALYTICS)\n\n\n@app.route('/<path:filename>')\ndef send_static(filename):\n    if current_app.debug:\n        cache_timeout = 0\n    else:\n        cache_timeout = None\n\n    return send_from_directory(settings.STATIC_ASSETS_PATH, filename, cache_timeout=cache_timeout)\n", "path": "redash/handlers/static.py"}, {"content": "import json\nimport os\nimport urlparse\nfrom funcy import distinct\n\n\ndef parse_db_url(url):\n    url_parts = urlparse.urlparse(url)\n    connection = {'threadlocals': True}\n\n    if url_parts.hostname and not url_parts.path:\n        connection['name'] = url_parts.hostname\n    else:\n        connection['name'] = url_parts.path[1:]\n        connection['host'] = url_parts.hostname\n        connection['port'] = url_parts.port\n        connection['user'] = url_parts.username\n        connection['password'] = url_parts.password\n\n    return connection\n\n\ndef fix_assets_path(path):\n    fullpath = os.path.join(os.path.dirname(__file__), path)\n    return fullpath\n\n\ndef array_from_string(str):\n    array = str.split(',')\n    if \"\" in array:\n        array.remove(\"\")\n\n    return array\n\n\ndef set_from_string(str):\n    return set(array_from_string(str))\n\n\ndef parse_boolean(str):\n    return json.loads(str.lower())\n\n\ndef all_settings():\n    from types import ModuleType\n\n    settings = {}\n    for name, item in globals().iteritems():\n        if not callable(item) and not name.startswith(\"__\") and not isinstance(item, ModuleType):\n            settings[name] = item\n\n    return settings\n\n\nNAME = os.environ.get('REDASH_NAME', 're:dash')\n\nREDIS_URL = os.environ.get('REDASH_REDIS_URL', \"redis://localhost:6379/0\")\n\nSTATSD_HOST = os.environ.get('REDASH_STATSD_HOST', \"127.0.0.1\")\nSTATSD_PORT = int(os.environ.get('REDASH_STATSD_PORT', \"8125\"))\nSTATSD_PREFIX = os.environ.get('REDASH_STATSD_PREFIX', \"redash\")\n\n# Connection settings for re:dash's own database (where we store the queries, results, etc)\nDATABASE_CONFIG = parse_db_url(os.environ.get(\"REDASH_DATABASE_URL\", \"postgresql://postgres\"))\n\n# Celery related settings\nCELERY_BROKER = os.environ.get(\"REDASH_CELERY_BROKER\", REDIS_URL)\nCELERY_BACKEND = os.environ.get(\"REDASH_CELERY_BACKEND\", CELERY_BROKER)\n\n# The following enables periodic job (every 5 minutes) of removing unused query results.\nQUERY_RESULTS_CLEANUP_ENABLED = parse_boolean(os.environ.get(\"REDASH_QUERY_RESULTS_CLEANUP_ENABLED\", \"true\"))\n\nAUTH_TYPE = os.environ.get(\"REDASH_AUTH_TYPE\", \"api_key\")\nPASSWORD_LOGIN_ENABLED = parse_boolean(os.environ.get(\"REDASH_PASSWORD_LOGIN_ENABLED\", \"true\"))\n\n# Google Apps domain to allow access from; any user with email in this Google Apps will be allowed\n# access\nGOOGLE_APPS_DOMAIN = set_from_string(os.environ.get(\"REDASH_GOOGLE_APPS_DOMAIN\", \"\"))\n\nGOOGLE_CLIENT_ID = os.environ.get(\"REDASH_GOOGLE_CLIENT_ID\", \"\")\nGOOGLE_CLIENT_SECRET = os.environ.get(\"REDASH_GOOGLE_CLIENT_SECRET\", \"\")\nGOOGLE_OAUTH_ENABLED = GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET\n\nSAML_METADATA_URL = os.environ.get(\"REDASH_SAML_METADATA_URL\", \"\")\nSAML_LOGIN_ENABLED = SAML_METADATA_URL != \"\"\nSAML_CALLBACK_SERVER_NAME = os.environ.get(\"REDASH_SAML_CALLBACK_SERVER_NAME\", \"\")\n\nSTATIC_ASSETS_PATH = fix_assets_path(os.environ.get(\"REDASH_STATIC_ASSETS_PATH\", \"../rd_ui/app/\"))\nJOB_EXPIRY_TIME = int(os.environ.get(\"REDASH_JOB_EXPIRY_TIME\", 3600 * 6))\nCOOKIE_SECRET = os.environ.get(\"REDASH_COOKIE_SECRET\", \"c292a0a3aa32397cdb050e233733900f\")\nLOG_LEVEL = os.environ.get(\"REDASH_LOG_LEVEL\", \"INFO\")\nANALYTICS = os.environ.get(\"REDASH_ANALYTICS\", \"\")\n\n# Mail settings:\nMAIL_SERVER = os.environ.get('REDASH_MAIL_SERVER', 'localhost')\nMAIL_PORT = int(os.environ.get('REDASH_MAIL_PORT', 25))\nMAIL_USE_TLS = parse_boolean(os.environ.get('REDASH_MAIL_USE_TLS', 'false'))\nMAIL_USE_SSL = parse_boolean(os.environ.get('REDASH_MAIL_USE_SSL', 'false'))\nMAIL_USERNAME = os.environ.get('REDASH_MAIL_USERNAME', None)\nMAIL_PASSWORD = os.environ.get('REDASH_MAIL_PASSWORD', None)\nMAIL_DEFAULT_SENDER = os.environ.get('REDASH_MAIL_DEFAULT_SENDER', None)\nMAIL_MAX_EMAILS = os.environ.get('REDASH_MAIL_MAX_EMAILS', None)\nMAIL_ASCII_ATTACHMENTS = parse_boolean(os.environ.get('REDASH_MAIL_ASCII_ATTACHMENTS', 'false'))\n\nHOST = os.environ.get('REDASH_HOST', '')\n\n# CORS settings for the Query Result API (and possbily future external APIs).\n# In most cases all you need to do is set REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN\n# to the calling domain (or domains in a comma separated list).\nACCESS_CONTROL_ALLOW_ORIGIN = set_from_string(os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN\", \"\"))\nACCESS_CONTROL_ALLOW_CREDENTIALS = parse_boolean(os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_CREDENTIALS\", \"false\"))\nACCESS_CONTROL_REQUEST_METHOD = os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_REQUEST_METHOD\", \"GET, POST, PUT\")\nACCESS_CONTROL_ALLOW_HEADERS = os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS\", \"Content-Type\")\n\n# Query Runners\ndefault_query_runners = [\n    'redash.query_runner.big_query',\n    'redash.query_runner.google_spreadsheets',\n    'redash.query_runner.graphite',\n    'redash.query_runner.mongodb',\n    'redash.query_runner.mysql',\n    'redash.query_runner.pg',\n    'redash.query_runner.url',\n    'redash.query_runner.influx_db',\n    'redash.query_runner.elasticsearch',\n    'redash.query_runner.presto',\n    'redash.query_runner.hive_ds',\n    'redash.query_runner.impala_ds',\n    'redash.query_runner.vertica',\n    'redash.query_runner.treasuredata'\n]\n\nenabled_query_runners = array_from_string(os.environ.get(\"REDASH_ENABLED_QUERY_RUNNERS\", \",\".join(default_query_runners)))\nadditional_query_runners = array_from_string(os.environ.get(\"REDASH_ADDITIONAL_QUERY_RUNNERS\", \"\"))\n\nQUERY_RUNNERS = distinct(enabled_query_runners + additional_query_runners)\n\n# Support for Sentry (http://getsentry.com/). Just set your Sentry DSN to enable it:\nSENTRY_DSN = os.environ.get(\"REDASH_SENTRY_DSN\", \"\")\n\n# Client side toggles:\nALLOW_SCRIPTS_IN_USER_INPUT = parse_boolean(os.environ.get(\"REDASH_ALLOW_SCRIPTS_IN_USER_INPUT\", \"false\"))\nCLIENT_SIDE_METRICS = parse_boolean(os.environ.get(\"REDASH_CLIENT_SIDE_METRICS\", \"false\"))\n# http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold\nHIGHCHARTS_TURBO_THRESHOLD = int(os.environ.get(\"REDASH_HIGHCHARTS_TURBO_THRESHOLD\", \"1000\"))\n\n# Features:\nFEATURE_ALLOW_ALL_TO_EDIT_QUERIES = parse_boolean(os.environ.get(\"REDASH_FEATURE_ALLOW_ALL_TO_EDIT\", \"true\"))\nFEATURE_TABLES_PERMISSIONS = parse_boolean(os.environ.get(\"REDASH_FEATURE_TABLES_PERMISSIONS\", \"false\"))\n\n# BigQuery\nBIGQUERY_HTTP_TIMEOUT = int(os.environ.get(\"REDASH_BIGQUERY_HTTP_TIMEOUT\", \"600\"))\n", "path": "redash/settings.py"}], "after_files": [{"content": "import hashlib\nimport json\n\nfrom flask import render_template, send_from_directory, current_app\nfrom flask_login import current_user, login_required\n\nfrom redash import settings\nfrom redash.wsgi import app\n\n\n@app.route('/admin/<anything>/<whatever>')\n@app.route('/admin/<anything>')\n@app.route('/dashboard/<anything>')\n@app.route('/alerts')\n@app.route('/alerts/<pk>')\n@app.route('/queries')\n@app.route('/data_sources')\n@app.route('/data_sources/<pk>')\n@app.route('/users')\n@app.route('/users/<pk>')\n@app.route('/queries/<query_id>')\n@app.route('/queries/<query_id>/<anything>')\n@app.route('/personal')\n@app.route('/')\n@login_required\ndef index(**kwargs):\n    email_md5 = hashlib.md5(current_user.email.lower()).hexdigest()\n    gravatar_url = \"https://www.gravatar.com/avatar/%s?s=40\" % email_md5\n\n    user = {\n        'gravatar_url': gravatar_url,\n        'id': current_user.id,\n        'name': current_user.name,\n        'email': current_user.email,\n        'groups': current_user.groups,\n        'permissions': current_user.permissions\n    }\n\n    client_config = {\n        'clientSideMetrics': settings.CLIENT_SIDE_METRICS,\n        'allowScriptsInUserInput': settings.ALLOW_SCRIPTS_IN_USER_INPUT,\n        'highChartsTurboThreshold': settings.HIGHCHARTS_TURBO_THRESHOLD,\n        'dateFormat': settings.DATE_FORMAT,\n        'dateTimeFormat': \"{0} HH:mm\".format(settings.DATE_FORMAT)\n    }\n\n    return render_template(\"index.html\", user=json.dumps(user), name=settings.NAME,\n                           client_config=json.dumps(client_config),\n                           analytics=settings.ANALYTICS)\n\n\n@app.route('/<path:filename>')\ndef send_static(filename):\n    if current_app.debug:\n        cache_timeout = 0\n    else:\n        cache_timeout = None\n\n    return send_from_directory(settings.STATIC_ASSETS_PATH, filename, cache_timeout=cache_timeout)\n", "path": "redash/handlers/static.py"}, {"content": "import json\nimport os\nimport urlparse\nfrom funcy import distinct\n\n\ndef parse_db_url(url):\n    url_parts = urlparse.urlparse(url)\n    connection = {'threadlocals': True}\n\n    if url_parts.hostname and not url_parts.path:\n        connection['name'] = url_parts.hostname\n    else:\n        connection['name'] = url_parts.path[1:]\n        connection['host'] = url_parts.hostname\n        connection['port'] = url_parts.port\n        connection['user'] = url_parts.username\n        connection['password'] = url_parts.password\n\n    return connection\n\n\ndef fix_assets_path(path):\n    fullpath = os.path.join(os.path.dirname(__file__), path)\n    return fullpath\n\n\ndef array_from_string(str):\n    array = str.split(',')\n    if \"\" in array:\n        array.remove(\"\")\n\n    return array\n\n\ndef set_from_string(str):\n    return set(array_from_string(str))\n\n\ndef parse_boolean(str):\n    return json.loads(str.lower())\n\n\ndef all_settings():\n    from types import ModuleType\n\n    settings = {}\n    for name, item in globals().iteritems():\n        if not callable(item) and not name.startswith(\"__\") and not isinstance(item, ModuleType):\n            settings[name] = item\n\n    return settings\n\n\nNAME = os.environ.get('REDASH_NAME', 're:dash')\n\nREDIS_URL = os.environ.get('REDASH_REDIS_URL', \"redis://localhost:6379/0\")\n\nSTATSD_HOST = os.environ.get('REDASH_STATSD_HOST', \"127.0.0.1\")\nSTATSD_PORT = int(os.environ.get('REDASH_STATSD_PORT', \"8125\"))\nSTATSD_PREFIX = os.environ.get('REDASH_STATSD_PREFIX', \"redash\")\n\n# Connection settings for re:dash's own database (where we store the queries, results, etc)\nDATABASE_CONFIG = parse_db_url(os.environ.get(\"REDASH_DATABASE_URL\", \"postgresql://postgres\"))\n\n# Celery related settings\nCELERY_BROKER = os.environ.get(\"REDASH_CELERY_BROKER\", REDIS_URL)\nCELERY_BACKEND = os.environ.get(\"REDASH_CELERY_BACKEND\", CELERY_BROKER)\n\n# The following enables periodic job (every 5 minutes) of removing unused query results.\nQUERY_RESULTS_CLEANUP_ENABLED = parse_boolean(os.environ.get(\"REDASH_QUERY_RESULTS_CLEANUP_ENABLED\", \"true\"))\n\nAUTH_TYPE = os.environ.get(\"REDASH_AUTH_TYPE\", \"api_key\")\nPASSWORD_LOGIN_ENABLED = parse_boolean(os.environ.get(\"REDASH_PASSWORD_LOGIN_ENABLED\", \"true\"))\n\n# Google Apps domain to allow access from; any user with email in this Google Apps will be allowed\n# access\nGOOGLE_APPS_DOMAIN = set_from_string(os.environ.get(\"REDASH_GOOGLE_APPS_DOMAIN\", \"\"))\n\nGOOGLE_CLIENT_ID = os.environ.get(\"REDASH_GOOGLE_CLIENT_ID\", \"\")\nGOOGLE_CLIENT_SECRET = os.environ.get(\"REDASH_GOOGLE_CLIENT_SECRET\", \"\")\nGOOGLE_OAUTH_ENABLED = GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET\n\nSAML_METADATA_URL = os.environ.get(\"REDASH_SAML_METADATA_URL\", \"\")\nSAML_LOGIN_ENABLED = SAML_METADATA_URL != \"\"\nSAML_CALLBACK_SERVER_NAME = os.environ.get(\"REDASH_SAML_CALLBACK_SERVER_NAME\", \"\")\n\nSTATIC_ASSETS_PATH = fix_assets_path(os.environ.get(\"REDASH_STATIC_ASSETS_PATH\", \"../rd_ui/app/\"))\nJOB_EXPIRY_TIME = int(os.environ.get(\"REDASH_JOB_EXPIRY_TIME\", 3600 * 6))\nCOOKIE_SECRET = os.environ.get(\"REDASH_COOKIE_SECRET\", \"c292a0a3aa32397cdb050e233733900f\")\nLOG_LEVEL = os.environ.get(\"REDASH_LOG_LEVEL\", \"INFO\")\nANALYTICS = os.environ.get(\"REDASH_ANALYTICS\", \"\")\n\n# Mail settings:\nMAIL_SERVER = os.environ.get('REDASH_MAIL_SERVER', 'localhost')\nMAIL_PORT = int(os.environ.get('REDASH_MAIL_PORT', 25))\nMAIL_USE_TLS = parse_boolean(os.environ.get('REDASH_MAIL_USE_TLS', 'false'))\nMAIL_USE_SSL = parse_boolean(os.environ.get('REDASH_MAIL_USE_SSL', 'false'))\nMAIL_USERNAME = os.environ.get('REDASH_MAIL_USERNAME', None)\nMAIL_PASSWORD = os.environ.get('REDASH_MAIL_PASSWORD', None)\nMAIL_DEFAULT_SENDER = os.environ.get('REDASH_MAIL_DEFAULT_SENDER', None)\nMAIL_MAX_EMAILS = os.environ.get('REDASH_MAIL_MAX_EMAILS', None)\nMAIL_ASCII_ATTACHMENTS = parse_boolean(os.environ.get('REDASH_MAIL_ASCII_ATTACHMENTS', 'false'))\n\nHOST = os.environ.get('REDASH_HOST', '')\n\n# CORS settings for the Query Result API (and possbily future external APIs).\n# In most cases all you need to do is set REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN\n# to the calling domain (or domains in a comma separated list).\nACCESS_CONTROL_ALLOW_ORIGIN = set_from_string(os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN\", \"\"))\nACCESS_CONTROL_ALLOW_CREDENTIALS = parse_boolean(os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_CREDENTIALS\", \"false\"))\nACCESS_CONTROL_REQUEST_METHOD = os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_REQUEST_METHOD\", \"GET, POST, PUT\")\nACCESS_CONTROL_ALLOW_HEADERS = os.environ.get(\"REDASH_CORS_ACCESS_CONTROL_ALLOW_HEADERS\", \"Content-Type\")\n\n# Query Runners\ndefault_query_runners = [\n    'redash.query_runner.big_query',\n    'redash.query_runner.google_spreadsheets',\n    'redash.query_runner.graphite',\n    'redash.query_runner.mongodb',\n    'redash.query_runner.mysql',\n    'redash.query_runner.pg',\n    'redash.query_runner.url',\n    'redash.query_runner.influx_db',\n    'redash.query_runner.elasticsearch',\n    'redash.query_runner.presto',\n    'redash.query_runner.hive_ds',\n    'redash.query_runner.impala_ds',\n    'redash.query_runner.vertica',\n    'redash.query_runner.treasuredata'\n]\n\nenabled_query_runners = array_from_string(os.environ.get(\"REDASH_ENABLED_QUERY_RUNNERS\", \",\".join(default_query_runners)))\nadditional_query_runners = array_from_string(os.environ.get(\"REDASH_ADDITIONAL_QUERY_RUNNERS\", \"\"))\n\nQUERY_RUNNERS = distinct(enabled_query_runners + additional_query_runners)\n\n# Support for Sentry (http://getsentry.com/). Just set your Sentry DSN to enable it:\nSENTRY_DSN = os.environ.get(\"REDASH_SENTRY_DSN\", \"\")\n\n# Client side toggles:\nALLOW_SCRIPTS_IN_USER_INPUT = parse_boolean(os.environ.get(\"REDASH_ALLOW_SCRIPTS_IN_USER_INPUT\", \"false\"))\nCLIENT_SIDE_METRICS = parse_boolean(os.environ.get(\"REDASH_CLIENT_SIDE_METRICS\", \"false\"))\n# http://api.highcharts.com/highcharts#plotOptions.series.turboThreshold\nHIGHCHARTS_TURBO_THRESHOLD = int(os.environ.get(\"REDASH_HIGHCHARTS_TURBO_THRESHOLD\", \"1000\"))\nDATE_FORMAT = os.environ.get(\"REDASH_DATE_FORMAT\", \"DD/MM/YY\")\n\n# Features:\nFEATURE_ALLOW_ALL_TO_EDIT_QUERIES = parse_boolean(os.environ.get(\"REDASH_FEATURE_ALLOW_ALL_TO_EDIT\", \"true\"))\nFEATURE_TABLES_PERMISSIONS = parse_boolean(os.environ.get(\"REDASH_FEATURE_TABLES_PERMISSIONS\", \"false\"))\n\n# BigQuery\nBIGQUERY_HTTP_TIMEOUT = int(os.environ.get(\"REDASH_BIGQUERY_HTTP_TIMEOUT\", \"600\"))\n", "path": "redash/settings.py"}]}