mirror of https://github.com/apache/superset.git
fix: catch error when masking encrypted extra is none (#21570)
This commit is contained in:
parent
c1ba3290d9
commit
ef78ec6b30
|
@ -1618,7 +1618,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods
|
||||||
return user.username if user else None
|
return user.username if user else None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mask_encrypted_extra(cls, encrypted_extra: str) -> str:
|
def mask_encrypted_extra(cls, encrypted_extra: Optional[str]) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Mask ``encrypted_extra``.
|
Mask ``encrypted_extra``.
|
||||||
|
|
||||||
|
@ -1631,7 +1631,9 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
@classmethod
|
@classmethod
|
||||||
def unmask_encrypted_extra(cls, old: str, new: str) -> str:
|
def unmask_encrypted_extra(
|
||||||
|
cls, old: Optional[str], new: Optional[str]
|
||||||
|
) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Remove masks from ``encrypted_extra``.
|
Remove masks from ``encrypted_extra``.
|
||||||
|
|
||||||
|
|
|
@ -396,10 +396,13 @@ class BigQueryEngineSpec(BaseEngineSpec):
|
||||||
raise ValidationError("Invalid service credentials")
|
raise ValidationError("Invalid service credentials")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mask_encrypted_extra(cls, encrypted_extra: str) -> str:
|
def mask_encrypted_extra(cls, encrypted_extra: Optional[str]) -> Optional[str]:
|
||||||
|
if encrypted_extra is None:
|
||||||
|
return encrypted_extra
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = json.loads(encrypted_extra)
|
config = json.loads(encrypted_extra)
|
||||||
except json.JSONDecodeError:
|
except (json.JSONDecodeError, TypeError):
|
||||||
return encrypted_extra
|
return encrypted_extra
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -410,14 +413,19 @@ class BigQueryEngineSpec(BaseEngineSpec):
|
||||||
return json.dumps(config)
|
return json.dumps(config)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unmask_encrypted_extra(cls, old: str, new: str) -> str:
|
def unmask_encrypted_extra(
|
||||||
|
cls, old: Optional[str], new: Optional[str]
|
||||||
|
) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Reuse ``private_key`` if available and unchanged.
|
Reuse ``private_key`` if available and unchanged.
|
||||||
"""
|
"""
|
||||||
|
if old is None or new is None:
|
||||||
|
return new
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_config = json.loads(old)
|
old_config = json.loads(old)
|
||||||
new_config = json.loads(new)
|
new_config = json.loads(new)
|
||||||
except json.JSONDecodeError:
|
except (TypeError, json.JSONDecodeError):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
if "credentials_info" not in new_config:
|
if "credentials_info" not in new_config:
|
||||||
|
|
|
@ -140,10 +140,13 @@ class GSheetsEngineSpec(SqliteEngineSpec):
|
||||||
raise ValidationError("Invalid service credentials")
|
raise ValidationError("Invalid service credentials")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mask_encrypted_extra(cls, encrypted_extra: str) -> str:
|
def mask_encrypted_extra(cls, encrypted_extra: Optional[str]) -> Optional[str]:
|
||||||
|
if encrypted_extra is None:
|
||||||
|
return encrypted_extra
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = json.loads(encrypted_extra)
|
config = json.loads(encrypted_extra)
|
||||||
except json.JSONDecodeError:
|
except (TypeError, json.JSONDecodeError):
|
||||||
return encrypted_extra
|
return encrypted_extra
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -154,14 +157,19 @@ class GSheetsEngineSpec(SqliteEngineSpec):
|
||||||
return json.dumps(config)
|
return json.dumps(config)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unmask_encrypted_extra(cls, old: str, new: str) -> str:
|
def unmask_encrypted_extra(
|
||||||
|
cls, old: Optional[str], new: Optional[str]
|
||||||
|
) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Reuse ``private_key`` if available and unchanged.
|
Reuse ``private_key`` if available and unchanged.
|
||||||
"""
|
"""
|
||||||
|
if old is None or new is None:
|
||||||
|
return new
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_config = json.loads(old)
|
old_config = json.loads(old)
|
||||||
new_config = json.loads(new)
|
new_config = json.loads(new)
|
||||||
except json.JSONDecodeError:
|
except (TypeError, json.JSONDecodeError):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
if "service_account_info" not in new_config:
|
if "service_account_info" not in new_config:
|
||||||
|
|
|
@ -248,7 +248,7 @@ class Database(
|
||||||
return sqlalchemy_url.get_backend_name()
|
return sqlalchemy_url.get_backend_name()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def masked_encrypted_extra(self) -> str:
|
def masked_encrypted_extra(self) -> Optional[str]:
|
||||||
return self.db_engine_spec.mask_encrypted_extra(self.encrypted_extra)
|
return self.db_engine_spec.mask_encrypted_extra(self.encrypted_extra)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -261,10 +261,12 @@ class Database(
|
||||||
masked_encrypted_extra = db_engine_spec.mask_encrypted_extra(
|
masked_encrypted_extra = db_engine_spec.mask_encrypted_extra(
|
||||||
self.encrypted_extra
|
self.encrypted_extra
|
||||||
)
|
)
|
||||||
|
encrypted_config = {}
|
||||||
|
if masked_encrypted_extra is not None:
|
||||||
try:
|
try:
|
||||||
encrypted_config = json.loads(masked_encrypted_extra)
|
encrypted_config = json.loads(masked_encrypted_extra)
|
||||||
except (TypeError, json.JSONDecodeError):
|
except (TypeError, json.JSONDecodeError):
|
||||||
encrypted_config = {}
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# pylint: disable=useless-suppression
|
# pylint: disable=useless-suppression
|
||||||
|
|
|
@ -186,9 +186,61 @@ def test_unmask_encrypted_extra() -> None:
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert json.loads(BigQueryEngineSpec.unmask_encrypted_extra(old, new)) == {
|
assert json.loads(str(BigQueryEngineSpec.unmask_encrypted_extra(old, new))) == {
|
||||||
"credentials_info": {
|
"credentials_info": {
|
||||||
"project_id": "yellow-unicorn-314419",
|
"project_id": "yellow-unicorn-314419",
|
||||||
"private_key": "SECRET",
|
"private_key": "SECRET",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_unmask_encrypted_extra_when_empty() -> None:
|
||||||
|
"""
|
||||||
|
Test that a None value works for ``encrypted_extra``.
|
||||||
|
"""
|
||||||
|
from superset.db_engine_specs.bigquery import BigQueryEngineSpec
|
||||||
|
|
||||||
|
old = None
|
||||||
|
new = json.dumps(
|
||||||
|
{
|
||||||
|
"credentials_info": {
|
||||||
|
"project_id": "yellow-unicorn-314419",
|
||||||
|
"private_key": "XXXXXXXXXX",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert json.loads(str(BigQueryEngineSpec.unmask_encrypted_extra(old, new))) == {
|
||||||
|
"credentials_info": {
|
||||||
|
"project_id": "yellow-unicorn-314419",
|
||||||
|
"private_key": "XXXXXXXXXX",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_unmask_encrypted_extra_when_new_is_empty() -> None:
|
||||||
|
"""
|
||||||
|
Test that a None value works for ``encrypted_extra``.
|
||||||
|
"""
|
||||||
|
from superset.db_engine_specs.bigquery import BigQueryEngineSpec
|
||||||
|
|
||||||
|
old = json.dumps(
|
||||||
|
{
|
||||||
|
"credentials_info": {
|
||||||
|
"project_id": "black-sanctum-314419",
|
||||||
|
"private_key": "SECRET",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
new = None
|
||||||
|
|
||||||
|
assert BigQueryEngineSpec.unmask_encrypted_extra(old, new) is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_mask_encrypted_extra_when_empty() -> None:
|
||||||
|
"""
|
||||||
|
Test that the encrypted extra will return a none value if the field is empty.
|
||||||
|
"""
|
||||||
|
from superset.db_engine_specs.bigquery import BigQueryEngineSpec
|
||||||
|
|
||||||
|
assert BigQueryEngineSpec.mask_encrypted_extra(None) is None
|
||||||
|
|
|
@ -228,9 +228,52 @@ def test_unmask_encrypted_extra() -> None:
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert json.loads(GSheetsEngineSpec.unmask_encrypted_extra(old, new)) == {
|
assert json.loads(str(GSheetsEngineSpec.unmask_encrypted_extra(old, new))) == {
|
||||||
"service_account_info": {
|
"service_account_info": {
|
||||||
"project_id": "yellow-unicorn-314419",
|
"project_id": "yellow-unicorn-314419",
|
||||||
"private_key": "SECRET",
|
"private_key": "SECRET",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_unmask_encrypted_extra_when_old_is_none() -> None:
|
||||||
|
"""
|
||||||
|
Test that a None value works for ``encrypted_extra``.
|
||||||
|
"""
|
||||||
|
from superset.db_engine_specs.gsheets import GSheetsEngineSpec
|
||||||
|
|
||||||
|
old = None
|
||||||
|
new = json.dumps(
|
||||||
|
{
|
||||||
|
"service_account_info": {
|
||||||
|
"project_id": "yellow-unicorn-314419",
|
||||||
|
"private_key": "XXXXXXXXXX",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert json.loads(str(GSheetsEngineSpec.unmask_encrypted_extra(old, new))) == {
|
||||||
|
"service_account_info": {
|
||||||
|
"project_id": "yellow-unicorn-314419",
|
||||||
|
"private_key": "XXXXXXXXXX",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_unmask_encrypted_extra_when_new_is_none() -> None:
|
||||||
|
"""
|
||||||
|
Test that a None value works for ``encrypted_extra``.
|
||||||
|
"""
|
||||||
|
from superset.db_engine_specs.gsheets import GSheetsEngineSpec
|
||||||
|
|
||||||
|
old = json.dumps(
|
||||||
|
{
|
||||||
|
"service_account_info": {
|
||||||
|
"project_id": "yellow-unicorn-314419",
|
||||||
|
"private_key": "XXXXXXXXXX",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
new = None
|
||||||
|
|
||||||
|
assert GSheetsEngineSpec.unmask_encrypted_extra(old, new) is None
|
||||||
|
|
Loading…
Reference in New Issue