diff --git a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs index 6ebf58c3..093ec442 100644 --- a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs +++ b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs @@ -338,6 +338,7 @@ public async Task CreateBpnCredential(CreateBpnCredentialRequest requestDa { var companyCredentialDetailsRepository = _repositories.GetInstance(); var holderDid = await GetHolderInformation(requestData.Holder, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + var expiryDate = DateTimeOffset.UtcNow.AddMonths(12); var schemaData = new BpnCredential( Guid.NewGuid(), Context, @@ -345,7 +346,7 @@ public async Task CreateBpnCredential(CreateBpnCredentialRequest requestDa "BpnCredential", "Bpn Credential", DateTimeOffset.UtcNow, - DateTimeOffset.UtcNow.AddMonths(12), + expiryDate, _settings.IssuerDid, new BpnCredentialSubject( holderDid, @@ -357,7 +358,7 @@ public async Task CreateBpnCredential(CreateBpnCredentialRequest requestDa StatusList) ); var schema = JsonSerializer.Serialize(schemaData, Options); - return await HandleCredentialProcessCreation(requestData.BusinessPartnerNumber, VerifiedCredentialTypeKindId.BPN, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, schema, requestData.TechnicalUserDetails, null, requestData.CallbackUrl, companyCredentialDetailsRepository); + return await HandleCredentialProcessCreation(requestData.BusinessPartnerNumber, VerifiedCredentialTypeKindId.BPN, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, expiryDate, schema, requestData.TechnicalUserDetails, null, requestData.CallbackUrl, companyCredentialDetailsRepository); } public async Task CreateMembershipCredential(CreateMembershipCredentialRequest requestData, CancellationToken cancellationToken) @@ -365,6 +366,7 @@ public async Task CreateMembershipCredential(CreateMembershipCredentialReq var companyCredentialDetailsRepository = _repositories.GetInstance(); var holderDid = await GetHolderInformation(requestData.Holder, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + var expiryDate = DateTimeOffset.UtcNow.AddMonths(12); var schemaData = new MembershipCredential( Guid.NewGuid(), Context, @@ -372,7 +374,7 @@ public async Task CreateMembershipCredential(CreateMembershipCredentialReq "MembershipCredential", "Membership Credential", DateTimeOffset.UtcNow, - DateTimeOffset.UtcNow.AddMonths(12), + expiryDate, _settings.IssuerDid, new MembershipCredentialSubject( holderDid, @@ -384,7 +386,7 @@ public async Task CreateMembershipCredential(CreateMembershipCredentialReq StatusList) ); var schema = JsonSerializer.Serialize(schemaData, Options); - return await HandleCredentialProcessCreation(requestData.HolderBpn, VerifiedCredentialTypeKindId.MEMBERSHIP, VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE, schema, requestData.TechnicalUserDetails, null, requestData.CallbackUrl, companyCredentialDetailsRepository); + return await HandleCredentialProcessCreation(requestData.HolderBpn, VerifiedCredentialTypeKindId.MEMBERSHIP, VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE, expiryDate, schema, requestData.TechnicalUserDetails, null, requestData.CallbackUrl, companyCredentialDetailsRepository); } public async Task CreateFrameworkCredential(CreateFrameworkCredentialRequest requestData, CancellationToken cancellationToken) @@ -455,12 +457,12 @@ public async Task CreateFrameworkCredential(CreateFrameworkCredentialReque StatusList) ); var schema = JsonSerializer.Serialize(schemaData, Options); - return await HandleCredentialProcessCreation(requestData.HolderBpn, VerifiedCredentialTypeKindId.FRAMEWORK, requestData.UseCaseFrameworkId, schema, requestData.TechnicalUserDetails, requestData.UseCaseFrameworkVersionId, requestData.CallbackUrl, companyCredentialDetailsRepository); + return await HandleCredentialProcessCreation(requestData.HolderBpn, VerifiedCredentialTypeKindId.FRAMEWORK, requestData.UseCaseFrameworkId, result.Expiry, schema, requestData.TechnicalUserDetails, requestData.UseCaseFrameworkVersionId, requestData.CallbackUrl, companyCredentialDetailsRepository); } private async Task GetHolderInformation(string didDocumentLocation, CancellationToken cancellationToken) { - if (!Uri.TryCreate(didDocumentLocation, UriKind.Absolute, out var uri) || uri.Scheme != "https" || !string.IsNullOrEmpty(uri.Query) || !string.IsNullOrEmpty(uri.Fragment) || UrlPathInvalidCharsRegex.IsMatch(uri.AbsolutePath)) + if (!Uri.TryCreate(didDocumentLocation, UriKind.Absolute, out var uri) || (uri.Scheme != "https" || !string.IsNullOrEmpty(uri.Query) || !string.IsNullOrEmpty(uri.Fragment) || UrlPathInvalidCharsRegex.IsMatch(uri.AbsolutePath)) { throw ControllerArgumentException.Create(IssuerErrors.INVALID_DID_LOCATION, null, nameof(didDocumentLocation)); } @@ -481,6 +483,7 @@ private async Task HandleCredentialProcessCreation( string bpnl, VerifiedCredentialTypeKindId kindId, VerifiedCredentialTypeId typeId, + DateTimeOffset expiryDate, string schema, TechnicalUserDetails? technicalUserDetails, Guid? detailVersionId, @@ -515,6 +518,7 @@ private async Task HandleCredentialProcessCreation( { c.VerifiedCredentialExternalTypeDetailVersionId = detailVersionId; c.ProcessId = processId; + c.ExpiryDate = expiryDate; }).Id; documentRepository.AssignDocumentToCompanySsiDetails(docId, ssiDetailId); diff --git a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs index 40462f38..4eb8f4b3 100644 --- a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs +++ b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs @@ -676,6 +676,8 @@ public async Task CreateBpnCredential_ReturnsExpected() var didId = Guid.NewGuid().ToString(); var didDocument = new DidDocument(didId); var data = new CreateBpnCredentialRequest("https://example.org/holder/BPNL12343546/did.json", Bpnl, null, null); + var detail = new CompanySsiDetail(CredentialId, _identity.Bpnl, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, CompanySsiDetailStatusId.ACTIVE, IssuerBpnl, _identity.IdentityId, DateTimeOffset.Now); + HttpRequestMessage? request = null; ConfigureHttpClientFactoryFixture(new HttpResponseMessage { @@ -683,6 +685,9 @@ public async Task CreateBpnCredential_ReturnsExpected() Content = new StringContent(JsonSerializer.Serialize(didDocument)) }, requestMessage => request = requestMessage); + A.CallTo(() => _companySsiDetailsRepository.CreateSsiDetails(_identity.Bpnl, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, CompanySsiDetailStatusId.ACTIVE, IssuerBpnl, _identity.IdentityId, A>._)) + .Invokes((string bpnl, VerifiedCredentialTypeId verifiedCredentialTypeId, CompanySsiDetailStatusId companySsiDetailStatusId, string issuerBpn, string userId, Action? setOptionalFields) => setOptionalFields?.Invoke(detail)); + // Act await _sut.CreateBpnCredential(data, CancellationToken.None); @@ -694,6 +699,7 @@ public async Task CreateBpnCredential_ReturnsExpected() A.CallTo(() => _documentRepository.AssignDocumentToCompanySsiDetails(A._, A._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _issuerRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + Assert.NotNull(detail.ExpiryDate); } [Theory] @@ -746,6 +752,8 @@ public async Task CreateMembershipCredential_ReturnsExpected() var didId = Guid.NewGuid().ToString(); var didDocument = new DidDocument(didId); var data = new CreateMembershipCredentialRequest("https://example.org/holder/BPNL12343546/did.json", Bpnl, "Test", null, null); + var detail = new CompanySsiDetail(CredentialId, _identity.Bpnl, VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE, CompanySsiDetailStatusId.ACTIVE, IssuerBpnl, _identity.IdentityId, DateTimeOffset.Now); + HttpRequestMessage? request = null; A.CallTo(() => _companySsiDetailsRepository.GetCertificateTypes(A._)) .Returns(Enum.GetValues().ToAsyncEnumerable()); @@ -755,6 +763,9 @@ public async Task CreateMembershipCredential_ReturnsExpected() Content = new StringContent(JsonSerializer.Serialize(didDocument)) }, requestMessage => request = requestMessage); + A.CallTo(() => _companySsiDetailsRepository.CreateSsiDetails(_identity.Bpnl, VerifiedCredentialTypeId.DISMANTLER_CERTIFICATE, CompanySsiDetailStatusId.ACTIVE, IssuerBpnl, _identity.IdentityId, A>._)) + .Invokes((string bpnl, VerifiedCredentialTypeId verifiedCredentialTypeId, CompanySsiDetailStatusId companySsiDetailStatusId, string issuerBpn, string userId, Action? setOptionalFields) => setOptionalFields?.Invoke(detail)); + // Act await _sut.CreateMembershipCredential(data, CancellationToken.None); @@ -766,6 +777,7 @@ public async Task CreateMembershipCredential_ReturnsExpected() A.CallTo(() => _documentRepository.AssignDocumentToCompanySsiDetails(A._, A._)) .MustHaveHappenedOnceExactly(); A.CallTo(() => _issuerRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + Assert.NotNull(detail.ExpiryDate); } #endregion