Skip to content

Commit

Permalink
Init acknowledgment phase in present-proof, Update responses in issue…
Browse files Browse the repository at this point in the history
… and present protocols, Add endpoint for swagger retrieval
  • Loading branch information
Karol Krzosa committed Dec 28, 2020
1 parent 0f2a519 commit 6a7b67f
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 29 deletions.
1 change: 0 additions & 1 deletion aries_cloudagent/holder/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ async def register(app: web.Application):
def post_process_routes(app: web.Application):
"""Amend swagger API."""

print("SWAGGER: ", app._state["swagger_dict"])
# Add top-level tags description
if "tags" not in app._state["swagger_dict"]:
app._state["swagger_dict"]["tags"] = []
Expand Down
6 changes: 6 additions & 0 deletions aries_cloudagent/pdstorage_thcf/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ async def get_table_of_records(request: web.BaseRequest):
return web.json_response(json.loads(result))


@docs(tags=["Swagger"], summary="Get agent's swagger schema in json format")
async def get_swagger_schema(request: web.BaseRequest):
return web.json_response(request.app._state["swagger_dict"])


async def register(app: web.Application):
"""Register routes."""
app.add_routes(
Expand Down Expand Up @@ -318,5 +323,6 @@ async def register(app: web.Application):
get_table_of_records,
allow_head=False,
),
web.get("/swagger", get_swagger_schema, allow_head=False),
]
)
47 changes: 36 additions & 11 deletions aries_cloudagent/protocols/issue_credential/v1_1/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ async def issue_credential(request: web.BaseRequest):

credential_exchange_id = request.query.get("credential_exchange_id")
exchange = await retrieve_credential_exchange(context, credential_exchange_id)

raise_exception_invalid_state(
exchange,
CredentialExchangeRecord.STATE_REQUEST_RECEIVED,
CredentialExchangeRecord.ROLE_ISSUER,
web.HTTPBadRequest,
)

connection = await retrieve_connection(context, exchange.connection_id)
request = exchange.credential_request
credential = await create_credential(
Expand All @@ -67,38 +69,55 @@ async def issue_credential(request: web.BaseRequest):
their_public_did=exchange.their_public_did,
exception=web.HTTPError,
)
LOG("CREDENTIAL %s", credential)

LOG("CREDENTIAL %s", credential)
issue = CredentialIssue(credential=credential)
issue.assign_thread_id(exchange.thread_id)
await outbound_handler(issue, connection_id=connection.connection_id)

exchange.state = CredentialExchangeRecord.STATE_ISSUED
await exchange.save(context)

return web.json_response(credential)
return web.json_response(
{
"success": True,
"credential_exchange_id": exchange._id,
}
)


async def routes_get_public_did(context):
wallet: BaseWallet = await context.inject(BaseWallet)
public_did = await wallet.get_public_did()

if public_did is None:
raise web.HTTPBadRequest(
reason="Your public did is None!, acquire a public did before requesting a credential"
)

public_did = public_did[0]

if public_did is None:
raise web.HTTPBadRequest(
reason="Your public did is None!, acquire a public did before requesting a credential"
)

return public_did


@docs(tags=["issue-credential"], summary="Request Credential")
@request_schema(RequestCredentialSchema())
async def request_credential(request: web.BaseRequest):
context = request.app["request_context"]
outbound_handler = request.app["outbound_message_router"]
wallet: BaseWallet = await context.inject(BaseWallet)

body = await request.json()
credential_values = body.get("credential_values")
connection_id = body.get("connection_id")
connection_record = await retrieve_connection(context, connection_id)
public_did = await wallet.get_public_did()
public_did = public_did[0]
public_did = await routes_get_public_did(context)
print("Public DID: ", public_did)

if public_did is None:
raise web.HTTPBadRequest(
reason="Your public did is None!, acquire a public did before requesting a credential"
)

issue = CredentialRequest(
credential={"credential_values": credential_values}, did=public_did
)
Expand All @@ -117,7 +136,13 @@ async def request_credential(request: web.BaseRequest):
context, reason="Save record of agent credential exchange"
)

return web.json_response({"credential_exchange_id": exchange_id})
return web.json_response(
{
"success": True,
"thread_id": issue._thread_id,
"credential_exchange_id": exchange_id,
}
)


@docs(tags=["issue-credential"], summary="Retrieve Credential Exchange")
Expand Down
1 change: 1 addition & 0 deletions aries_cloudagent/protocols/issue_credential/v1_1/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ async def create_credential(
"""
credential_type = credential_request.get("credential_type")
credential_values = credential_request.get("credential_values")

if their_public_did is not None:
assert_type(their_public_did, str)
credential_values.update({"id": their_public_did})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from .....messaging.base_handler import (
BaseHandler,
BaseResponder,
HandlerException,
RequestContext,
)
from aries_cloudagent.aathcf.utils import debug_handler
from aries_cloudagent.protocols.present_proof.v1_1.models.presentation_exchange import (
THCFPresentationExchange,
)
from aries_cloudagent.protocols.present_proof.v1_1.messages.acknowledge_proof import (
AcknowledgeProof,
)
from aries_cloudagent.verifier.base import BaseVerifier
from ..models.utils import retrieve_exchange_by_thread
import json
from collections import OrderedDict
from aries_cloudagent.aathcf.credentials import raise_exception_invalid_state


# TODO Error handling
class AcknowledgeProofHandler(BaseHandler):
"""
Message handler logic for incoming credential presentations / incoming proofs.
"""

async def handle(self, context: RequestContext, responder: BaseResponder):
debug_handler(self._logger.info, context, AcknowledgeProof)

exchange_record: THCFPresentationExchange = await retrieve_exchange_by_thread(
context,
responder.connection_id,
context.message._thread_id,
HandlerException,
)

raise_exception_invalid_state(
exchange_record,
THCFPresentationExchange.STATE_PRESENTATION_SENT,
THCFPresentationExchange.ROLE_PROVER,
HandlerException,
)

exchange_record.acknowledgment_credential = context.message.credential
exchange_record.state = exchange_record.STATE_ACKNOWLEDGED
await exchange_record.save(context)

await responder.send_webhook(
"present_proof",
{
"type": "acknowledge_proof",
"exchange_record_id": exchange_record._id,
"connection_id": responder.connection_id,
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ async def handle(self, context: RequestContext, responder: BaseResponder):

exchange_record.presentation = presentation
exchange_record.verified = True
exchange_record.state = exchange_record.STATE_VERIFIED
exchange_record.prover_public_did = context.message.prover_public_did
exchange_record.state = exchange_record.STATE_PRESENTATION_RECEIVED
await exchange_record.save(context, reason="PresentationExchange updated!")

await responder.send_webhook(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@

REQUEST_PROOF = f"{PROTOCOL_URI}/request-proof"
PRESENT_PROOF = f"{PROTOCOL_URI}/present-proof"
ACKNOWLEDGE_PROOF = f"{PROTOCOL_URI}/acknowledge-proof"

MESSAGE_TYPES = {
REQUEST_PROOF: (f"{PROTOCOL_PACKAGE}.messages.request_proof.RequestProof"),
PRESENT_PROOF: (f"{PROTOCOL_PACKAGE}.messages.present_proof.PresentProof"),
ACKNOWLEDGE_PROOF: (
f"{PROTOCOL_PACKAGE}.messages.acknowledge_proof.AcknowledgeProof"
),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from marshmallow import fields
from .....messaging.agent_message import AgentMessage, AgentMessageSchema
from ..message_types import ACKNOWLEDGE_PROOF, PROTOCOL_PACKAGE

HANDLER_CLASS = f"{PROTOCOL_PACKAGE}.handlers.acknowledge_proof.AcknowledgeProofHandler"


class AcknowledgeProof(AgentMessage):
class Meta:
handler_class = HANDLER_CLASS
schema_class = "AcknowledgeProofSchema"
message_type = ACKNOWLEDGE_PROOF

def __init__(
self,
_id: str = None,
*,
credential=None,
**kwargs,
):
"""Initialize credential issue object."""
super().__init__(_id=_id, **kwargs)
self.credential = credential


class AcknowledgeProofSchema(AgentMessageSchema):
"""Credential schema."""

class Meta:
"""Credential schema metadata."""

model_class = AcknowledgeProof

credential = fields.Str(required=False)
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from typing import Sequence
from marshmallow import fields
from .....messaging.agent_message import AgentMessage, AgentMessageSchema
from ..message_types import PRESENT_PROOF, PROTOCOL_PACKAGE
Expand All @@ -17,11 +16,13 @@ def __init__(
_id: str = None,
*,
credential_presentation=None,
prover_public_did=None,
**kwargs,
):
"""Initialize credential issue object."""
super().__init__(_id=_id, **kwargs)
self.credential_presentation = credential_presentation
self.prover_public_did = prover_public_did


class PresentProofSchema(AgentMessageSchema):
Expand All @@ -33,3 +34,4 @@ class Meta:
model_class = PresentProof

credential_presentation = fields.Str(required=True)
prover_public_did = fields.Str(required=True)
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
from typing import Sequence
from marshmallow import fields
from .....messaging.agent_message import AgentMessage, AgentMessageSchema
from ..message_types import REQUEST_PROOF, PROTOCOL_PACKAGE
from aries_cloudagent.aathcf.credentials import (
PresentationRequestSchema,
PresentationRequestedAttributesSchema,
)
import uuid

HANDLER_CLASS = f"{PROTOCOL_PACKAGE}.handlers.request_proof.RequestProofHandler"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,23 @@ class Meta:
STATE_REQUEST_RECEIVED = "request_received"
STATE_PRESENTATION_SENT = "presentation_sent"
STATE_PRESENTATION_RECEIVED = "presentation_received"
STATE_VERIFIED = "verified"
STATE_PRESENTATION_ACKED = "presentation_acked"
STATE_ACKNOWLEDGED = "presentation_acknowledged"

def __init__(
self,
*,
presentation_exchange_id: str = None,
connection_id: str = None,
prover_public_did: str = None,
thread_id: str = None,
initiator: str = None,
role: str = None,
state: str = None,
presentation_proposal: dict = None,
presentation_request: dict = None,
presentation: dict = None,
acknowledgment_credential: str = None,
verified: str = None,
auto_present: bool = False,
error_msg: str = None,
Expand All @@ -64,6 +66,8 @@ def __init__(
self.state = state
self.presentation_proposal = presentation_proposal
self.presentation_request = presentation_request
self.prover_public_did = prover_public_did
self.acknowledgment_credential = acknowledgment_credential
self.presentation = presentation
self.verified = verified
self.auto_present = auto_present
Expand All @@ -86,6 +90,8 @@ def record_value(self) -> dict:
"initiator",
"presentation_proposal",
"presentation_request",
"acknowledgment_credential",
"prover_public_did",
"presentation",
"role",
"state",
Expand Down Expand Up @@ -171,7 +177,7 @@ class Meta:
state = fields.Str(
required=False,
description="Present-proof exchange state",
example=THCFPresentationExchange.STATE_VERIFIED,
example=THCFPresentationExchange.STATE_ACKNOWLEDGED,
)
presentation_proposal = fields.Dict(
required=False, description="Serialized presentation proposal message"
Expand All @@ -198,3 +204,5 @@ class Meta:
error_msg = fields.Str(
required=False, description="Error message", example="Invalid structure"
)
prover_public_did = fields.Str(required=False)
acknowledgment_credential = fields.Str(required=False)
5 changes: 3 additions & 2 deletions aries_cloudagent/protocols/present_proof/v1_1/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async def retrieve_exchange(context, record_id, exception):
exchange_record: THCFPresentationExchange = (
await THCFPresentationExchange.retrieve_by_id(context, record_id)
)
except StorageNotFoundError as err:
except StorageNotFoundError:
raise exception(
reason=f"Couldnt find exchange_record through this id {record_id}"
)
Expand All @@ -30,7 +30,8 @@ async def retrieve_exchange_by_thread(context, connection_id, thread_id, excepti
raise exception(
f"""Couldnt find exchange_record through this:
connection id: {connection_id}
thread id: {thread_id}"""
thread id: {thread_id}
Exception: {err.roll_up}"""
)
except StorageError as err:
raise exception(err.roll_up)
Expand Down
Loading

0 comments on commit 6a7b67f

Please sign in to comment.