diff --git a/charts/dim/templates/deployment.yaml b/charts/dim/templates/deployment.yaml index 9289dac..899a123 100644 --- a/charts/dim/templates/deployment.yaml +++ b/charts/dim/templates/deployment.yaml @@ -81,6 +81,8 @@ spec: value: "{{ .Values.dim.swaggerEnabled }}" - name: "DIM__ROOTDIRECTORYID" value: "{{ .Values.dim.rootDirectoryId }}" + - name: "DIM__OPERATORID" + value: "{{ .Values.dim.operatorId }}" - name: "JWTBEAREROPTIONS__METADATAADDRESS" value: "{{ .Values.idp.address }}{{ .Values.idp.jwtBearerOptions.metadataPath }}" - name: "JWTBEAREROPTIONS__REQUIREHTTPSMETADATA" @@ -91,6 +93,19 @@ spec: value: "{{ .Values.idp.address }}{{ .Values.idp.jwtBearerOptions.tokenValidationParameters.validIssuerPath }}" - name: "JWTBEAREROPTIONS__REFRESHINTERVAL" value: "{{ .Values.idp.jwtBearerOptions.refreshInterval }}" + - name: "CF__CLIENTID" + value: "{{ .Values.processesworker.cf.clientId }}" + - name: "CF__CLIENTSECRET" + valueFrom: + secretKeyRef: + name: "{{ template "dim.secretName" . }}" + key: "client-secret-cf" + - name: "CF__TOKENADDRESS" + value: "{{ .Values.processesworker.cf.tokenAddress }}" + - name: "CF__BASEURL" + value: "{{ .Values.processesworker.cf.baseUrl }}" + - name: "CF__GRANTTYPE" + value: "{{ .Values.processesworker.cf.grantType }}" ports: - name: http containerPort: {{ .Values.portContainer }} diff --git a/charts/dim/values.yaml b/charts/dim/values.yaml index a9ef6bd..2610a01 100644 --- a/charts/dim/values.yaml +++ b/charts/dim/values.yaml @@ -42,6 +42,7 @@ dim: path: "/ready" swaggerEnabled: false rootDirectoryId: "00000000-0000-0000-0000-000000000000" + operatorId: "00000000-0000-0000-0000-000000000000" migrations: name: "migrations" diff --git a/consortia/environments/values-dev.yaml b/consortia/environments/values-dev.yaml index 771413c..3031b54 100644 --- a/consortia/environments/values-dev.yaml +++ b/consortia/environments/values-dev.yaml @@ -43,6 +43,7 @@ dim: imagePullPolicy: "Always" swaggerEnabled: true rootDirectoryId: "27fee02a-e265-4cfc-af70-4f217a33840b" + operatorId: "27fee02a-e265-4cfc-af70-4f217a33840b" migrations: image: diff --git a/consortia/environments/values-int.yaml b/consortia/environments/values-int.yaml index 2896a3c..4471535 100644 --- a/consortia/environments/values-int.yaml +++ b/consortia/environments/values-int.yaml @@ -40,6 +40,7 @@ ingress: dim: swaggerEnabled: true rootDirectoryId: "27fee02a-e265-4cfc-af70-4f217a33840b" + operatorId: "27fee02a-e265-4cfc-af70-4f217a33840b" migrations: logging: diff --git a/src/clients/Dim.Clients/Api/Dim/DimClient.cs b/src/clients/Dim.Clients/Api/Dim/DimClient.cs index 79bede7..8231000 100644 --- a/src/clients/Dim.Clients/Api/Dim/DimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/DimClient.cs @@ -155,4 +155,60 @@ await client.PatchAsJsonAsync($"{dimBaseUrl}/api/v2.0.0/companyIdentities/{compa return (false, message); }).ConfigureAwait(false); } + + public async Task GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken) + { + var client = await _basicAuthTokenService.GetBasicAuthorizedClient(dimAuth, cancellationToken).ConfigureAwait(false); + var result = await client.GetAsync($"{dimBaseUrl}/api/v2.0.0/companyIdentities/{companyId}/revocationLists", cancellationToken); + try + { + var response = await result.Content + .ReadFromJsonAsync(JsonSerializerExtensions.Options, cancellationToken) + .ConfigureAwait(false); + if (response == null) + { + throw new ServiceException("Response must not be null"); + } + + if (!response.Data.Any(x => x.RemainingSpace > 0)) + { + throw new ConflictException("There is no status list with remaining space, please create a new one."); + } + + return response.Data.First(x => x.RemainingSpace > 0).StatusListCredential; + } + catch (JsonException je) + { + throw new ServiceException(je.Message); + } + } + + public async Task CreateStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken) + { + var client = await _basicAuthTokenService.GetBasicAuthorizedClient(dimAuth, cancellationToken).ConfigureAwait(false); + var data = new CreateStatusListRequest(new CreateStatusListPaypload(new CreateStatusList("StatusList2021", DateTimeOffset.UtcNow.ToString("yyyyMMdd"), "New revocation list", 2097152))); + var result = await client.PostAsJsonAsync($"{dimBaseUrl}/api/v2.0.0/companyIdentities/{companyId}/revocationLists", data, JsonSerializerExtensions.Options, cancellationToken) + .CatchingIntoServiceExceptionFor("assign-application", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, + async m => + { + var message = await m.Content.ReadAsStringAsync().ConfigureAwait(false); + return (false, message); + }).ConfigureAwait(false); + try + { + var response = await result.Content + .ReadFromJsonAsync(JsonSerializerExtensions.Options, cancellationToken) + .ConfigureAwait(false); + if (response == null) + { + throw new ServiceException("Response must not be null"); + } + + return response.RevocationVc.Id; + } + catch (JsonException je) + { + throw new ServiceException(je.Message); + } + } } diff --git a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs index 5727cd6..850430b 100644 --- a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs @@ -30,4 +30,6 @@ public interface IDimClient Task GetApplication(BasicAuthSettings dimAuth, string dimBaseUrl, string applicationId, CancellationToken cancellationToken); Task AssignApplicationToCompany(BasicAuthSettings dimAuth, string dimBaseUrl, string applicationKey, Guid companyId, CancellationToken cancellationToken); + Task GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken); + Task CreateStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken); } diff --git a/src/clients/Dim.Clients/Api/Dim/StatusListResponse.cs b/src/clients/Dim.Clients/Api/Dim/StatusListResponse.cs new file mode 100644 index 0000000..cc76aec --- /dev/null +++ b/src/clients/Dim.Clients/Api/Dim/StatusListResponse.cs @@ -0,0 +1,60 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Dim.Clients.Api.Dim; + +public record CreateStatusListRequest( + [property: JsonPropertyName("payload")] CreateStatusListPaypload Payload +); + +public record CreateStatusListPaypload( + [property: JsonPropertyName("create")] CreateStatusList Create +); + +public record CreateStatusList( + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("length")] int Length +); + +public record CreateStatusListResponse( + [property: JsonPropertyName("id")] Guid Id, + [property: JsonPropertyName("revocationVc")] RevocationVc RevocationVc +); + +public record RevocationVc( + [property: JsonPropertyName("id")] string Id +); + +public record StatusListListResponse( + [property: JsonPropertyName("count")] int Count, + [property: JsonPropertyName("data")] IEnumerable Data +); + +public record StatusListResponse( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("statusListCredential")] string StatusListCredential, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("length")] int Length, + [property: JsonPropertyName("remainingSpace")] int RemainingSpace +); diff --git a/src/clients/Dim.Clients/Dim.Clients.csproj b/src/clients/Dim.Clients/Dim.Clients.csproj index 76626ce..1145386 100644 --- a/src/clients/Dim.Clients/Dim.Clients.csproj +++ b/src/clients/Dim.Clients/Dim.Clients.csproj @@ -30,12 +30,11 @@ - - - + + diff --git a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs index 2cf69bc..cb7fcd4 100644 --- a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs @@ -33,5 +33,6 @@ public interface ITenantRepository Task GetDimInstanceId(Guid tenantId); Task<(string bpn, string? DownloadUrl, string? Did, Guid? DimInstanceId)> GetCallbackData(Guid tenantId); Task<(Guid? DimInstanceId, string HostingUrl, bool IsIssuer)> GetDimInstanceIdAndHostingUrl(Guid tenantId); - Task<(string? ApplicationId, Guid? CompanyId, Guid? DimInstanceId)> GetApplicationAndCompanyId(Guid tenantId); + Task<(string? ApplicationId, Guid? CompanyId, Guid? DimInstanceId, bool IsIssuer)> GetApplicationAndCompanyId(Guid tenantId); + Task<(bool Exists, Guid? CompanyId, Guid? InstanceId)> GetCompanyAndInstanceIdForBpn(string bpn); } diff --git a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs index b6107df..769ffc3 100644 --- a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs @@ -91,12 +91,18 @@ public void AttachAndModifyTenant(Guid tenantId, Action? initialize, Act .Select(x => new ValueTuple(x.DimInstanceId, x.DidDocumentLocation, x.IsIssuer)) .SingleOrDefaultAsync(); - public Task<(string? ApplicationId, Guid? CompanyId, Guid? DimInstanceId)> GetApplicationAndCompanyId(Guid tenantId) => + public Task<(string? ApplicationId, Guid? CompanyId, Guid? DimInstanceId, bool IsIssuer)> GetApplicationAndCompanyId(Guid tenantId) => _context.Tenants .Where(x => x.Id == tenantId) - .Select(x => new ValueTuple( + .Select(x => new ValueTuple( x.ApplicationId, x.CompanyId, - x.DimInstanceId)) + x.DimInstanceId, + x.IsIssuer)) + .SingleOrDefaultAsync(); + + public Task<(bool Exists, Guid? CompanyId, Guid? InstanceId)> GetCompanyAndInstanceIdForBpn(string bpn) => + _context.Tenants.Where(x => x.Bpn == bpn) + .Select(x => new ValueTuple(true, x.CompanyId, x.DimInstanceId)) .SingleOrDefaultAsync(); } diff --git a/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs b/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs index b5c02cf..2c7bbf2 100644 --- a/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs +++ b/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs @@ -38,5 +38,6 @@ public enum ProcessStepTypeId CREATE_APPLICATION = 14, CREATE_COMPANY_IDENTITY = 15, ASSIGN_COMPANY_APPLICATION = 16, - SEND_CALLBACK = 17 + CREATE_STATUS_LIST = 17, + SEND_CALLBACK = 18 } diff --git a/src/database/Dim.Migrations/Dim.Migrations.csproj b/src/database/Dim.Migrations/Dim.Migrations.csproj index 1cf70a3..dcb2fc9 100644 --- a/src/database/Dim.Migrations/Dim.Migrations.csproj +++ b/src/database/Dim.Migrations/Dim.Migrations.csproj @@ -60,4 +60,8 @@ + + + + diff --git a/src/database/Dim.Migrations/Migrations/20240307101150_initial.Designer.cs b/src/database/Dim.Migrations/Migrations/20240403114716_Initial.Designer.cs similarity index 98% rename from src/database/Dim.Migrations/Migrations/20240307101150_initial.Designer.cs rename to src/database/Dim.Migrations/Migrations/20240403114716_Initial.Designer.cs index fb5fd8d..a13e9e7 100644 --- a/src/database/Dim.Migrations/Migrations/20240307101150_initial.Designer.cs +++ b/src/database/Dim.Migrations/Migrations/20240403114716_Initial.Designer.cs @@ -31,8 +31,8 @@ namespace Dim.Migrations.Migrations { [DbContext(typeof(DimDbContext))] - [Migration("20240307101150_initial")] - partial class initial + [Migration("20240403114716_Initial")] + partial class Initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -267,6 +267,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) new { Id = 17, + Label = "CREATE_STATUS_LIST" + }, + new + { + Id = 18, Label = "SEND_CALLBACK" }); }); diff --git a/src/database/Dim.Migrations/Migrations/20240307101150_initial.cs b/src/database/Dim.Migrations/Migrations/20240403114716_Initial.cs similarity index 98% rename from src/database/Dim.Migrations/Migrations/20240307101150_initial.cs rename to src/database/Dim.Migrations/Migrations/20240403114716_Initial.cs index 8210535..c650a97 100644 --- a/src/database/Dim.Migrations/Migrations/20240307101150_initial.cs +++ b/src/database/Dim.Migrations/Migrations/20240403114716_Initial.cs @@ -27,7 +27,7 @@ namespace Dim.Migrations.Migrations { /// - public partial class initial : Migration + public partial class Initial : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -202,7 +202,8 @@ protected override void Up(MigrationBuilder migrationBuilder) { 14, "CREATE_APPLICATION" }, { 15, "CREATE_COMPANY_IDENTITY" }, { 16, "ASSIGN_COMPANY_APPLICATION" }, - { 17, "SEND_CALLBACK" } + { 17, "CREATE_STATUS_LIST" }, + { 18, "SEND_CALLBACK" } }); migrationBuilder.InsertData( diff --git a/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs b/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs index fb3151e..0f77b75 100644 --- a/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs +++ b/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs @@ -18,14 +18,10 @@ ********************************************************************************/ // -using System; + using Dim.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable namespace Dim.Migrations.Migrations { @@ -264,6 +260,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = 17, + Label = "CREATE_STATUS_LIST" + }, + new + { + Id = 18, Label = "SEND_CALLBACK" }); }); diff --git a/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs b/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs index 8d22159..ceab18a 100644 --- a/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs +++ b/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs @@ -48,6 +48,7 @@ public class DimProcessTypeExecutor : IProcessTypeExecutor ProcessStepTypeId.GET_DIM_DETAILS, ProcessStepTypeId.CREATE_APPLICATION, ProcessStepTypeId.CREATE_COMPANY_IDENTITY, + ProcessStepTypeId.CREATE_STATUS_LIST, ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION, ProcessStepTypeId.SEND_CALLBACK); @@ -126,9 +127,11 @@ public DimProcessTypeExecutor( .ConfigureAwait(false), ProcessStepTypeId.CREATE_COMPANY_IDENTITY => await _dimProcessHandler.CreateCompanyIdentity(_tenantId, _tenantName, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION => await _dimProcessHandler.AssignCompanyApplication(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.CREATE_STATUS_LIST => await _dimProcessHandler.CreateStatusList(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.SEND_CALLBACK => await _dimProcessHandler.SendCallback(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION => await _dimProcessHandler.AssignCompanyApplication(_tenantId, cancellationToken) + .ConfigureAwait(false), + ProcessStepTypeId.SEND_CALLBACK => await _dimProcessHandler.SendCallback(_tenantId, cancellationToken) .ConfigureAwait(false), _ => (null, ProcessStepStatusId.TODO, false, null) }; diff --git a/src/processes/DimProcess.Library/DimProcessHandler.cs b/src/processes/DimProcess.Library/DimProcessHandler.cs index 5e00ac6..a78460e 100644 --- a/src/processes/DimProcess.Library/DimProcessHandler.cs +++ b/src/processes/DimProcess.Library/DimProcessHandler.cs @@ -459,9 +459,9 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe null); } - public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AssignCompanyApplication(Guid tenantId, string tenantName, CancellationToken cancellationToken) + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AssignCompanyApplication(Guid tenantId, CancellationToken cancellationToken) { - var (applicationId, companyId, dimInstanceId) = await _dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); + var (applicationId, companyId, dimInstanceId, isIssuer) = await _dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); if (applicationId == null) { throw new ConflictException("ApplicationId must always be set here"); @@ -496,6 +496,36 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe { tenant.ApplicationKey = applicationKey; }); + return new ValueTuple?, ProcessStepStatusId, bool, string?>( + Enumerable.Repeat(isIssuer ? ProcessStepTypeId.CREATE_STATUS_LIST : ProcessStepTypeId.SEND_CALLBACK, 1), + ProcessStepStatusId.DONE, + false, + null); + } + + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateStatusList(Guid tenantId, CancellationToken cancellationToken) + { + var (_, companyId, dimInstanceId, _) = await _dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); + if (companyId == null) + { + throw new ConflictException("CompanyId must always be set here"); + } + + if (dimInstanceId == null) + { + throw new ConflictException("DimInstanceId must not be null."); + } + + var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var dimAuth = new BasicAuthSettings + { + TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token", + ClientId = dimDetails.Credentials.Uaa.ClientId, + ClientSecret = dimDetails.Credentials.Uaa.ClientSecret + }; + var dimBaseUrl = dimDetails.Credentials.Url; + await _dimClient.CreateStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); + return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.SEND_CALLBACK, 1), ProcessStepStatusId.DONE, @@ -503,7 +533,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe null); } - public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, string tenantName, CancellationToken cancellationToken) + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, CancellationToken cancellationToken) { var (bpn, downloadUrl, did, dimInstanceId) = await _dimRepositories.GetInstance().GetCallbackData(tenantId).ConfigureAwait(false); if (downloadUrl == null) diff --git a/src/processes/DimProcess.Library/IDimProcessHandler.cs b/src/processes/DimProcess.Library/IDimProcessHandler.cs index 1685812..0ba310c 100644 --- a/src/processes/DimProcess.Library/IDimProcessHandler.cs +++ b/src/processes/DimProcess.Library/IDimProcessHandler.cs @@ -38,6 +38,7 @@ public interface IDimProcessHandler Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateApplication(string tenantName, Guid tenantId, CancellationToken cancellationToken); Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> GetDimDetails(string tenantName, Guid tenantId, CancellationToken cancellationToken); Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateCompanyIdentity(Guid tenantId, string tenantName, CancellationToken cancellationToken); - Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AssignCompanyApplication(Guid tenantId, string tenantName, CancellationToken cancellationToken); - Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, string tenantName, CancellationToken cancellationToken); + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateStatusList(Guid tenantId, CancellationToken cancellationToken); + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AssignCompanyApplication(Guid tenantId, CancellationToken cancellationToken); + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, CancellationToken cancellationToken); } diff --git a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs index e134312..fe48706 100644 --- a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs +++ b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs @@ -17,23 +17,30 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Dim.Clients.Api.Cf; +using Dim.Clients.Api.Dim; +using Dim.Clients.Token; using Dim.DbAccess; using Dim.DbAccess.Repositories; using Dim.Entities.Enums; +using Dim.Web.ErrorHandling; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; -using System.Text.RegularExpressions; namespace Dim.Web.BusinessLogic; public class DimBusinessLogic : IDimBusinessLogic { private readonly IDimRepositories _dimRepositories; + private readonly ICfClient _cfClient; + private readonly IDimClient _dimClient; private readonly DimSettings _settings; - public DimBusinessLogic(IDimRepositories dimRepositories, IOptions options) + public DimBusinessLogic(IDimRepositories dimRepositories, ICfClient cfClient, IDimClient dimClient, IOptions options) { _dimRepositories = dimRepositories; + _cfClient = cfClient; + _dimClient = dimClient; _settings = options.Value; } @@ -47,4 +54,62 @@ public async Task StartSetupDim(string companyName, string bpn, string didDocume await _dimRepositories.SaveAsync().ConfigureAwait(false); } + + public async Task GetStatusList(string bpn, CancellationToken cancellationToken) + { + var (exists, companyId, instanceId) = await _dimRepositories.GetInstance().GetCompanyAndInstanceIdForBpn(bpn).ConfigureAwait(false); + if (!exists) + { + throw NotFoundException.Create(DimErrors.NO_COMPANY_FOR_BPN, new ErrorParameter[] { new("bpn", bpn) }); + } + + if (companyId is null) + { + throw ConflictException.Create(DimErrors.NO_COMPANY_ID_SET); + } + + if (instanceId is null) + { + throw ConflictException.Create(DimErrors.NO_INSTANCE_ID_SET); + } + + var dimDetails = await _cfClient.GetServiceBindingDetails(instanceId.Value, cancellationToken).ConfigureAwait(false); + var dimAuth = new BasicAuthSettings + { + TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token", + ClientId = dimDetails.Credentials.Uaa.ClientId, + ClientSecret = dimDetails.Credentials.Uaa.ClientSecret + }; + var dimBaseUrl = dimDetails.Credentials.Url; + return await _dimClient.GetStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); + } + + public async Task CreateStatusList(string bpn, CancellationToken cancellationToken) + { + var (exists, companyId, instanceId) = await _dimRepositories.GetInstance().GetCompanyAndInstanceIdForBpn(bpn).ConfigureAwait(false); + if (!exists) + { + throw NotFoundException.Create(DimErrors.NO_COMPANY_FOR_BPN, new ErrorParameter[] { new("bpn", bpn) }); + } + + if (companyId is null) + { + throw ConflictException.Create(DimErrors.NO_COMPANY_ID_SET); + } + + if (instanceId is null) + { + throw ConflictException.Create(DimErrors.NO_INSTANCE_ID_SET); + } + + var dimDetails = await _cfClient.GetServiceBindingDetails(instanceId.Value, cancellationToken).ConfigureAwait(false); + var dimAuth = new BasicAuthSettings + { + TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token", + ClientId = dimDetails.Credentials.Uaa.ClientId, + ClientSecret = dimDetails.Credentials.Uaa.ClientSecret + }; + var dimBaseUrl = dimDetails.Credentials.Url; + return await _dimClient.CreateStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); + } } diff --git a/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs b/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs index 27b1e8a..757dce5 100644 --- a/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs +++ b/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs @@ -24,4 +24,6 @@ namespace Dim.Web.BusinessLogic; public interface IDimBusinessLogic : ITransient { Task StartSetupDim(string companyName, string bpn, string didDocumentLocation, bool isIssuer); + Task GetStatusList(string bpn, CancellationToken cancellationToken); + Task CreateStatusList(string bpn, CancellationToken cancellationToken); } diff --git a/src/web/Dim.Web/Controllers/DimController.cs b/src/web/Dim.Web/Controllers/DimController.cs index 36374d0..f90b739 100644 --- a/src/web/Dim.Web/Controllers/DimController.cs +++ b/src/web/Dim.Web/Controllers/DimController.cs @@ -19,6 +19,7 @@ using Dim.Web.BusinessLogic; using Dim.Web.Extensions; +using Dim.Web.Models; using Microsoft.AspNetCore.Mvc; namespace Dim.Web.Controllers; @@ -50,6 +51,20 @@ public static RouteGroupBuilder MapDimApi(this RouteGroupBuilder group) .RequireAuthorization(r => r.RequireRole("setup_wallet")) .Produces(StatusCodes.Status201Created); + policyHub.MapGet("status-list", ([FromQuery] string bpn, CancellationToken cancellationToken, [FromServices] IDimBusinessLogic dimBusinessLogic) => dimBusinessLogic.GetStatusList(bpn, cancellationToken)) + .WithSwaggerDescription("Gets the status list for the given company", + "Example: GET: api/dim/status-list/{bpn}", + "id of the dim company") + .RequireAuthorization(r => r.RequireRole("view_status_list")) + .Produces(StatusCodes.Status200OK, responseType: typeof(string), contentType: Constants.JsonContentType); + + policyHub.MapPost("status-list", ([FromQuery] string bpn, CancellationToken cancellationToken, [FromServices] IDimBusinessLogic dimBusinessLogic) => dimBusinessLogic.CreateStatusList(bpn, cancellationToken)) + .WithSwaggerDescription("Creates a status list for the given company", + "Example: Post: api/dim/status-list/{bpn}", + "bpn of the company") + .RequireAuthorization(r => r.RequireRole("create_status_list")) + .Produces(StatusCodes.Status200OK, responseType: typeof(string), contentType: Constants.JsonContentType); + return group; } } diff --git a/src/web/Dim.Web/Dim.Web.csproj b/src/web/Dim.Web/Dim.Web.csproj index f147a9d..d777a94 100644 --- a/src/web/Dim.Web/Dim.Web.csproj +++ b/src/web/Dim.Web/Dim.Web.csproj @@ -20,6 +20,7 @@ + diff --git a/src/web/Dim.Web/ErrorHandling/DimErrorMessageContainer.cs b/src/web/Dim.Web/ErrorHandling/DimErrorMessageContainer.cs new file mode 100644 index 0000000..ac1a7df --- /dev/null +++ b/src/web/Dim.Web/ErrorHandling/DimErrorMessageContainer.cs @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Dim.Web.ErrorHandling; + +[ExcludeFromCodeCoverage] +public class DimErrorMessageContainer : IErrorMessageContainer +{ + private static readonly IReadOnlyDictionary _messageContainer = new Dictionary { + { DimErrors.NO_COMPANY_FOR_BPN, "No Tenant found for Bpn {bpn}" }, + { DimErrors.NO_COMPANY_ID_SET, "No Company Id set" }, + { DimErrors.NO_INSTANCE_ID_SET, "No Instnace Id set" }, + }.ToImmutableDictionary(x => (int)x.Key, x => x.Value); + + public Type Type { get => typeof(DimErrors); } + public IReadOnlyDictionary MessageContainer { get => _messageContainer; } +} + +public enum DimErrors +{ + NO_COMPANY_FOR_BPN, + NO_COMPANY_ID_SET, + NO_INSTANCE_ID_SET +} diff --git a/src/web/Dim.Web/Program.cs b/src/web/Dim.Web/Program.cs index 846c98e..ed84b62 100644 --- a/src/web/Dim.Web/Program.cs +++ b/src/web/Dim.Web/Program.cs @@ -17,6 +17,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Dim.Clients.Api.Cf.DependencyInjection; +using Dim.Clients.Api.Dim.DependencyInjection; +using Dim.Clients.Token; using Dim.DbAccess.DependencyInjection; using Dim.Web.Authentication; using Dim.Web.Controllers; @@ -32,7 +35,10 @@ builder => { builder.Services + .AddTransient() .AddTransient() + .AddDimClient() + .AddCfClient(builder.Configuration.GetSection("Cf")) .AddDim(builder.Configuration.GetSection("Dim")) .AddEndpointsApiExplorer() .AddDatabase(builder.Configuration) diff --git a/src/web/Dim.Web/appsettings.json b/src/web/Dim.Web/appsettings.json index 0431a71..ec589e9 100644 --- a/src/web/Dim.Web/appsettings.json +++ b/src/web/Dim.Web/appsettings.json @@ -10,7 +10,15 @@ "DimDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=placeholder;Ssl Mode=Disable;" }, "Dim": { - "RootDirectoryId": "" + "RootDirectoryId": "", + "OperatorId": "" + }, + "Cf": { + "ClientId": "", + "ClientSecret": "", + "TokenAddress": "", + "BaseUrl": "", + "GrantType": "" }, "SwaggerEnabled": false, "JwtBearerOptions": { diff --git a/tests/processes/DimProcess.Executor.Tests/DimProcessTypeExecutorTests.cs b/tests/processes/DimProcess.Executor.Tests/DimProcessTypeExecutorTests.cs index 5726a01..27252e5 100644 --- a/tests/processes/DimProcess.Executor.Tests/DimProcessTypeExecutorTests.cs +++ b/tests/processes/DimProcess.Executor.Tests/DimProcessTypeExecutorTests.cs @@ -66,7 +66,7 @@ public void IsExecutableStepTypeId_WithValid_ReturnsExpected() public void GetExecutableStepTypeIds_ReturnsExpected() { // Assert - _sut.GetExecutableStepTypeIds().Should().HaveCount(17).And.Satisfy( + _sut.GetExecutableStepTypeIds().Should().HaveCount(18).And.Satisfy( x => x == ProcessStepTypeId.CREATE_SUBACCOUNT, x => x == ProcessStepTypeId.CREATE_SERVICEMANAGER_BINDINGS, x => x == ProcessStepTypeId.ASSIGN_ENTITLEMENTS, @@ -82,6 +82,7 @@ public void GetExecutableStepTypeIds_ReturnsExpected() x => x == ProcessStepTypeId.GET_DIM_DETAILS, x => x == ProcessStepTypeId.CREATE_APPLICATION, x => x == ProcessStepTypeId.CREATE_COMPANY_IDENTITY, + x => x == ProcessStepTypeId.CREATE_STATUS_LIST, x => x == ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION, x => x == ProcessStepTypeId.SEND_CALLBACK); } @@ -161,6 +162,7 @@ public async Task ExecuteProcessStep_WithoutRegistrationId_ThrowsUnexpectedCondi [InlineData(ProcessStepTypeId.GET_DIM_DETAILS)] [InlineData(ProcessStepTypeId.CREATE_APPLICATION)] [InlineData(ProcessStepTypeId.CREATE_COMPANY_IDENTITY)] + [InlineData(ProcessStepTypeId.CREATE_STATUS_LIST)] [InlineData(ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION)] [InlineData(ProcessStepTypeId.SEND_CALLBACK)] public async Task ExecuteProcessStep_WithValidData_CallsExpected(ProcessStepTypeId processStepTypeId) @@ -311,10 +313,13 @@ private void SetupMock(Guid tenantId, string tenantName) A.CallTo(() => _dimProcessHandler.CreateCompanyIdentity(tenantId, tenantName, A._)) .Returns(new ValueTuple?, ProcessStepStatusId, bool, string?>(null, ProcessStepStatusId.DONE, false, null)); - A.CallTo(() => _dimProcessHandler.AssignCompanyApplication(tenantId, tenantName, A._)) + A.CallTo(() => _dimProcessHandler.CreateStatusList(tenantId, A._)) .Returns(new ValueTuple?, ProcessStepStatusId, bool, string?>(null, ProcessStepStatusId.DONE, false, null)); - A.CallTo(() => _dimProcessHandler.SendCallback(tenantId, tenantName, A._)) + A.CallTo(() => _dimProcessHandler.AssignCompanyApplication(tenantId, A._)) + .Returns(new ValueTuple?, ProcessStepStatusId, bool, string?>(null, ProcessStepStatusId.DONE, false, null)); + + A.CallTo(() => _dimProcessHandler.SendCallback(tenantId, A._)) .Returns(new ValueTuple?, ProcessStepStatusId, bool, string?>(null, ProcessStepStatusId.DONE, false, null)); } diff --git a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs index 03074d8..703c219 100644 --- a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs +++ b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs @@ -760,16 +760,18 @@ public async Task CreateCompanyIdentity_WithNotExisting_ReturnsExpected() ex.Message.Should().Be("DimInstanceId must not be null."); } - [Fact] - public async Task CreateCompanyIdentity_WithValidData_ReturnsExpected() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task CreateCompanyIdentity_WithValidData_ReturnsExpected(bool isIssuer) { // Arrange var serviceCrenentialBinding = _fixture.Create(); var identityResponse = _fixture.Create(); var dimInstanceId = Guid.NewGuid(); - var tenant = new Tenant(_tenantId, "test", "Corp", "https://example.org/did", false, _processId, _operatorId); + var tenant = new Tenant(_tenantId, "test", "Corp", "https://example.org/did", isIssuer, _processId, _operatorId); A.CallTo(() => _tenantRepositories.GetDimInstanceIdAndHostingUrl(_tenantId)) - .Returns((dimInstanceId, "https://example.org/hosting", false)); + .Returns((dimInstanceId, "https://example.org/hosting", tenant.IsIssuer)); A.CallTo(() => _cfClient.GetServiceBindingDetails(dimInstanceId, A._)) .Returns(serviceCrenentialBinding); A.CallTo(() => _tenantRepositories.AttachAndModifyTenant(_tenantId, A>._, A>._)) @@ -778,14 +780,14 @@ public async Task CreateCompanyIdentity_WithValidData_ReturnsExpected() initialize?.Invoke(tenant); modify(tenant); }); - A.CallTo(() => _dimClient.CreateCompanyIdentity(A._, "https://example.org/hosting", A._, _tenantName, false, A._)) + A.CallTo(() => _dimClient.CreateCompanyIdentity(A._, "https://example.org/hosting", A._, _tenantName, tenant.IsIssuer, A._)) .Returns(identityResponse); // Act var result = await _sut.CreateCompanyIdentity(_tenantId, _tenantName, CancellationToken.None); // Assert - A.CallTo(() => _dimClient.CreateCompanyIdentity(A._, A._, A._, _tenantName, false, A._)) + A.CallTo(() => _dimClient.CreateCompanyIdentity(A._, A._, A._, _tenantName, tenant.IsIssuer, A._)) .MustHaveHappenedOnceExactly(); result.modified.Should().BeFalse(); @@ -806,8 +808,8 @@ public async Task AssignCompanyApplication_WithNotExisting_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) - .Returns(((string?)null, (Guid?)null, (Guid?)null)); - async Task Act() => await _sut.AssignCompanyApplication(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + .Returns(((string?)null, (Guid?)null, (Guid?)null, false)); + async Task Act() => await _sut.AssignCompanyApplication(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -821,8 +823,8 @@ public async Task AssignCompanyApplication_WithNoCompanyId_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) - .Returns((Guid.NewGuid().ToString(), (Guid?)null, (Guid?)null)); - async Task Act() => await _sut.AssignCompanyApplication(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + .Returns((Guid.NewGuid().ToString(), (Guid?)null, (Guid?)null, false)); + async Task Act() => await _sut.AssignCompanyApplication(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -836,8 +838,8 @@ public async Task AssignCompanyApplication_WithNoDimInstanceId_ReturnsExpected() { // Arrange A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) - .Returns((Guid.NewGuid().ToString(), Guid.NewGuid(), null)); - async Task Act() => await _sut.AssignCompanyApplication(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + .Returns((Guid.NewGuid().ToString(), Guid.NewGuid(), null, false)); + async Task Act() => await _sut.AssignCompanyApplication(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -846,8 +848,10 @@ public async Task AssignCompanyApplication_WithNoDimInstanceId_ReturnsExpected() ex.Message.Should().Be("DimInstanceId must not be null."); } - [Fact] - public async Task AssignCompanyApplication_WithValidData_ReturnsExpected() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task AssignCompanyApplication_WithValidData_ReturnsExpected(bool isIssuer) { // Arrange var serviceCrenentialBinding = _fixture.Create(); @@ -858,7 +862,7 @@ public async Task AssignCompanyApplication_WithValidData_ReturnsExpected() var dimInstanceId = Guid.NewGuid(); var tenant = new Tenant(_tenantId, "test", "Corp", "https://example.org/did", false, _processId, _operatorId); A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) - .Returns((applicationId, companyId, dimInstanceId)); + .Returns((applicationId, companyId, dimInstanceId, isIssuer)); A.CallTo(() => _cfClient.GetServiceBindingDetails(dimInstanceId, A._)) .Returns(serviceCrenentialBinding); A.CallTo(() => _dimClient.GetApplication(A._, A._, applicationId, A._)) @@ -873,7 +877,7 @@ public async Task AssignCompanyApplication_WithValidData_ReturnsExpected() .Returns(identityResponse); // Act - var result = await _sut.AssignCompanyApplication(_tenantId, _tenantName, CancellationToken.None); + var result = await _sut.AssignCompanyApplication(_tenantId, CancellationToken.None); // Assert A.CallTo(() => _dimClient.AssignApplicationToCompany(A._, A._, applicationKey, companyId, A._)) @@ -882,12 +886,72 @@ public async Task AssignCompanyApplication_WithValidData_ReturnsExpected() result.modified.Should().BeFalse(); result.processMessage.Should().BeNull(); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); - result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.SEND_CALLBACK); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(isIssuer ? ProcessStepTypeId.CREATE_STATUS_LIST : ProcessStepTypeId.SEND_CALLBACK); tenant.ApplicationKey.Should().Be(applicationKey); } #endregion + #region CreateStatusList + + [Fact] + public async Task CreateStatusList_WithNoCompanyId_ReturnsExpected() + { + // Arrange + A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) + .Returns((Guid.NewGuid().ToString(), (Guid?)null, (Guid?)null, false)); + async Task Act() => await _sut.CreateStatusList(_tenantId, CancellationToken.None).ConfigureAwait(false); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("CompanyId must always be set here"); + } + + [Fact] + public async Task CreateStatusList_WithNoDimInstanceId_ReturnsExpected() + { + // Arrange + A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) + .Returns((Guid.NewGuid().ToString(), Guid.NewGuid(), null, false)); + async Task Act() => await _sut.CreateStatusList(_tenantId, CancellationToken.None).ConfigureAwait(false); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("DimInstanceId must not be null."); + } + + [Fact] + public async Task CreateStatusList_WithValidData_ReturnsExpected() + { + // Arrange + var serviceCrenentialBinding = _fixture.Create(); + var applicationId = Guid.NewGuid().ToString(); + var companyId = Guid.NewGuid(); + var dimInstanceId = Guid.NewGuid(); + A.CallTo(() => _tenantRepositories.GetApplicationAndCompanyId(_tenantId)) + .Returns((applicationId, companyId, dimInstanceId, false)); + A.CallTo(() => _cfClient.GetServiceBindingDetails(dimInstanceId, A._)) + .Returns(serviceCrenentialBinding); + + // Act + var result = await _sut.CreateStatusList(_tenantId, CancellationToken.None); + + // Assert + A.CallTo(() => _dimClient.CreateStatusList(A._, A._, companyId, A._)) + .MustHaveHappenedOnceExactly(); + + result.modified.Should().BeFalse(); + result.processMessage.Should().BeNull(); + result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.SEND_CALLBACK); + } + + #endregion + #region SendCallback [Fact] @@ -896,7 +960,7 @@ public async Task SendCallback_WithNotExisting_ReturnsExpected() // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) .Returns(("bpn123", (string?)null, (string?)null, (Guid?)null)); - async Task Act() => await _sut.SendCallback(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -911,7 +975,7 @@ public async Task SendCallback_WithNoCompanyId_ReturnsExpected() // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) .Returns(("bpn123", "https://example.org/did", (string?)null, (Guid?)null)); - async Task Act() => await _sut.SendCallback(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -926,7 +990,7 @@ public async Task SendCallback_WithNoDimInstanceId_ReturnsExpected() // Arrange A.CallTo(() => _tenantRepositories.GetCallbackData(_tenantId)) .Returns(("bpn123", "https://example.org/did", Guid.NewGuid().ToString(), (Guid?)null)); - async Task Act() => await _sut.SendCallback(_tenantId, _tenantName, CancellationToken.None).ConfigureAwait(false); + async Task Act() => await _sut.SendCallback(_tenantId, CancellationToken.None).ConfigureAwait(false); // Act var ex = await Assert.ThrowsAsync(Act); @@ -960,7 +1024,7 @@ public async Task SendCallback_WithValidData_ReturnsExpected() .Returns(identityResponse); // Act - var result = await _sut.SendCallback(_tenantId, _tenantName, CancellationToken.None); + var result = await _sut.SendCallback(_tenantId, CancellationToken.None); // Assert A.CallTo(() => _callbackService.SendCallback("bpn123", A._, A._, did, A._)) diff --git a/tests/processes/Processes.Worker.Library.Tests/ProcessExecutorTests.cs b/tests/processes/Processes.Worker.Library.Tests/ProcessExecutorTests.cs index 047eafe..3d7f411 100644 --- a/tests/processes/Processes.Worker.Library.Tests/ProcessExecutorTests.cs +++ b/tests/processes/Processes.Worker.Library.Tests/ProcessExecutorTests.cs @@ -873,8 +873,5 @@ public class TestException : Exception public TestException() { } public TestException(string message) : base(message) { } public TestException(string message, Exception inner) : base(message, inner) { } - protected TestException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } }