diff --git a/charts/dim/templates/cronjob-processes.yaml b/charts/dim/templates/cronjob-processes.yaml index 9cab75a..e61e41b 100644 --- a/charts/dim/templates/cronjob-processes.yaml +++ b/charts/dim/templates/cronjob-processes.yaml @@ -84,6 +84,10 @@ spec: value: "{{ .Values.processesworker.provisioning.encryptionConfigs.index0.paddingMode }}" - name: "DIM__STATUSLISTTYPE" value: "{{ .Values.processesworker.dim.statusListType }}" + - name: "DIM__ISSUERDID" + value: "{{ .Values.processesworker.dim.issuerDid }}" + - name: "DIM__ISSUERNAME" + value: "{{ .Values.processesworker.dim.issuerName }}" - name: "PROVISIONING__CLIENTID" value: "{{ .Values.processesworker.provisioning.clientId }}" - name: "PROVISIONING__CLIENTSECRET" diff --git a/charts/dim/values.yaml b/charts/dim/values.yaml index c8e8a30..fb12158 100644 --- a/charts/dim/values.yaml +++ b/charts/dim/values.yaml @@ -88,6 +88,8 @@ processesworker: # -- Sets the type of the status list which will be created for the issuer wallet # -- valid types are: StatusList2021, BitstringStatusList statusListType: "StatusList2021" + issuerDid: "" + issuerName: "" provisioning: clientId: "" clientSecret: "" diff --git a/environments/helm-values/values-int.yaml b/environments/helm-values/values-int.yaml index f97833b..36c6f4f 100644 --- a/environments/helm-values/values-int.yaml +++ b/environments/helm-values/values-int.yaml @@ -54,6 +54,8 @@ processesworker: default: "Debug" dim: applicationName: "catena-x-portal" + issuerDid: "" + issuerName: "" provisioning: clientId: "" clientSecret: "" diff --git a/environments/helm-values/values-stable.yaml b/environments/helm-values/values-stable.yaml index 4386d97..507391a 100644 --- a/environments/helm-values/values-stable.yaml +++ b/environments/helm-values/values-stable.yaml @@ -53,6 +53,8 @@ processesworker: default: "Debug" dim: applicationName: "catena-x-portal" + issuerDid: "" + issuerName: "" provisioning: clientId: "" clientSecret: "" diff --git a/src/clients/Dim.Clients/Api/Dim/DimClient.cs b/src/clients/Dim.Clients/Api/Dim/DimClient.cs index 3d7fa17..c618dd9 100644 --- a/src/clients/Dim.Clients/Api/Dim/DimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/DimClient.cs @@ -62,6 +62,34 @@ public async Task GetCompanyData(BasicAuthSettings dimAuth, string } } + public async Task UpdateCompanyStatus(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken) + { + var client = await basicAuthTokenService.GetBasicAuthorizedClient(dimAuth, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + var result = await client.PatchAsync($"{dimBaseUrl}/api/v2.0.0/companyIdentities/{companyId}/status", null, cancellationToken) + .CatchingIntoServiceExceptionFor("update-company-status", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, + async m => + { + var message = await m.Content.ReadAsStringAsync().ConfigureAwait(ConfigureAwaitOptions.None); + return (false, message); + }).ConfigureAwait(false); + try + { + var response = await result.Content + .ReadFromJsonAsync(JsonSerializerExtensions.Options, cancellationToken) + .ConfigureAwait(ConfigureAwaitOptions.None); + if (response?.Status == null || response.Status != "successful") + { + throw new ServiceException("Company status update failed", true); + } + + return response.Status; + } + catch (JsonException je) + { + throw new ServiceException(je.Message); + } + } + public async Task GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken) { var client = await basicAuthTokenService.GetBasicAuthorizedClient(dimAuth, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); diff --git a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs index 32445f0..645ec47 100644 --- a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs @@ -27,6 +27,7 @@ namespace Dim.Clients.Api.Dim; public interface IDimClient { Task GetCompanyData(BasicAuthSettings dimAuth, string dimBaseUrl, string tenantName, string application, CancellationToken cancellationToken); + Task UpdateCompanyStatus(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken); Task GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken); Task CreateStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken); } diff --git a/src/clients/Dim.Clients/Api/Dim/Models/CompanyData.cs b/src/clients/Dim.Clients/Api/Dim/Models/CompanyData.cs index db8b66b..aa29f6f 100644 --- a/src/clients/Dim.Clients/Api/Dim/Models/CompanyData.cs +++ b/src/clients/Dim.Clients/Api/Dim/Models/CompanyData.cs @@ -30,3 +30,8 @@ public record CompanyData( [property: JsonPropertyName("id")] Guid CompanyId, [property: JsonPropertyName("downloadURL")] string DownloadUrl ); + +public record CompanyStatusResponse( + [property: JsonPropertyName("operation")] string Operation, + [property: JsonPropertyName("status")] string Status +); diff --git a/src/clients/Dim.Clients/Api/Div/DependencyInjection/ProvisioningSettings.cs b/src/clients/Dim.Clients/Api/Div/DependencyInjection/ProvisioningSettings.cs index 034953d..e179126 100644 --- a/src/clients/Dim.Clients/Api/Div/DependencyInjection/ProvisioningSettings.cs +++ b/src/clients/Dim.Clients/Api/Div/DependencyInjection/ProvisioningSettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 BMW Group AG + * Copyright (c) 2025 BMW Group AG * Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/clients/Dim.Clients/Api/Div/IProvisioningClient.cs b/src/clients/Dim.Clients/Api/Div/IProvisioningClient.cs index 139bd3b..9f1e2f1 100644 --- a/src/clients/Dim.Clients/Api/Div/IProvisioningClient.cs +++ b/src/clients/Dim.Clients/Api/Div/IProvisioningClient.cs @@ -24,7 +24,7 @@ namespace Dim.Clients.Api.Div; public interface IProvisioningClient { - Task CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, CancellationToken cancellationToken); + Task CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, string issuerDid, string issuerName, CancellationToken cancellationToken); Task GetOperation(Guid operationId, CancellationToken cancellationToken); Task CreateServiceKey(string technicalUserName, Guid walletId, CancellationToken cancellationToken); Task DeleteServiceKey(Guid walletId, Guid serviceKeyId, CancellationToken cancellationToken); diff --git a/src/clients/Dim.Clients/Api/Div/Models/OperationRequest.cs b/src/clients/Dim.Clients/Api/Div/Models/OperationRequest.cs index ad14eef..4218f82 100644 --- a/src/clients/Dim.Clients/Api/Div/Models/OperationRequest.cs +++ b/src/clients/Dim.Clients/Api/Div/Models/OperationRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 BMW Group AG + * Copyright (c) 2025 BMW Group AG * Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional @@ -48,7 +48,7 @@ public record WalletApplication( public record ApplicationCompany( [property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("hostingURL")] string HostingUrl, - [property: JsonPropertyName("services")] IEnumerable Services, + [property: JsonPropertyName("protocols")] string[] Protocols, [property: JsonPropertyName("keys")] IEnumerable Keys ); @@ -64,9 +64,15 @@ public record ApplicationCompanyKey( public record TrustedIssuer( [property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("did")] string Did, + [property: JsonPropertyName("credentialTypeConfiguration")] IEnumerable CredentialTypeConfiguration, [property: JsonPropertyName("ignoreMissingHashlist")] bool IgnoreMissingHashlist ); +public record CredentialTypeConfiguration( + [property: JsonPropertyName("credentialType")] string CredentialType, + [property: JsonPropertyName("autoAcceptOffers")] bool AutoAcceptOffers +); + public record OperationRequest( [property: JsonPropertyName("operationId")] Guid OperationId ); diff --git a/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs b/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs index b9c62af..ffae2eb 100644 --- a/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs +++ b/src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 BMW Group AG + * Copyright (c) 2025 BMW Group AG * Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional @@ -35,7 +35,7 @@ public class ProvisioningClient(IBasicAuthTokenService basicAuthTokenService, IO { private readonly ProvisioningSettings _settings = options.Value; - public async Task CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, CancellationToken cancellationToken) + public async Task CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, string issuerDid, string issuerName, CancellationToken cancellationToken) { var data = new OperationCreationRequest( "provision", @@ -50,7 +50,7 @@ public async Task CreateOperation(Guid customerId, string customerName, st Enumerable.Repeat(new ApplicationCompany( companyName, didDocumentLocation, - [new ApplicationCompanyService("CredentialService", "https://dis-agent-prod.eu10.dim.cloud.sap/api/v1.0.0/iatp")], + isIssuer ? ["dcp-issuer", "dcp-holder"] : ["dcp-holder"], isIssuer ? [ new("SIGNING"), @@ -61,7 +61,21 @@ [new ApplicationCompanyService("CredentialService", "https://dis-agent-prod.eu10 new("SIGNING") } ), 1), - Enumerable.Empty() + isIssuer + ? Enumerable.Empty() + : new[] + { + new TrustedIssuer( + issuerName, + issuerDid, + [ + new CredentialTypeConfiguration("BpnCredential", true), + new CredentialTypeConfiguration("MembershipCredential", true), + new CredentialTypeConfiguration("DataExchangeGovernanceCredential", true) + ], + false + ) + } ), 1) ) ) @@ -139,7 +153,7 @@ public async Task CreateServiceKey(string technicalUserName, Guid walletId new ServiceKeyCreationPayloadData( walletId, technicalUserName, - new ServiceKeyParameter(new[] { "IatpOperations", "ReadCompanyIdentity", "ResolveDID" }) + new ServiceKeyParameter(new[] { "IatpOperations", "DcpOperations", "ReadCompanyIdentity", "ResolveDID" }) ) ); var client = await basicAuthTokenService diff --git a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs index c6e384f..11ba7af 100644 --- a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs @@ -35,7 +35,7 @@ public interface ITenantRepository Task<(string? BaseUrl, WalletData WalletData)> GetCompanyRequestData(Guid tenantId); Task<(bool Exists, Guid? CompanyId, string? BaseUrl, WalletData WalletData)> GetCompanyAndWalletDataForBpn(string bpn); Task<(Guid? CompanyId, string? BaseUrl, WalletData WalletData)> GetStatusListCreationData(Guid tenantId); - Task<(string Bpn, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId); + Task<(string Bpn, Guid? CompanyId, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId); Task<(string? DownloadUrl, bool IsIssuer)> GetDownloadUrlAndIsIssuer(Guid tenantId); Task GetWalletProcessForTenant(string bpn, string companyName); } diff --git a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs index 2a6d55a..5bca1c4 100644 --- a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs @@ -112,11 +112,12 @@ public Task IsTenantExisting(string companyName, string bpn) => ))) .SingleOrDefaultAsync(); - public Task<(string Bpn, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId) => + public Task<(string Bpn, Guid? CompanyId, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId) => dbContext.Tenants .Where(x => x.Id == tenantId) - .Select(x => new ValueTuple( + .Select(x => new ValueTuple( x.Bpn, + x.CompanyId, x.BaseUrl, new WalletData( x.TokenAddress, diff --git a/src/processes/DimProcess.Library/Callback/CallbackService.cs b/src/processes/DimProcess.Library/Callback/CallbackService.cs index 8c46b81..34624cb 100644 --- a/src/processes/DimProcess.Library/Callback/CallbackService.cs +++ b/src/processes/DimProcess.Library/Callback/CallbackService.cs @@ -23,6 +23,7 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions; using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; +using System.Net; using System.Net.Http.Json; using System.Text.Json; @@ -42,8 +43,12 @@ public async Task SendCallback(string bpn, AuthenticationDetail authenticationDe didDocument, authenticationDetail ); + ValueTask<(bool, string?)> CustomErrorHandling(HttpResponseMessage errorResponse) => new( + (errorResponse.StatusCode == HttpStatusCode.Conflict, + null)); + await httpClient.PostAsJsonAsync($"/api/administration/registration/dim/{bpn}", data, JsonSerializerExtensions.Options, cancellationToken) - .CatchingIntoServiceExceptionFor("send-callback", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE) + .CatchingIntoServiceExceptionFor("send-callback", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CustomErrorHandling) .ConfigureAwait(false); } diff --git a/src/processes/DimProcess.Library/DependencyInjection/DimHandlerSettings.cs b/src/processes/DimProcess.Library/DependencyInjection/DimHandlerSettings.cs index 3c67da7..c07cbb6 100644 --- a/src/processes/DimProcess.Library/DependencyInjection/DimHandlerSettings.cs +++ b/src/processes/DimProcess.Library/DependencyInjection/DimHandlerSettings.cs @@ -39,4 +39,10 @@ public class DimHandlerSettings [Required] public StatusListType StatusListType { get; set; } + + [Required] + public string IssuerDid { get; set; } = null!; + + [Required] + public string IssuerName { get; set; } = null!; } diff --git a/src/processes/DimProcess.Library/DimProcessHandler.cs b/src/processes/DimProcess.Library/DimProcessHandler.cs index 4e5eb2a..647ac23 100644 --- a/src/processes/DimProcess.Library/DimProcessHandler.cs +++ b/src/processes/DimProcess.Library/DimProcessHandler.cs @@ -56,7 +56,7 @@ public class DimProcessHandler( throw new UnexpectedConditionException("DidDocumentLocation must always be set"); } - var operationId = await provisioningClient.CreateOperation(tenantId, tenantName, _settings.ApplicationName, tenantName, didDocumentLocation, isIssuer, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + var operationId = await provisioningClient.CreateOperation(tenantId, tenantName, _settings.ApplicationName, tenantName, didDocumentLocation, isIssuer, _settings.IssuerDid, _settings.IssuerName, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); tenantRepository.AttachAndModifyTenant(tenantId, t => t.OperationId = null, t => t.OperationId = operationId); return new ValueTuple?, ProcessStepStatusId, bool, string?>( @@ -226,7 +226,7 @@ public class DimProcessHandler( public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, CancellationToken cancellationToken) { - var (bpn, baseUrl, walletData, did, downloadUrl) = await dimRepositories.GetInstance().GetCallbackData(tenantId).ConfigureAwait(ConfigureAwaitOptions.None); + var (bpn, companyId, baseUrl, walletData, did, downloadUrl) = await dimRepositories.GetInstance().GetCallbackData(tenantId).ConfigureAwait(ConfigureAwaitOptions.None); var (tokenAddress, clientId, clientSecret, initializationVector, encryptionMode) = walletData.ValidateData(); if (baseUrl == null) { @@ -243,6 +243,11 @@ public class DimProcessHandler( throw new UnexpectedConditionException("DownloadUrl must always be set"); } + if (companyId == null) + { + throw new UnexpectedConditionException("CompanyId must always be set"); + } + var cryptoHelper = _settings.EncryptionConfigs.GetCryptoHelper(encryptionMode); var secret = cryptoHelper.Decrypt(clientSecret, initializationVector); @@ -250,6 +255,16 @@ public class DimProcessHandler( var uaa = new AuthenticationDetail(tokenAddress, clientId, secret); await callbackService.SendCallback(bpn, uaa, didDocument, did, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + var dimAuth = new BasicAuthSettings + { + TokenAddress = $"{tokenAddress}/oauth/token", + ClientId = clientId, + ClientSecret = secret + }; + await dimClient + .UpdateCompanyStatus(dimAuth, baseUrl, companyId.Value, cancellationToken) + .ConfigureAwait(ConfigureAwaitOptions.None); + return new ValueTuple?, ProcessStepStatusId, bool, string?>( null, ProcessStepStatusId.DONE, diff --git a/src/processes/Processes.Worker/appsettings.json b/src/processes/Processes.Worker/appsettings.json index 8598525..4ba67f0 100644 --- a/src/processes/Processes.Worker/appsettings.json +++ b/src/processes/Processes.Worker/appsettings.json @@ -34,7 +34,9 @@ "PaddingMode": "" } ], - "StatusListType": "" + "StatusListType": "", + "IssuerDid": "", + "IssuerName": "" }, "Processes": { "LockExpirySeconds": 300 diff --git a/tests/clients/Dim.Clients.Tests/ProvisioningClientTests.cs b/tests/clients/Dim.Clients.Tests/ProvisioningClientTests.cs index 821b737..0a68cef 100644 --- a/tests/clients/Dim.Clients.Tests/ProvisioningClientTests.cs +++ b/tests/clients/Dim.Clients.Tests/ProvisioningClientTests.cs @@ -86,7 +86,7 @@ public async Task CreateOperation_WithNoContent_ThrowsServiceException() // Arrange _fixture.ConfigureTokenServiceFixture(new HttpResponseMessage(HttpStatusCode.OK)); var sut = _fixture.Create(); - Task Act() => sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, CancellationToken.None); + Task Act() => sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, "did:web:example", "example", CancellationToken.None); // Act var ex = await Assert.ThrowsAsync(Act); @@ -101,7 +101,7 @@ public async Task CreateOperation_WithNoSpaceLeft_ThrowsConflictException() // Arrange _fixture.ConfigureTokenServiceFixture(new HttpResponseMessage(HttpStatusCode.BadRequest)); var sut = _fixture.Create(); - Task Act() => sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, CancellationToken.None); + Task Act() => sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, "did:web:example", "example", CancellationToken.None); // Act var ex = await Assert.ThrowsAsync(Act); @@ -125,12 +125,45 @@ public async Task CreateOperation_WithValidData_ReturnsCompanyData() var sut = _fixture.Create(); // Act - var result = await sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, CancellationToken.None); + var result = await sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, "did:web:example", "example", CancellationToken.None); // Assert result.Should().Be(operationId); } + [Fact] + public async Task CreateOperation_WithNonIssuer_ValidatesCredentialConfiguration() + { + // Arrange + var operationId = Guid.NewGuid(); + var data = new OperationRequest(operationId); + var capturedRequestContent = string.Empty; + + using (var responseMessage = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent(JsonSerializer.Serialize(data, JsonSerializerExtensions.Options)) + }) + { + _fixture.ConfigureTokenServiceFixture( + responseMessage, + request => capturedRequestContent = request?.Content?.ReadAsStringAsync().Result ?? string.Empty); + var sut = _fixture.Create(); + + // Act + await sut.CreateOperation(Guid.NewGuid(), "corp", "application1", "test corp", "https://example.org/did", false, "did:web:example", "example", CancellationToken.None); + } + + // Assert - Validate credential configuration + capturedRequestContent.Should().NotBeEmpty(); + var request = JsonSerializer.Deserialize(capturedRequestContent, JsonSerializerExtensions.Options); + var trustedIssuer = request!.Payload.WalletServiceParameter.Applications.First().TrustedIssuers.First(); + + trustedIssuer.CredentialTypeConfiguration.Should().HaveCount(3); + trustedIssuer.CredentialTypeConfiguration.Should().Contain(c => c.CredentialType == "BpnCredential" && c.AutoAcceptOffers); + trustedIssuer.CredentialTypeConfiguration.Should().Contain(c => c.CredentialType == "MembershipCredential" && c.AutoAcceptOffers); + trustedIssuer.CredentialTypeConfiguration.Should().Contain(c => c.CredentialType == "DataExchangeGovernanceCredential" && c.AutoAcceptOffers); + } + #endregion #region CreateServiceKey diff --git a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs index a387022..c4e9577 100644 --- a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs +++ b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs @@ -128,7 +128,7 @@ public async Task CreateOperation_WithValidData_ReturnsExpected() initialize?.Invoke(tenant); modify(tenant); }); - A.CallTo(() => _provisioningClient.CreateOperation(A._, TenantName, A._, A._, A._, A._, A._)) + A.CallTo(() => _provisioningClient.CreateOperation(A._, TenantName, A._, A._, A._, A._, A._, A._, A._)) .Returns(operationId); // Act @@ -402,7 +402,7 @@ public async Task SendCallback_WithoutBaseUrl_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) - .Returns(("bpn123", null, _fixture.Create(), null, null)); + .Returns(("bpn123", Guid.NewGuid(), null, _fixture.Create(), null, null)); async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None); // Act @@ -417,7 +417,7 @@ public async Task SendCallback_WithoutDid_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) - .Returns(("bpn123", "https://example.org/base", _fixture.Create(), null, null)); + .Returns(("bpn123", Guid.NewGuid(), "https://example.org/base", _fixture.Create(), null, null)); async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None); // Act @@ -432,7 +432,7 @@ public async Task SendCallback_WithoutDownloadUrl_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) - .Returns(("bpn123", "https://example.org/base", _fixture.Create(), "did:web:example:org:base", null)); + .Returns(("bpn123", Guid.NewGuid(), "https://example.org/base", _fixture.Create(), "did:web:example:org:base", null)); async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None); // Act @@ -456,7 +456,7 @@ public async Task SendCallback_WithValidData_ReturnsExpected() var (encryptSecret, initializationVector) = cryptoHelper.Encrypt("test123"); var walletData = new WalletData("https://example.org/token", "cl1", encryptSecret, initializationVector, _settings.EncryptionConfigIndex); A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) - .Returns(("bpn123", "https://example.org/base", walletData, tenant.Did, tenant.DidDownloadUrl)); + .Returns(("bpn123", Guid.NewGuid(), "https://example.org/base", walletData, tenant.Did, tenant.DidDownloadUrl)); // Act var result = await _sut.SendCallback(_tenantId, CancellationToken.None);