Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attachment decorator ident #210

Merged
merged 4 commits into from
Oct 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions aries_cloudagent/messaging/decorators/attach_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

import base64
import json
import uuid

from typing import Union

from marshmallow import fields

from ..models.base import BaseModel, BaseModelSchema
from ..valid import BASE64, INDY_ISO8601_DATETIME, SHA256
from ..valid import BASE64, INDY_ISO8601_DATETIME, SHA256, UUIDFour


class AttachDecoratorData(BaseModel):
Expand Down Expand Up @@ -136,7 +137,7 @@ class Meta:
def __init__(
self,
*,
append_id: str = None,
ident: str = None,
description: str = None,
filename: str = None,
mime_type: str = None,
Expand All @@ -152,8 +153,7 @@ def __init__(
content to a message.

Args:
append_id ("@id" in serialization): if appending,
identifier for the appendage
ident ("@id" in serialization): identifier for the appendage
mime_type ("mime-type" in serialization): MIME type for attachment
filename: file name
lastmod_time: last modification time, "%Y-%m-%d %H:%M:%SZ"
Expand All @@ -162,7 +162,7 @@ def __init__(

"""
super().__init__(**kwargs)
self.append_id = append_id
self.ident = ident
self.description = description
self.filename = filename
self.mime_type = mime_type
Expand All @@ -182,7 +182,16 @@ def indy_dict(self):
return json.loads(base64.b64decode(self.data.base64_.encode()).decode())

@classmethod
def from_indy_dict(cls, indy_dict: dict):
def from_indy_dict(
cls,
indy_dict: dict,
*,
ident: str = None,
description: str = None,
filename: str = None,
lastmod_time: str = None,
byte_count: int = None,
):
"""
Create `AttachDecorator` instance from indy object (dict).

Expand All @@ -191,9 +200,20 @@ def from_indy_dict(cls, indy_dict: dict):

Args:
indy_dict: indy (dict) data structure
ident: optional attachment identifier (default random UUID4)
description: optional attachment description
filename: optional attachment filename
lastmod_time: optional attachment last modification time
byte_count: optional attachment byte count

"""
return AttachDecorator(
ident=ident or str(uuid.uuid4()),
description=description,
filename=filename,
mime_type="application/json",
lastmod_time=lastmod_time,
byte_count=byte_count,
data=AttachDecoratorData(
base64_=base64.b64encode(json.dumps(indy_dict).encode()).decode()
)
Expand All @@ -208,12 +228,11 @@ class Meta:

model_class = AttachDecorator

append_id = fields.Str(
ident = fields.Str(
description="Attachment identifier",
example="view-1",
example=UUIDFour.EXAMPLE,
required=False,
allow_none=False,
attribute="append_id",
data_key="@id"
)
mime_type = fields.Str(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@

import base64
import json
import uuid

from ..attach_decorator import AttachDecorator, AttachDecoratorData


class TestAttachDecorator(TestCase):
append_id = 'image-0'
mime_type = 'image/png'
ident = str(uuid.uuid4())
description = 'To one trained by "Bob," Truth can be found in a potato'
filename = 'potato.png'
byte_count = 123456
mime_type = 'image/png'
lastmod_time = datetime.now().replace(tzinfo=timezone.utc).isoformat(" ", "seconds")
description = 'To one trained by "Bob," Truth can be found in a potato'
byte_count = 123456
data_b64 = AttachDecoratorData(
base64_=base64.b64encode('sample image with padding'.encode()).decode()
)
Expand Down Expand Up @@ -89,15 +90,15 @@ def test_serialize_load_embedded_b64(self):

def test_init_appended_b64(self):
decorator = AttachDecorator(
append_id=self.append_id,
ident=self.ident,
mime_type=self.mime_type,
filename=self.filename,
lastmod_time=self.lastmod_time,
description=self.description,
data=self.data_b64
)

assert decorator.append_id == self.append_id
assert decorator.ident == self.ident
assert decorator.mime_type == self.mime_type
assert decorator.filename == self.filename
assert decorator.lastmod_time == self.lastmod_time
Expand All @@ -106,7 +107,7 @@ def test_init_appended_b64(self):

def test_serialize_load_appended_b64(self):
decorator = AttachDecorator(
append_id=self.append_id,
ident=self.ident,
mime_type=self.mime_type,
filename=self.filename,
lastmod_time=self.lastmod_time,
Expand All @@ -117,7 +118,7 @@ def test_serialize_load_appended_b64(self):
dumped = decorator.serialize()
loaded = AttachDecorator.deserialize(dumped)

assert loaded.append_id == self.append_id
assert loaded.ident == self.ident
assert loaded.mime_type == self.mime_type
assert loaded.filename == self.filename
assert loaded.lastmod_time == self.lastmod_time
Expand All @@ -126,15 +127,15 @@ def test_serialize_load_appended_b64(self):

def test_init_appended_links(self):
decorator = AttachDecorator(
append_id=self.append_id,
ident=self.ident,
mime_type=self.mime_type,
filename=self.filename,
byte_count=self.byte_count,
lastmod_time=self.lastmod_time,
description=self.description,
data=self.data_links
)
assert decorator.append_id == self.append_id
assert decorator.ident == self.ident
assert decorator.mime_type == self.mime_type
assert decorator.filename == self.filename
assert decorator.byte_count == self.byte_count
Expand All @@ -144,7 +145,7 @@ def test_init_appended_links(self):

def test_serialize_load_appended_links(self):
decorator = AttachDecorator(
append_id=self.append_id,
ident=self.ident,
mime_type=self.mime_type,
filename=self.filename,
byte_count=self.byte_count,
Expand All @@ -156,7 +157,7 @@ def test_serialize_load_appended_links(self):
dumped = decorator.serialize()
loaded = AttachDecorator.deserialize(dumped)

assert loaded.append_id == self.append_id
assert loaded.ident == self.ident
assert loaded.mime_type == self.mime_type
assert loaded.filename == self.filename
assert loaded.byte_count == self.byte_count
Expand All @@ -165,7 +166,22 @@ def test_serialize_load_appended_links(self):
assert loaded.data == self.data_links

def test_indy_dict(self):
deco_indy = AttachDecorator.from_indy_dict(self.indy_cred)
deco_indy = AttachDecorator.from_indy_dict(
indy_dict=self.indy_cred,
ident=self.ident,
description=self.description,
filename=self.filename,
lastmod_time=self.lastmod_time,
byte_count=self.byte_count
)
assert deco_indy.mime_type == 'application/json'
assert hasattr(deco_indy.data, 'base64_')
assert deco_indy.indy_dict == self.indy_cred
assert deco_indy.ident == self.ident
assert deco_indy.description == self.description
assert deco_indy.filename == self.filename
assert deco_indy.lastmod_time == self.lastmod_time
assert deco_indy.byte_count == self.byte_count

deco_indy_auto_id = AttachDecorator.from_indy_dict(indy_dict=self.indy_cred)
assert deco_indy_auto_id.ident
21 changes: 18 additions & 3 deletions aries_cloudagent/messaging/issue_credential/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
from .messages.credential_request import CredentialRequest
from .messages.credential_stored import CredentialStored
from .messages.inner.credential_preview import CredentialPreview
from .message_types import (
ATTACH_DECO_IDS,
CREDENTIAL_ISSUE,
CREDENTIAL_OFFER,
CREDENTIAL_REQUEST,
)
from .models.credential_exchange import V10CredentialExchange


Expand Down Expand Up @@ -331,7 +337,12 @@ async def create_offer(
credential_offer_message = CredentialOffer(
comment=comment,
credential_preview=cred_preview,
offers_attach=[AttachDecorator.from_indy_dict(credential_offer)],
offers_attach=[
AttachDecorator.from_indy_dict(
indy_dict=credential_offer,
ident=ATTACH_DECO_IDS[CREDENTIAL_OFFER],
)
],
)

credential_offer_message._thread = {
Expand Down Expand Up @@ -410,7 +421,8 @@ async def create_request(
credential_request_message = CredentialRequest(
requests_attach=[
AttachDecorator.from_indy_dict(
credential_exchange_record.credential_request
indy_dict=credential_exchange_record.credential_request,
ident=ATTACH_DECO_IDS[CREDENTIAL_REQUEST],
)
]
)
Expand Down Expand Up @@ -505,7 +517,10 @@ async def issue_credential(
credential_message = CredentialIssue(
comment=comment,
credentials_attach=[
AttachDecorator.from_indy_dict(credential_exchange_record.credential)
AttachDecorator.from_indy_dict(
indy_dict=credential_exchange_record.credential,
ident=ATTACH_DECO_IDS[CREDENTIAL_ISSUE]
)
],
)
credential_message._thread = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,10 @@

# Inner object types
CREDENTIAL_PREVIEW = f"{MESSAGE_FAMILY}credential-preview"

# Identifiers to use in attachment decorators
ATTACH_DECO_IDS = {
CREDENTIAL_OFFER: "libindy-cred-offer-0",
CREDENTIAL_REQUEST: "libindy-cred-request-0",
CREDENTIAL_ISSUE: "libindy-cred-0"
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from .....decorators.attach_decorator import AttachDecorator
from ...message_types import CREDENTIAL_ISSUE
from ...message_types import ATTACH_DECO_IDS, CREDENTIAL_ISSUE
from ..credential_issue import CredentialIssue

from unittest import mock, TestCase


class TestCredentialIssue(TestCase):
"""Credential issue tests"""

Expand Down Expand Up @@ -77,23 +76,39 @@ class TestCredentialIssue(TestCase):

cred_issue = CredentialIssue(
comment="Test",
credentials_attach=[AttachDecorator.from_indy_dict(indy_cred)]
credentials_attach=[
AttachDecorator.from_indy_dict(
indy_dict=indy_cred,
ident=ATTACH_DECO_IDS[CREDENTIAL_ISSUE],
)
]
)

def test_init(self):
"""Test initializer"""
credential_issue = CredentialIssue(
comment="Test",
credentials_attach=[AttachDecorator.from_indy_dict(self.indy_cred)]
credentials_attach=[
AttachDecorator.from_indy_dict(
indy_dict=self.indy_cred,
ident=ATTACH_DECO_IDS[CREDENTIAL_ISSUE],
)
]
)
assert credential_issue.credentials_attach[0].indy_dict == self.indy_cred
assert credential_issue.credentials_attach[0].ident # auto-generates UUID4
assert credential_issue.indy_credential(0) == self.indy_cred

def test_type(self):
"""Test type"""
credential_issue = CredentialIssue(
comment="Test",
credentials_attach=[AttachDecorator.from_indy_dict(self.indy_cred)]
credentials_attach=[
AttachDecorator.from_indy_dict(
indy_dict=self.indy_cred,
ident=ATTACH_DECO_IDS[CREDENTIAL_ISSUE],
)
]
)

assert credential_issue._type == CREDENTIAL_ISSUE
Expand Down Expand Up @@ -134,7 +149,6 @@ class TestCredentialIssueSchema(TestCase):

credential_issue = CredentialIssue(
comment="Test",
# credentials_attach=[AttachDecorator.from_indy_dict(TestCredentialIssue.indy_cred)]
credentials_attach=[AttachDecorator.from_indy_dict({'hello': 'world'})]
)

Expand Down
Loading