Skip to content

Commit 12dd160

Browse files
author
Lily Kuang
committed
Merge branch 'master' into lily/upgrade-react-router-dom
2 parents fa28829 + d6a4a5d commit 12dd160

File tree

10 files changed

+171
-19
lines changed

10 files changed

+171
-19
lines changed

superset/databases/api.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
from superset.databases.ssh_tunnel.commands.delete import DeleteSSHTunnelCommand
7676
from superset.databases.ssh_tunnel.commands.exceptions import (
7777
SSHTunnelDeleteFailedError,
78+
SSHTunnelingNotEnabledError,
7879
SSHTunnelNotFoundError,
7980
)
8081
from superset.databases.utils import get_table_metadata
@@ -349,6 +350,8 @@ def post(self) -> FlaskResponse:
349350
exc_info=True,
350351
)
351352
return self.response_422(message=str(ex))
353+
except SSHTunnelingNotEnabledError as ex:
354+
return self.response_400(message=str(ex))
352355
except SupersetException as ex:
353356
return self.response(ex.status, message=ex.message)
354357

@@ -433,6 +436,8 @@ def put(self, pk: int) -> Response:
433436
exc_info=True,
434437
)
435438
return self.response_422(message=str(ex))
439+
except SSHTunnelingNotEnabledError as ex:
440+
return self.response_400(message=str(ex))
436441

437442
@expose("/<int:pk>", methods=["DELETE"])
438443
@protect()
@@ -782,8 +787,11 @@ def test_connection(self) -> FlaskResponse:
782787
# This validates custom Schema with custom validations
783788
except ValidationError as error:
784789
return self.response_400(message=error.messages)
785-
TestConnectionDatabaseCommand(item).run()
786-
return self.response(200, message="OK")
790+
try:
791+
TestConnectionDatabaseCommand(item).run()
792+
return self.response(200, message="OK")
793+
except SSHTunnelingNotEnabledError as ex:
794+
return self.response_400(message=str(ex))
787795

788796
@expose("/<int:pk>/related_objects/", methods=["GET"])
789797
@protect()
@@ -1320,3 +1328,11 @@ def delete_ssh_tunnel(self, pk: int) -> Response:
13201328
exc_info=True,
13211329
)
13221330
return self.response_422(message=str(ex))
1331+
except SSHTunnelingNotEnabledError as ex:
1332+
logger.error(
1333+
"Error deleting SSH Tunnel %s: %s",
1334+
self.__class__.__name__,
1335+
str(ex),
1336+
exc_info=True,
1337+
)
1338+
return self.response_400(message=str(ex))

superset/databases/commands/create.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from flask_appbuilder.models.sqla import Model
2121
from marshmallow import ValidationError
2222

23+
from superset import is_feature_enabled
2324
from superset.commands.base import BaseCommand
2425
from superset.dao.exceptions import DAOCreateFailedError
2526
from superset.databases.commands.exceptions import (
@@ -34,6 +35,7 @@
3435
from superset.databases.ssh_tunnel.commands.create import CreateSSHTunnelCommand
3536
from superset.databases.ssh_tunnel.commands.exceptions import (
3637
SSHTunnelCreateFailedError,
38+
SSHTunnelingNotEnabledError,
3739
SSHTunnelInvalidError,
3840
)
3941
from superset.exceptions import SupersetErrorsException
@@ -52,7 +54,7 @@ def run(self) -> Model:
5254
try:
5355
# Test connection before starting create transaction
5456
TestConnectionDatabaseCommand(self._properties).run()
55-
except SupersetErrorsException as ex:
57+
except (SupersetErrorsException, SSHTunnelingNotEnabledError) as ex:
5658
event_logger.log_with_context(
5759
action=f"db_creation_failed.{ex.__class__.__name__}",
5860
engine=self._properties.get("sqlalchemy_uri", "").split(":")[0],
@@ -78,6 +80,9 @@ def run(self) -> Model:
7880

7981
ssh_tunnel = None
8082
if ssh_tunnel_properties := self._properties.get("ssh_tunnel"):
83+
if not is_feature_enabled("SSH_TUNNELING"):
84+
db.session.rollback()
85+
raise SSHTunnelingNotEnabledError()
8186
try:
8287
# So database.id is not None
8388
db.session.flush()

superset/databases/commands/test_connection.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@
2525
from sqlalchemy.engine import Engine
2626
from sqlalchemy.exc import DBAPIError, NoSuchModuleError
2727

28+
from superset import is_feature_enabled
2829
from superset.commands.base import BaseCommand
2930
from superset.databases.commands.exceptions import (
3031
DatabaseSecurityUnsafeError,
3132
DatabaseTestConnectionDriverError,
3233
DatabaseTestConnectionUnexpectedError,
3334
)
3435
from superset.databases.dao import DatabaseDAO
36+
from superset.databases.ssh_tunnel.commands.exceptions import (
37+
SSHTunnelingNotEnabledError,
38+
)
3539
from superset.databases.ssh_tunnel.dao import SSHTunnelDAO
3640
from superset.databases.ssh_tunnel.models import SSHTunnel
3741
from superset.databases.utils import make_url_safe
@@ -64,7 +68,7 @@ def __init__(self, data: Dict[str, Any]):
6468
self._properties = data.copy()
6569
self._model: Optional[Database] = None
6670

67-
def run(self) -> None: # pylint: disable=too-many-statements
71+
def run(self) -> None: # pylint: disable=too-many-statements, too-many-branches
6872
self.validate()
6973
ex_str = ""
7074
uri = self._properties.get("sqlalchemy_uri", "")
@@ -107,6 +111,8 @@ def run(self) -> None: # pylint: disable=too-many-statements
107111

108112
# Generate tunnel if present in the properties
109113
if ssh_tunnel:
114+
if not is_feature_enabled("SSH_TUNNELING"):
115+
raise SSHTunnelingNotEnabledError()
110116
# If there's an existing tunnel for that DB we need to use the stored
111117
# password, private_key and private_key_password instead
112118
if ssh_tunnel_id := ssh_tunnel.pop("id", None):
@@ -203,6 +209,15 @@ def ping(engine: Engine) -> bool:
203209
)
204210
# bubble up the exception to return a 408
205211
raise ex
212+
except SSHTunnelingNotEnabledError as ex:
213+
event_logger.log_with_context(
214+
action=get_log_connection_action(
215+
"test_connection_error", ssh_tunnel, ex
216+
),
217+
engine=database.db_engine_spec.__name__,
218+
)
219+
# bubble up the exception to return a 400
220+
raise ex
206221
except Exception as ex:
207222
event_logger.log_with_context(
208223
action=get_log_connection_action(

superset/databases/commands/update.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from flask_appbuilder.models.sqla import Model
2121
from marshmallow import ValidationError
2222

23+
from superset import is_feature_enabled
2324
from superset.commands.base import BaseCommand
2425
from superset.dao.exceptions import DAOCreateFailedError, DAOUpdateFailedError
2526
from superset.databases.commands.exceptions import (
@@ -33,7 +34,9 @@
3334
from superset.databases.ssh_tunnel.commands.create import CreateSSHTunnelCommand
3435
from superset.databases.ssh_tunnel.commands.exceptions import (
3536
SSHTunnelCreateFailedError,
37+
SSHTunnelingNotEnabledError,
3638
SSHTunnelInvalidError,
39+
SSHTunnelUpdateFailedError,
3740
)
3841
from superset.databases.ssh_tunnel.commands.update import UpdateSSHTunnelCommand
3942
from superset.extensions import db, security_manager
@@ -102,6 +105,9 @@ def run(self) -> Model:
102105
)
103106

104107
if ssh_tunnel_properties := self._properties.get("ssh_tunnel"):
108+
if not is_feature_enabled("SSH_TUNNELING"):
109+
db.session.rollback()
110+
raise SSHTunnelingNotEnabledError()
105111
existing_ssh_tunnel_model = DatabaseDAO.get_ssh_tunnel(database.id)
106112
if existing_ssh_tunnel_model is None:
107113
# We couldn't found an existing tunnel so we need to create one
@@ -118,7 +124,7 @@ def run(self) -> Model:
118124
UpdateSSHTunnelCommand(
119125
existing_ssh_tunnel_model.id, ssh_tunnel_properties
120126
).run()
121-
except (SSHTunnelInvalidError, SSHTunnelCreateFailedError) as ex:
127+
except (SSHTunnelInvalidError, SSHTunnelUpdateFailedError) as ex:
122128
# So we can show the original message
123129
raise ex
124130
except Exception as ex:

superset/databases/ssh_tunnel/commands/delete.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
from flask_appbuilder.models.sqla import Model
2121

22+
from superset import is_feature_enabled
2223
from superset.commands.base import BaseCommand
2324
from superset.dao.exceptions import DAODeleteFailedError
2425
from superset.databases.ssh_tunnel.commands.exceptions import (
2526
SSHTunnelDeleteFailedError,
27+
SSHTunnelingNotEnabledError,
2628
SSHTunnelNotFoundError,
2729
)
2830
from superset.databases.ssh_tunnel.dao import SSHTunnelDAO
@@ -37,6 +39,8 @@ def __init__(self, model_id: int):
3739
self._model: Optional[SSHTunnel] = None
3840

3941
def run(self) -> Model:
42+
if not is_feature_enabled("SSH_TUNNELING"):
43+
raise SSHTunnelingNotEnabledError()
4044
self.validate()
4145
try:
4246
ssh_tunnel = SSHTunnelDAO.delete(self._model)

superset/databases/ssh_tunnel/commands/exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ class SSHTunnelCreateFailedError(CommandException):
4646
message = _("Creating SSH Tunnel failed for an unknown reason")
4747

4848

49+
class SSHTunnelingNotEnabledError(CommandException):
50+
status = 400
51+
message = _("SSH Tunneling is not enabled")
52+
53+
4954
class SSHTunnelRequiredFieldValidationError(ValidationError):
5055
def __init__(self, field_name: str) -> None:
5156
super().__init__(

0 commit comments

Comments
 (0)