"""A credential preview inner object."""
from typing import Sequence
from marshmallow import fields
from ......messaging.models.base import BaseModel, BaseModelSchema
from ......wallet.util import b64_to_str
from ...message_types import CREDENTIAL_PREVIEW
[docs]class CredAttrSpec(BaseModel):
"""Class representing a preview of an attibute."""
def __init__(self, *, name: str, value: str, mime_type: str = None, **kwargs):
"""
Initialize attribute preview object.
Args:
name: attribute name
value: attribute value; caller must base64-encode for attributes with
non-empty MIME type
mime_type: MIME type (default null)
"""
super().__init__(**kwargs)
self.name = name
self.value = value
self.mime_type = mime_type.lower() if mime_type else None
[docs] @staticmethod
def list_plain(plain: dict):
"""
Return a list of `CredAttrSpec` without MIME types from names/values.
Args:
plain: dict mapping names to values
Returns:
List of CredAttrSpecs with no MIME types
"""
return [CredAttrSpec(name=k, value=plain[k]) for k in plain]
[docs] def b64_decoded_value(self) -> str:
"""Value, base64-decoded if applicable."""
return b64_to_str(self.value) if self.value and self.mime_type else self.value
def __eq__(self, other):
"""Equality comparator."""
if self.name != other.name:
return False # distinct attribute names
if self.mime_type != other.mime_type:
return False # distinct MIME types
return self.b64_decoded_value() == other.b64_decoded_value()
[docs]class CredAttrSpecSchema(BaseModelSchema):
"""Attribute preview schema."""
name = fields.Str(
description="Attribute name", required=True, example="favourite_drink"
)
mime_type = fields.Str(
description="MIME type: omit for (null) default",
required=False,
data_key="mime-type",
example="image/jpeg",
allow_none=True,
)
value = fields.Str(
description="Attribute value: base64-encode if MIME type is present",
required=True,
example="martini",
)
[docs]class CredentialPreview(BaseModel):
"""Class representing a credential preview inner object."""
def __init__(
self, *, _type: str = None, attributes: Sequence[CredAttrSpec] = None, **kwargs
):
"""
Initialize credential preview object.
Args:
_type: formalism for Marshmallow model creation: ignored
attributes (list): list of attribute preview dicts; e.g., [
{
"name": "attribute_name",
"value": "value"
},
{
"name": "icon",
"mime-type": "image/png",
"value": "cG90YXRv"
}
]
"""
super().__init__(**kwargs)
self.attributes = list(attributes) if attributes else []
@property
def _type(self):
"""Accessor for message type."""
return CredentialPreview.Meta.message_type
[docs] def attr_dict(self, decode: bool = False):
"""
Return name:value pair per attribute.
Args:
decode: whether first to decode attributes with MIME type
"""
return {
attr.name: b64_to_str(attr.value)
if attr.mime_type and decode
else attr.value
for attr in self.attributes
}
[docs] def mime_types(self):
"""
Return per-attribute mapping from name to MIME type.
Return empty dict if no attribute has MIME type.
"""
return {attr.name: attr.mime_type for attr in self.attributes if attr.mime_type}
[docs]class CredentialPreviewSchema(BaseModelSchema):
"""Credential preview schema."""
_type = fields.Str(
description="Message type identifier",
required=False,
example=CREDENTIAL_PREVIEW,
data_key="@type",
)
attributes = fields.Nested(
CredAttrSpecSchema, many=True, required=True, data_key="attributes"
)