public void InitialCredentialRecordIsOfferedAndHasTag() { var record = new CredentialRecord(); Assert.True(record.State == CredentialState.Offered); Assert.True(record.GetTag(nameof(CredentialRecord.State)) == CredentialState.Offered.ToString("G")); }
/// <inheritdoc /> public virtual async Task <string> ProcessOfferAsync(IAgentContext agentContext, CredentialOfferMessage credentialOffer, ConnectionRecord connection) { var offerJson = credentialOffer.OfferJson; var offer = JObject.Parse(offerJson); var definitionId = offer["cred_def_id"].ToObject <string>(); var schemaId = offer["schema_id"].ToObject <string>(); var nonce = offer["nonce"].ToObject <string>(); // Write offer record to local wallet var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), OfferJson = offerJson, ConnectionId = connection.Id, CredentialDefinitionId = definitionId, SchemaId = schemaId, State = CredentialState.Offered }; credentialRecord.SetTag(TagConstants.Role, TagConstants.Holder); credentialRecord.SetTag(TagConstants.Nonce, nonce); await RecordService.AddAsync(agentContext.Wallet, credentialRecord); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credentialRecord.Id, MessageType = credentialOffer.Type, }); return(credentialRecord.Id); }
public CredentialViewModel(IUserDialogs userDialogs, INavigationService navigationService, CredentialRecord credential, IAgentProvider agentProvider, ICredentialService credentialService, IEventAggregator eventAggregator, IConnectionService connectionService) : base(nameof(CredentialViewModel), userDialogs, navigationService) { _connectionService = connectionService; _agentProvider = agentProvider; _credentialService = credentialService; _eventAggregator = eventAggregator; Title = "Credential Detail"; _credential = credential; _attributes = credential.CredentialAttributesValues; _credId = _credential.Id; _state = _credential.State; _credentialName = ConvertNameFromeSchemaId(_credential.SchemaId).ToTitleCase(); if (_credential.CreatedAtUtc != null) { IssuedDate = (DateTime)_credential.CreatedAtUtc; } someMaterialColor = new Helpers.SomeMaterialColor(); }
public void InitialCredentialRecordIsOfferedAndHasTag() { var record = new CredentialRecord(); Assert.True(record.State == CredentialState.Offered); Assert.True(record.Tags[TagConstants.State] == CredentialState.Offered.ToString("G")); }
private bool IsCredentialNew(CredentialRecord credential) { // TODO OS-200, Currently a Placeholder for a mix of new and not new cells Random random = new Random(); return(random.Next(0, 2) == 1); }
public async Task <CredentialViewModel> Assemble(CredentialRecord credentialRecord) { if (credentialRecord == null) { return(null); } var context = await _agentContextProvider.GetContextAsync(); CredentialViewModel credential = _scope.Resolve <CredentialViewModel>(new NamedParameter("credential", credentialRecord)); var credentialDefinitionId = CredentialDefinitionId.Parse(credentialRecord.CredentialDefinitionId); credential.CredentialName = credentialDefinitionId.Tag; var connectionRecord = await _connectionService.GetAsync(context, credentialRecord.ConnectionId); credential.CredentialSubtitle = connectionRecord.Alias.Name; credential.IssuedAt = connectionRecord.CreatedAtUtc.HasValue ? connectionRecord.CreatedAtUtc.Value.ToLocalTime() : (DateTime?)null; if (credentialRecord.State == CredentialState.Offered) { var attributes = new List <CredentialAttribute>(); credential.Attributes = attributes; foreach (var credentialPreviewAttribute in credentialRecord.CredentialAttributesValues) { var attribute = new CredentialAttribute { Name = credentialPreviewAttribute.Name, Value = credentialPreviewAttribute.Value.ToString(), Type = "Text" }; attribute.Type = attribute.Value != null && (attribute.Value.ToString().StartsWith("data:image/jpeg;base64") || attribute.Value.ToString().StartsWith("data:image/png;base64")) ? "Image" : "Text"; attribute.Image = attribute.Value != null && (attribute.Value.ToString().StartsWith("data:image/jpeg;base64") || attribute.Value.ToString().StartsWith("data:image/png;base64")) ? ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(attribute.Value.ToString().Replace("data:image/jpeg;base64,", "").Replace("data:image/png;base64,", "")))) : null; attributes.Add(attribute); } } return(credential); }
public void CreateWithExistingGuid() { var customGuid = new Guid(); _credentialRecord = new CredentialRecord(customGuid); Assert.That(_credentialRecord.Id, Is.EqualTo(customGuid)); }
private bool IsCredentialNew(CredentialRecord credential) { //// TODO OS-200, Currently a Placeholder for a mix of new and not new cells //Random random = new Random(); //return random.Next(0, 2) == 1; return(_credential.State == CredentialState.Offered); }
public CredOfferViewModel(IUserDialogs userDialogs, INavigationService navigationService, IAgentProvider agentProvider, ICredentialService credentialService, IMessageService messageService, IPoolService poolService, IWalletRecordService recordService, IConnectionService connectionService, IEventAggregator eventAggregator, CredentialRecord credentialOffer) : base(nameof(CredOfferViewModel), userDialogs, navigationService) { _credentialOffer = credentialOffer; _agentProvider = agentProvider; _credentialService = credentialService; _connectionService = connectionService; _messageService = messageService; _poolService = poolService; _recordService = recordService; _eventAggregator = eventAggregator; Title = "Offer Detail"; CredentialName = ConvertNameFromeSchemaId(CredentialOffer.SchemaId); if (_credentialOffer.CreatedAtUtc != null) { IssuedDate = (DateTime)_credentialOffer.CreatedAtUtc; } }
public async Task <IActionResult> SendCredentialProposalAsync(OperationBody body) { var context = await _agentContextProvider.GetContextAsync(); var proposal = body.Data; var connectionId = (string)proposal["connection_id"]; var credentialPreview = proposal["credential_proposal"].ToObject <CustomCredentialPreviewMessage>(); var credentialDefinitionId = (string)proposal["cred_def_id"]; var schemaId = (string)proposal["schema_id"]; var connection = await _connectionService.GetAsync(context, connectionId); // TODO: Handle AriesFrameworkException if connection not found var threadId = Guid.NewGuid().ToString(); credentialPreview.Attributes = CleanCredentialPreviewAttributes(credentialPreview.Attributes); // TODO: add support for v1.1 wich includes 'schema_issuer_did', 'schema_name', 'schema_version', 'issuer_did' // TODO: should we support in response to previous message? Not possible with AATH atm I think. var credentialProposeMessage = new CustomCredentialProposeMessage { Id = threadId, Comment = (string)proposal["comment"] ?? "hello", // ACA-Py requires comment CredentialProposal = credentialPreview, CredentialDefinitionId = credentialDefinitionId, SchemaId = schemaId }; var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), ConnectionId = connectionId, CredentialAttributesValues = credentialPreview.Attributes, CredentialDefinitionId = credentialDefinitionId, SchemaId = schemaId, // State should be proposal-received State = CredentialState.Offered }; credentialRecord.SetTag(TagConstants.Role, TagConstants.Holder); credentialRecord.SetTag(TagConstants.LastThreadId, threadId); await _recordService.AddAsync(context.Wallet, credentialRecord); var THCredentialExchange = new TestHarnessCredentialExchange { RecordId = credentialRecord.Id, ThreadId = threadId, State = TestHarnessCredentialExchangeState.ProposalSent, }; _credentialCache.Set(THCredentialExchange.ThreadId, THCredentialExchange); // Listen for credential offer to update the state UpdateStateOnMessage(THCredentialExchange, TestHarnessCredentialExchangeState.OfferReceived, _ => _.MessageType == MessageTypes.IssueCredentialNames.OfferCredential && _.ThreadId == THCredentialExchange.ThreadId); await _messageService.SendAsync(context.Wallet, credentialProposeMessage, connection); return(Ok(THCredentialExchange)); }
public void Setup() { _credentialRecord = new CredentialRecord { Username = "******", Domain = "domainHere", Password = "******".ConvertToSecureString() }; }
public void AllCredentialsSerialized() { var cred2 = new CredentialRecord { Title = "testcred2", Username = "******", Domain = "otherdomain", Password = "******".ConvertToSecureString() }; var serialized = _serializer.Serialize(new[] { _cred1, cred2 }); var serializedCount = XDocument.Parse(serialized).Descendants("Credential").Count(); Assert.That(serializedCount, Is.EqualTo(2)); }
private async Task DisplayCredentialOffer(string recordId) { IAgentContext context = await _agentContextProvider.GetContextAsync(); CredentialRecord credentialRecord = await _credentialService.GetAsync(context, recordId); CredentialViewModel credential = await _credentialAssembler.Assemble(credentialRecord); await NavigationService.NavigateToAsync(credential, null, NavigationType.Modal); }
/// <inheritdoc /> public async Task <bool> IsRevokedAsync(IAgentContext context, CredentialRecord record) { if (record.RevocationRegistryId == null) { return(false); } if (record.State == CredentialState.Offered || record.State == CredentialState.Requested) { return(false); } if (record.State == CredentialState.Revoked || record.State == CredentialState.Rejected) { return(true); } var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var proofRequest = new ProofRequest { Name = "revocation check", Version = "1.0", Nonce = await AnonCreds.GenerateNonceAsync(), RequestedAttributes = new Dictionary <string, ProofAttributeInfo> { { "referent1", new ProofAttributeInfo { Name = record.CredentialAttributesValues.First().Name } } }, NonRevoked = new RevocationInterval { From = (uint)now, To = (uint)now } }; var proof = await CreateProofAsync(context, proofRequest, new RequestedCredentials { RequestedAttributes = new Dictionary <string, RequestedAttribute> { { "referent1", new RequestedAttribute { CredentialId = record.CredentialId, Timestamp = now, Revealed = true } } } }); var isValid = await VerifyProofAsync(context, proofRequest.ToJson(), proof); if (!isValid) { await record.TriggerAsync(CredentialTrigger.Revoke); record.SetTag("LastRevocationCheck", now.ToString()); await RecordService.UpdateAsync(context.Wallet, record); } return(!isValid); }
/// <inheritdoc /> public virtual async Task <CredentialOfferMessage> CreateOfferAsync(Wallet wallet, DefaultCreateOfferConfiguration config) { Logger.LogInformation(LoggingEvents.CreateCredentialOffer, "DefinitionId {0}, ConnectionId {1}, IssuerDid {2}", config.CredentialDefinitionId, config.ConnectionId, config.IssuerDid); var connection = await ConnectionService.GetAsync(wallet, config.ConnectionId); var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync(wallet, config.CredentialDefinitionId); var nonce = JObject.Parse(offerJson)["nonce"].ToObject <string>(); // Write offer record to local wallet var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), CredentialDefinitionId = config.CredentialDefinitionId, OfferJson = offerJson, ValuesJson = CredentialUtils.FormatCredentialValues(config.CredentialAttributeValues), State = CredentialState.Offered, ConnectionId = connection.GetId(), }; credentialRecord.Tags.Add(TagConstants.Nonce, nonce); credentialRecord.Tags.Add(TagConstants.Role, TagConstants.Issuer); credentialRecord.Tags.Add(TagConstants.ConnectionId, connection.GetId()); if (!string.IsNullOrEmpty(config.IssuerDid)) { credentialRecord.Tags.Add(TagConstants.IssuerDid, config.IssuerDid); } if (config.Tags != null) { foreach (var tag in config.Tags) { if (!credentialRecord.Tags.Keys.Contains(tag.Key)) { credentialRecord.Tags.Add(tag.Key, tag.Value); } } } await RecordService.AddAsync(wallet, credentialRecord); var credentialOffer = await MessageSerializer.PackSealedAsync <CredentialOfferMessage>( new CredentialOfferDetails { OfferJson = offerJson }, wallet, connection.MyVk, connection.TheirVk); credentialOffer.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.CredentialOffer); return(credentialOffer); }
private bool ContainsAttributeName(CredentialRecord credentialRecord) { foreach (CredentialPreviewAttribute credentialAttribute in credentialRecord.CredentialAttributesValues) { if (credentialAttribute.Name == _attributeName) { return(true); } } return(false); }
private void AssignSelectedAttributeValue(CredentialRecord credentialRecord, ProofAttributeViewModel proofAttribute) { proofAttribute.CredentialId = credentialRecord.Id; foreach (CredentialPreviewAttribute credentialPreviewAttribute in credentialRecord.CredentialAttributesValues) { if (credentialPreviewAttribute.Name == proofAttribute.Name) { proofAttribute.Value = credentialPreviewAttribute.Value.ToString(); } } }
private ICredentialRecord BuildCredential(XElement element, ICryptographyProvider cryptographyProvider, SecureString decryptionKey) { var credential = new CredentialRecord { Title = $"{element.Attribute("Username")?.Value}\\{element.Attribute("Domain")?.Value}", Username = element.Attribute("Username")?.Value, Domain = element.Attribute("Domain")?.Value, Password = cryptographyProvider.Decrypt(element.Attribute("Password")?.Value, decryptionKey).ConvertToSecureString() }; return(credential); }
public CredentialViewModel( IUserDialogs userDialogs, INavigationService navigationService, CredentialRecord credential ) : base( nameof(CredentialViewModel), userDialogs, navigationService ) { _credential = credential; _isNew = IsCredentialNew(_credential); #if DEBUG _credentialName = "Credential Name"; _credentialImageUrl = "http://placekitten.com/g/200/200"; _credentialSubtitle = "10/22/2017"; _credentialType = "Bank Statement"; _qRImageUrl = "http://placekitten.com/g/100/100"; var attributes = new List <CredentialAttribute>(new CredentialAttribute[] { new CredentialAttribute { Type = "Text", Name = "First Name", Value = "Jamie" }, new CredentialAttribute { Type = "Text", Name = "Last Name", Value = "Doe" }, new CredentialAttribute { Type = "Text", Name = "Country of Residence", Value = "New Zealand" }, new CredentialAttribute { Type = "File", Name = "Statement", Value = "Statement.pdf", FileExt = "PDF", Date = "05 Aug 2018" } }); _attributes = attributes .OrderByDescending(o => o.Type).OrderBy(o => o.Date); #endif }
public async Task <GetCredentialResponse> Handle ( GetCredentialRequest aGetCredentialRequest, CancellationToken aCancellationToken ) { IAgentContext agentContext = await AgentProvider.GetContextAsync(); CredentialRecord credentialRecord = await CredentialService.GetAsync(agentContext, aGetCredentialRequest.CredentialId); var response = new GetCredentialResponse(aGetCredentialRequest.CorrelationId, credentialRecord); return(response); }
public SSICredentialViewModel(CredentialRecord credential) { _credential = credential; Attributes = new RangeEnabledObservableCollection <SSICredentialAttribute>(); foreach (var cred in _credential.CredentialAttributesValues) { Console.WriteLine("credential-name: " + cred.Name); Attributes.Add(new SSICredentialAttribute() { Name = cred.Name, Value = cred.Value, }); } }
public CredentialViewModel( IUserDialogs userDialogs, INavigationService navigationService, IAgentProvider agentContextProvider, ICredentialService credentialService, IEventAggregator eventAggregator, IMessageService messageService, IPoolConfigurator poolConfigurator, IConnectionService connectionService, CredentialRecord credential ) : base( "Credential Details", userDialogs, navigationService ) { _credential = credential; _agentContextProvider = agentContextProvider; _credentialService = credentialService; _eventAggregator = eventAggregator; _messageService = messageService; _connectionService = connectionService; _isNew = IsCredentialNew(_credential); _poolConfigurator = poolConfigurator; if (credential.State == CredentialState.Offered) { IsPending = true; AreButtonsVisible = true; } if (credential.State == CredentialState.Issued) { IsIssued = true; AreButtonsVisible = false; if (credential.CredentialAttributesValues != null) { Attributes = credential.CredentialAttributesValues .Select(p => new CredentialAttribute() { Name = p.Name, Value = p.Value?.ToString(), Type = p.Value != null && (p.Value.ToString().StartsWith("data:image/jpeg;base64") || p.Value.ToString().StartsWith("data:image/png;base64")) ? "Image" : "Text", Image = p.Value != null && (p.Value.ToString().StartsWith("data:image/jpeg;base64") || p.Value.ToString().StartsWith("data:image/png;base64")) ? ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(p.Value.ToString().Replace("data:image/jpeg;base64,", "").Replace("data:image/png;base64,", "")))) : null }) .ToList(); } } }
public async Task <GetCredentialResponse> Handle ( GetCredentialRequest aGetCredentialRequest, CancellationToken aCancellationToken ) { IAgentContext agentContext = await AgentProvider.GetContextAsync(); List <CredentialRecord> credentialRecords = await CredentialService.ListAsync(agentContext); CredentialRecord credentialRecord = credentialRecords .FirstOrDefault(aCredentialRecord => aCredentialRecord.CredentialId == aGetCredentialRequest.CredentialId); var response = new GetCredentialResponse(aGetCredentialRequest.CorrelationId, credentialRecord); return(response); }
/// <inheritdoc /> public virtual async Task <string> ProcessOfferAsync(Wallet wallet, CredentialOfferMessage credentialOffer) { var(didOrKey, _) = MessageUtils.ParseMessageType(credentialOffer.Type); var connectionSearch = await ConnectionService.ListAsync(wallet, new SearchRecordQuery { { TagConstants.MyDid, didOrKey } }); if (!connectionSearch.Any()) { throw new Exception($"Can't find connection record for type {credentialOffer.Type}"); } var connection = connectionSearch.First(); var(offerDetails, _) = await MessageSerializer.UnpackSealedAsync <CredentialOfferDetails>( credentialOffer.Content, wallet, connection.MyVk); var offerJson = offerDetails.OfferJson; var offer = JObject.Parse(offerJson); var definitionId = offer["cred_def_id"].ToObject <string>(); var schemaId = offer["schema_id"].ToObject <string>(); var nonce = offer["nonce"].ToObject <string>(); // Write offer record to local wallet var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), OfferJson = offerJson, ConnectionId = connection.GetId(), CredentialDefinitionId = definitionId, State = CredentialState.Offered }; credentialRecord.Tags.Add(TagConstants.ConnectionId, connection.GetId()); credentialRecord.Tags.Add(TagConstants.Role, TagConstants.Holder); credentialRecord.Tags.Add(TagConstants.Nonce, nonce); credentialRecord.Tags.Add(TagConstants.SchemaId, schemaId); credentialRecord.Tags.Add(TagConstants.DefinitionId, definitionId); await RecordService.AddAsync(wallet, credentialRecord); return(credentialRecord.GetId()); }
/// <inheritdoc /> public async Task <string> ProcessOfferAsync(IAgentContext agentContext, CredentialOfferMessage credentialOffer, ConnectionRecord connection) { var offerAttachment = credentialOffer.Offers.FirstOrDefault(x => x.Id == "libindy-cred-offer-0") ?? throw new ArgumentNullException(nameof(CredentialOfferMessage.Offers)); var offerJson = offerAttachment.Data.Base64.GetBytesFromBase64().GetUTF8String(); var offer = JObject.Parse(offerJson); var definitionId = offer["cred_def_id"].ToObject <string>(); var schemaId = offer["schema_id"].ToObject <string>(); // Write offer record to local wallet var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), OfferJson = offerJson, ConnectionId = connection.Id, CredentialDefinitionId = definitionId, CredentialAttributesValues = credentialOffer.CredentialPreview?.Attributes .Select(x => new CredentialPreviewAttribute { Name = x.Name, MimeType = x.MimeType, Value = x.Value }).ToArray(), SchemaId = schemaId, State = CredentialState.Offered }; credentialRecord.SetTag(TagConstants.Role, TagConstants.Holder); credentialRecord.SetTag(TagConstants.LastThreadId, credentialOffer.GetThreadId()); await RecordService.AddAsync(agentContext.Wallet, credentialRecord); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credentialRecord.Id, MessageType = credentialOffer.Type, ThreadId = credentialOffer.GetThreadId() }); return(credentialRecord.Id); }
public SSICredentialViewModel( INavigationService navigationService, CredentialRecord credential ) : base( nameof(SSICredentialViewModel), navigationService ) { _credential = credential; Console.WriteLine("credential-id:" + credential.Id); Preferences.Set("credential-id", credential.Id); Attributes = new RangeEnabledObservableCollection <SSICredentialAttribute>(); foreach (var cred in _credential.CredentialAttributesValues) { Attributes.Add(new SSICredentialAttribute() { Name = cred.Name, Value = cred.Value, }); } }
private async Task AcceptCredentialOffer(CredentialRecord credentialRecord) { if (credentialRecord.State != CredentialState.Offered) { await DialogService.AlertAsync(string.Format("res-CredentialStateShouldBe", CredentialState.Offered)); await NavigationService.PopModalAsync(); return; } await _poolConfigurator.ConfigurePoolsAsync(); var context = await _agentContextProvider.GetContextAsync(); var(msg, rec) = await _credentialService.CreateRequestAsync(context, credentialRecord.Id); var connectionRecord = await _connectionService.GetAsync(context, credentialRecord.ConnectionId); if (connectionRecord == null) { //await _messageService.SendAsync(context.Wallet, msg, conectionRecord.TheirVk ?? rec.GetTag("InvitationKey") ?? throw new InvalidOperationException("Cannot locate recipient Key"), conectionRecord.Endpoint.Uri, // conectionRecord.Endpoint?.Verkey == null ? null : conectionRecord.Endpoint.Verkey, conectionRecord.MyVk); await DialogService.AlertAsync("Connection-less credentials not supported."); return; } else { await _messageService.SendAsync(context.Wallet, msg, connectionRecord); } _eventAggregator.Publish(new ApplicationEvent() { Type = ApplicationEventType.CredentialUpdated }); await NavigationService.PopModalAsync(); }
/// <summary> /// Processes the agent message /// </summary> /// <param name="agentContext"></param> /// <param name="messageContext">The agent message.</param> /// <returns></returns> /// <exception cref="AriesFrameworkException">Unsupported message type {messageType}</exception> public async Task <AgentMessage> ProcessAsync(IAgentContext agentContext, UnpackedMessageContext messageContext) { switch (messageContext.GetMessageType()) { case MessageTypes.IssueCredentialNames.ProposeCredential: case MessageTypesHttps.IssueCredentialNames.ProposeCredential: { var credentialProposal = messageContext.GetMessage <CustomCredentialProposeMessage>(); CredentialRecord credentialRecord; TestHarnessCredentialExchange THCredentialExchange; try { // Credential can be proposed for an existing exchange // so we must first check if the message contains THCredentialExchange = _credentialCache.Get <TestHarnessCredentialExchange>(credentialProposal.GetThreadId()); credentialRecord = await _credentialService.GetByThreadIdAsync(agentContext, THCredentialExchange.ThreadId); // check if the proposal came from the same connection if (messageContext.Connection?.Id != credentialRecord.ConnectionId) { throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, "Connection from credential proposal is not same as previously stored record."); } } catch { // Create new CredentialRecord if no existing credential record exists credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), ConnectionId = messageContext.Connection?.Id, }; credentialRecord.SetTag(TagConstants.Role, TagConstants.Issuer); credentialRecord.SetTag(TagConstants.LastThreadId, credentialProposal.GetThreadId()); await _recordService.AddAsync(agentContext.Wallet, credentialRecord); THCredentialExchange = new TestHarnessCredentialExchange { RecordId = credentialRecord.Id, ThreadId = credentialProposal.GetThreadId(), State = TestHarnessCredentialExchangeState.ProposalReceived, }; _credentialCache.Set(THCredentialExchange.ThreadId, THCredentialExchange); } // Updates that should be applied both when the credential record already exists or not credentialRecord.CredentialDefinitionId = credentialProposal.CredentialDefinitionId; credentialRecord.SchemaId = credentialProposal.SchemaId; credentialRecord.CredentialAttributesValues = credentialProposal.CredentialProposal?.Attributes .Select(x => new CredentialPreviewAttribute { Name = x.Name, MimeType = x.MimeType, Value = x.Value }).ToArray(); // State should be proposal-received credentialRecord.State = CredentialState.Offered; await _recordService.UpdateAsync(agentContext.Wallet, credentialRecord); _eventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credentialRecord.Id, MessageType = credentialProposal.Type, ThreadId = credentialProposal.GetThreadId() }); messageContext.ContextRecord = credentialRecord; return(null); } case MessageTypes.IssueCredentialNames.OfferCredential: case MessageTypesHttps.IssueCredentialNames.OfferCredential: { var offer = messageContext.GetMessage <CredentialOfferMessage>(); var recordId = await this.ProcessOfferAsync( agentContext, offer, messageContext.Connection); messageContext.ContextRecord = await _credentialService.GetAsync(agentContext, recordId); return(null); } case MessageTypes.IssueCredentialNames.RequestCredential: case MessageTypesHttps.IssueCredentialNames.RequestCredential: { var request = messageContext.GetMessage <CredentialRequestMessage>(); var recordId = await _credentialService.ProcessCredentialRequestAsync( agentContext : agentContext, credentialRequest : request, connection : messageContext.Connection); if (request.ReturnRoutingRequested() && messageContext.Connection == null) { var(message, record) = await _credentialService.CreateCredentialAsync(agentContext, recordId); messageContext.ContextRecord = record; return(message); } else { messageContext.ContextRecord = await _credentialService.GetAsync(agentContext, recordId); return(null); } } case MessageTypes.IssueCredentialNames.IssueCredential: case MessageTypesHttps.IssueCredentialNames.IssueCredential: { var credential = messageContext.GetMessage <CredentialIssueMessage>(); var recordId = await _credentialService.ProcessCredentialAsync( agentContext, credential, messageContext.Connection); messageContext.ContextRecord = await UpdateValuesAsync( credentialId : recordId, credentialIssue : messageContext.GetMessage <CredentialIssueMessage>(), agentContext : agentContext); return(null); } default: throw new AriesFrameworkException(ErrorCode.InvalidMessage, $"Unsupported message type {messageContext.GetMessageType()}"); } }
/// <summary> /// Process an offer, taking previous proposals into account. The framework doesn't fully /// support credential proposals, and I don't know how to override one service function /// so for now we just use a custom handler and this function. /// </summary> /// <param name="agentContext"></param> /// <param name="credentialOffer"></param> /// <param name="connection"></param> /// <returns></returns> private async Task <string> ProcessOfferAsync(IAgentContext agentContext, CredentialOfferMessage credentialOffer, ConnectionRecord connection) { var offerAttachment = credentialOffer.Offers.FirstOrDefault(x => x.Id == "libindy-cred-offer-0") ?? throw new ArgumentNullException(nameof(CredentialOfferMessage.Offers)); var offerJson = offerAttachment.Data.Base64.GetBytesFromBase64().GetUTF8String(); var offer = JObject.Parse(offerJson); var definitionId = offer["cred_def_id"].ToObject <string>(); var schemaId = offer["schema_id"].ToObject <string>(); // check if credential already exists CredentialRecord credentialRecord; try { credentialRecord = await _credentialService.GetByThreadIdAsync(agentContext, credentialOffer.GetThreadId()); if (credentialRecord.ConnectionId != connection.Id) { throw new AriesFrameworkException(ErrorCode.InvalidRecordData, "Connection from credential offer is not same as previously stored record."); } } catch { // Write offer record to local wallet credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), ConnectionId = connection?.Id, }; credentialRecord.SetTag(TagConstants.Role, TagConstants.Holder); credentialRecord.SetTag(TagConstants.LastThreadId, credentialOffer.GetThreadId()); await _recordService.AddAsync(agentContext.Wallet, credentialRecord); var THCredentialExchange = new TestHarnessCredentialExchange { RecordId = credentialRecord.Id, ThreadId = credentialOffer.GetThreadId(), State = TestHarnessCredentialExchangeState.OfferReceived }; _credentialCache.Set(THCredentialExchange.ThreadId, THCredentialExchange); } credentialRecord.OfferJson = offerJson; credentialRecord.CredentialDefinitionId = definitionId; credentialRecord.SchemaId = schemaId; credentialRecord.CredentialAttributesValues = credentialOffer.CredentialPreview?.Attributes .Select(x => new CredentialPreviewAttribute { Name = x.Name, MimeType = x.MimeType, Value = x.Value }).ToArray(); credentialRecord.State = CredentialState.Offered; await _recordService.UpdateAsync(agentContext.Wallet, credentialRecord); _eventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credentialRecord.Id, MessageType = credentialOffer.Type, ThreadId = credentialOffer.GetThreadId() }); return(credentialRecord.Id); }
public async Task <(CredentialOfferMessage, CredentialRecord)> CreateOfferV1Async(IAgentContext agentContext, OfferConfiguration config, string connectionId = null) { Logger.LogInformation(LoggingEvents.CreateCredentialOffer, "DefinitionId {0}, IssuerDid {1}", config.CredentialDefinitionId, config.IssuerDid); var threadId = Guid.NewGuid().ToString(); if (!string.IsNullOrEmpty(connectionId)) { var connection = await ConnectionService.GetAsync(agentContext, connectionId); if (connection.State != ConnectionState.Connected) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'"); } } if (config.CredentialAttributeValues != null && config.CredentialAttributeValues.Any()) { CredentialUtils.ValidateCredentialPreviewAttributes(config.CredentialAttributeValues); } var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync( agentContext.Wallet, config.CredentialDefinitionId); var offerJobj = JObject.Parse(offerJson); var schemaId = offerJobj["schema_id"].ToObject <string>(); // Write offer record to local wallet var credentialRecord = new CredentialRecord { Id = Guid.NewGuid().ToString(), CredentialDefinitionId = config.CredentialDefinitionId, OfferJson = offerJson, ConnectionId = connectionId, SchemaId = schemaId, CredentialAttributesValues = config.CredentialAttributeValues, State = CredentialState.Offered, }; credentialRecord.SetTag(TagConstants.LastThreadId, threadId); credentialRecord.SetTag(TagConstants.Role, TagConstants.Issuer); if (!string.IsNullOrEmpty(config.IssuerDid)) { credentialRecord.SetTag(TagConstants.IssuerDid, config.IssuerDid); } if (config.Tags != null) { foreach (var tag in config.Tags) { if (!credentialRecord.Tags.Keys.Contains(tag.Key)) { credentialRecord.Tags.Add(tag.Key, tag.Value); } } } await RecordService.AddAsync(agentContext.Wallet, credentialRecord); return(new CredentialOfferMessage { Id = threadId, Offers = new Attachment[] { new Attachment { Id = "libindy-cred-offer-0", MimeType = CredentialMimeTypes.ApplicationJsonMimeType, Data = new AttachmentContent { Base64 = offerJson.GetUTF8Bytes().ToBase64String() } } }, CredentialPreview = credentialRecord.CredentialAttributesValues != null ? new CredentialPreviewMessage { Attributes = credentialRecord.CredentialAttributesValues.Select(x => new CredentialPreviewAttriubute { Name = x.Name, MimeType = x.MimeType, Value = x.Value?.ToString() }).ToArray() } : null }, credentialRecord); }