From f59afcccf75286caf45953cb767f980fb21504f0 Mon Sep 17 00:00:00 2001 From: Ethan Paul Date: Tue, 10 Mar 2020 23:29:05 -0400 Subject: [PATCH] Add basic roundtrip test for domain serializer Fix dumping and loading compatibility of domain model Fix (untested) dumping and loading compatibility of account model Loosen simple name regex requirements --- keyosk/constants.py | 2 +- keyosk/serializers/account.py | 8 +++----- keyosk/serializers/domain.py | 16 ++++++++-------- tests/test_serializers_domain.py | 20 ++++++++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 tests/test_serializers_domain.py diff --git a/keyosk/constants.py b/keyosk/constants.py index 984c456..b619010 100644 --- a/keyosk/constants.py +++ b/keyosk/constants.py @@ -4,7 +4,7 @@ DEFAULT_CONFIG_PATH = "/etc/keyosk/conf.toml" ENV_CONFIG_PATH = "KYSK_CONF_PATH" -REGEX_FRIENDLY_NAME = r"^([a-z][a-z0-9]+)(-[a-z0-9]+)*$" +REGEX_FRIENDLY_NAME = r"^([a-z0-9]+)(-[a-z0-9]+)*$" REGEX_DOMAIN_NAME = REGEX_FRIENDLY_NAME diff --git a/keyosk/serializers/account.py b/keyosk/serializers/account.py index a8d1fe0..08d8c1e 100644 --- a/keyosk/serializers/account.py +++ b/keyosk/serializers/account.py @@ -28,9 +28,8 @@ class AccountSerializer(msh.Schema): ) scopes = msh.fields.List(msh.fields.Nested(AccountScopeSerializer), required=True) - @staticmethod @msh.post_load - def _make_model(data: Dict[str, Any], **kwargs) -> KeyoskAccount: + def _make_model(self, data: Dict[str, Any], **kwargs) -> KeyoskAccount: scopes = [] for item in data["scopes"]: item.account_id = data["uuid"] @@ -38,11 +37,10 @@ class AccountSerializer(msh.Schema): data["scopes"] = scopes return KeyoskAccount(**data) - @staticmethod @msh.pre_dump - def _unmake_model(data: KeyoskAccount, **kwargs) -> Dict[str, Any]: + def _unmake_model(self, data: KeyoskAccount, **kwargs) -> Dict[str, Any]: return shortcuts.model_to_dict( - data, recurse=False, backrefs=True, extra_attrs=["extras"], + data, recurse=True, backrefs=True, max_depth=1, extra_attrs=["extras"], ) @classmethod diff --git a/keyosk/serializers/domain.py b/keyosk/serializers/domain.py index b945a24..71e7691 100644 --- a/keyosk/serializers/domain.py +++ b/keyosk/serializers/domain.py @@ -87,7 +87,7 @@ class DomainSerializer(msh.Schema): @staticmethod def serialize_access_lists(obj: Dict[Any, Any]) -> List[str]: - return [item.name for item in obj["access_lists"]] + return [item["name"] for item in obj.get("access_lists", [])] @staticmethod def deserialize_permissions(value: List[str]) -> List[KeyoskDomainPermission]: @@ -110,11 +110,10 @@ class DomainSerializer(msh.Schema): @staticmethod def serialize_permissions(obj: Dict[Any, Any]) -> List[str]: - return [item.name for item in obj["permissions"]] + return [item["name"] for item in obj.get("permissions", [])] - @staticmethod @msh.post_load - def _make_model(data: Dict[str, Any], **kwargs) -> KeyoskDomain: + def _make_model(self, data: Dict[str, Any], **kwargs) -> KeyoskDomain: acls = [] for item in data["access_lists"]: item.domain_id = data["uuid"] @@ -129,14 +128,15 @@ class DomainSerializer(msh.Schema): return KeyoskDomain(**data) - @staticmethod @msh.pre_dump - def _unmake_model(data: KeyoskDomain, **kwargs) -> Dict[str, Any]: + def _unmake_model(self, data: KeyoskDomain, **kwargs) -> Dict[str, Any]: return shortcuts.model_to_dict( data, - recurse=False, + recurse=True, backrefs=True, - extra_attrs=["lifespan_access", "lifespan_refresh",], + exclude=[KeyoskDomain._lifespan_access, KeyoskDomain._lifespan_refresh], + extra_attrs=["lifespan_access", "lifespan_refresh"], + max_depth=1, ) @classmethod diff --git a/tests/test_serializers_domain.py b/tests/test_serializers_domain.py new file mode 100644 index 0000000..ade2942 --- /dev/null +++ b/tests/test_serializers_domain.py @@ -0,0 +1,20 @@ +# pylint: disable=unused-argument,redefined-outer-name,unused-import +import pytest +from fixtures import demo_database + +from keyosk import database +from keyosk import serializers + + +def test_roundtrip(demo_database): + serializer = serializers.DomainSerializer() + + for domain in database.KeyoskDomain.select(): + dumped = serializer.dump(domain) + assert sorted(dumped["permissions"]) == sorted( + [permission.name for permission in domain.permissions] + ) + assert sorted(dumped["access-lists"]) == sorted( + acl.name for acl in domain.access_lists + ) + assert domain == serializer.load(dumped)