/// <summary> /// Constructs their DID doc in a pairwise relationship from a connection record. /// </summary> /// <param name="connection">Connectio record.</param> /// <returns>DID Doc</returns> public static DidDoc TheirDidDoc(this ConnectionRecord connection) { return(new DidDoc { Keys = new List <DidDocKey> { new DidDocKey { Id = $"{connection.MyDid}#keys-1", Type = DefaultKeyType, Controller = connection.TheirDid, PublicKeyBase58 = connection.TheirVk } }, Services = new List <IDidDocServiceEndpoint> { new IndyAgentDidDocService { Id = $"{connection.MyDid};indy", ServiceEndpoint = connection.Endpoint.Verkey, RecipientKeys = connection.TheirVk != null ? new[] { connection.TheirVk } : new string[0], RoutingKeys = connection.Endpoint?.Verkey != null ? new[] { connection.Endpoint.Verkey } : new string[0] } } }); }
/// <summary> /// Constructs my DID doc in a pairwise relationship from a connection record and the agents provisioning record. /// </summary> /// <param name="connection">Connection record.</param> /// <param name="provisioningRecord">Provisioning record.</param> /// <returns>DID Doc</returns> public static DidDoc MyDidDoc(this ConnectionRecord connection, ProvisioningRecord provisioningRecord) { var doc = new DidDoc { Keys = new List <DidDocKey> { new DidDocKey { Id = $"{connection.MyDid}#keys-1", Type = DefaultKeyType, Controller = connection.MyDid, PublicKeyBase58 = connection.MyVk } } }; if (!string.IsNullOrEmpty(provisioningRecord.Endpoint.Uri)) { doc.Services = new List <IDidDocServiceEndpoint> { new IndyAgentDidDocService { Id = $"{connection.MyDid};indy", ServiceEndpoint = provisioningRecord.Endpoint.Uri, RecipientKeys = connection.MyVk != null ? new[] { connection.MyVk } : new string[0], RoutingKeys = provisioningRecord.Endpoint?.Verkey != null ? new[] { provisioningRecord.Endpoint.Verkey } : new string[0] } }; } return(doc); }
/// <inheritdoc /> public virtual async Task <(ConnectionInvitationMessage, ConnectionRecord)> CreateInvitationAsync(IAgentContext agentContext, InviteConfiguration config = null) { var connectionId = !string.IsNullOrEmpty(config?.ConnectionId) ? config.ConnectionId : Guid.NewGuid().ToString(); config = config ?? new InviteConfiguration(); Logger.LogInformation(LoggingEvents.CreateInvitation, "ConnectionId {0}", connectionId); var connectionKey = await Crypto.CreateKeyAsync(agentContext.Wallet, "{}"); var connection = new ConnectionRecord { Id = connectionId }; connection.SetTag(TagConstants.ConnectionKey, connectionKey); if (config.AutoAcceptConnection) { connection.SetTag(TagConstants.AutoAcceptConnection, "true"); } connection.MultiPartyInvitation = config.MultiPartyInvitation; if (!config.MultiPartyInvitation) { connection.Alias = config.TheirAlias; if (!string.IsNullOrEmpty(config.TheirAlias.Name)) { connection.SetTag(TagConstants.Alias, config.TheirAlias.Name); } } foreach (var tag in config.Tags) { connection.SetTag(tag.Key, tag.Value); } var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); if (string.IsNullOrEmpty(provisioning.Endpoint.Uri)) { throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, "Provision record has no endpoint information specified"); } await RecordService.AddAsync(agentContext.Wallet, connection); return(new ConnectionInvitationMessage { ServiceEndpoint = provisioning.Endpoint.Uri, RoutingKeys = provisioning.Endpoint.Verkey != null ? provisioning.Endpoint.Verkey : null, RecipientKeys = new[] { connectionKey }, Label = config.MyAlias.Name ?? provisioning.Owner.Name, ImageUrl = config.MyAlias.ImageUrl ?? provisioning.Owner.ImageUrl }, connection); }
/// <inheritdoc /> public virtual async Task <string> ProcessResponseAsync(IAgentContext agentContext, ConnectionResponseMessage response, ConnectionRecord connection) { Logger.LogTrace(LoggingEvents.AcceptConnectionResponse, "To {1}", connection.MyDid); //TODO throw exception or a problem report if the connection request features a did doc that has no indy agent did doc convention featured //i.e there is no way for this agent to respond to messages. And or no keys specified var connectionObj = await SignatureUtils.UnpackAndVerifyAsync <Connection>(response.ConnectionSig); await Did.StoreTheirDidAsync(agentContext.Wallet, new { did = connectionObj.Did, verkey = connectionObj.DidDoc.Keys[0].PublicKeyBase58 }.ToJson()); connection.TheirDid = connectionObj.Did; connection.TheirVk = connectionObj.DidDoc.Keys[0].PublicKeyBase58; connection.SetTag(TagConstants.LastThreadId, response.GetThreadId()); if (connectionObj.DidDoc.Services[0] is IndyAgentDidDocService service) { connection.Endpoint = new AgentEndpoint(service.ServiceEndpoint, null, service.RoutingKeys != null && service.RoutingKeys.Count > 0 ? service.RoutingKeys.ToArray() : null); } await connection.TriggerAsync(ConnectionTrigger.Response); await RecordService.UpdateAsync(agentContext.Wallet, connection); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = connection.Id, MessageType = response.Type, ThreadId = response.GetThreadId() }); return(connection.Id); }
/// <inheritdoc /> public virtual async Task <string> ProcessRequestAsync(IAgentContext agentContext, ConnectionRequestMessage request, ConnectionRecord connection) { Logger.LogInformation(LoggingEvents.ProcessConnectionRequest, "Did {0}", request.Connection.Did); var my = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}"); //TODO throw exception or a problem report if the connection request features a did doc that has no indy agent did doc convention featured //i.e there is no way for this agent to respond to messages. And or no keys specified await Did.StoreTheirDidAsync(agentContext.Wallet, new { did = request.Connection.Did, verkey = request.Connection.DidDoc.Keys[0].PublicKeyBase58 }.ToJson()); if (request.Connection.DidDoc.Services != null && request.Connection.DidDoc.Services.Count > 0 && request.Connection.DidDoc.Services[0] is IndyAgentDidDocService service) { connection.Endpoint = new AgentEndpoint(service.ServiceEndpoint, null, service.RoutingKeys != null && service.RoutingKeys.Count > 0 ? service.RoutingKeys.ToArray() : null); } connection.TheirDid = request.Connection.Did; connection.TheirVk = request.Connection.DidDoc.Keys[0].PublicKeyBase58; connection.MyDid = my.Did; connection.MyVk = my.VerKey; connection.SetTag(TagConstants.LastThreadId, request.Id); if (connection.Alias == null) { connection.Alias = new ConnectionAlias(); } if (!string.IsNullOrEmpty(request.Label) && string.IsNullOrEmpty(connection.Alias.Name)) { connection.Alias.Name = request.Label; } if (!string.IsNullOrEmpty(request.ImageUrl) && string.IsNullOrEmpty(connection.Alias.ImageUrl)) { connection.Alias.ImageUrl = request.ImageUrl; } if (!connection.MultiPartyInvitation) { await connection.TriggerAsync(ConnectionTrigger.InvitationAccept); await RecordService.UpdateAsync(agentContext.Wallet, connection); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = connection.Id, MessageType = request.Type, ThreadId = request.GetThreadId() }); return(connection.Id); } var newConnection = connection.DeepCopy(); newConnection.Id = Guid.NewGuid().ToString(); newConnection.MultiPartyInvitation = false; await newConnection.TriggerAsync(ConnectionTrigger.InvitationAccept); await RecordService.AddAsync(agentContext.Wallet, newConnection); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = newConnection.Id, MessageType = request.Type, ThreadId = request.GetThreadId() }); return(newConnection.Id); }
/// <inheritdoc /> public virtual async Task <(ConnectionRequestMessage, ConnectionRecord)> CreateRequestAsync(IAgentContext agentContext, ConnectionInvitationMessage invitation) { Logger.LogInformation(LoggingEvents.AcceptInvitation, "Key {0}, Endpoint {1}", invitation.RecipientKeys[0], invitation.ServiceEndpoint); var my = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}"); var connection = new ConnectionRecord { Endpoint = new AgentEndpoint(invitation.ServiceEndpoint, null, invitation.RoutingKeys != null && invitation.RoutingKeys.Count != 0 ? invitation.RoutingKeys.ToArray() : null), MyDid = my.Did, MyVk = my.VerKey, Id = Guid.NewGuid().ToString().ToLowerInvariant() }; connection.SetTag("InvitationKey", invitation.RecipientKeys.First()); if (!string.IsNullOrEmpty(invitation.Label) || !string.IsNullOrEmpty(invitation.ImageUrl)) { connection.Alias = new ConnectionAlias { Name = invitation.Label, ImageUrl = invitation.ImageUrl }; if (string.IsNullOrEmpty(invitation.Label)) { connection.SetTag(TagConstants.Alias, invitation.Label); } } await connection.TriggerAsync(ConnectionTrigger.InvitationAccept); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = new ConnectionRequestMessage { Connection = new Connection { Did = connection.MyDid, DidDoc = connection.MyDidDoc(provisioning) }, Label = provisioning.Owner?.Name, ImageUrl = provisioning.Owner?.ImageUrl }; // also set image as attachment if (provisioning.Owner?.ImageUrl != null) { request.AddAttachment(new Attachment { Nickname = "profile-image", Data = new AttachmentContent { Links = new[] { provisioning.Owner.ImageUrl } } }); } await RecordService.AddAsync(agentContext.Wallet, connection); return(request, connection); }