Skip to content

Commit 48402b2

Browse files
Feature #12: Protocol to list all the data agreement templates available in remote agent.
Protocol contains 2 messages. 1. data-agreements/1.0/read-all-template 2. data-agreements/1.0/read-all-template-response This protocol is intended to deprecate following messages. 1. igrantio-operator/1.0/list-data-certificate-types 2. igrantio-operator/1.0/list-data-certificate-types-response. Signed-off-by: George J Padayatti <[email protected]>
1 parent 06c59be commit 48402b2

7 files changed

+357
-5
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from aries_cloudagent.messaging.base_handler import BaseHandler, BaseResponder, RequestContext
2+
3+
from ..messages.read_all_data_agreement_template import ReadAllDataAgreementTemplateMessage
4+
from ..manager import ADAManager
5+
6+
import json
7+
8+
9+
class ReadAllDataAgreementTemplateHandler(BaseHandler):
10+
"""Handle for data-agreements/1.0/read-all-template message"""
11+
12+
async def handle(self, context: RequestContext, responder: BaseResponder):
13+
"""
14+
Message handler logic for data-agreements/1.0/read-all-template message.
15+
"""
16+
17+
# Assert if received message is of type ReadAllDataAgreementTemplateMessage
18+
assert isinstance(context.message, ReadAllDataAgreementTemplateMessage)
19+
20+
self._logger.info(
21+
"Received data-agreements/1.0/read-all-template message: \n%s",
22+
json.dumps(context.message.serialize(), indent=4)
23+
)
24+
25+
# Initialize ADA manager
26+
ada_manager = ADAManager(context)
27+
28+
# Call the function
29+
30+
await ada_manager.process_read_all_data_agreement_template_message(
31+
read_all_data_agreement_template_message=context.message,
32+
receipt=context.message_receipt,
33+
)
34+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from aries_cloudagent.messaging.base_handler import BaseHandler, BaseResponder, RequestContext
2+
3+
from ..messages.read_all_data_agreement_template_response import ReadAllDataAgreementTemplateResponseMessage
4+
5+
import json
6+
7+
8+
class ReadAllDataAgreementTemplateResponseHandler(BaseHandler):
9+
"""Handle for data-agreements/1.0/read-all-template-response message"""
10+
11+
async def handle(self, context: RequestContext, responder: BaseResponder):
12+
"""
13+
Message handler logic for data-agreements/1.0/read-all-template-response message.
14+
"""
15+
16+
# Assert if received message is of type ReadAllDataAgreementTemplateResponseMessage
17+
assert isinstance(context.message, ReadAllDataAgreementTemplateResponseMessage)
18+
19+
self._logger.info(
20+
"Received data-agreements/1.0/read-all-template-response message: \n%s",
21+
json.dumps(context.message.serialize(), indent=4)
22+
)
23+

mydata_did/v1_0/manager.py

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import logging
44
import json
55
import os
6-
from re import A
76
import time
87
import uuid
98
import typing
@@ -66,6 +65,8 @@
6665
from .messages.json_ld_processed import JSONLDProcessedMessage
6766
from .messages.json_ld_processed_response import JSONLDProcessedResponseMessage
6867
from .messages.json_ld_problem_report import JSONLDProblemReport, JSONLDProblemReportReason
68+
from .messages.read_all_data_agreement_template import ReadAllDataAgreementTemplateMessage
69+
from .messages.read_all_data_agreement_template_response import ReadAllDataAgreementTemplateResponseMessage
6970

7071
from .models.data_agreement_model import DATA_AGREEMENT_V1_SCHEMA_CONTEXT, DataAgreementEventSchema, DataAgreementV1, DataAgreementPersonalData, DataAgreementV1Schema
7172
from .models.read_data_agreement_model import ReadDataAgreementBody
@@ -3805,7 +3806,6 @@ async def create_invitation(
38053806
await connection.attach_invitation(self.context, invitation)
38063807

38073808
return connection, invitation
3808-
38093809

38103810
async def generate_firebase_dynamic_link_for_connection_invitation(self, conn_id: str) -> str:
38113811
"""Generate a Firebase Dynamic Link for a connection invitation."""
@@ -3821,7 +3821,7 @@ async def generate_firebase_dynamic_link_for_connection_invitation(self, conn_id
38213821
self.context,
38223822
conn_id
38233823
)
3824-
3824+
38253825
except StorageError as err:
38263826
raise ADAManagerError(
38273827
f"Failed to fetch connection record: {err}"
@@ -3868,4 +3868,92 @@ async def generate_firebase_dynamic_link_for_connection_invitation(self, conn_id
38683868
f"Failed to generate firebase dynamic link for connection-invitation: {resp.status} {await resp.text()}"
38693869
)
38703870

3871-
return jresp["shortLink"]
3871+
return jresp["shortLink"]
3872+
3873+
async def process_read_all_data_agreement_template_message(self, read_all_data_agreement_template_message: ReadAllDataAgreementTemplateMessage, receipt: MessageReceipt) -> None:
3874+
"""
3875+
Process read all data agreement template message.
3876+
3877+
Respond with all the data agreement templates available for an organisation.
3878+
"""
3879+
3880+
# Responder instance
3881+
responder: DispatcherResponder = await self.context.inject(BaseResponder, required=False)
3882+
3883+
# From and To MyData DIDs
3884+
to_did: DIDMyData = DIDMyData.from_public_key_b58(
3885+
receipt.sender_verkey, key_type=KeyType.ED25519)
3886+
from_did: DIDMyData = DIDMyData.from_public_key_b58(
3887+
receipt.recipient_verkey, key_type=KeyType.ED25519)
3888+
3889+
results = []
3890+
3891+
# Query all the data agreement templates.
3892+
3893+
tag_filter = {
3894+
"published_flag": "True",
3895+
"delete_flag": "False",
3896+
}
3897+
data_agreement_v1_records: typing.List[DataAgreementV1Record] = await DataAgreementV1Record.query(
3898+
self.context,
3899+
tag_filter=tag_filter
3900+
)
3901+
3902+
if data_agreement_v1_records:
3903+
for data_agreement_v1_record in data_agreement_v1_records:
3904+
data_agreement: DataAgreementV1 = DataAgreementV1Schema().load(
3905+
data_agreement_v1_record.data_agreement)
3906+
results.append(data_agreement)
3907+
3908+
# Construct ReadAllDataAgreementTemplateResponse message
3909+
3910+
read_all_data_agreement_template_response: ReadAllDataAgreementTemplateResponseMessage = ReadAllDataAgreementTemplateResponseMessage(
3911+
from_did=from_did.did,
3912+
to_did=to_did.did,
3913+
created_time=round(time.time() * 1000),
3914+
body=results
3915+
)
3916+
3917+
# Send ReadAllDataAgreementTemplateResponse message to the requester.
3918+
3919+
if responder:
3920+
await responder.send_reply(read_all_data_agreement_template_response, connection_id=self.context.connection_record.connection_id)
3921+
3922+
async def send_read_all_data_agreement_template_message(self, conn_id: str) -> None:
3923+
"""Send read all data agreement template message to the remote agent."""
3924+
3925+
# Responder instance
3926+
responder: DispatcherResponder = await self.context.inject(BaseResponder, required=False)
3927+
3928+
try:
3929+
3930+
# Retrieve connection record by id
3931+
connection_record: ConnectionRecord = await ConnectionRecord.retrieve_by_id(
3932+
self.context,
3933+
conn_id
3934+
)
3935+
3936+
except StorageError as err:
3937+
3938+
raise ADAManagerError(
3939+
f"Failed to retrieve connection record: {err}"
3940+
)
3941+
3942+
# From and to mydata dids
3943+
from_did: DIDMyData = DIDMyData.from_public_key_b58(
3944+
connection_record.my_did, key_type=KeyType.ED25519
3945+
)
3946+
to_did: DIDMyData = DIDMyData.from_public_key_b58(
3947+
connection_record.their_did, key_type=KeyType.ED25519
3948+
)
3949+
3950+
# Construct ReadAllDataAgreementTemplate Message
3951+
read_all_data_agreement_template_message = ReadAllDataAgreementTemplateMessage(
3952+
from_did=from_did.did,
3953+
to_did=to_did.did,
3954+
created_time=round(time.time() * 1000)
3955+
)
3956+
3957+
# Send JSONLD Processed Message
3958+
if responder:
3959+
await responder.send_reply(read_all_data_agreement_template_message, connection_id=connection_record.connection_id)

mydata_did/v1_0/message_types.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
READ_DATA_AGREEMENT_RESPONSE = f"data-agreements/1.0/read-data-agreement-response"
2929
DATA_AGREEMENT_PROBLEM_REPORT = f"data-agreements/1.0/problem-report"
3030

31+
# Message type for reading all data agreement templates available in an organisation.
32+
READ_ALL_DATA_AGREEMENT_TEMPLATE = f"data-agreements/1.0/read-all-template"
33+
READ_ALL_DATA_AGREEMENT_TEMPLATE_RESPONSE = f"data-agreements/1.0/read-all-template-response"
34+
3135
# Message types for ADA RFC 0003 - Data Agreement Negotiation Protocol 1.0
3236
DATA_AGREEMENT_NEGOTIATION_OFFER = f"data-agreement-negotiation/1.0/offer"
3337
DATA_AGREEMENT_NEGOTIATION_REJECT = f"data-agreement-negotiation/1.0/reject"
@@ -126,5 +130,11 @@
126130
JSON_LD_PROBLEM_REPORT: (
127131
f"{PROTOCOL_PACKAGE}.messages.json_ld_problem_report.JSONLDProblemReport"
128132
),
133+
READ_ALL_DATA_AGREEMENT_TEMPLATE: (
134+
f"{PROTOCOL_PACKAGE}.messages.read_all_data_agreement_template.ReadAllDataAgreementTemplateMessage"
135+
),
136+
READ_ALL_DATA_AGREEMENT_TEMPLATE_RESPONSE: (
137+
f"{PROTOCOL_PACKAGE}.messages.read_all_data_agreement_template_response.ReadAllDataAgreementTemplateResponseMessage"
138+
),
129139
},
130140
)
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from aries_cloudagent.messaging.agent_message import AgentMessage, AgentMessageSchema
2+
from marshmallow import EXCLUDE, fields
3+
4+
from ..message_types import READ_ALL_DATA_AGREEMENT_TEMPLATE, PROTOCOL_PACKAGE
5+
from ..utils.regex import MYDATA_DID
6+
7+
# Handler class for read all data agreement template message
8+
HANDLER_CLASS = (
9+
f"{PROTOCOL_PACKAGE}.handlers"
10+
".read_all_data_agreement_template_handler.ReadAllDataAgreementTemplateHandler"
11+
)
12+
13+
class ReadAllDataAgreementTemplateMessage(AgentMessage):
14+
"""
15+
Message class for read all data agreement template message.
16+
"""
17+
18+
class Meta:
19+
# Handler class that can handle this message
20+
handler_class = HANDLER_CLASS
21+
22+
# Message type
23+
message_type = READ_ALL_DATA_AGREEMENT_TEMPLATE
24+
25+
# Message schema class
26+
schema_class = "ReadAllDataAgreementTemplateMessageSchema"
27+
28+
def __init__(
29+
self,
30+
*,
31+
from_did,
32+
to_did,
33+
created_time,
34+
**kwargs
35+
):
36+
"""
37+
Initialize a ReadAllDataAgreementTemplateMessage message instance.
38+
"""
39+
super().__init__(**kwargs)
40+
41+
# Sender DID
42+
self.from_did = from_did
43+
44+
# Recipient DID
45+
self.to_did = to_did
46+
47+
# The time the message was created
48+
self.created_time = created_time
49+
50+
51+
class ReadAllDataAgreementTemplateMessageSchema(AgentMessageSchema):
52+
"""
53+
Schema class for read all data agreement template message
54+
"""
55+
56+
class Meta:
57+
# The message class that this schema is for
58+
model_class = ReadAllDataAgreementTemplateMessage
59+
60+
# Unknown fields to exclude from the schema (handled by marshmallow)
61+
unknown = EXCLUDE
62+
63+
# From DID
64+
from_did = fields.Str(data_key="from", **MYDATA_DID)
65+
66+
# To DID
67+
to_did = fields.Str(data_key="to", **MYDATA_DID)
68+
69+
# Created time
70+
created_time = fields.Str(data_key="created_time")
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import typing
2+
from aries_cloudagent.messaging.agent_message import AgentMessage, AgentMessageSchema
3+
from marshmallow import EXCLUDE, fields
4+
5+
from ..message_types import READ_ALL_DATA_AGREEMENT_TEMPLATE_RESPONSE, PROTOCOL_PACKAGE
6+
from ..models.data_agreement_model import DataAgreementV1Schema, DataAgreementV1
7+
from ..utils.regex import MYDATA_DID
8+
9+
# Handler class for read all data agreement template response message
10+
HANDLER_CLASS = (
11+
f"{PROTOCOL_PACKAGE}.handlers"
12+
".read_all_data_agreement_template_response_handler.ReadAllDataAgreementTemplateResponseHandler"
13+
)
14+
15+
16+
class ReadAllDataAgreementTemplateResponseMessage(AgentMessage):
17+
"""
18+
Message class for read all data agreement template response message.
19+
"""
20+
21+
class Meta:
22+
# Handler class that can handle this message
23+
handler_class = HANDLER_CLASS
24+
25+
# Message type
26+
message_type = READ_ALL_DATA_AGREEMENT_TEMPLATE_RESPONSE
27+
28+
# Message schema class
29+
schema_class = "ReadAllDataAgreementTemplateResponseMessageSchema"
30+
31+
def __init__(
32+
self,
33+
*,
34+
from_did,
35+
to_did,
36+
created_time,
37+
body: typing.List[DataAgreementV1],
38+
**kwargs
39+
):
40+
"""
41+
Initialize a ReadAllDataAgreementTemplateResponseMessage message instance.
42+
"""
43+
super().__init__(**kwargs)
44+
45+
# Sender DID
46+
self.from_did = from_did
47+
48+
# Recipient DID
49+
self.to_did = to_did
50+
51+
# The time the message was created
52+
self.created_time = created_time
53+
54+
# The list of data agreements
55+
self.body = body
56+
57+
58+
class ReadAllDataAgreementTemplateResponseMessageSchema(AgentMessageSchema):
59+
"""
60+
Schema class for read all data agreement template response message
61+
"""
62+
63+
class Meta:
64+
# The message class that this schema is for
65+
model_class = ReadAllDataAgreementTemplateResponseMessage
66+
67+
# Unknown fields to exclude from the schema (handled by marshmallow)
68+
unknown = EXCLUDE
69+
70+
# From DID
71+
from_did = fields.Str(data_key="from", **MYDATA_DID)
72+
73+
# To DID
74+
to_did = fields.Str(data_key="to", **MYDATA_DID)
75+
76+
# Created time
77+
created_time = fields.Str(data_key="created_time")
78+
79+
# body
80+
body = fields.List(
81+
fields.Nested(DataAgreementV1Schema),
82+
required=True,
83+
description="Data Agreement template"
84+
)

0 commit comments

Comments
 (0)