This is an automated email from the ASF dual-hosted git repository.
maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 87f50ba Make SHOW_STACKTRACE config apply across the board (#7845)
87f50ba is described below
commit 87f50ba0d8fd33b9dd66fdc90759f3f670c649a9
Author: Maxime Beauchemin <[email protected]>
AuthorDate: Fri Jul 12 08:58:44 2019 -0700
Make SHOW_STACKTRACE config apply across the board (#7845)
---
superset/common/query_context.py | 3 +--
superset/config.py | 14 ++++++--------
superset/utils/core.py | 8 +++++++-
superset/views/base.py | 9 ++++-----
superset/views/core.py | 9 +++------
superset/viz.py | 3 +--
tests/utils_tests.py | 18 ++++++++++++++++++
7 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/superset/common/query_context.py b/superset/common/query_context.py
index 40e3291..4992405 100644
--- a/superset/common/query_context.py
+++ b/superset/common/query_context.py
@@ -18,7 +18,6 @@
from datetime import datetime, timedelta
import logging
import pickle as pkl
-import traceback
from typing import Dict, List
import numpy as np
@@ -199,7 +198,7 @@ class QueryContext:
if not error_message:
error_message = "{}".format(e)
status = utils.QueryStatus.FAILED
- stacktrace = traceback.format_exc()
+ stacktrace = utils.get_stacktrace()
if is_loaded and cache_key and cache and status !=
utils.QueryStatus.FAILED:
try:
diff --git a/superset/config.py b/superset/config.py
index 4261b54..7679d20 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -102,7 +102,9 @@ WTF_CSRF_EXEMPT_LIST = ["superset.views.core.log"]
DEBUG = os.environ.get("FLASK_ENV") == "development"
FLASK_USE_RELOAD = True
-# Whether to show the stacktrace on 500 error
+# Superset allows server-side python stacktraces to be surfaced to the
+# user when this feature is on. This may has security implications
+# and it's more secure to turn it off in production settings.
SHOW_STACKTRACE = True
# Extract and use X-Forwarded-For/X-Forwarded-Proto headers?
@@ -309,10 +311,8 @@ DEFAULT_MODULE_DS_MAP = OrderedDict(
ADDITIONAL_MODULE_DS_MAP = {}
ADDITIONAL_MIDDLEWARE = []
-"""
-1) https://docs.python-guide.org/writing/logging/
-2) https://docs.python.org/2/library/logging.config.html
-"""
+# 1) https://docs.python-guide.org/writing/logging/
+# 2) https://docs.python.org/2/library/logging.config.html
# Console Log Settings
@@ -404,10 +404,8 @@ class CeleryConfig(object):
CELERY_CONFIG = CeleryConfig
-"""
# Set celery config to None to disable all the above configuration
-CELERY_CONFIG = None
-"""
+# CELERY_CONFIG = None
# Additional static HTTP headers to be served by your Superset server. Note
# Flask-Talisman aplies the relevant security HTTP headers.
diff --git a/superset/utils/core.py b/superset/utils/core.py
index 6e50db6..3ad1c62 100644
--- a/superset/utils/core.py
+++ b/superset/utils/core.py
@@ -32,6 +32,7 @@ import signal
import smtplib
import sys
from time import struct_time
+import traceback
from typing import List, NamedTuple, Optional, Tuple
from urllib.parse import unquote_plus
import uuid
@@ -41,7 +42,7 @@ import bleach
import celery
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
-from flask import flash, Flask, g, Markup, render_template
+from flask import current_app, flash, Flask, g, Markup, render_template
from flask_appbuilder.security.sqla.models import User
from flask_babel import gettext as __
from flask_babel import lazy_gettext as _
@@ -1185,3 +1186,8 @@ def shortid() -> str:
class DatasourceName(NamedTuple):
table: str
schema: str
+
+
+def get_stacktrace():
+ if current_app.config.get("SHOW_STACKTRACE"):
+ return traceback.format_exc()
diff --git a/superset/views/base.py b/superset/views/base.py
index a77cf51..c82db76 100644
--- a/superset/views/base.py
+++ b/superset/views/base.py
@@ -66,8 +66,7 @@ def get_error_msg():
def json_error_response(msg=None, status=500, stacktrace=None, payload=None,
link=None):
if not payload:
payload = {"error": "{}".format(msg)}
- if stacktrace and conf.get("SHOW_STACKTRACE"):
- payload["stacktrace"] = stacktrace
+ payload["stacktrace"] = utils.get_stacktrace()
if link:
payload["link"] = link
@@ -125,20 +124,20 @@ def handle_api_exception(f):
return json_error_response(
utils.error_msg_from_exception(e),
status=e.status,
- stacktrace=traceback.format_exc(),
+ stacktrace=utils.get_stacktrace(),
link=e.link,
)
except SupersetException as e:
logging.exception(e)
return json_error_response(
utils.error_msg_from_exception(e),
- stacktrace=traceback.format_exc(),
+ stacktrace=utils.get_stacktrace(),
status=e.status,
)
except Exception as e:
logging.exception(e)
return json_error_response(
- utils.error_msg_from_exception(e),
stacktrace=traceback.format_exc()
+ utils.error_msg_from_exception(e),
stacktrace=utils.get_stacktrace()
)
return functools.update_wrapper(wraps, f)
diff --git a/superset/views/core.py b/superset/views/core.py
index 749812f..b0dfda9 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -21,7 +21,6 @@ import inspect
import logging
import os
import re
-import traceback
from typing import Dict, List # noqa: F401
from urllib import parse
@@ -3261,11 +3260,9 @@ class Superset(BaseSupersetView):
return self.json_response(schemas_allowed_processed)
except Exception:
return json_error_response(
- (
- "Failed to fetch schemas allowed for csv upload in this
database! "
- "Please contact Superset Admin!\n\n"
- "The error message returned was:\n{}"
- ).format(traceback.format_exc())
+ "Failed to fetch schemas allowed for csv upload in this
database! "
+ "Please contact Superset Admin!",
+ stacktrace=utils.get_stacktrace(),
)
diff --git a/superset/viz.py b/superset/viz.py
index f802787..5498bec 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -31,7 +31,6 @@ import logging
import math
import pickle as pkl
import re
-import traceback
import uuid
from dateutil import relativedelta as rdelta
@@ -423,7 +422,7 @@ class BaseViz(object):
if not self.error_message:
self.error_message = "{}".format(e)
self.status = utils.QueryStatus.FAILED
- stacktrace = traceback.format_exc()
+ stacktrace = utils.get_stacktrace()
if (
is_loaded
diff --git a/tests/utils_tests.py b/tests/utils_tests.py
index 4361682..be2ce79 100644
--- a/tests/utils_tests.py
+++ b/tests/utils_tests.py
@@ -22,12 +22,14 @@ import uuid
import numpy
+from superset import app
from superset.exceptions import SupersetException
from superset.utils.core import (
base_json_conv,
convert_legacy_filters_into_adhoc,
datetime_f,
get_since_until,
+ get_stacktrace,
json_int_dttm_ser,
json_iso_dttm_ser,
JSONEncodedDict,
@@ -763,3 +765,19 @@ class UtilsTestCase(unittest.TestCase):
def test_parse_js_uri_path_items_item_optional(self):
self.assertIsNone(parse_js_uri_path_item(None))
self.assertIsNotNone(parse_js_uri_path_item("item"))
+
+ def test_get_stacktrace(self):
+ with app.app_context():
+ app.config["SHOW_STACKTRACE"] = True
+ try:
+ raise Exception("NONONO!")
+ except Exception:
+ stacktrace = get_stacktrace()
+ self.assertIn("NONONO", stacktrace)
+
+ app.config["SHOW_STACKTRACE"] = False
+ try:
+ raise Exception("NONONO!")
+ except Exception:
+ stacktrace = get_stacktrace()
+ assert stacktrace is None