WIP add initial serializers

This commit is contained in:
Ethan Paul 2020-02-23 16:51:22 -05:00
parent 733ffa6cd8
commit 199cad3f43
5 changed files with 125 additions and 0 deletions

View File

@ -1,7 +1,9 @@
"""Custom fields for handing de/serializing custom data types"""
from datetime import datetime
from enum import Enum
from pathlib import Path
from typing import Any
from typing import Sequence
from typing import Type
from typing import Union
@ -80,3 +82,50 @@ class PathString(msh.fields.String):
def _deserialize(self, value: str, attr, data, **kwargs) -> Path:
return Path(super()._deserialize(value, attr, data, **kwargs))
class Epoch(msh.fields.Field):
"""Translate between datetime objects and an integer reperesenting epoch time"""
def _serialize(self, value: Union[datetime, int], attr, obj, **kwargs) -> int:
"""Serialize a datetime object to an integer"""
if isinstance(value, datetime):
return int(value.timestamp())
return value
def _deserialize(self, value: int, attr, data, **kwargs) -> datetime:
"""Deserialize an integer to a datetime object"""
try:
if value < 0:
raise msh.ValidationError(f"Invalid epoch time '{value}'")
except TypeError:
raise msh.ValidationError(
f"Invalid epoch value '{value}' of type '{type(value)}'"
)
return datetime.fromtimestamp(int(value))
class RawMultiType(msh.fields.Raw):
"""Like raw, but limits the types the value can be to a specified list
.. note:: Like the Marshmallow :class:`Raw` field, no additional validation is done on the value
beyond checking its type.
"""
def __init__(self, types: Sequence[type], *args, **kwargs):
"""Initialize the field
:param types: Sequence of types that the value to de/serialize can be
"""
super().__init__(*args, **kwargs)
self._types = tuple(types)
def _deserialize(self, value: Any, attr, data, **kwargs) -> Any:
"""Deserialize the value, raising a validation error if it is not of an allowed type"""
if not isinstance(value, self._types):
raise msh.ValidationError(
f"Invalid value '{value}' of type {type(value)}: expected one of {self._types}"
)
return value

View File

View File

@ -0,0 +1,25 @@
from typing import List
import marshmallow as msh
from keyosk import fields as custom_fields
from keyosk.serializers.account_acl import AccountACLSerializer
class AccountSerializer(msh.Schema):
uuid = msh.fields.UUID(required=True)
created = custom_fields.Epoch(required=True)
updated = custom_fields.Epoch(required=True)
username = msh.fields.String(required=True)
enabled = msh.fields.Boolean(required=True)
extras = msh.fields.Dict(
keys=msh.fields.String(),
values=custom_fields.RawMultiType([int, float, bool, str, None]),
required=True,
)
acls = msh.fields.List(msh.fields.Nested(AccountACLSerializer), required=True)
@staticmethod
def creation_fields() -> List[str]:
return ["uuid", "created", "updated"]

View File

@ -0,0 +1,13 @@
import marshmallow as msh
class AccountACLSerializer(msh.Schema):
access_list = msh.fields.String(required=True, data_key="access-list")
permission = msh.fields.String(required=True)
with_server_secret = msh.fields.Boolean(
required=True, data_key="with-server-secret"
)
with_client_secret = msh.fields.Boolean(
required=True, data_key="with-client-secret"
)

View File

@ -0,0 +1,38 @@
import marshmallow as msh
class DomainSerializer(msh.Schema):
uuid = msh.fields.UUID(required=True)
created = msh.fields.DateTime(required=True)
updated = msh.fields.DateTime(required=True)
name = msh.fields.String(required=True)
audience = msh.fields.String(required=True)
title = msh.fields.String(required=True, allow_none=True)
description = msh.fields.String(required=True, allow_none=True)
contact = msh.fields.String(required=True, allow_none=True)
enabled = msh.fields.Boolean(required=True)
enable_client_set_auth = msh.fields.Boolean(
required=True, data_key="enable-client-set-auth"
)
enable_server_set_auth = msh.fields.Boolean(
required=True, data_key="enable-server-set-auth"
)
enable_refresh = msh.fields.Boolean(required=True, data_key="enable-refresh")
lifespan_access = msh.fields.Boolean(required=True, data_key="lifespan-access")
lifespan_refresh = msh.fields.Boolean(required=True, data_key="lifespan-refresh")
access_lists = msh.fields.List()
# created = peewee.DateTimeField(null=False, default=datetime.datetime.utcnow)
# updated = peewee.DateTimeField(null=False, default=datetime.datetime.utcnow)
# name = peewee.CharField(null=False, unique=True)
# audience = peewee.CharField(null=False, unique=True)
# title = peewee.CharField(null=True)
# description = peewee.CharField(null=True)
# contact = peewee.CharField(null=True)
# enabled = peewee.BooleanField(null=False)
# enable_client_set_auth = peewee.BooleanField(null=False)
# enable_server_set_auth = peewee.BooleanField(null=False)
# enable_refresh = peewee.BooleanField(null=False)
# lifespan_access = peewee.IntegerField(null=False)
# lifespan_refresh = peewee.IntegerField(null=False)