fix: accept old database payload (#21923)

This commit is contained in:
Beto Dealmeida 2022-10-25 10:29:29 -07:00 committed by GitHub
parent fa67315f5b
commit 1388f21ee3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 4 deletions

View File

@ -14,6 +14,9 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# pylint: disable=no-self-use, unused-argument
import inspect
import json
from typing import Any, Dict
@ -240,7 +243,6 @@ class DatabaseParametersSchemaMixin: # pylint: disable=too-few-public-methods
missing=ConfigurationMethod.SQLALCHEMY_FORM,
)
# pylint: disable=no-self-use, unused-argument
@pre_load
def build_sqlalchemy_uri(
self, data: Dict[str, Any], **kwargs: Any
@ -303,10 +305,28 @@ class DatabaseParametersSchemaMixin: # pylint: disable=too-few-public-methods
return data
def rename_encrypted_extra(
self: Schema,
data: Dict[str, Any],
**kwargs: Any,
) -> Dict[str, Any]:
"""
Rename ``encrypted_extra`` to ``masked_encrypted_extra``.
PR #21248 changed the database schema for security reasons. This pre-loader keeps
Superset backwards compatible with older clients.
"""
if "encrypted_extra" in data:
data["masked_encrypted_extra"] = data.pop("encrypted_extra")
return data
class DatabaseValidateParametersSchema(Schema):
class Meta: # pylint: disable=too-few-public-methods
unknown = EXCLUDE
rename_encrypted_extra = pre_load(rename_encrypted_extra)
id = fields.Integer(allow_none=True, description="Database ID (for updates)")
engine = fields.String(required=True, description="SQLAlchemy engine to use")
driver = fields.String(allow_none=True, description="SQLAlchemy driver to use")
@ -349,6 +369,8 @@ class DatabasePostSchema(Schema, DatabaseParametersSchemaMixin):
class Meta: # pylint: disable=too-few-public-methods
unknown = EXCLUDE
rename_encrypted_extra = pre_load(rename_encrypted_extra)
database_name = fields.String(
description=database_name_description,
required=True,
@ -393,6 +415,8 @@ class DatabasePutSchema(Schema, DatabaseParametersSchemaMixin):
class Meta: # pylint: disable=too-few-public-methods
unknown = EXCLUDE
rename_encrypted_extra = pre_load(rename_encrypted_extra)
database_name = fields.String(
description=database_name_description,
allow_none=True,
@ -433,6 +457,9 @@ class DatabasePutSchema(Schema, DatabaseParametersSchemaMixin):
class DatabaseTestConnectionSchema(Schema, DatabaseParametersSchemaMixin):
rename_encrypted_extra = pre_load(rename_encrypted_extra)
database_name = fields.String(
description=database_name_description,
allow_none=True,
@ -578,7 +605,6 @@ class DatabaseFunctionNamesResponse(Schema):
class ImportV1DatabaseExtraSchema(Schema):
# pylint: disable=no-self-use, unused-argument
@pre_load
def fix_schemas_allowed_for_csv_upload( # pylint: disable=invalid-name
self, data: Dict[str, Any], **kwargs: Any
@ -616,7 +642,6 @@ class ImportV1DatabaseExtraSchema(Schema):
class ImportV1DatabaseSchema(Schema):
# pylint: disable=no-self-use, unused-argument
@pre_load
def fix_allow_csv_upload(
self, data: Dict[str, Any], **kwargs: Any
@ -647,7 +672,6 @@ class ImportV1DatabaseSchema(Schema):
is_managed_externally = fields.Boolean(allow_none=True, default=False)
external_url = fields.String(allow_none=True)
# pylint: disable=no-self-use, unused-argument
@validates_schema
def validate_password(self, data: Dict[str, Any], **kwargs: Any) -> None:
"""If sqlalchemy_uri has a masked password, password is required"""

View File

@ -190,3 +190,38 @@ def test_database_parameters_schema_mixin_invalid_type(
dummy_schema.load(payload)
except ValidationError as err:
assert err.messages == {"port": ["Not a valid integer."]}
def test_rename_encrypted_extra() -> None:
"""
Test that ``encrypted_extra`` gets renamed to ``masked_encrypted_extra``.
"""
from superset.databases.schemas import ConfigurationMethod, DatabasePostSchema
schema = DatabasePostSchema()
# current schema
payload = schema.load(
{
"database_name": "My database",
"masked_encrypted_extra": "{}",
}
)
assert payload == {
"database_name": "My database",
"configuration_method": ConfigurationMethod.SQLALCHEMY_FORM,
"masked_encrypted_extra": "{}",
}
# previous schema
payload = schema.load(
{
"database_name": "My database",
"encrypted_extra": "{}",
}
)
assert payload == {
"database_name": "My database",
"configuration_method": ConfigurationMethod.SQLALCHEMY_FORM,
"masked_encrypted_extra": "{}",
}