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

Reply via email to