69
69
from .messages .read_all_data_agreement_template_response import ReadAllDataAgreementTemplateResponseMessage
70
70
from .messages .data_controller_details import DataControllerDetailsMessage
71
71
from .messages .data_controller_details_response import DataControllerDetailsResponseMessage
72
+ from .messages .existing_connections import ExistingConnectionsMessage
72
73
73
74
from .models .data_agreement_model import DATA_AGREEMENT_V1_SCHEMA_CONTEXT , DataAgreementEventSchema , DataAgreementV1 , DataAgreementPersonalData , DataAgreementV1Schema
74
75
from .models .read_data_agreement_model import ReadDataAgreementBody
88
89
from .models .json_ld_processed_response_model import JSONLDProcessedResponseBody
89
90
from .models .json_ld_processed_model import JSONLDProcessedBody
90
91
from .models .data_controller_model import DataController , DataControllerSchema
92
+ from .models .existing_connections_model import ExistingConnectionsBody
91
93
92
94
from .utils .diddoc import DIDDoc
93
95
from .utils .did .mydata_did import DIDMyData
@@ -146,6 +148,9 @@ class ADAManager:
146
148
# Record for data controller details
147
149
RECORD_TYPE_DATA_CONTROLLER_DETAILS = "data_controller_details"
148
150
151
+ # Record for existing connection details.
152
+ RECORD_TYPE_EXISTING_CONNECTION = "existing_connection"
153
+
149
154
DATA_AGREEMENT_RECORD_TYPE = "dataagreement_record"
150
155
151
156
def __init__ (self , context : InjectionContext ) -> None :
@@ -1549,7 +1554,7 @@ async def create_and_store_data_agreement_in_wallet(self, data_agreement: dict,
1549
1554
await data_agreement_v1_record .save (self .context )
1550
1555
1551
1556
return data_agreement_v1_record
1552
-
1557
+
1553
1558
async def publish_data_agreement_in_wallet (self , data_agreement_id : str ) -> DataAgreementV1Record :
1554
1559
"""
1555
1560
Publish a data agreement in the wallet.
@@ -1579,13 +1584,15 @@ async def publish_data_agreement_in_wallet(self, data_agreement_id: str) -> Data
1579
1584
{"data_agreement_id" : data_agreement_id }
1580
1585
).fetch_single ()
1581
1586
1582
- personal_data_new_list_for_proof_request = json .loads (storage_record .value )
1587
+ personal_data_new_list_for_proof_request = json .loads (
1588
+ storage_record .value )
1583
1589
1584
1590
# Delete the temporary record
1585
1591
await storage .delete_record (storage_record )
1586
1592
1587
1593
# Generate data agreement model class instance
1588
- data_agreement : DataAgreementV1 = DataAgreementV1Schema ().load (data_agreement_record .data_agreement )
1594
+ data_agreement : DataAgreementV1 = DataAgreementV1Schema ().load (
1595
+ data_agreement_record .data_agreement )
1589
1596
1590
1597
if data_agreement .method_of_use == DataAgreementV1Record .METHOD_OF_USE_DATA_SOURCE :
1591
1598
# If method-of-use is "data-source", then create a schema and credential defintion
@@ -4100,9 +4107,8 @@ async def send_read_all_data_agreement_template_message(self, conn_id: str) -> N
4100
4107
# Send JSONLD Processed Message
4101
4108
if responder :
4102
4109
await responder .send_reply (read_all_data_agreement_template_message , connection_id = connection_record .connection_id )
4103
-
4104
4110
4105
- async def fetch_org_details_from_igrantio (self )-> str :
4111
+ async def fetch_org_details_from_igrantio (self ) -> str :
4106
4112
"""
4107
4113
Fetch org details from iGrant.io.
4108
4114
"""
@@ -4139,7 +4145,7 @@ async def fetch_org_details_from_igrantio(self)-> str:
4139
4145
4140
4146
for exclude_key in exclude_keys :
4141
4147
organization_details .pop (exclude_key , None )
4142
-
4148
+
4143
4149
data_controller = DataController (
4144
4150
organisation_id = organization_details ["ID" ],
4145
4151
organisation_name = organization_details ["Name" ],
@@ -4151,7 +4157,7 @@ async def fetch_org_details_from_igrantio(self)-> str:
4151
4157
policy_url = organization_details ["PolicyURL" ],
4152
4158
eula_url = organization_details ["EulaURL" ]
4153
4159
).to_json ()
4154
-
4160
+
4155
4161
return data_controller
4156
4162
4157
4163
async def create_or_update_data_controller_details_in_wallet (self ) -> StorageRecord :
@@ -4169,7 +4175,6 @@ async def create_or_update_data_controller_details_in_wallet(self) -> StorageRec
4169
4175
self .RECORD_TYPE_DATA_CONTROLLER_DETAILS
4170
4176
).fetch_single ()
4171
4177
4172
-
4173
4178
data_controller = await self .fetch_org_details_from_igrantio ()
4174
4179
4175
4180
await storage .update_record_value (storage_record , data_controller )
@@ -4197,14 +4202,13 @@ async def create_or_update_data_controller_details_in_wallet(self) -> StorageRec
4197
4202
result ,
4198
4203
)
4199
4204
4200
-
4201
4205
await storage .add_record (storage_record )
4202
4206
4203
4207
return result
4204
-
4208
+
4205
4209
except ADAManagerError as err :
4206
4210
pass
4207
-
4211
+
4208
4212
return result
4209
4213
4210
4214
async def process_data_controller_details_message (self , data_controller_details_message : DataControllerDetailsMessage , receipt : MessageReceipt ) -> None :
@@ -4225,7 +4229,8 @@ async def process_data_controller_details_message(self, data_controller_details_
4225
4229
data_controller_details : str = await self .create_or_update_data_controller_details_in_wallet ()
4226
4230
4227
4231
# Construct Data Controller model class
4228
- data_controller : DataController = DataControllerSchema ().load (json .loads (data_controller_details ))
4232
+ data_controller : DataController = DataControllerSchema ().load (
4233
+ json .loads (data_controller_details ))
4229
4234
4230
4235
# Construct DataControllerDetailsResponseMessage
4231
4236
data_controller_details_response_message = DataControllerDetailsResponseMessage (
@@ -4239,7 +4244,7 @@ async def process_data_controller_details_message(self, data_controller_details_
4239
4244
4240
4245
if responder :
4241
4246
await responder .send_reply (data_controller_details_response_message , connection_id = self .context .connection_record .connection_id )
4242
-
4247
+
4243
4248
async def send_data_controller_details_message (self , conn_id : str ) -> None :
4244
4249
"""Send data controller details message."""
4245
4250
@@ -4278,3 +4283,124 @@ async def send_data_controller_details_message(self, conn_id: str) -> None:
4278
4283
# Send message
4279
4284
if responder :
4280
4285
await responder .send_reply (data_controller_details_message , connection_id = connection_record .connection_id )
4286
+
4287
+ async def process_existing_connections_message (self , existing_connections_message : ExistingConnectionsMessage , receipt : MessageReceipt ) -> None :
4288
+ """Processing connections/1.0/exists message."""
4289
+
4290
+ # Storage instance
4291
+ storage = await self .context .inject (BaseStorage )
4292
+
4293
+ invitation_key = receipt .recipient_verkey
4294
+
4295
+ # fetch current connection record using invitation key
4296
+ connection = await ConnectionRecord .retrieve_by_invitation_key (
4297
+ self .context , invitation_key )
4298
+
4299
+ # Fetch existing connections record for the current connection.
4300
+
4301
+ existing_connection = await storage .search_records (
4302
+ type_filter = self .RECORD_TYPE_EXISTING_CONNECTION ,
4303
+ tag_query = {
4304
+ "connection_id" : connection .connection_id
4305
+ }
4306
+ ).fetch_all ()
4307
+
4308
+ if existing_connection :
4309
+ # delete existing connections record
4310
+ existing_connection = existing_connection [0 ]
4311
+ await storage .delete_record (existing_connection )
4312
+
4313
+ existing_connection = None
4314
+
4315
+ # fetch the existing connection by did
4316
+ existing_connection = await ConnectionRecord .retrieve_by_did (
4317
+ self .context , their_did = None , my_did = existing_connections_message .body .theirdid )
4318
+
4319
+ # create existing_connections record with connection_id, did, connection_status available
4320
+ record_tags = {
4321
+ "existing_connection_id" : existing_connection .connection_id ,
4322
+ "my_did" : existing_connection .my_did ,
4323
+ "connection_status" : "available" ,
4324
+ "connection_id" : connection .connection_id
4325
+ }
4326
+
4327
+ record = StorageRecord (
4328
+ self .RECORD_TYPE_EXISTING_CONNECTION ,
4329
+ connection .connection_id ,
4330
+ record_tags
4331
+ )
4332
+ await storage .add_record (record )
4333
+
4334
+ # updating the current connection invitation status to inactive
4335
+ connection .state = ConnectionRecord .STATE_INACTIVE
4336
+ await connection .save (context = self .context )
4337
+
4338
+ async def send_existing_connections_message (self , theirdid : str , connection_id : str ) -> None :
4339
+ """Send existing connections message."""
4340
+
4341
+ # Responder instance
4342
+ responder : DispatcherResponder = await self .context .inject (BaseResponder , required = False )
4343
+
4344
+ try :
4345
+ connection_mgr = ConnectionManager (self .context )
4346
+
4347
+ # Retrieve connection record by id
4348
+ connection_record : ConnectionRecord = await ConnectionRecord .retrieve_by_id (
4349
+ self .context ,
4350
+ connection_id
4351
+ )
4352
+
4353
+ connection_invitation : ConnectionInvitation = await connection_record .retrieve_invitation (self .context )
4354
+
4355
+ request = await connection_mgr .create_request (connection_record )
4356
+
4357
+ except StorageError as err :
4358
+
4359
+ raise ADAManagerError (
4360
+ f"Failed to retrieve connection record: { err } "
4361
+ )
4362
+
4363
+ # From and to mydata dids
4364
+ from_did : DIDMyData = DIDMyData .from_public_key_b58 (
4365
+ request .connection .did , key_type = KeyType .ED25519
4366
+ )
4367
+ to_did : DIDMyData = DIDMyData .from_public_key_b58 (
4368
+ request .connection .did , key_type = KeyType .ED25519
4369
+ )
4370
+
4371
+ # Construct ExistingConnectionsMessage Message
4372
+ existing_connections_message = ExistingConnectionsMessage (
4373
+ from_did = from_did .did ,
4374
+ to_did = to_did .did ,
4375
+ created_time = round (time .time () * 1000 ),
4376
+ body = ExistingConnectionsBody (
4377
+ theirdid = theirdid
4378
+ )
4379
+ )
4380
+
4381
+ # Send message
4382
+ if responder :
4383
+ await responder .send_reply (existing_connections_message , connection_id = connection_record .connection_id )
4384
+
4385
+ async def fetch_existing_connections_record_for_current_connection (self , connection_id : str ) -> dict :
4386
+ """
4387
+ Fetch existing connections record for the current connection.
4388
+ """
4389
+
4390
+ # Storage instance
4391
+ storage = await self .context .inject (BaseStorage )
4392
+
4393
+ # Fetch existing connections record for the current connection.
4394
+
4395
+ existing_connection = await storage .search_records (
4396
+ type_filter = self .RECORD_TYPE_EXISTING_CONNECTION ,
4397
+ tag_query = {
4398
+ "connection_id" : connection_id
4399
+ }
4400
+ ).fetch_all ()
4401
+
4402
+ if existing_connection :
4403
+ existing_connection = existing_connection [0 ]
4404
+ return existing_connection .tags
4405
+ else :
4406
+ return {}
0 commit comments