From 1365c5fbbbb4eea5d46b55644a7658d5d3fa67c3 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Thu, 1 Aug 2024 14:26:16 +0200 Subject: [PATCH 01/26] feat: Created the base structure for the renewal credential job --- .../RenewalServiceExtensions.cs | 44 ++++++++++++ .../Program.cs | 69 +++++++++++++++++++ .../Properties/launchSettings.json | 11 +++ .../Services/RenewalService.cs | 49 +++++++++++++ .../SsiCredentialIssuer.Renewal.App.csproj | 60 ++++++++++++++++ .../appsettings.json | 39 +++++++++++ 6 files changed, 272 insertions(+) create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/appsettings.json diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs new file mode 100644 index 00000000..a96d9553 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; + +/// +/// Extension method to register the renewal service and dependent services +/// +public static class RenewalServiceExtensions +{ + /// + /// Adds the renewal service + /// + /// the services + /// the configuration section to setup the settings + /// the enriched service collection + public static IServiceCollection AddRenewalService(this IServiceCollection services, IConfigurationSection section) + { + services + .AddTransient() + .AddTransient(); + return services; + } +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs new file mode 100644 index 00000000..b0b2b7b3 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs @@ -0,0 +1,69 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; +using Serilog; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; + +LoggingExtensions.EnsureInitialized(); +Log.Information("Building worker"); +try +{ + var host = Host + .CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services + //.AddTransient() + .AddProcessIdentity(hostContext.Configuration.GetSection("ProcessIdentity")) + .AddRenewalService(hostContext.Configuration.GetSection("Renewal")) + .AddIssuerRepositories(hostContext.Configuration); + }) + .AddLogging() + .Build(); + Log.Information("Building worker completed"); + + using var tokenSource = new CancellationTokenSource(); + Console.CancelKeyPress += (s, e) => + { + Log.Information("Canceling..."); + tokenSource.Cancel(); + e.Cancel = true; + }; + + Log.Information("Start processing"); + var workerInstance = host.Services.GetRequiredService(); + await workerInstance.ExecuteAsync(tokenSource.Token).ConfigureAwait(ConfigureAwaitOptions.None); + Log.Information("Execution finished shutting down"); +} +catch (Exception ex) when (!ex.GetType().Name.Equals("StopTheHostException", StringComparison.Ordinal)) +{ + Log.Fatal(ex, "Unhandled exception"); +} +finally +{ + Log.Information("Server Shutting down"); + await Log.CloseAndFlushAsync().ConfigureAwait(false); +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json b/src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json new file mode 100644 index 00000000..57157e42 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "SsiCredentialIssuer.Renewal.App": { + "commandName": "Project", + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs new file mode 100644 index 00000000..1a1c4b62 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs @@ -0,0 +1,49 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System.Text.Json; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; + +/// +/// Service to re-issue credentials that will expire in the day after. +/// +public class RenewalService +{ + private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly ILogger _logger; + + public RenewalService(IServiceScopeFactory serviceScopeFactory, + ILogger logger) + { + _serviceScopeFactory = serviceScopeFactory; + _logger = logger; + } + + public async Task ExecuteAsync(CancellationToken stoppingToken) + { + if (!stoppingToken.IsCancellationRequested) + { + _logger.LogInformation("ADD IMPLEMENTATION TO RENEWAL THE CREDENTRIALS"); + } + } +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj new file mode 100644 index 00000000..e7d17321 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj @@ -0,0 +1,60 @@ + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App + Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App + Exe + net8.0 + enable + enable + 47895ab5-89cb-4818-9b08-570588b6aaf3 + Linux + ..\..\.. + True + + + diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/appsettings.json b/src/credentials/SsiCredentialIssuer.Renewal.App/appsettings.json new file mode 100644 index 00000000..63a834b4 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/appsettings.json @@ -0,0 +1,39 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console" ], + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "System": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "Org.Eclipse.TractusX.SsiCredentialIssuer": "Information" + } + }, + "WriteTo": [ + { "Name": "Console" } + ], + "Enrich": [ + "FromLogContext" + ], + "Properties": { + "Application": "Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App" + } + }, + "ConnectionStrings": { + "PortalDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=placeholder;Ssl Mode=Disable;" + }, + "ProcessIdentity": { + "IdentityId": "" + }, + "Portal": { + "Username": "", + "Password": "", + "ClientId": "", + "GrantType": "", + "ClientSecret": "", + "Scope": "", + "TokenAddress": "", + "BaseAddress": "" + } +} From d6aa4bbc8648d4b1af31af152e1c1efe56cbd8c2 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Thu, 1 Aug 2024 14:28:27 +0200 Subject: [PATCH 02/26] feat: added the new renewal credential app to the project solution --- src/SsiCredentialIssuer.sln | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/SsiCredentialIssuer.sln b/src/SsiCredentialIssuer.sln index 7a965431..ed9687da 100644 --- a/src/SsiCredentialIssuer.sln +++ b/src/SsiCredentialIssuer.sln @@ -1,4 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 +# +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "database", "database", "{E9E08CE9-985A-4507-BBD3-9470623986CF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issuer", "issuer", "{32D0AE23-BFAA-4D65-AF9D-2DF951BA5A3B}" @@ -59,6 +62,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Callback.Service", "externa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Callback.Service.Tests", "..\tests\externalservices\Callback.Service.Tests\Callback.Service.Tests.csproj", "{61DB2ADF-DBC1-4647-AAD2-A8E992E75B37}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Renewal.App", "credentials\SsiCredentialIssuer.Renewal.App\SsiCredentialIssuer.Renewal.App.csproj", "{2757DB44-F658-420F-B00A-48EC6DBA6035}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -161,6 +166,13 @@ Global {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37}.Debug|Any CPU.Build.0 = Debug|Any CPU {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37}.Release|Any CPU.ActiveCfg = Release|Any CPU {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37}.Release|Any CPU.Build.0 = Release|Any CPU + {2757DB44-F658-420F-B00A-48EC6DBA6035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2757DB44-F658-420F-B00A-48EC6DBA6035}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2757DB44-F658-420F-B00A-48EC6DBA6035}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2757DB44-F658-420F-B00A-48EC6DBA6035}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {6905B6DF-722B-4882-A2CB-5E6BFD0244F2} = {32D0AE23-BFAA-4D65-AF9D-2DF951BA5A3B} @@ -187,5 +199,6 @@ Global {0A9C65F7-62B6-421F-ADA5-709A1EE10901} = {A2FC3E0F-5AFE-44FA-909B-B8016DD1EB44} {E1821527-A5F9-4D56-BAB0-6F45FE6F3299} = {A37A220C-4242-4FB2-98ED-EF4B602EF6C1} {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37} = {A2FC3E0F-5AFE-44FA-909B-B8016DD1EB44} + {2757DB44-F658-420F-B00A-48EC6DBA6035} = {A79FF417-08E7-4175-8089-5F21054F5BDE} EndGlobalSection EndGlobal From 46bf75e28d7ad3c6964e48f9a138a6f19ea90eb8 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 5 Aug 2024 13:02:46 +0200 Subject: [PATCH 03/26] feat: Creation of the job renewal structure acceesing the database --- .../Services/RenewalService.cs | 43 +++++++++++++++++-- .../Models/CredentialExpiryData.cs | 12 ++++++ .../CompanySsiDetailsRepository.cs | 25 +++++++++++ .../ICompanySsiDetailsRepository.cs | 1 + 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs index 1a1c4b62..398de311 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs @@ -19,6 +19,11 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using System.Text.Json; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; @@ -28,22 +33,54 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; /// public class RenewalService { - private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ILogger _logger; + private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; + /// + /// Creates a new instance of + /// + /// access to the services + /// the logger public RenewalService(IServiceScopeFactory serviceScopeFactory, ILogger logger) { _serviceScopeFactory = serviceScopeFactory; _logger = logger; } - + + /// + /// Handles the process of re-issuing new verifiable credentias + /// + /// Cancellation Tokenpublic async Task ExecuteAsync(CancellationToken stoppingToken) public async Task ExecuteAsync(CancellationToken stoppingToken) { if (!stoppingToken.IsCancellationRequested) { - _logger.LogInformation("ADD IMPLEMENTATION TO RENEWAL THE CREDENTRIALS"); + try + { + using var processServiceScope = _serviceScopeFactory.CreateScope(); + var dateTimeProvider = processServiceScope.ServiceProvider.GetRequiredService(); + var repositories = processServiceScope.ServiceProvider.GetRequiredService(); + var expirationDate = dateTimeProvider.OffsetNow.AddDays(1); + var companySsiDetailsRepository = repositories.GetInstance(); + + var credentialsAboutToExpire = companySsiDetailsRepository.GetCredentialsAboutToExpire(expirationDate); + await CreateNewCredentials(credentialsAboutToExpire); + } + catch (Exception ex) + { + Environment.ExitCode = 1; + _logger.LogError("Verified Credential re-issuance check failed with error: {Errors}", ex.Message); + } + } + } + + private async Task CreateNewCredentials(IAsyncEnumerable credentialsAboutToExpire) + { + await foreach(var item in credentialsAboutToExpire) + { + _logger.LogInformation("HolderBpn: {0}", item.HolderBpn); } } } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs index 3f515bcb..cf008bb6 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs @@ -18,6 +18,7 @@ ********************************************************************************/ using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using System.Text.Json; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; @@ -39,3 +40,14 @@ public record CredentialScheduleData( bool IsOneMonthNotification, bool IsVcToDecline ); + +public record CredentialAboutToExpireData( + string Holder, + string HolderBpn, + JsonDocument schema, + string WalletUrl, + string ClientId, + byte[]? ClientSecret, + string? CallbackUrl +); + diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs index df47ecc3..64e896c2 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs @@ -22,6 +22,8 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography.X509Certificates; using System.Text.Json; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; @@ -291,4 +293,27 @@ public void AttachAndModifyProcessData(Guid companySsiDetailId, Action GetCredentialsAboutToExpire(DateTimeOffset expirationDate) + { + return context.CompanySsiDetails + .Select(x => new + { + Details = x, + IsDateAboutToExpire = x.ExpiryDate != null && x.ExpiryDate.Value.Date.CompareTo(expirationDate.Date) == 0, + IsSsiStatusIdActive = x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE, + IsValidCredendialType = x.CompanySsiProcessData != null && (x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.BPN || x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.MEMBERSHIP) + }) + .Where(ssi => ssi.IsSsiStatusIdActive && ssi.IsDateAboutToExpire && ssi.IsValidCredendialType) + .Select(x => new CredentialAboutToExpireData( + x.Details.Bpnl, + x.Details.Bpnl, + x.Details.CompanySsiProcessData.Schema, + x.Details.CompanySsiProcessData.HolderWalletUrl, + x.Details.CompanySsiProcessData.ClientId, + x.Details.CompanySsiProcessData.ClientSecret, + x.Details.CompanySsiProcessData.CallbackUrl + )) + .AsAsyncEnumerable(); + } } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs index 6291c544..b8d62555 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs @@ -103,4 +103,5 @@ public interface ICompanySsiDetailsRepository void RemoveSsiDetail(Guid companySsiDetailId, string bpnl, string userId); void CreateProcessData(Guid companySsiDetailId, JsonDocument schema, VerifiedCredentialTypeKindId credentialTypeKindId, Action? setOptionalFields); void AttachAndModifyProcessData(Guid companySsiDetailId, Action? initialize, Action setOptionalFields); + IAsyncEnumerable GetCredentialsAboutToExpire(DateTimeOffset expirationDate); } From 39a50d6424ff0f3e9f4b1daafa00a201084b2301 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Thu, 8 Aug 2024 18:55:49 +0200 Subject: [PATCH 04/26] feat: Added new library to hold the common objects for the credential --- .../Configuration/CredentialSettings.cs | 65 +++++++++++++++ .../Context/CredentialContext.cs | 26 ++++++ .../CredentialServiceExtensions.cs | 39 +++++++++ .../Models/CredentialData.cs | 82 +++++++++++++++++++ .../SsiCredentialIssuer.Api.csproj | 27 ++++++ 5 files changed, 239 insertions(+) create mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs create mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs create mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs create mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs create mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs new file mode 100644 index 00000000..a44ac6df --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs @@ -0,0 +1,65 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 + ********************************************************************************/ + +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Validation; +using System.ComponentModel.DataAnnotations; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; + +public class CredentialSettings +{ + [Required(AllowEmptyStrings = false)] + public string IssuerBpn { get; set; } = null!; +} + +public static class CompanyDataSettingsExtensions +{ + public static IServiceCollection ConfigureCredentialSettings( + this IServiceCollection services, + IConfigurationSection section) + { + services.AddOptions() + .Bind(section) + .ValidateDataAnnotations() + .ValidateDistinctValues(section) + .ValidateEnumEnumeration(section) + .ValidateOnStart(); + return services; + } +} diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs new file mode 100644 index 00000000..491a8094 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; +public class CredentialContext +{ + private static readonly IEnumerable _context = ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0"]; + + public static IEnumerable Context => _context; +} \ No newline at end of file diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs new file mode 100644 index 00000000..434db62d --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; +using Microsoft.Extensions.Configuration; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; + +/// +/// Extension method to register the credential settings and dependent services +/// +public static class CredentialServiceExtensions +{ + /// + /// Adds the renewal service + /// + /// the services + /// the enriched service collection + public static IServiceCollection AddICredentialServiceExtensions(this IServiceCollection services, IConfiguration config) => + services + .ConfigureCredentialSettings(config.GetSection("Credential")); +} diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs new file mode 100644 index 00000000..1694b634 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs @@ -0,0 +1,82 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; + +public record FrameworkCredential( + [property: JsonPropertyName("id")] Guid Id, + [property: JsonPropertyName("@context")] IEnumerable Context, + [property: JsonPropertyName("type")] IEnumerable Type, + [property: JsonPropertyName("issuanceDate")] DateTimeOffset IssuanceDate, + [property: JsonPropertyName("expirationDate")] DateTimeOffset ExpirationDate, + [property: JsonPropertyName("issuer")] string Issuer, + [property: JsonPropertyName("credentialSubject")] FrameworkCredentialSubject CredentialSubject, + [property: JsonPropertyName("credentialStatus")] CredentialStatus CredentialStatus); + +public record FrameworkCredentialSubject( + [property: JsonPropertyName("id")] string Did, + [property: JsonPropertyName("holderIdentifier")] string HolderIdentifier, + [property: JsonPropertyName("group")] string Group, + [property: JsonPropertyName("useCase")] string UseCase, + [property: JsonPropertyName("contractTemplate")] string ContractTemplate, + [property: JsonPropertyName("contractVersion")] string ContractVersion +); + +public record MembershipCredential( + [property: JsonPropertyName("id")] Guid Id, + [property: JsonPropertyName("@context")] IEnumerable Context, + [property: JsonPropertyName("type")] IEnumerable Type, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("issuanceDate")] DateTimeOffset IssuanceDate, + [property: JsonPropertyName("expirationDate")] DateTimeOffset ExpirationDate, + [property: JsonPropertyName("issuer")] string Issuer, + [property: JsonPropertyName("credentialSubject")] MembershipCredentialSubject CredentialSubject, + [property: JsonPropertyName("credentialStatus")] CredentialStatus CredentialStatus); + +public record MembershipCredentialSubject( + [property: JsonPropertyName("id")] string Did, + [property: JsonPropertyName("holderIdentifier")] string HolderIdentifier, + [property: JsonPropertyName("memberOf")] string MemberOf +); + +public record BpnCredential( + [property: JsonPropertyName("id")] Guid Id, + [property: JsonPropertyName("@context")] IEnumerable Context, + [property: JsonPropertyName("type")] IEnumerable Type, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("issuanceDate")] DateTimeOffset IssuanceDate, + [property: JsonPropertyName("expirationDate")] DateTimeOffset ExpirationDate, + [property: JsonPropertyName("issuer")] string Issuer, + [property: JsonPropertyName("credentialSubject")] BpnCredentialSubject CredentialSubject, + [property: JsonPropertyName("credentialStatus")] CredentialStatus CredentialStatus); + +public record CredentialStatus( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("type")] string Type +); + +public record BpnCredentialSubject( + [property: JsonPropertyName("id")] string Did, + [property: JsonPropertyName("holderIdentifier")] string HolderIdentifier, + [property: JsonPropertyName("bpn")] string Bpn +); diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj b/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj new file mode 100644 index 00000000..2e295e63 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library + Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library + net8.0 + enable + enable + + + From e80764f9d9a39c251013b28690e492ed204efa6f Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Thu, 8 Aug 2024 19:09:20 +0200 Subject: [PATCH 05/26] feat: New service to handle the credential reissuance --- .../RenewalServiceExtensions.cs | 14 ++- .../Handler/CredentialIssuerHandler.cs | 102 ++++++++++++++++++ .../Handler/ICredentialIssuerHandler.cs | 6 ++ .../Handler/IssuerCredentialRequest.cs | 43 ++++++++ .../Program.cs | 10 +- .../Services/IRenewalService.cs | 6 ++ .../Services/RenewalService.cs | 89 +++++++++++++-- .../SsiCredentialIssuer.Renewal.App.csproj | 3 +- 8 files changed, 256 insertions(+), 17 deletions(-) create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs create mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Services/IRenewalService.cs diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs index a96d9553..ed9d968c 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs @@ -20,6 +20,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; @@ -32,13 +33,18 @@ public static class RenewalServiceExtensions /// Adds the renewal service /// /// the services - /// the configuration section to setup the settings /// the enriched service collection - public static IServiceCollection AddRenewalService(this IServiceCollection services, IConfigurationSection section) + public static IServiceCollection AddRenewalService(this IServiceCollection services) { services - .AddTransient() - .AddTransient(); + .AddTransient() + .AddTransient() + .AddCredentialIssuerHandlerService(); + return services; } + + private static IServiceCollection AddCredentialIssuerHandlerService(this IServiceCollection services) => + services + .AddTransient(); } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs new file mode 100644 index 00000000..f86181c2 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs @@ -0,0 +1,102 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; + +/// +/// Handles the re-issuance of a new credential then creates a new create credential process +/// +public class CredentialIssuerHandler : ICredentialIssuerHandler +{ + private readonly CredentialSettings _settings; + private readonly IServiceScopeFactory _serviceScopeFactory; + /// + /// Constructor + /// + /// + /// + public CredentialIssuerHandler(IServiceScopeFactory serviceScopeFactory, IOptions options) + { + _serviceScopeFactory = serviceScopeFactory; + _settings = options.Value; + } + + /// + /// Hadkes the request to create a new credential process + /// + /// Credential Request Object + /// + public async Task HandleCredentialProcessCreation(IssuerCredentialRequest credentialRequest) + { + var documentContent = Encoding.UTF8.GetBytes(credentialRequest.Schema); + var hash = SHA512.HashData(documentContent); + using var processServiceScope = _serviceScopeFactory.CreateScope(); + var repositories = processServiceScope.ServiceProvider.GetRequiredService(); + var documentRepository = repositories.GetInstance(); + var companyCredentialDetailsRepository = repositories.GetInstance(); + var docId = documentRepository.CreateDocument($"{credentialRequest.TypeId}.json", documentContent, + hash, MediaTypeId.JSON, DocumentTypeId.PRESENTATION, x => + { + x.IdentityId = credentialRequest.IdentiyId; + x.DocumentStatusId = DocumentStatusId.ACTIVE; + }).Id; + + Guid? processId = CreateProcess(repositories); + + var ssiDetailId = companyCredentialDetailsRepository.CreateSsiDetails( + credentialRequest.Bpnl, + credentialRequest.TypeId, + CompanySsiDetailStatusId.ACTIVE, + _settings.IssuerBpn, + credentialRequest.IdentiyId, + c => + { + c.VerifiedCredentialExternalTypeDetailVersionId = credentialRequest.DetailVersionId; + c.ProcessId = processId; + c.ExpiryDate = credentialRequest.ExpiryDate; + }).Id; + documentRepository.AssignDocumentToCompanySsiDetails(docId, ssiDetailId); + + companyCredentialDetailsRepository.CreateProcessData(ssiDetailId, JsonDocument.Parse(credentialRequest.Schema), credentialRequest.KindId, + c => + { + c.HolderWalletUrl = credentialRequest.HolderWalletUrl; + c.CallbackUrl = credentialRequest.CallbackUrl; + }); + + await repositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + } + private static Guid CreateProcess(IIssuerRepositories repositories) + { + var processStepRepository = repositories.GetInstance(); + var processId = processStepRepository.CreateProcess(ProcessTypeId.CREATE_CREDENTIAL).Id; + processStepRepository.CreateProcessStep(ProcessStepTypeId.CREATE_CREDENTIAL, ProcessStepStatusId.TODO, processId); + return processId; + } +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs new file mode 100644 index 00000000..5941cf81 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs @@ -0,0 +1,6 @@ +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; + +public interface ICredentialIssuerHandler +{ + public Task HandleCredentialProcessCreation(IssuerCredentialRequest issuerCredentialRequest); +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs new file mode 100644 index 00000000..c6e3ddf4 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; + +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +public class IssuerCredentialRequest( + string bpnl, + VerifiedCredentialTypeKindId kindId, + VerifiedCredentialTypeId typeId, + DateTimeOffset expiryDate, + string identiyId, + string schema, + string? holderWalletUrl, + Guid? detailVersionId, + string? callbackUrl) +{ + public string Bpnl { get; } = bpnl; + public VerifiedCredentialTypeKindId KindId { get; } = kindId; + public VerifiedCredentialTypeId TypeId { get; } = typeId; + public DateTimeOffset ExpiryDate { get; } = expiryDate; + public string IdentiyId { get; } = identiyId; + public string Schema { get; } = schema; + public string? HolderWalletUrl { get; } = holderWalletUrl; + public Guid? DetailVersionId { get; } = detailVersionId; + public string CallbackUrl { get; } = callbackUrl; +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs index b0b2b7b3..66b0ff86 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs @@ -23,9 +23,10 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; using Serilog; using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; LoggingExtensions.EnsureInitialized(); Log.Information("Building worker"); @@ -38,8 +39,9 @@ services //.AddTransient() .AddProcessIdentity(hostContext.Configuration.GetSection("ProcessIdentity")) - .AddRenewalService(hostContext.Configuration.GetSection("Renewal")) - .AddIssuerRepositories(hostContext.Configuration); + .AddIssuerRepositories(hostContext.Configuration) + .AddICredentialServiceExtensions(hostContext.Configuration) + .AddRenewalService(); }) .AddLogging() .Build(); @@ -54,7 +56,7 @@ }; Log.Information("Start processing"); - var workerInstance = host.Services.GetRequiredService(); + var workerInstance = host.Services.GetRequiredService(); await workerInstance.ExecuteAsync(tokenSource.Token).ConfigureAwait(ConfigureAwaitOptions.None); Log.Information("Execution finished shutting down"); } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/IRenewalService.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/IRenewalService.cs new file mode 100644 index 00000000..adac01a2 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/IRenewalService.cs @@ -0,0 +1,6 @@ +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; + +public interface IRenewalService +{ + Task ExecuteAsync(CancellationToken stoppingToken); +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs index 398de311..d9de960b 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs @@ -23,29 +23,37 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Text.Json; +using Microsoft.Extensions.Options; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; /// /// Service to re-issue credentials that will expire in the day after. /// -public class RenewalService +public class RenewalService : IRenewalService { + private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ILogger _logger; - private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; - + private readonly ICredentialIssuerHandler _credentialIssuerHandler; /// /// Creates a new instance of /// /// access to the services + /// access to the credential issuer handler service /// the logger public RenewalService(IServiceScopeFactory serviceScopeFactory, + ICredentialIssuerHandler credentialIssuerHandler, ILogger logger) { _serviceScopeFactory = serviceScopeFactory; + _credentialIssuerHandler = credentialIssuerHandler; _logger = logger; } @@ -64,9 +72,9 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) var repositories = processServiceScope.ServiceProvider.GetRequiredService(); var expirationDate = dateTimeProvider.OffsetNow.AddDays(1); var companySsiDetailsRepository = repositories.GetInstance(); - + var credentialIssuerHandler = processServiceScope.ServiceProvider.GetRequiredService(); var credentialsAboutToExpire = companySsiDetailsRepository.GetCredentialsAboutToExpire(expirationDate); - await CreateNewCredentials(credentialsAboutToExpire); + await ProcessCredentials(credentialsAboutToExpire, dateTimeProvider); } catch (Exception ex) { @@ -76,11 +84,76 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) } } - private async Task CreateNewCredentials(IAsyncEnumerable credentialsAboutToExpire) + private async Task ProcessCredentials(IAsyncEnumerable credentialsAboutToExpire, IDateTimeProvider dateTimeProvider) + { + await foreach(var credential in credentialsAboutToExpire) + { + var expirationDate = dateTimeProvider.OffsetNow.AddMonths(12); + + var schemaData = CreateNewCredential(credential, expirationDate); + + await _credentialIssuerHandler.HandleCredentialProcessCreation(new IssuerCredentialRequest( + credential.HolderBpn, + credential.VerifiedCredentialTypeKindId, + credential.VerifiedCredentialTypeId, + expirationDate, + credential.IdentityId, + schemaData, + credential.WalletUrl, + credential.DetailVersionId, + credential.CallbackUrl + )); + + } + } + + private string CreateNewCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { - await foreach(var item in credentialsAboutToExpire) + string schemaData; + if (credential.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.BPN) { - _logger.LogInformation("HolderBpn: {0}", item.HolderBpn); + schemaData = CreateBpnCredential(credential, credential.Schema, expirationDate); } + else + { + schemaData = CreateMembershipCredential(credential, credential.Schema, expirationDate); + } + return schemaData; + } + + private string CreateBpnCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) + { + var bpnAboutToExpire = credential.Schema.Deserialize(); + var bpnCredential = new BpnCredential( + Guid.NewGuid(), + CredentialContext.Context, + bpnAboutToExpire.Type, + bpnAboutToExpire.Name, + bpnAboutToExpire.Description, + DateTimeOffset.UtcNow, + expirationDate, + bpnAboutToExpire.Issuer, + bpnAboutToExpire.CredentialSubject, + bpnAboutToExpire.CredentialStatus); + + return JsonSerializer.Serialize(bpnCredential, Options); + } + + private string CreateMembershipCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) + { + var membershipAboutToExpire = credential.Schema.Deserialize(); + var membershipCredential = new MembershipCredential( + Guid.NewGuid(), + CredentialContext.Context, + membershipAboutToExpire.Type, + membershipAboutToExpire.Name, + membershipAboutToExpire.Description, + DateTimeOffset.UtcNow, + expirationDate, + membershipAboutToExpire.Issuer, + membershipAboutToExpire.CredentialSubject, + membershipAboutToExpire.CredentialStatus); + + return JsonSerializer.Serialize(membershipCredential, Options); } } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj index e7d17321..3eb8b3fb 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj @@ -21,8 +21,9 @@ - + + From 43529275070e09e39aa4df5b90f828ab2d61f0d0 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Thu, 8 Aug 2024 19:10:58 +0200 Subject: [PATCH 06/26] feat: Added new type and query for the issuer repository --- .../Models/CredentialExpiryData.cs | 10 ++++++---- .../Repositories/CompanySsiDetailsRepository.cs | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs index cf008bb6..42d57ce7 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs @@ -44,10 +44,12 @@ bool IsVcToDecline public record CredentialAboutToExpireData( string Holder, string HolderBpn, - JsonDocument schema, - string WalletUrl, - string ClientId, - byte[]? ClientSecret, + VerifiedCredentialTypeId VerifiedCredentialTypeId, + VerifiedCredentialTypeKindId VerifiedCredentialTypeKindId, + JsonDocument Schema, + string IdentityId, + string? WalletUrl, + Guid? DetailVersionId, string? CallbackUrl ); diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs index 64e896c2..768a0412 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs @@ -308,10 +308,12 @@ public IAsyncEnumerable GetCredentialsAboutToExpire .Select(x => new CredentialAboutToExpireData( x.Details.Bpnl, x.Details.Bpnl, + x.Details.VerifiedCredentialTypeId, + x.Details.CompanySsiProcessData!.CredentialTypeKindId, x.Details.CompanySsiProcessData.Schema, - x.Details.CompanySsiProcessData.HolderWalletUrl, - x.Details.CompanySsiProcessData.ClientId, - x.Details.CompanySsiProcessData.ClientSecret, + x.Details.Documents.Select(document => document.IdentityId).SingleOrDefault()!, + x.Details.CompanySsiProcessData.HolderWalletUrl!, + x.Details.VerifiedCredentialExternalTypeDetailVersion!.Id, x.Details.CompanySsiProcessData.CallbackUrl )) .AsAsyncEnumerable(); From f348ef4012b7b63634bbb3cdcc2d081d59c045ea Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Fri, 9 Aug 2024 18:18:54 +0200 Subject: [PATCH 07/26] feat: Creation of new issuance repository and process to mark credentials as reissued --- src/SsiCredentialIssuer.sln | 7 + ...redentialIssuer.Credential.Library.csproj} | 0 .../Handler/CredentialIssuerHandler.cs | 14 +- .../Handler/ICredentialIssuerHandler.cs | 29 +- .../Handler/IssuerCredentialRequest.cs | 5 +- .../Services/RenewalService.cs | 11 +- .../SsiCredentialIssuer.Renewal.App.csproj | 3 +- .../IssuerRepositories.cs | 1 + .../Models/CredentialExpiryData.cs | 2 +- .../CompanySsiDetailsRepository.cs | 7 +- .../Repositories/IReissuanceRepository.cs | 25 + .../Repositories/ReissuanceRepository.cs | 41 + .../Entities/CompanySsiDetail.cs | 1 + .../Entities/ReissuanceProcess.cs | 36 + .../IssuerDbContext.cs | 11 + ...240809153759_ReissuanceChanges.Designer.cs | 1671 +++++++++++++++++ .../20240809153759_ReissuanceChanges.cs | 43 + .../IssuerDbContextModelSnapshot.cs | 37 +- 18 files changed, 1922 insertions(+), 22 deletions(-) rename src/credentials/SsiCredentialIssuer.Credential.Library/{SsiCredentialIssuer.Api.csproj => SsiCredentialIssuer.Credential.Library.csproj} (100%) create mode 100644 src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs create mode 100644 src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs create mode 100644 src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs create mode 100644 src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs create mode 100644 src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs diff --git a/src/SsiCredentialIssuer.sln b/src/SsiCredentialIssuer.sln index ed9687da..6a64c248 100644 --- a/src/SsiCredentialIssuer.sln +++ b/src/SsiCredentialIssuer.sln @@ -64,6 +64,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Callback.Service.Tests", ". EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Renewal.App", "credentials\SsiCredentialIssuer.Renewal.App\SsiCredentialIssuer.Renewal.App.csproj", "{2757DB44-F658-420F-B00A-48EC6DBA6035}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "credentials\SsiCredentialIssuer.Credential.Library", "credentials\SsiCredentialIssuer.Credential.Library\SsiCredentialIssuer.Credential.Library.csproj", "{832CA2B5-E08D-4EB6-9C99-020E01A86A2C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -170,6 +172,10 @@ Global {2757DB44-F658-420F-B00A-48EC6DBA6035}.Debug|Any CPU.Build.0 = Debug|Any CPU {2757DB44-F658-420F-B00A-48EC6DBA6035}.Release|Any CPU.ActiveCfg = Release|Any CPU {2757DB44-F658-420F-B00A-48EC6DBA6035}.Release|Any CPU.Build.0 = Release|Any CPU + {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -200,5 +206,6 @@ Global {E1821527-A5F9-4D56-BAB0-6F45FE6F3299} = {A37A220C-4242-4FB2-98ED-EF4B602EF6C1} {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37} = {A2FC3E0F-5AFE-44FA-909B-B8016DD1EB44} {2757DB44-F658-420F-B00A-48EC6DBA6035} = {A79FF417-08E7-4175-8089-5F21054F5BDE} + {832CA2B5-E08D-4EB6-9C99-020E01A86A2C} = {A79FF417-08E7-4175-8089-5F21054F5BDE} EndGlobalSection EndGlobal diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj b/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj similarity index 100% rename from src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Api.csproj rename to src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs index f86181c2..5fd9431c 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs @@ -29,9 +29,7 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; -/// -/// Handles the re-issuance of a new credential then creates a new create credential process -/// +/// public class CredentialIssuerHandler : ICredentialIssuerHandler { private readonly CredentialSettings _settings; @@ -47,11 +45,7 @@ public CredentialIssuerHandler(IServiceScopeFactory serviceScopeFactory, IOption _settings = options.Value; } - /// - /// Hadkes the request to create a new credential process - /// - /// Credential Request Object - /// + /// public async Task HandleCredentialProcessCreation(IssuerCredentialRequest credentialRequest) { var documentContent = Encoding.UTF8.GetBytes(credentialRequest.Schema); @@ -59,6 +53,7 @@ public async Task HandleCredentialProcessCreation(IssuerCredentialRequest creden using var processServiceScope = _serviceScopeFactory.CreateScope(); var repositories = processServiceScope.ServiceProvider.GetRequiredService(); var documentRepository = repositories.GetInstance(); + var reissuanceRepository = repositories.GetInstance(); var companyCredentialDetailsRepository = repositories.GetInstance(); var docId = documentRepository.CreateDocument($"{credentialRequest.TypeId}.json", documentContent, hash, MediaTypeId.JSON, DocumentTypeId.PRESENTATION, x => @@ -81,8 +76,11 @@ public async Task HandleCredentialProcessCreation(IssuerCredentialRequest creden c.ProcessId = processId; c.ExpiryDate = credentialRequest.ExpiryDate; }).Id; + documentRepository.AssignDocumentToCompanySsiDetails(docId, ssiDetailId); + reissuanceRepository.CreateReissuanceProcess(credentialRequest.Id, ssiDetailId); + companyCredentialDetailsRepository.CreateProcessData(ssiDetailId, JsonDocument.Parse(credentialRequest.Schema), credentialRequest.KindId, c => { diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs index 5941cf81..211d6c92 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs @@ -1,6 +1,33 @@ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 + ********************************************************************************/ +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; + +/// +/// Handles the re-issuance of a new credential then creates a new create credential process +/// public interface ICredentialIssuerHandler { + /// + /// Hadkes the request to create a new credential process + /// + /// Credential Request Object + /// public Task HandleCredentialProcessCreation(IssuerCredentialRequest issuerCredentialRequest); } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs index c6e3ddf4..8303080f 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs @@ -20,7 +20,9 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; + public class IssuerCredentialRequest( + Guid id, string bpnl, VerifiedCredentialTypeKindId kindId, VerifiedCredentialTypeId typeId, @@ -31,6 +33,7 @@ public class IssuerCredentialRequest( Guid? detailVersionId, string? callbackUrl) { + public Guid Id { get; } = id; public string Bpnl { get; } = bpnl; public VerifiedCredentialTypeKindId KindId { get; } = kindId; public VerifiedCredentialTypeId TypeId { get; } = typeId; @@ -39,5 +42,5 @@ public class IssuerCredentialRequest( public string Schema { get; } = schema; public string? HolderWalletUrl { get; } = holderWalletUrl; public Guid? DetailVersionId { get; } = detailVersionId; - public string CallbackUrl { get; } = callbackUrl; + public string? CallbackUrl { get; } = callbackUrl; } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs index d9de960b..c343c4ec 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs @@ -93,6 +93,7 @@ private async Task ProcessCredentials(IAsyncEnumerable(); var bpnCredential = new BpnCredential( Guid.NewGuid(), CredentialContext.Context, - bpnAboutToExpire.Type, + bpnAboutToExpire!.Type, bpnAboutToExpire.Name, bpnAboutToExpire.Description, DateTimeOffset.UtcNow, @@ -139,13 +140,13 @@ private string CreateBpnCredential(CredentialAboutToExpireData credential, JsonD return JsonSerializer.Serialize(bpnCredential, Options); } - private string CreateMembershipCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) + private static string CreateMembershipCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) { var membershipAboutToExpire = credential.Schema.Deserialize(); var membershipCredential = new MembershipCredential( Guid.NewGuid(), CredentialContext.Context, - membershipAboutToExpire.Type, + membershipAboutToExpire!.Type, membershipAboutToExpire.Name, membershipAboutToExpire.Description, DateTimeOffset.UtcNow, diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj index 3eb8b3fb..b17c047f 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj +++ b/src/credentials/SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj @@ -22,7 +22,7 @@ - + @@ -56,6 +56,7 @@ Linux ..\..\.. True + CS1591 diff --git a/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs b/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs index 20699e59..b02fda94 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs @@ -34,6 +34,7 @@ public class IssuerRepositories : IIssuerRepositories { typeof(ICredentialRepository), context => new CredentialRepository(context) }, { typeof(IDocumentRepository), context => new DocumentRepository(context) }, { typeof(IProcessStepRepository), context => new ProcessStepRepository(context) }, + { typeof(IReissuanceRepository), context => new ReissuanceRepository(context) }, }.ToImmutableDictionary(); public IssuerRepositories(IssuerDbContext dbContext) diff --git a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs index 42d57ce7..d871b8b2 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Models/CredentialExpiryData.cs @@ -42,7 +42,7 @@ bool IsVcToDecline ); public record CredentialAboutToExpireData( - string Holder, + Guid Id, string HolderBpn, VerifiedCredentialTypeId VerifiedCredentialTypeId, VerifiedCredentialTypeKindId VerifiedCredentialTypeKindId, diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs index 768a0412..6c065fd6 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs @@ -302,11 +302,12 @@ public IAsyncEnumerable GetCredentialsAboutToExpire Details = x, IsDateAboutToExpire = x.ExpiryDate != null && x.ExpiryDate.Value.Date.CompareTo(expirationDate.Date) == 0, IsSsiStatusIdActive = x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE, - IsValidCredendialType = x.CompanySsiProcessData != null && (x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.BPN || x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.MEMBERSHIP) + IsValidCredendialType = x.CompanySsiProcessData != null && (x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.BPN || x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.MEMBERSHIP), + IsCredentialNotReissued = x.ReissuanceProcess == null }) - .Where(ssi => ssi.IsSsiStatusIdActive && ssi.IsDateAboutToExpire && ssi.IsValidCredendialType) + .Where(ssi => ssi.IsSsiStatusIdActive && ssi.IsDateAboutToExpire && ssi.IsValidCredendialType && ssi.IsCredentialNotReissued) .Select(x => new CredentialAboutToExpireData( - x.Details.Bpnl, + x.Details.Id, x.Details.Bpnl, x.Details.VerifiedCredentialTypeId, x.Details.CompanySsiProcessData!.CredentialTypeKindId, diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs new file mode 100644 index 00000000..ee7a3150 --- /dev/null +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; + +public interface IReissuanceRepository +{ + void CreateReissuanceProcess(Guid id, Guid reissuedCredentialId); +} diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs new file mode 100644 index 00000000..0def8b31 --- /dev/null +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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.SsiCredentialIssuer.Entities; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; + +public class ReissuanceRepository : IReissuanceRepository +{ + private readonly IssuerDbContext _dbContext; + + /// + /// Constructor. + /// + /// IssuerDbContext context. + public ReissuanceRepository(IssuerDbContext dbContext) + { + _dbContext = dbContext; + } + public void CreateReissuanceProcess(Guid id, Guid reissuedCredentialId) + { + var reissuanceProcess = new ReissuanceProcess(id, reissuedCredentialId); + _dbContext.Reissuances.Add(reissuanceProcess); + } +} diff --git a/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs b/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs index 343018d6..ced344bc 100644 --- a/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs +++ b/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs @@ -73,6 +73,7 @@ public CompanySsiDetail(Guid id, string bpnl, VerifiedCredentialTypeId verifiedC public virtual ExpiryCheckType? ExpiryCheckType { get; set; } public virtual CompanySsiDetailStatus? CompanySsiDetailStatus { get; set; } public virtual Process? Process { get; set; } + public virtual ReissuanceProcess? ReissuanceProcess { get; set; } public virtual VerifiedCredentialExternalTypeDetailVersion? VerifiedCredentialExternalTypeDetailVersion { get; set; } public virtual CompanySsiProcessData? CompanySsiProcessData { get; set; } public virtual ICollection Documents { get; private set; } diff --git a/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs b/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs new file mode 100644 index 00000000..a1d46621 --- /dev/null +++ b/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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.SsiCredentialIssuer.Entities.Auditing; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; + +public class ReissuanceProcess : IBaseEntity +{ + public ReissuanceProcess(Guid id, Guid reissuedCredentialId) + { + Id = id; + ReissuedCredentialId = reissuedCredentialId; + } + + public Guid Id { get; private set; } + public Guid ReissuedCredentialId { get; private set; } + + // Navigation properties + public virtual CompanySsiDetail? CompanySsiDetail { get; private set; } +} \ No newline at end of file diff --git a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs index 529a769d..751305cd 100644 --- a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs +++ b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs @@ -61,6 +61,7 @@ public IssuerDbContext(DbContextOptions options, IAuditHandler public virtual DbSet ProcessStepStatuses { get; set; } = default!; public virtual DbSet ProcessStepTypes { get; set; } = default!; public virtual DbSet ProcessTypes { get; set; } = default!; + public virtual DbSet Reissuances { get; set; } = default!; public virtual DbSet UseCases { get; set; } = default!; public virtual DbSet VerifiedCredentialExternalTypes { get; set; } = default!; public virtual DbSet VerifiedCredentialExternalTypeDetailVersions { get; set; } = default!; @@ -143,6 +144,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(x => x.CredentialTypeKindId); }); + modelBuilder.Entity(e => + { + e.HasKey(x => x.Id); + + e.HasOne(x => x.CompanySsiDetail) + .WithOne(x => x.ReissuanceProcess) + .HasForeignKey(x => x.Id); + }); + modelBuilder.Entity(entity => { entity.HasAuditV2Triggers(); @@ -182,6 +192,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(d => d.ProcessTypeId) .OnDelete(DeleteBehavior.ClientSetNull); + modelBuilder.Entity() .HasOne(d => d.Process) .WithMany(p => p!.ProcessSteps) diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs new file mode 100644 index 00000000..35c601c5 --- /dev/null +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs @@ -0,0 +1,1671 @@ +// +using System; +using System.Text.Json; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities; + +#nullable disable + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations +{ + [DbContext(typeof(IssuerDbContext))] + [Migration("20240809153759_ReissuanceChanges")] + partial class ReissuanceChanges + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("issuer") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditCompanySsiDetail20240228", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("Bpnl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpnl"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .HasColumnType("uuid") + .HasColumnName("creator_user_id"); + + b.Property("Credential") + .HasColumnType("text") + .HasColumnName("credential"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("ExpiryCheckTypeId") + .HasColumnType("integer") + .HasColumnName("expiry_check_type_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("ExternalCredentialId") + .HasColumnType("uuid") + .HasColumnName("external_credential_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IssuerBpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("issuer_bpn"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("VerifiedCredentialExternalTypeDetailVersionId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_detail_version_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_company_ssi_detail20240228"); + + b.ToTable("audit_company_ssi_detail20240228", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditCompanySsiDetail20240419", b => + { + b.Property("AuditV2Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v2id"); + + b.Property("AuditV2DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v2date_last_changed"); + + b.Property("AuditV2LastEditorId") + .HasColumnType("text") + .HasColumnName("audit_v2last_editor_id"); + + b.Property("AuditV2OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v2operation_id"); + + b.Property("Bpnl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpnl"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("creator_user_id"); + + b.Property("Credential") + .HasColumnType("text") + .HasColumnName("credential"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("ExpiryCheckTypeId") + .HasColumnType("integer") + .HasColumnName("expiry_check_type_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("ExternalCredentialId") + .HasColumnType("uuid") + .HasColumnName("external_credential_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IssuerBpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("issuer_bpn"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("VerifiedCredentialExternalTypeDetailVersionId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_detail_version_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("AuditV2Id") + .HasName("pk_audit_company_ssi_detail20240419"); + + b.ToTable("audit_company_ssi_detail20240419", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditDocument20240305", b => + { + b.Property("AuditV1Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v1id"); + + b.Property("AuditV1DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v1date_last_changed"); + + b.Property("AuditV1LastEditorId") + .HasColumnType("uuid") + .HasColumnName("audit_v1last_editor_id"); + + b.Property("AuditV1OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v1operation_id"); + + b.Property("CompanyUserId") + .HasColumnType("uuid") + .HasColumnName("company_user_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentContent") + .HasColumnType("bytea") + .HasColumnName("document_content"); + + b.Property("DocumentHash") + .HasColumnType("bytea") + .HasColumnName("document_hash"); + + b.Property("DocumentName") + .HasColumnType("text") + .HasColumnName("document_name"); + + b.Property("DocumentStatusId") + .HasColumnType("integer") + .HasColumnName("document_status_id"); + + b.Property("DocumentTypeId") + .HasColumnType("integer") + .HasColumnName("document_type_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LastEditorId") + .HasColumnType("uuid") + .HasColumnName("last_editor_id"); + + b.Property("MediaTypeId") + .HasColumnType("integer") + .HasColumnName("media_type_id"); + + b.HasKey("AuditV1Id") + .HasName("pk_audit_document20240305"); + + b.ToTable("audit_document20240305", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditDocument20240419", b => + { + b.Property("AuditV2Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v2id"); + + b.Property("AuditV2DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v2date_last_changed"); + + b.Property("AuditV2LastEditorId") + .HasColumnType("text") + .HasColumnName("audit_v2last_editor_id"); + + b.Property("AuditV2OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v2operation_id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentContent") + .HasColumnType("bytea") + .HasColumnName("document_content"); + + b.Property("DocumentHash") + .HasColumnType("bytea") + .HasColumnName("document_hash"); + + b.Property("DocumentName") + .HasColumnType("text") + .HasColumnName("document_name"); + + b.Property("DocumentStatusId") + .HasColumnType("integer") + .HasColumnName("document_status_id"); + + b.Property("DocumentTypeId") + .HasColumnType("integer") + .HasColumnName("document_type_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IdentityId") + .HasColumnType("text") + .HasColumnName("identity_id"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("MediaTypeId") + .HasColumnType("integer") + .HasColumnName("media_type_id"); + + b.HasKey("AuditV2Id") + .HasName("pk_audit_document20240419"); + + b.ToTable("audit_document20240419", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Bpnl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpnl"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("creator_user_id"); + + b.Property("Credential") + .HasColumnType("text") + .HasColumnName("credential"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("ExpiryCheckTypeId") + .HasColumnType("integer") + .HasColumnName("expiry_check_type_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("ExternalCredentialId") + .HasColumnType("uuid") + .HasColumnName("external_credential_id"); + + b.Property("IssuerBpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("issuer_bpn"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("VerifiedCredentialExternalTypeDetailVersionId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_detail_version_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("Id") + .HasName("pk_company_ssi_details"); + + b.HasIndex("CompanySsiDetailStatusId") + .HasDatabaseName("ix_company_ssi_details_company_ssi_detail_status_id"); + + b.HasIndex("ExpiryCheckTypeId") + .HasDatabaseName("ix_company_ssi_details_expiry_check_type_id"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_company_ssi_details_process_id"); + + b.HasIndex("VerifiedCredentialExternalTypeDetailVersionId") + .HasDatabaseName("ix_company_ssi_details_verified_credential_external_type_detai"); + + b.HasIndex("VerifiedCredentialTypeId") + .HasDatabaseName("ix_company_ssi_details_verified_credential_type_id"); + + b.ToTable("company_ssi_details", "issuer", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailAssignedDocument", b => + { + b.Property("DocumentId") + .HasColumnType("uuid") + .HasColumnName("document_id"); + + b.Property("CompanySsiDetailId") + .HasColumnType("uuid") + .HasColumnName("company_ssi_detail_id"); + + b.HasKey("DocumentId", "CompanySsiDetailId") + .HasName("pk_company_ssi_detail_assigned_documents"); + + b.HasIndex("CompanySsiDetailId") + .HasDatabaseName("ix_company_ssi_detail_assigned_documents_company_ssi_detail_id"); + + b.ToTable("company_ssi_detail_assigned_documents", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_company_ssi_detail_statuses"); + + b.ToTable("company_ssi_detail_statuses", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "PENDING" + }, + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "REVOKED" + }, + new + { + Id = 4, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiProcessData", b => + { + b.Property("CompanySsiDetailId") + .HasColumnType("uuid") + .HasColumnName("company_ssi_detail_id"); + + b.Property("CallbackUrl") + .HasColumnType("text") + .HasColumnName("callback_url"); + + b.Property("ClientId") + .HasColumnType("text") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("bytea") + .HasColumnName("client_secret"); + + b.Property("CredentialTypeKindId") + .HasColumnType("integer") + .HasColumnName("credential_type_kind_id"); + + b.Property("EncryptionMode") + .HasColumnType("integer") + .HasColumnName("encryption_mode"); + + b.Property("HolderWalletUrl") + .HasColumnType("text") + .HasColumnName("holder_wallet_url"); + + b.Property("InitializationVector") + .HasColumnType("bytea") + .HasColumnName("initialization_vector"); + + b.Property("Schema") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("schema"); + + b.HasKey("CompanySsiDetailId") + .HasName("pk_company_ssi_process_data"); + + b.HasIndex("CredentialTypeKindId") + .HasDatabaseName("ix_company_ssi_process_data_credential_type_kind_id"); + + b.ToTable("company_ssi_process_data", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("DocumentContent") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("document_content"); + + b.Property("DocumentHash") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("document_hash"); + + b.Property("DocumentName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("document_name"); + + b.Property("DocumentStatusId") + .HasColumnType("integer") + .HasColumnName("document_status_id"); + + b.Property("DocumentTypeId") + .HasColumnType("integer") + .HasColumnName("document_type_id"); + + b.Property("IdentityId") + .HasColumnType("text") + .HasColumnName("identity_id"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("MediaTypeId") + .HasColumnType("integer") + .HasColumnName("media_type_id"); + + b.HasKey("Id") + .HasName("pk_documents"); + + b.HasIndex("DocumentStatusId") + .HasDatabaseName("ix_documents_document_status_id"); + + b.HasIndex("DocumentTypeId") + .HasDatabaseName("ix_documents_document_type_id"); + + b.HasIndex("MediaTypeId") + .HasDatabaseName("ix_documents_media_type_id"); + + b.ToTable("documents", "issuer", t => + { + t.HasTrigger("LC_TRIGGER_AFTER_INSERT_DOCUMENT"); + + t.HasTrigger("LC_TRIGGER_AFTER_UPDATE_DOCUMENT"); + }); + + b + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_DOCUMENT", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_DOCUMENT\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_DOCUMENT$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_document20240419\" (\"id\", \"date_created\", \"document_hash\", \"document_content\", \"document_name\", \"media_type_id\", \"document_type_id\", \"document_status_id\", \"identity_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"document_hash\", \r\n NEW.\"document_content\", \r\n NEW.\"document_name\", \r\n NEW.\"media_type_id\", \r\n NEW.\"document_type_id\", \r\n NEW.\"document_status_id\", \r\n NEW.\"identity_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_DOCUMENT$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_DOCUMENT AFTER INSERT\r\nON \"issuer\".\"documents\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_DOCUMENT\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_DOCUMENT", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_DOCUMENT\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_DOCUMENT$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_document20240419\" (\"id\", \"date_created\", \"document_hash\", \"document_content\", \"document_name\", \"media_type_id\", \"document_type_id\", \"document_status_id\", \"identity_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"date_created\", \r\n NEW.\"document_hash\", \r\n NEW.\"document_content\", \r\n NEW.\"document_name\", \r\n NEW.\"media_type_id\", \r\n NEW.\"document_type_id\", \r\n NEW.\"document_status_id\", \r\n NEW.\"identity_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_DOCUMENT$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_DOCUMENT AFTER UPDATE\r\nON \"issuer\".\"documents\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_DOCUMENT\"();"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_document_status"); + + b.ToTable("document_status", "issuer"); + + b.HasData( + new + { + Id = 2, + Label = "ACTIVE" + }, + new + { + Id = 3, + Label = "INACTIVE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_document_types"); + + b.ToTable("document_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "PRESENTATION" + }, + new + { + Id = 2, + Label = "CREDENTIAL" + }, + new + { + Id = 3, + Label = "VERIFIED_CREDENTIAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ExpiryCheckType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_expiry_check_types"); + + b.ToTable("expiry_check_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "ONE_MONTH" + }, + new + { + Id = 2, + Label = "TWO_WEEKS" + }, + new + { + Id = 3, + Label = "ONE_DAY" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.MediaType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_media_types"); + + b.ToTable("media_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "JPEG" + }, + new + { + Id = 2, + Label = "GIF" + }, + new + { + Id = 3, + Label = "PNG" + }, + new + { + Id = 4, + Label = "SVG" + }, + new + { + Id = 5, + Label = "TIFF" + }, + new + { + Id = 6, + Label = "PDF" + }, + new + { + Id = 7, + Label = "JSON" + }, + new + { + Id = 8, + Label = "PEM" + }, + new + { + Id = 9, + Label = "CA_CERT" + }, + new + { + Id = 10, + Label = "PKX_CER" + }, + new + { + Id = 11, + Label = "OCTET" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Process", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LockExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("lock_expiry_date"); + + b.Property("ProcessTypeId") + .HasColumnType("integer") + .HasColumnName("process_type_id"); + + b.Property("Version") + .IsConcurrencyToken() + .HasColumnType("uuid") + .HasColumnName("version"); + + b.HasKey("Id") + .HasName("pk_processes"); + + b.HasIndex("ProcessTypeId") + .HasDatabaseName("ix_processes_process_type_id"); + + b.ToTable("processes", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ProcessStepStatusId") + .HasColumnType("integer") + .HasColumnName("process_step_status_id"); + + b.Property("ProcessStepTypeId") + .HasColumnType("integer") + .HasColumnName("process_step_type_id"); + + b.HasKey("Id") + .HasName("pk_process_steps"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_process_steps_process_id"); + + b.HasIndex("ProcessStepStatusId") + .HasDatabaseName("ix_process_steps_process_step_status_id"); + + b.HasIndex("ProcessStepTypeId") + .HasDatabaseName("ix_process_steps_process_step_type_id"); + + b.ToTable("process_steps", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_statuses"); + + b.ToTable("process_step_statuses", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "TODO" + }, + new + { + Id = 2, + Label = "DONE" + }, + new + { + Id = 3, + Label = "SKIPPED" + }, + new + { + Id = 4, + Label = "FAILED" + }, + new + { + Id = 5, + Label = "DUPLICATE" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_types"); + + b.ToTable("process_step_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "CREATE_CREDENTIAL" + }, + new + { + Id = 2, + Label = "SIGN_CREDENTIAL" + }, + new + { + Id = 3, + Label = "SAVE_CREDENTIAL_DOCUMENT" + }, + new + { + Id = 4, + Label = "CREATE_CREDENTIAL_FOR_HOLDER" + }, + new + { + Id = 5, + Label = "TRIGGER_CALLBACK" + }, + new + { + Id = 100, + Label = "REVOKE_CREDENTIAL" + }, + new + { + Id = 101, + Label = "TRIGGER_NOTIFICATION" + }, + new + { + Id = 102, + Label = "TRIGGER_MAIL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_types"); + + b.ToTable("process_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "CREATE_CREDENTIAL" + }, + new + { + Id = 2, + Label = "DECLINE_CREDENTIAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.UseCase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("Shortname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("shortname"); + + b.HasKey("Id") + .HasName("pk_use_cases"); + + b.ToTable("use_cases", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_external_types"); + + b.ToTable("verified_credential_external_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "TRACEABILITY_CREDENTIAL" + }, + new + { + Id = 2, + Label = "PCF_CREDENTIAL" + }, + new + { + Id = 3, + Label = "BEHAVIOR_TWIN_CREDENTIAL" + }, + new + { + Id = 4, + Label = "MEMBERSHIP_CREDENTIAL" + }, + new + { + Id = 5, + Label = "CIRCULAR_ECONOMY" + }, + new + { + Id = 6, + Label = "QUALITY_CREDENTIAL" + }, + new + { + Id = 7, + Label = "BUSINESS_PARTNER_NUMBER" + }, + new + { + Id = 8, + Label = "DEMAND_AND_CAPACITY_MANAGEMENT" + }, + new + { + Id = 9, + Label = "DEMAND_AND_CAPACITY_MANAGEMENT_PURIS" + }, + new + { + Id = 10, + Label = "BUSINESS_PARTNER_DATA_MANAGEMENT" + }, + new + { + Id = 11, + Label = "FRAMEWORK_AGREEMENT" + }, + new + { + Id = 12, + Label = "DATA_EXCHANGE_GOVERNANCE_CREDENTIAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Expiry") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry"); + + b.Property("Template") + .HasColumnType("text") + .HasColumnName("template"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone") + .HasColumnName("valid_from"); + + b.Property("VerifiedCredentialExternalTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_external_type_id"); + + b.Property("Version") + .HasColumnType("text") + .HasColumnName("version"); + + b.HasKey("Id") + .HasName("pk_verified_credential_external_type_detail_versions"); + + b.HasIndex("VerifiedCredentialExternalTypeId", "Version") + .IsUnique() + .HasDatabaseName("ix_verified_credential_external_type_detail_versions_verified_"); + + b.ToTable("verified_credential_external_type_detail_versions", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_types"); + + b.ToTable("verified_credential_types", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "TRACEABILITY_FRAMEWORK" + }, + new + { + Id = 2, + Label = "PCF_FRAMEWORK" + }, + new + { + Id = 3, + Label = "BEHAVIOR_TWIN_FRAMEWORK" + }, + new + { + Id = 4, + Label = "MEMBERSHIP" + }, + new + { + Id = 5, + Label = "CIRCULAR_ECONOMY" + }, + new + { + Id = 6, + Label = "FRAMEWORK_AGREEMENT_QUALITY" + }, + new + { + Id = 7, + Label = "BUSINESS_PARTNER_NUMBER" + }, + new + { + Id = 8, + Label = "DEMAND_AND_CAPACITY_MANAGEMENT" + }, + new + { + Id = 9, + Label = "DEMAND_AND_CAPACITY_MANAGEMENT_PURIS" + }, + new + { + Id = 10, + Label = "BUSINESS_PARTNER_DATA_MANAGEMENT" + }, + new + { + Id = 11, + Label = "FRAMEWORK_AGREEMENT" + }, + new + { + Id = 12, + Label = "DATA_EXCHANGE_GOVERNANCE_CREDENTIAL" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedExternalType", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("VerifiedCredentialExternalTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_external_type_id"); + + b.HasKey("VerifiedCredentialTypeId", "VerifiedCredentialExternalTypeId") + .HasName("pk_verified_credential_type_assigned_external_types"); + + b.HasIndex("VerifiedCredentialExternalTypeId") + .HasDatabaseName("ix_verified_credential_type_assigned_external_types_verified_c"); + + b.HasIndex("VerifiedCredentialTypeId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_external_types_verified_c1"); + + b.ToTable("verified_credential_type_assigned_external_types", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedKind", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("VerifiedCredentialTypeKindId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_kind_id"); + + b.HasKey("VerifiedCredentialTypeId", "VerifiedCredentialTypeKindId") + .HasName("pk_verified_credential_type_assigned_kinds"); + + b.HasIndex("VerifiedCredentialTypeId") + .HasDatabaseName("ix_verified_credential_type_assigned_kinds_verified_credential"); + + b.HasIndex("VerifiedCredentialTypeKindId") + .HasDatabaseName("ix_verified_credential_type_assigned_kinds_verified_credential1"); + + b.ToTable("verified_credential_type_assigned_kinds", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedUseCase", b => + { + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.Property("UseCaseId") + .HasColumnType("uuid") + .HasColumnName("use_case_id"); + + b.HasKey("VerifiedCredentialTypeId", "UseCaseId") + .HasName("pk_verified_credential_type_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_use_cases_use_case_id"); + + b.HasIndex("VerifiedCredentialTypeId") + .IsUnique() + .HasDatabaseName("ix_verified_credential_type_assigned_use_cases_verified_creden"); + + b.ToTable("verified_credential_type_assigned_use_cases", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeKind", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_verified_credential_type_kinds"); + + b.ToTable("verified_credential_type_kinds", "issuer"); + + b.HasData( + new + { + Id = 1, + Label = "FRAMEWORK" + }, + new + { + Id = 2, + Label = "MEMBERSHIP" + }, + new + { + Id = 3, + Label = "BPN" + }); + }); + + modelBuilder.Entity("ReissuanceProcess", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + + b.HasKey("Id") + .HasName("pk_reissuances"); + + b.ToTable("reissuances", "issuer"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", "CompanySsiDetailStatus") + .WithMany("CompanySsiDetails") + .HasForeignKey("CompanySsiDetailStatusId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_company_ssi_detail_statuses_company_ssi"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ExpiryCheckType", "ExpiryCheckType") + .WithMany("CompanySsiDetails") + .HasForeignKey("ExpiryCheckTypeId") + .HasConstraintName("fk_company_ssi_details_expiry_check_types_expiry_check_type_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Process", "Process") + .WithMany("CompanySsiDetails") + .HasForeignKey("ProcessId") + .HasConstraintName("fk_company_ssi_details_processes_process_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", "VerifiedCredentialExternalTypeDetailVersion") + .WithMany("CompanySsiDetails") + .HasForeignKey("VerifiedCredentialExternalTypeDetailVersionId") + .HasConstraintName("fk_company_ssi_details_verified_credential_external_type_detai"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithMany("CompanySsiDetails") + .HasForeignKey("VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_company_ssi_details_verified_credential_types_verified_cred"); + + b.Navigation("CompanySsiDetailStatus"); + + b.Navigation("ExpiryCheckType"); + + b.Navigation("Process"); + + b.Navigation("VerifiedCredentialExternalTypeDetailVersion"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailAssignedDocument", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") + .WithMany() + .HasForeignKey("CompanySsiDetailId") + .IsRequired() + .HasConstraintName("fk_company_ssi_detail_assigned_documents_company_ssi_details_c"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .IsRequired() + .HasConstraintName("fk_company_ssi_detail_assigned_documents_documents_document_id"); + + b.Navigation("CompanySsiDetail"); + + b.Navigation("Document"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiProcessData", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") + .WithOne("CompanySsiProcessData") + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiProcessData", "CompanySsiDetailId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_ssi_process_data_company_ssi_details_company_ssi_de"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeKind", "CredentialTypeKind") + .WithMany("CompanySsiProcessData") + .HasForeignKey("CredentialTypeKindId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_company_ssi_process_data_verified_credential_type_kinds_cre"); + + b.Navigation("CompanySsiDetail"); + + b.Navigation("CredentialTypeKind"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Document", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentStatus", "DocumentStatus") + .WithMany("Documents") + .HasForeignKey("DocumentStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_document_status_document_status_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentType", "DocumentType") + .WithMany("Documents") + .HasForeignKey("DocumentTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_document_types_document_type_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.MediaType", "MediaType") + .WithMany("Documents") + .HasForeignKey("MediaTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_documents_media_types_media_type_id"); + + b.Navigation("DocumentStatus"); + + b.Navigation("DocumentType"); + + b.Navigation("MediaType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Process", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessType", "ProcessType") + .WithMany("Processes") + .HasForeignKey("ProcessTypeId") + .IsRequired() + .HasConstraintName("fk_processes_process_types_process_type_id"); + + b.Navigation("ProcessType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStep", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Process", "Process") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_process_steps_processes_process_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepStatus", "ProcessStepStatus") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_statuses_process_step_status_id"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepType", "ProcessStepType") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_types_process_step_type_id"); + + b.Navigation("Process"); + + b.Navigation("ProcessStepStatus"); + + b.Navigation("ProcessStepType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalType", "VerifiedCredentialExternalType") + .WithMany("VerifiedCredentialExternalTypeDetailVersions") + .HasForeignKey("VerifiedCredentialExternalTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_external_type_detail_versions_verified_"); + + b.Navigation("VerifiedCredentialExternalType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedExternalType", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalType", "VerifiedCredentialExternalType") + .WithMany("VerifiedCredentialTypeAssignedExternalTypes") + .HasForeignKey("VerifiedCredentialExternalTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_external_types_verified_c"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedExternalType") + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedExternalType", "VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_external_types_verified_c1"); + + b.Navigation("VerifiedCredentialExternalType"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedKind", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedKind") + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedKind", "VerifiedCredentialTypeId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_kinds_verified_credential"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeKind", "VerifiedCredentialTypeKind") + .WithMany("VerifiedCredentialTypeAssignedKinds") + .HasForeignKey("VerifiedCredentialTypeKindId") + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_kinds_verified_credential1"); + + b.Navigation("VerifiedCredentialType"); + + b.Navigation("VerifiedCredentialTypeKind"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedUseCase", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.UseCase", "UseCase") + .WithOne("VerifiedCredentialAssignedUseCase") + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedUseCase", "UseCaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_use_cases_use_cases_use_c"); + + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", "VerifiedCredentialType") + .WithOne("VerifiedCredentialTypeAssignedUseCase") + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeAssignedUseCase", "VerifiedCredentialTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_verified_credential_type_assigned_use_cases_verified_creden"); + + b.Navigation("UseCase"); + + b.Navigation("VerifiedCredentialType"); + }); + + modelBuilder.Entity("ReissuanceProcess", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") + .WithOne("ReissuanceProcess") + .HasForeignKey("ReissuanceProcess", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_reissuances_company_ssi_details_id"); + + b.Navigation("CompanySsiDetail"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => + { + b.Navigation("CompanySsiProcessData"); + + b.Navigation("ReissuanceProcess"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", b => + { + b.Navigation("CompanySsiDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentStatus", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.DocumentType", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ExpiryCheckType", b => + { + b.Navigation("CompanySsiDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.MediaType", b => + { + b.Navigation("Documents"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.Process", b => + { + b.Navigation("CompanySsiDetails"); + + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepStatus", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessStepType", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.ProcessType", b => + { + b.Navigation("Processes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.UseCase", b => + { + b.Navigation("VerifiedCredentialAssignedUseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalType", b => + { + b.Navigation("VerifiedCredentialExternalTypeDetailVersions"); + + b.Navigation("VerifiedCredentialTypeAssignedExternalTypes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", b => + { + b.Navigation("CompanySsiDetails"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialType", b => + { + b.Navigation("CompanySsiDetails"); + + b.Navigation("VerifiedCredentialTypeAssignedExternalType"); + + b.Navigation("VerifiedCredentialTypeAssignedKind"); + + b.Navigation("VerifiedCredentialTypeAssignedUseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialTypeKind", b => + { + b.Navigation("CompanySsiProcessData"); + + b.Navigation("VerifiedCredentialTypeAssignedKinds"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs new file mode 100644 index 00000000..d8ba0f7a --- /dev/null +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations +{ + /// + public partial class ReissuanceChanges : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "reissuances", + schema: "issuer", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + reissued_credential_id = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_reissuances", x => x.id); + table.ForeignKey( + name: "fk_reissuances_company_ssi_details_id", + column: x => x.id, + principalSchema: "issuer", + principalTable: "company_ssi_details", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "reissuances", + schema: "issuer"); + } + } +} diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs index e0972ada..fd49cb11 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -22,8 +22,11 @@ using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; + using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities; +#nullable disable + namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations { [DbContext(typeof(IssuerDbContext))] @@ -35,7 +38,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder .HasDefaultSchema("issuer") .UseCollation("en_US.utf8") - .HasAnnotation("ProductVersion", "8.0.5") + .HasAnnotation("ProductVersion", "8.0.7") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -1341,6 +1344,22 @@ protected override void BuildModel(ModelBuilder modelBuilder) }); }); + modelBuilder.Entity("ReissuanceProcess", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + + b.HasKey("Id") + .HasName("pk_reissuances"); + + b.ToTable("reissuances", "issuer"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", "CompanySsiDetailStatus") @@ -1561,9 +1580,23 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("VerifiedCredentialType"); }); + modelBuilder.Entity("ReissuanceProcess", b => + { + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") + .WithOne("ReissuanceProcess") + .HasForeignKey("ReissuanceProcess", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_reissuances_company_ssi_details_id"); + + b.Navigation("CompanySsiDetail"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.Navigation("CompanySsiProcessData"); + + b.Navigation("ReissuanceProcess"); }); modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", b => From bcd275cddeef7164ec99e3ebe5ac73fb73869952 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 16:22:46 +0200 Subject: [PATCH 08/26] feat: Added revocation process for reissued credentials. --- src/SsiCredentialIssuer.sln | 2 +- .../ReissuanceServiceExtensions.cs} | 9 ++- .../Handler/CredentialIssuerHandler.cs | 2 +- .../Handler/ICredentialIssuerHandler.cs | 2 +- .../Handler/IssuerCredentialRequest.cs | 2 +- .../Program.cs | 10 ++- .../Properties/launchSettings.json | 0 .../Services/IReissuanceService.cs | 6 ++ .../Services/ReissuanceService.cs} | 20 +++-- ...SsiCredentialIssuer.Reissuance.App.csproj} | 0 .../Services/IRenewalService.cs | 6 -- .../appsettings.json | 39 --------- .../Repositories/IReissuanceRepository.cs | 6 ++ .../Repositories/ReissuanceRepository.cs | 14 ++++ .../Enums/ProcessStepTypeId.cs | 1 + ...40812093252_ReissuanceChanges.Designer.cs} | 7 +- ...cs => 20240812093252_ReissuanceChanges.cs} | 12 +++ .../IssuerDbContextModelSnapshot.cs | 31 +++---- .../CredentialCreationProcessHandler.cs | 2 +- .../CredentialHandlerExtensions.cs | 8 ++ .../CredentialReissuanceProcessHandler.cs | 81 +++++++++++++++++++ .../ICredentialReissuanceProcessHandler.cs | 27 +++++++ .../CredentialCreationProcessTypeExecutor.cs | 9 ++- .../CredentialProcessCollectionExtensions.cs | 1 + src/processes/Processes.Worker/Program.cs | 4 +- 25 files changed, 207 insertions(+), 94 deletions(-) rename src/credentials/{SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs => SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs} (84%) rename src/credentials/{SsiCredentialIssuer.Renewal.App => SsiCredentialIssuer.Reissuance.App}/Handler/CredentialIssuerHandler.cs (98%) rename src/credentials/{SsiCredentialIssuer.Renewal.App => SsiCredentialIssuer.Reissuance.App}/Handler/ICredentialIssuerHandler.cs (94%) rename src/credentials/{SsiCredentialIssuer.Renewal.App => SsiCredentialIssuer.Reissuance.App}/Handler/IssuerCredentialRequest.cs (95%) rename src/credentials/{SsiCredentialIssuer.Renewal.App => SsiCredentialIssuer.Reissuance.App}/Program.cs (85%) rename src/credentials/{SsiCredentialIssuer.Renewal.App => SsiCredentialIssuer.Reissuance.App}/Properties/launchSettings.json (100%) create mode 100644 src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs rename src/credentials/{SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs => SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs} (92%) rename src/credentials/{SsiCredentialIssuer.Renewal.App/SsiCredentialIssuer.Renewal.App.csproj => SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj} (100%) delete mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/Services/IRenewalService.cs delete mode 100644 src/credentials/SsiCredentialIssuer.Renewal.App/appsettings.json rename src/database/SsiCredentialIssuer.Migrations/Migrations/{20240809153759_ReissuanceChanges.Designer.cs => 20240812093252_ReissuanceChanges.Designer.cs} (99%) rename src/database/SsiCredentialIssuer.Migrations/Migrations/{20240809153759_ReissuanceChanges.cs => 20240812093252_ReissuanceChanges.cs} (77%) create mode 100644 src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs create mode 100644 src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs diff --git a/src/SsiCredentialIssuer.sln b/src/SsiCredentialIssuer.sln index 6a64c248..19600845 100644 --- a/src/SsiCredentialIssuer.sln +++ b/src/SsiCredentialIssuer.sln @@ -62,7 +62,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Callback.Service", "externa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Callback.Service.Tests", "..\tests\externalservices\Callback.Service.Tests\Callback.Service.Tests.csproj", "{61DB2ADF-DBC1-4647-AAD2-A8E992E75B37}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Renewal.App", "credentials\SsiCredentialIssuer.Renewal.App\SsiCredentialIssuer.Renewal.App.csproj", "{2757DB44-F658-420F-B00A-48EC6DBA6035}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Reissuance.App", "credentials\SsiCredentialIssuer.Reissuance.App\SsiCredentialIssuer.Reissuance.App.csproj", "{2757DB44-F658-420F-B00A-48EC6DBA6035}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "credentials\SsiCredentialIssuer.Credential.Library", "credentials\SsiCredentialIssuer.Credential.Library\SsiCredentialIssuer.Credential.Library.csproj", "{832CA2B5-E08D-4EB6-9C99-020E01A86A2C}" EndProject diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs similarity index 84% rename from src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs index ed9d968c..544f3c8f 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/DependencyInjection/RenewalServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs @@ -20,14 +20,15 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; /// /// Extension method to register the renewal service and dependent services /// -public static class RenewalServiceExtensions +public static class ReissuanceServiceExtensions { /// /// Adds the renewal service @@ -37,7 +38,7 @@ public static class RenewalServiceExtensions public static IServiceCollection AddRenewalService(this IServiceCollection services) { services - .AddTransient() + .AddTransient() .AddTransient() .AddCredentialIssuerHandlerService(); diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs similarity index 98% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs index 5fd9431c..d647b29c 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/CredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs @@ -27,7 +27,7 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; /// public class CredentialIssuerHandler : ICredentialIssuerHandler diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs similarity index 94% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs index 211d6c92..2b17d162 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/ICredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; /// /// Handles the re-issuance of a new credential then creates a new create credential process diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs similarity index 95% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs index 8303080f..2724ebdc 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Handler/IssuerCredentialRequest.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs similarity index 85% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs index 66b0ff86..bb6f08d0 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs @@ -22,11 +22,12 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; using Serilog; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; LoggingExtensions.EnsureInitialized(); Log.Information("Building worker"); @@ -37,9 +38,10 @@ .ConfigureServices((hostContext, services) => { services - //.AddTransient() + .AddTransient() .AddProcessIdentity(hostContext.Configuration.GetSection("ProcessIdentity")) .AddIssuerRepositories(hostContext.Configuration) + .AddPortalService(hostContext.Configuration.GetSection("Portal")) .AddICredentialServiceExtensions(hostContext.Configuration) .AddRenewalService(); }) @@ -56,7 +58,7 @@ }; Log.Information("Start processing"); - var workerInstance = host.Services.GetRequiredService(); + var workerInstance = host.Services.GetRequiredService(); await workerInstance.ExecuteAsync(tokenSource.Token).ConfigureAwait(ConfigureAwaitOptions.None); Log.Information("Execution finished shutting down"); } diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json b/src/credentials/SsiCredentialIssuer.Reissuance.App/Properties/launchSettings.json similarity index 100% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Properties/launchSettings.json rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Properties/launchSettings.json diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs new file mode 100644 index 00000000..10e8587f --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs @@ -0,0 +1,6 @@ +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; + +public interface IReissuanceService +{ + Task ExecuteAsync(CancellationToken stoppingToken); +} diff --git a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs similarity index 92% rename from src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index c343c4ec..40f6728b 100644 --- a/src/credentials/SsiCredentialIssuer.Renewal.App/Services/RenewalService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -23,40 +23,38 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; -using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Text.Json; -using Microsoft.Extensions.Options; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; /// /// Service to re-issue credentials that will expire in the day after. /// -public class RenewalService : IRenewalService +public class ReissuanceService : IReissuanceService { private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; private readonly IServiceScopeFactory _serviceScopeFactory; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ICredentialIssuerHandler _credentialIssuerHandler; /// - /// Creates a new instance of + /// Creates a new instance of /// /// access to the services /// access to the credential issuer handler service /// the logger - public RenewalService(IServiceScopeFactory serviceScopeFactory, + public ReissuanceService(IServiceScopeFactory serviceScopeFactory, ICredentialIssuerHandler credentialIssuerHandler, - ILogger logger) + ILogger logger) { _serviceScopeFactory = serviceScopeFactory; _credentialIssuerHandler = credentialIssuerHandler; _logger = logger; } - + /// /// Handles the process of re-issuing new verifiable credentias /// @@ -89,7 +87,7 @@ private async Task ProcessCredentials(IAsyncEnumerable ssi.ReissuedCredentialId == companySsiDetaillId) + .Select(ssi => ssi.Id).SingleOrDefault(); + } + + public bool IsReissuedCredential(Guid companySsiDetaillId) + { + return _dbContext.Reissuances + .Where(ssi => ssi.ReissuedCredentialId == companySsiDetaillId) + .Select(ssi => true).SingleOrDefault(); + } } diff --git a/src/database/SsiCredentialIssuer.Entities/Enums/ProcessStepTypeId.cs b/src/database/SsiCredentialIssuer.Entities/Enums/ProcessStepTypeId.cs index e870cf07..199208f0 100644 --- a/src/database/SsiCredentialIssuer.Entities/Enums/ProcessStepTypeId.cs +++ b/src/database/SsiCredentialIssuer.Entities/Enums/ProcessStepTypeId.cs @@ -27,6 +27,7 @@ public enum ProcessStepTypeId SAVE_CREDENTIAL_DOCUMENT = 3, CREATE_CREDENTIAL_FOR_HOLDER = 4, TRIGGER_CALLBACK = 5, + REVOKE_REISSUED_CREDENTIAL = 6, // DECLINE PROCESS REVOKE_CREDENTIAL = 100, diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs similarity index 99% rename from src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs rename to src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs index 35c601c5..dc4dedf5 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.Designer.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs @@ -13,7 +13,7 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations { [DbContext(typeof(IssuerDbContext))] - [Migration("20240809153759_ReissuanceChanges")] + [Migration("20240812093252_ReissuanceChanges")] partial class ReissuanceChanges { /// @@ -958,6 +958,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) Label = "TRIGGER_CALLBACK" }, new + { + Id = 6, + Label = "REVOKE_REISSUED_CREDENTIAL" + }, + new { Id = 100, Label = "REVOKE_CREDENTIAL" diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs similarity index 77% rename from src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs rename to src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs index d8ba0f7a..97450f9e 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240809153759_ReissuanceChanges.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs @@ -30,6 +30,12 @@ protected override void Up(MigrationBuilder migrationBuilder) principalColumn: "id", onDelete: ReferentialAction.Cascade); }); + + migrationBuilder.InsertData( + schema: "issuer", + table: "process_step_types", + columns: new[] { "id", "label" }, + values: new object[] { 6, "REVOKE_REISSUED_CREDENTIAL" }); } /// @@ -38,6 +44,12 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "reissuances", schema: "issuer"); + + migrationBuilder.DeleteData( + schema: "issuer", + table: "process_step_types", + keyColumn: "id", + keyValue: 6); } } } diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs index fd49cb11..ba54338a 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs @@ -1,28 +1,10 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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; using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; - +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities; #nullable disable @@ -973,6 +955,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) Label = "TRIGGER_CALLBACK" }, new + { + Id = 6, + Label = "REVOKE_REISSUED_CREDENTIAL" + }, + new { Id = 100, Label = "REVOKE_CREDENTIAL" diff --git a/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs b/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs index e898ea10..590cdc00 100644 --- a/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs @@ -62,7 +62,7 @@ public CredentialCreationProcessHandler(IIssuerRepositories issuerRepositories, await _walletBusinessLogic.SignCredential(credentialId, externalCredentialId!.Value, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); return ( - Enumerable.Repeat(ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, 1), + Enumerable.Repeat(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, 1), ProcessStepStatusId.DONE, false, null); diff --git a/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs b/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs index e4d243eb..a0b5da2f 100644 --- a/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs +++ b/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs @@ -40,4 +40,12 @@ public static IServiceCollection AddCredentialExpiryProcessHandler(this IService return services; } + + public static IServiceCollection AddCredentialReissuedProcessHandler(this IServiceCollection services) + { + services + .AddTransient(); + + return services; + } } diff --git a/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs new file mode 100644 index 00000000..2412ced2 --- /dev/null +++ b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs @@ -0,0 +1,81 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; + +public class CredentialReissuanceProcessHandler : ICredentialReissuanceProcessHandler +{ + private readonly IIssuerRepositories _issuerRepositories; + private readonly ILogger _logger; + + public CredentialReissuanceProcessHandler(IIssuerRepositories issuerRepositories, ILogger logger) + { + _issuerRepositories = issuerRepositories; + _logger = logger; + } + + public Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> RevokeReissuedCredential(Guid credentialId) + { + var isReissuedCredential = _issuerRepositories.GetInstance().IsReissuedCredential(credentialId); + + if (isReissuedCredential) + { + CreateRevokeCredentialProcess(credentialId); + } + + (IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage) result = ( + Enumerable.Repeat(ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, 1), + ProcessStepStatusId.DONE, + false, + null); + + return Task.FromResult(result); + } + + private void CreateRevokeCredentialProcess(Guid credentialId) + { + var companySsiRepository = _issuerRepositories.GetInstance(); + var processStepRepository = _issuerRepositories.GetInstance(); + var processId = processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL).Id; + var credentialToRevokeId = _issuerRepositories.GetInstance().GetCompanySsiDetailId(credentialId); + + try + { + processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, processId); + companySsiRepository.AttachAndModifyCompanySsiDetails(credentialToRevokeId, c => + { + c.ProcessId = null; + }, + c => + { + c.ProcessId = processId; + }); + } + catch (Exception ex) + { + _logger.LogError("The revokation of the reissued credential failed with error: {Errors}", ex.Message); + } + } +} + diff --git a/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs new file mode 100644 index 00000000..6ee1d05c --- /dev/null +++ b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs @@ -0,0 +1,27 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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.SsiCredentialIssuer.Entities.Enums; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; + +public interface ICredentialReissuanceProcessHandler +{ + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> RevokeReissuedCredential(Guid credentialId); +} diff --git a/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs b/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs index 69357b87..70978ec0 100644 --- a/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs +++ b/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs @@ -18,6 +18,7 @@ ********************************************************************************/ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; @@ -31,10 +32,12 @@ public class CredentialCreationProcessTypeExecutor : IProcessTypeExecutor { private readonly IIssuerRepositories _issuerRepositories; private readonly ICredentialCreationProcessHandler _credentialCreationProcessHandler; + private readonly ICredentialReissuanceProcessHandler _credentialReissuanceProcessHandler; private readonly IEnumerable _executableProcessSteps = ImmutableArray.Create( ProcessStepTypeId.CREATE_CREDENTIAL, ProcessStepTypeId.SIGN_CREDENTIAL, + ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, ProcessStepTypeId.CREATE_CREDENTIAL_FOR_HOLDER, ProcessStepTypeId.TRIGGER_CALLBACK); @@ -43,10 +46,12 @@ public class CredentialCreationProcessTypeExecutor : IProcessTypeExecutor public CredentialCreationProcessTypeExecutor( IIssuerRepositories issuerRepositories, - ICredentialCreationProcessHandler credentialCreationProcessHandler) + ICredentialCreationProcessHandler credentialCreationProcessHandler, + ICredentialReissuanceProcessHandler credentialReissuanceProcessHandler) { _issuerRepositories = issuerRepositories; _credentialCreationProcessHandler = credentialCreationProcessHandler; + _credentialReissuanceProcessHandler = credentialReissuanceProcessHandler; } public ProcessTypeId GetProcessTypeId() => ProcessTypeId.CREATE_CREDENTIAL; @@ -86,6 +91,8 @@ public CredentialCreationProcessTypeExecutor( .ConfigureAwait(ConfigureAwaitOptions.None), ProcessStepTypeId.SIGN_CREDENTIAL => await _credentialCreationProcessHandler.SignCredential(_credentialId, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None), + ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL => await _credentialReissuanceProcessHandler.RevokeReissuedCredential(_credentialId) + .ConfigureAwait(ConfigureAwaitOptions.None), ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT => await _credentialCreationProcessHandler.SaveCredentialDocument(_credentialId, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None), ProcessStepTypeId.CREATE_CREDENTIAL_FOR_HOLDER => await _credentialCreationProcessHandler.CreateCredentialForHolder(_credentialId, cancellationToken) diff --git a/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs b/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs index b6732f70..f8c254a1 100644 --- a/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs +++ b/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs @@ -18,6 +18,7 @@ ********************************************************************************/ using Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Expiry; using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library; diff --git a/src/processes/Processes.Worker/Program.cs b/src/processes/Processes.Worker/Program.cs index 77400dd0..59382a75 100644 --- a/src/processes/Processes.Worker/Program.cs +++ b/src/processes/Processes.Worker/Program.cs @@ -22,6 +22,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; using Org.Eclipse.TractusX.SsiCredentialIssuer.Callback.Service.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; @@ -45,7 +46,8 @@ .AddCallbackService(hostContext.Configuration.GetSection("Callback")) .AddWalletService(hostContext.Configuration) .AddCredentialCreationProcessExecutor() - .AddCredentialExpiryProcessExecutor(); + .AddCredentialExpiryProcessExecutor() + .AddCredentialReissuedProcessHandler(); }) .AddLogging() .Build(); From 0055d0112bfae861997af2080f455ec66bb97caa Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 18:22:03 +0200 Subject: [PATCH 09/26] feat: Added reissuance expiry settings, docker file and helm configuration --- README.md | 1 + .../templates/cronjob-reissuance-app.yaml | 95 +++++++++++++++++++ charts/ssi-credential-issuer/values.yaml | 21 ++++ docker/Dockerfile-credential-reissuance-app | 35 +++++++ docker/notice-credential-reissuance-app.md | 22 +++++ docs/database/db-view.md | 11 +++ .../consortia/helm-values/values-dev.yaml | 7 ++ .../consortia/helm-values/values-int.yaml | 4 + .../consortia/helm-values/values-rc.yaml | 7 ++ environments/helm-values/values-int.yaml | 4 + .../ReissuanceExpirySettings.cs | 34 +++++++ .../ReissuanceServiceExtensions.cs | 4 +- .../Program.cs | 2 +- .../Services/ReissuanceService.cs | 8 +- 14 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml create mode 100644 docker/Dockerfile-credential-reissuance-app create mode 100644 docker/notice-credential-reissuance-app.md create mode 100644 src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs diff --git a/README.md b/README.md index 10c0e210..2fe509a8 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ See Docker notice files for more information: - [credential-issuer-service](./docker//notice-credential-issuer-service.md) - [credential-issuer-processes-worker](./docker/notice-credential-issuer-processes-worker.md) - [credential-expiry-app](./docker/notice-credential-expiry-app.md) +- [credential-reissuance-app](./docker/notice-credential-reissuance-app.md) - [credential-issuer-migrations](./docker/notice-credential-issuer-migrations.md) ## Contributing diff --git a/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml new file mode 100644 index 00000000..feae4b77 --- /dev/null +++ b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml @@ -0,0 +1,95 @@ +############################################################### +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# 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 +############################################################### + +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ include "issuer.fullname" . }}-{{ .Values.credentialReissuance.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "issuer.labels" . | nindent 4 }} +spec: + schedule: "0 0 * * *" + concurrencyPolicy: Forbid + jobTemplate: + metadata: + name: {{ include "issuer.fullname" . }}-{{ .Values.credentialReissuance.name }} + spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: {{ include "issuer.fullname" . }}-{{ .Values.credentialReissuance.name }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + image: "{{ .Values.credentialReissuance.image.name }}:{{ .Values.credentialReissuance.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.credentialReissuance.imagePullPolicy }}" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "ISSUER_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ template "issuer.postgresSecretName" . }}" + key: "password" + - name: "CONNECTIONSTRINGS__ISSUERDB" + value: "Server={{ template "issuer.postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(ISSUER_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "ISSUER_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.secret }}" + key: "password" + - name: "CONNECTIONSTRINGS__ISSUERDB" + value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(ISSUER_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + - name: "EXPIRY__EXPIREDVCSTOREISSUEINDAYS" + value: "{{ .Values.credentialReissuance.expiry.expiredVcsToReissueInDays }}" + - name: "PORTAL__CLIENTID" + value: "{{ .Values.service.portal.clientId }}" + - name: "PORTAL__CLIENTSECRET" + valueFrom: + secretKeyRef: + name: "{{ template "issuer.secretName" . }}" + key: "portal-client-secret" + - name: "PORTAL__GRANTTYPE" + value: "{{ .Values.processesworker.portal.grantType }}" + - name: "PORTAL__TOKENADDRESS" + value: "{{ .Values.centralidp.address }}{{ .Values.centralidp.tokenPath }}" + - name: "PORTAL__BASEADDRESS" + value: "{{ .Values.portalBackendAddress }}" + - name: "PORTAL__PASSWORD" + value: "empty" + - name: "PORTAL__SCOPE" + value: "{{ .Values.processesworker.portal.scope }}" + - name: "PORTAL__USERNAME" + value: "empty" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + resources: + {{- toYaml .Values.credentialReissuance.resources | nindent 14 }} diff --git a/charts/ssi-credential-issuer/values.yaml b/charts/ssi-credential-issuer/values.yaml index 6424b67c..a69833c2 100644 --- a/charts/ssi-credential-issuer/values.yaml +++ b/charts/ssi-credential-issuer/values.yaml @@ -147,6 +147,27 @@ credentialExpiry: expiredVcsToDeleteInMonth: 12 inactiveVcsToDeleteInWeeks: 12 +credentialReissuance: + name: "reissuance" + image: + name: "docker.io/tractusx/ssi-credential-reissuance-app" + tag: "" + imagePullPolicy: "IfNotPresent" + # -- We recommend to review the default resource limits as this should a conscious choice. + resources: + requests: + cpu: 15m + memory: 105M + limits: + cpu: 45m + memory: 105M + processIdentity: + identityId: 23db9ff3-20c7-476c-ba70-6bdfe5c97104 + logging: + default: "Information" + expiry: + expiredVcsToReissueInDays: 1 + # -- Secret containing the client-secrets for the connection to portal and wallet # as well as encryptionKeys for issuer.credential and processesworker.wallet existingSecret: "" diff --git a/docker/Dockerfile-credential-reissuance-app b/docker/Dockerfile-credential-reissuance-app new file mode 100644 index 00000000..86d1e483 --- /dev/null +++ b/docker/Dockerfile-credential-reissuance-app @@ -0,0 +1,35 @@ +############################################################### +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# 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 +############################################################### + +FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS publish +ARG TARGETARCH +WORKDIR / +COPY LICENSE NOTICE.md DEPENDENCIES / +COPY src/ src/ +RUN dotnet restore "src/credentials/SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj" +WORKDIR /src/credentials/SsiCredentialIssuer.Reissuance.App +RUN dotnet publish "SsiCredentialIssuer.Reissuance.App.csproj" -c Release -o /app/publish + +FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine +ENV COMPlus_EnableDiagnostics=0 +WORKDIR /app +COPY --from=publish /app/publish . +RUN chown -R 1000:3000 /app +USER 1000:3000 +ENTRYPOINT ["dotnet", "Org.Eclipse.TractusX.SsiCredentialIssuer.reissuance.App.dll"] diff --git a/docker/notice-credential-reissuance-app.md b/docker/notice-credential-reissuance-app.md new file mode 100644 index 00000000..59c12893 --- /dev/null +++ b/docker/notice-credential-reissuance-app.md @@ -0,0 +1,22 @@ +## Notice for Docker image + +DockerHub: [https://hub.docker.com/r/tractusx/ssi-credential-reissuance-app](https://hub.docker.com/r/tractusx/ssi-credential-reissuance-app) + +Eclipse Tractus-X product(s) installed within the image: + +__Credential Reissuance App__ + +- GitHub: https://github.com/eclipse-tractusx/ssi-credential-issuer +- Project home: https://projects.eclipse.org/projects/automotive.tractusx +- Dockerfile: https://github.com/eclipse-tractusx/ssi-credential-issuer/blob/main/docker/Dockerfile-credential-reissuance-app +- Project license: [Apache License, Version 2.0](https://github.com/eclipse-tractusx/ssi-credential-issuer/blob/main/LICENSE) + +__Used base images__ + +- Dockerfile: [mcr.microsoft.com/dotnet/runtime:8.0-alpine](https://github.com/dotnet/dotnet-docker/blob/main/src/runtime/8.0/alpine3.19/amd64/Dockerfile) +- GitHub project: [https://github.com/dotnet/dotnet-docker](https://github.com/dotnet/dotnet-docker) +- DockerHub: [https://hub.docker.com/_/microsoft-dotnet-runtime](https://hub.docker.com/_/microsoft-dotnet-runtime) + +As with all Docker images, these likely also contain other software which may be under other licenses (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained). + +As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within. diff --git a/docs/database/db-view.md b/docs/database/db-view.md index 20076d1c..c5ad460f 100644 --- a/docs/database/db-view.md +++ b/docs/database/db-view.md @@ -135,6 +135,10 @@ erDiagram timestamp lock_expiry_date uuid version } + REISSUANCES { + uuid id FK + uuid reissued_credential_id + } USE_CASES { uuid id PK text name @@ -187,6 +191,7 @@ erDiagram PROCESS_STEPS ||--|| PROCESS_STEP_TYPES : process_step_type_id PROCESS_STEPS ||--|| PROCESSES : process_id PROCESSES ||--|| PROCESS_TYPES : process_type_id + REISSUANCES ||--|| COMPANY_SSI_DETAILS : company_ssi_detail_id VERIFIED_CREDENTIAL_EXTERNAL_TYPE_DETAIL_VERSIONS ||--|| VERIFIED_CREDENTIAL_EXTERNAL_TYPES : verified_credential_external_type_id VERIFIED_CREDENTIAL_TYPE_ASSIGNED_EXTERNAL_TYPES ||--|| VERIFIED_CREDENTIAL_EXTERNAL_TYPES : has VERIFIED_CREDENTIAL_TYPE_ASSIGNED_EXTERNAL_TYPES ||--|| VERIFIED_CREDENTIAL_TYPES : has @@ -322,6 +327,7 @@ label (TEXT): The label of the process step type. - `CREATE_CREDENTIAL`: Creates a credential in the issuer wallet. - `SIGN_CREDENTIAL`: Signs the credential in the issuer wallet. +- `REVOKE_REISSUED_CREDENTIAL`: Revoke reissued credentials. - `SAVE_CREDENTIAL_DOCUMENT`: Saves the credential in the database. - `CREATE_CREDENTIAL_FOR_HOLDER`: Creates the credential in the holder wallet. - `TRIGGER_CALLBACK`: Triggers the callback to the portal. @@ -356,6 +362,11 @@ process_type_id (INTEGER): A foreign key referencing id in the PROCESS_TYPES tab lock_expiry_date (TIMESTAMP): The lock expiry date of the process. version (UUID): The version of the process. +### REISSUANCES + +id (UUID): A foreign key referencing id in the COMPANY_SSI_DETAILS. +reissued_credential_id(UUID): Id that identifies the reissued credential added to the COMPANY_SSI_DETAILS. + ### USE_CASES id (UUID): A unique identifier for the use case. This is the primary key of the table. diff --git a/environments/consortia/helm-values/values-dev.yaml b/environments/consortia/helm-values/values-dev.yaml index 6b014515..5bf99328 100644 --- a/environments/consortia/helm-values/values-dev.yaml +++ b/environments/consortia/helm-values/values-dev.yaml @@ -86,6 +86,13 @@ credentialExpiry: logging: default: "Debug" +credentialReissuance: + image: + tag: "main" + imagePullPolicy: "Always" + logging: + default: "Debug" + centralidp: address: "https://centralidp.dev.demo.catena-x.net" jwtBearerOptions: diff --git a/environments/consortia/helm-values/values-int.yaml b/environments/consortia/helm-values/values-int.yaml index ee584e55..b51ec389 100644 --- a/environments/consortia/helm-values/values-int.yaml +++ b/environments/consortia/helm-values/values-int.yaml @@ -74,6 +74,10 @@ credentialExpiry: logging: default: "Debug" +credentialReissuance: + logging: + default: "Debug" + centralidp: address: "https://centralidp.int.demo.catena-x.net" jwtBearerOptions: diff --git a/environments/consortia/helm-values/values-rc.yaml b/environments/consortia/helm-values/values-rc.yaml index 51a81e6a..5f6fd5d2 100644 --- a/environments/consortia/helm-values/values-rc.yaml +++ b/environments/consortia/helm-values/values-rc.yaml @@ -86,6 +86,13 @@ credentialExpiry: logging: default: "Debug" +credentialReissuance: + image: + tag: "rc" + imagePullPolicy: "Always" + logging: + default: "Debug" + centralidp: address: "https://centralidp-rc.dev.demo.catena-x.net" jwtBearerOptions: diff --git a/environments/helm-values/values-int.yaml b/environments/helm-values/values-int.yaml index ef8b970c..a8aef232 100644 --- a/environments/helm-values/values-int.yaml +++ b/environments/helm-values/values-int.yaml @@ -73,6 +73,10 @@ credentialExpiry: logging: default: "Debug" +credentialReissuance: + logging: + default: "Debug" + centralidp: address: "https://centralidp.int.catena-x.net" jwtBearerOptions: diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs new file mode 100644 index 00000000..ba8afa8a --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs @@ -0,0 +1,34 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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.ComponentModel.DataAnnotations; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; + +/// +/// Settings for the ReissuanceExpirySettings +/// +public class ReissuanceExpirySettings +{ + /// + /// Vcs which are about to expire in the next day(s). + /// + [Required] + public int ExpiredVcsToReissueInDays { get; init; } +} diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs index 544f3c8f..2d71b730 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs @@ -34,9 +34,11 @@ public static class ReissuanceServiceExtensions /// Adds the renewal service /// /// the services + /// Expiry section /// the enriched service collection - public static IServiceCollection AddRenewalService(this IServiceCollection services) + public static IServiceCollection AddReissuanceService(this IServiceCollection services, IConfigurationSection section) { + services.AddOptions().Bind(section); services .AddTransient() .AddTransient() diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs index bb6f08d0..b4588a2c 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs @@ -43,7 +43,7 @@ .AddIssuerRepositories(hostContext.Configuration) .AddPortalService(hostContext.Configuration.GetSection("Portal")) .AddICredentialServiceExtensions(hostContext.Configuration) - .AddRenewalService(); + .AddReissuanceService(hostContext.Configuration.GetSection("Expiry")); }) .AddLogging() .Build(); diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index 40f6728b..8e5c39db 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -28,6 +28,8 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Text.Json; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; +using Microsoft.Extensions.Options; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; @@ -40,18 +42,22 @@ public class ReissuanceService : IReissuanceService private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ILogger _logger; private readonly ICredentialIssuerHandler _credentialIssuerHandler; + private readonly ReissuanceExpirySettings _settings; /// /// Creates a new instance of /// /// access to the services /// access to the credential issuer handler service + /// access to the expiry section settings /// the logger public ReissuanceService(IServiceScopeFactory serviceScopeFactory, ICredentialIssuerHandler credentialIssuerHandler, + IOptions options, ILogger logger) { _serviceScopeFactory = serviceScopeFactory; _credentialIssuerHandler = credentialIssuerHandler; + _settings = options.Value; _logger = logger; } @@ -68,7 +74,7 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) using var processServiceScope = _serviceScopeFactory.CreateScope(); var dateTimeProvider = processServiceScope.ServiceProvider.GetRequiredService(); var repositories = processServiceScope.ServiceProvider.GetRequiredService(); - var expirationDate = dateTimeProvider.OffsetNow.AddDays(1); + var expirationDate = dateTimeProvider.OffsetNow.AddDays(_settings.ExpiredVcsToReissueInDays); var companySsiDetailsRepository = repositories.GetInstance(); var credentialIssuerHandler = processServiceScope.ServiceProvider.GetRequiredService(); var credentialsAboutToExpire = companySsiDetailsRepository.GetCredentialsAboutToExpire(expirationDate); From b0fcc9a85dcff4a28938c872e861a656a0de0d5e Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 18:59:01 +0200 Subject: [PATCH 10/26] feat: added credential settings to reissuance cronjob --- .../templates/cronjob-reissuance-app.yaml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml index feae4b77..174ed091 100644 --- a/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml +++ b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml @@ -25,7 +25,7 @@ metadata: labels: {{- include "issuer.labels" . | nindent 4 }} spec: - schedule: "0 0 * * *" + schedule: "0 23 * * *" concurrencyPolicy: Forbid jobTemplate: metadata: @@ -87,6 +87,25 @@ spec: value: "{{ .Values.processesworker.portal.scope }}" - name: "PORTAL__USERNAME" value: "empty" + - name: "CREDENTIAL__ISSUERDID" + value: "{{ .Values.service.credential.issuerDid }}" + - name: "CREDENTIAL__ISSUERBPN" + value: "{{ .Values.service.credential.issuerBpn }}" + - name: "CREDENTIAL__STATUSLISTURL" + value: "{{ .Values.service.credential.statusListUrl }}" + - name: "CREDENTIAL__ENCRYPTIONCONFIG__ENCRYPTIONCONFIGINDEX" + value: "{{ .Values.service.credential.encryptionConfigIndex }}" + - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__INDEX" + value: "{{ .Values.service.credential.encryptionConfigs.index0.index}}" + - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__CIPHERMODE" + value: "{{ .Values.service.credential.encryptionConfigs.index0.cipherMode}}" + - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__PADDINGMODE" + value: "{{ .Values.service.credential.encryptionConfigs.index0.paddingMode}}" + - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__ENCRYPTIONKEY" + valueFrom: + secretKeyRef: + name: "{{ template "issuer.secretName" . }}" + key: "credential-encryption-key0" ports: - name: http containerPort: {{ .Values.portContainer }} From 92c626c354b3079878a71b4df3f5f8aa6b1779e5 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 19:08:20 +0200 Subject: [PATCH 11/26] fix: adding a correct format --- .../Services/ReissuanceService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index 8e5c39db..118ab6e5 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -90,7 +90,7 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) private async Task ProcessCredentials(IAsyncEnumerable credentialsAboutToExpire, IDateTimeProvider dateTimeProvider) { - await foreach(var credential in credentialsAboutToExpire) + await foreach (var credential in credentialsAboutToExpire) { var expirationDate = dateTimeProvider.OffsetNow.AddMonths(12); From e2e53dafc6fcb85cee98d0e2ae1908b6fc1ef0bf Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 19:11:52 +0200 Subject: [PATCH 12/26] feat: added a new app settings for reissuance app --- .../appsettings.json | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json b/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json new file mode 100644 index 00000000..fffd6a79 --- /dev/null +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json @@ -0,0 +1,57 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console" ], + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "System": "Information", + "Microsoft.Hosting.Lifetime": "Information", + "Org.Eclipse.TractusX.SsiCredentialIssuer": "Information" + } + }, + "WriteTo": [ + { "Name": "Console" } + ], + "Enrich": [ + "FromLogContext" + ], + "Properties": { + "Application": "Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App" + } + }, + "ConnectionStrings": { + "IssuerDb": "Server=localhost;Database=issuer;Port=5432;User Id=issuer;Password=postgres;Ssl Mode=Disable;" + }, + "ProcessIdentity": { + "IdentityId": "" + }, + "Portal": { + "Username": "", + "Password": "", + "ClientId": "", + "GrantType": "", + "ClientSecret": "", + "Scope": "", + "TokenAddress": "", + "BaseAddress": "" + }, + "Expiry": { + "ExpiredVcsToReissueInDays": 1 + }, + "Credential": { + "IssuerDid": "", + "IssuerBpn": "", + "StatusListUrl": "", + "MaxPageSize": 0, + "EncryptionConfigIndex": 0, + "EncryptionConfigs": [ + { + "Index": 0, + "EncryptionKey": "", + "CipherMode": "", + "PaddingMode": "" + } + ] + } +} From 39d47c598d74d9f175da10edcae5df11497532ed Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 19:22:15 +0200 Subject: [PATCH 13/26] feat: added a generic contex to issuer service buisiness logic --- .../BusinessLogic/IssuerBusinessLogic.cs | 8 ++++---- .../SsiCredentialIssuer.Service.csproj | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs index b1b52548..c24a5cc9 100644 --- a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs +++ b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs @@ -34,6 +34,7 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Identity; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Globalization; using System.Security.Cryptography; using System.Text; @@ -47,7 +48,6 @@ public class IssuerBusinessLogic : IIssuerBusinessLogic { private const string StatusList = "StatusList2021"; private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - private static readonly IEnumerable Context = new[] { "https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0" }; private static readonly Regex UrlPathInvalidCharsRegex = new("""[""<>#%{}|\\^~\[\]`]+""", RegexOptions.Compiled, TimeSpan.FromSeconds(1)); private readonly IIssuerRepositories _repositories; @@ -341,7 +341,7 @@ public async Task CreateBpnCredential(CreateBpnCredentialRequest requestDa var expiryDate = DateTimeOffset.UtcNow.AddMonths(12); var schemaData = new BpnCredential( Guid.NewGuid(), - Context, + CredentialContext.Context, new[] { "VerifiableCredential", "BpnCredential" }, "BpnCredential", "Bpn Credential", @@ -369,7 +369,7 @@ public async Task CreateMembershipCredential(CreateMembershipCredentialReq var expiryDate = DateTimeOffset.UtcNow.AddMonths(12); var schemaData = new MembershipCredential( Guid.NewGuid(), - Context, + CredentialContext.Context, new[] { "VerifiableCredential", "MembershipCredential" }, "MembershipCredential", "Membership Credential", @@ -437,7 +437,7 @@ public async Task CreateFrameworkCredential(CreateFrameworkCredentialReque var holderDid = await GetHolderInformation(requestData.Holder, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); var schemaData = new FrameworkCredential( Guid.NewGuid(), - Context, + CredentialContext.Context, new[] { "VerifiableCredential", externalTypeId }, DateTimeOffset.UtcNow, GetExpiryDate(result.Expiry), diff --git a/src/issuer/SsiCredentialIssuer.Service/SsiCredentialIssuer.Service.csproj b/src/issuer/SsiCredentialIssuer.Service/SsiCredentialIssuer.Service.csproj index 8061431b..04df391e 100644 --- a/src/issuer/SsiCredentialIssuer.Service/SsiCredentialIssuer.Service.csproj +++ b/src/issuer/SsiCredentialIssuer.Service/SsiCredentialIssuer.Service.csproj @@ -67,6 +67,7 @@ + From 93c3b9b56bf4e315f36781d007ae5d94484dc3d3 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 12 Aug 2024 19:27:10 +0200 Subject: [PATCH 14/26] feat: added a general contex to business logic tests --- .../BusinessLogic/IssuerBusinessLogicTests.cs | 4 ++-- .../SsiCredentialIssuer.Service.Tests.csproj | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs index 87e3f6a1..991b73b1 100644 --- a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs +++ b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs @@ -32,6 +32,7 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Identity; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Net; using System.Security.Cryptography; using System.Text.Json; @@ -40,7 +41,6 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Tests.BusinessLogic; public class IssuerBusinessLogicTests { - private static readonly IEnumerable Context = new[] { "https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0" }; private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; private static readonly Guid CredentialId = Guid.NewGuid(); private static readonly string Bpnl = "BPNL00000001TEST"; @@ -470,7 +470,7 @@ private static string CreateSchema() { var schemaData = new FrameworkCredential( Guid.NewGuid(), - Context, + CredentialContext.Context, new[] { "VerifiableCredential", VerifiedCredentialExternalTypeId.TRACEABILITY_CREDENTIAL.ToString() }, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, diff --git a/tests/issuer/SsiCredentialIssuer.Service.Tests/SsiCredentialIssuer.Service.Tests.csproj b/tests/issuer/SsiCredentialIssuer.Service.Tests/SsiCredentialIssuer.Service.Tests.csproj index cf8f6f53..558791aa 100644 --- a/tests/issuer/SsiCredentialIssuer.Service.Tests/SsiCredentialIssuer.Service.Tests.csproj +++ b/tests/issuer/SsiCredentialIssuer.Service.Tests/SsiCredentialIssuer.Service.Tests.csproj @@ -58,5 +58,6 @@ + From 42804237a950c6d62dde54bbe25ddcdfe08bdf2b Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 14 Aug 2024 17:15:49 +0200 Subject: [PATCH 15/26] feat: Added process work tests for credential reissuance --- ...dentialCreationProcessTypeExecutorTests.cs | 47 ++++++- ...CredentialReissuanceProcessHandlerTests.cs | 121 ++++++++++++++++++ 2 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs index 16a6220d..7a2f346f 100644 --- a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs @@ -22,6 +22,7 @@ using FakeItEasy; using FluentAssertions; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; @@ -36,6 +37,7 @@ public class CredentialCreationProcessTypeExecutorTests private readonly CredentialCreationProcessTypeExecutor _sut; private readonly ICredentialCreationProcessHandler _credentialCreationProcessHandler; private readonly ICredentialRepository _credentialRepository; + private readonly ICredentialReissuanceProcessHandler _credentialReissuanceProcessHandler; public CredentialCreationProcessTypeExecutorTests() { @@ -46,12 +48,12 @@ public CredentialCreationProcessTypeExecutorTests() var issuerRepositories = A.Fake(); _credentialCreationProcessHandler = A.Fake(); - + _credentialReissuanceProcessHandler = A.Fake(); _credentialRepository = A.Fake(); A.CallTo(() => issuerRepositories.GetInstance()).Returns(_credentialRepository); - _sut = new CredentialCreationProcessTypeExecutor(issuerRepositories, _credentialCreationProcessHandler); + _sut = new CredentialCreationProcessTypeExecutor(issuerRepositories, _credentialCreationProcessHandler, _credentialReissuanceProcessHandler); } [Fact] @@ -68,13 +70,21 @@ public void IsExecutableStepTypeId_WithValid_ReturnsExpected() _sut.IsExecutableStepTypeId(ProcessStepTypeId.SIGN_CREDENTIAL).Should().BeTrue(); } + [Fact] + public void IsExecutableStepTypeId_Withdalid_RevokeReissuedCredential_ReturnsExpected() + { + // Assert + _sut.IsExecutableStepTypeId(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL).Should().BeTrue(); + } + [Fact] public void GetExecutableStepTypeIds_ReturnsExpected() { // Assert - _sut.GetExecutableStepTypeIds().Should().HaveCount(5).And.Satisfy( + _sut.GetExecutableStepTypeIds().Should().HaveCount(6).And.Satisfy( x => x == ProcessStepTypeId.CREATE_CREDENTIAL, x => x == ProcessStepTypeId.SIGN_CREDENTIAL, + x => x == ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, x => x == ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, x => x == ProcessStepTypeId.CREATE_CREDENTIAL_FOR_HOLDER, x => x == ProcessStepTypeId.TRIGGER_CALLBACK); @@ -232,5 +242,36 @@ public async Task ExecuteProcessStep_WithServiceException_ReturnsFailedAndRetrig result.SkipStepTypeIds.Should().BeNull(); } + [Fact] + public async Task ExecuteProcessStep_RevokeIssuedCredential_WithValidData_CallsExpected() + { + // Arrange InitializeProcess + var validProcessId = Guid.NewGuid(); + var credentialId = Guid.NewGuid(); + A.CallTo(() => _credentialRepository.GetDataForProcessId(validProcessId)) + .Returns((true, credentialId)); + + // Act InitializeProcess + var initializeResult = await _sut.InitializeProcess(validProcessId, Enumerable.Empty()); + + // Assert InitializeProcess + initializeResult.Modified.Should().BeFalse(); + initializeResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange + A.CallTo(() => _credentialReissuanceProcessHandler.RevokeReissuedCredential(credentialId)) + .Returns((null, ProcessStepStatusId.DONE, false, null)); + + // Act + var result = await _sut.ExecuteProcessStep(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, Enumerable.Empty(), CancellationToken.None); + + // Assert + result.Modified.Should().BeFalse(); + result.ScheduleStepTypeIds.Should().BeNull(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.ProcessMessage.Should().BeNull(); + result.SkipStepTypeIds.Should().BeNull(); + } + #endregion } diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs new file mode 100644 index 00000000..136553fb --- /dev/null +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs @@ -0,0 +1,121 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Xunit; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Tests; + +public class CredentialReissuanceProcessHandlerTests +{ + private readonly ICredentialReissuanceProcessHandler _sut; + private readonly IIssuerRepositories _issuerRepositories; + private readonly IReissuanceRepository _reissuanceRepository; + private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; + private readonly IProcessStepRepository _processStepRepository; + private readonly ILogger _logger; + + public CredentialReissuanceProcessHandlerTests() + { + _issuerRepositories = A.Fake(); + _reissuanceRepository = A.Fake(); + _companySsiDetailsRepository = A.Fake(); + _processStepRepository = A.Fake(); + + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_processStepRepository); + + _logger = A.Fake>(); + _sut = new CredentialReissuanceProcessHandler(_issuerRepositories, _logger); + } + + [Fact] + public void RevokeReissuedCredential_isReissuedCredentialFalse_ReturnsExpected() + { + // Arrange + var credentialId = Guid.NewGuid(); + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(false); + + // Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + AssertSuccessResult(revokeCredentialResponse); + } + + [Fact] + public void RevokeReissuedCredential_CreateProcessStepThrowsException_ReturnsExpected() + { + // Arrage Ids + var credentialId = Guid.NewGuid(); + var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); + + // Arrange + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); + A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); + A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)) + .Throws(new Exception("not possible to create step process exception")); + + //Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + AssertSuccessResult(revokeCredentialResponse); + } + + [Fact] + public void RevokeReissuedCredential_CreateProcessStep_ReturnsExpected() + { + // Arrage Ids + var credentialId = Guid.NewGuid(); + var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); + var processStep = A.Fake(); + + // Arrange + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); + A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); + A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)).Returns(processStep); + A.CallTo(() => _reissuanceRepository.GetCompanySsiDetailId(credentialId)).Returns(credentialId); + + //Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialId, null, null)).WithAnyArguments().MustHaveHappened(); + AssertSuccessResult(revokeCredentialResponse); + } + + private static void AssertSuccessResult(Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> revokeCredentialResponse) + { + var result = revokeCredentialResponse.Result; + result.nextStepTypeIds.Should().HaveCount(1).And.Satisfy( + x => x == ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT); + result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.modified.Should().BeFalse(); + result.processMessage.Should().BeNull(); + } +} From 6c04b54ddb1876e0744cee1b1bd7d0f79b6aed9c Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 14 Aug 2024 17:15:49 +0200 Subject: [PATCH 16/26] fix: correct the type of a mocked method --- ...dentialCreationProcessTypeExecutorTests.cs | 47 ++++++- ...CredentialReissuanceProcessHandlerTests.cs | 121 ++++++++++++++++++ 2 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs index 16a6220d..7a2f346f 100644 --- a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs @@ -22,6 +22,7 @@ using FakeItEasy; using FluentAssertions; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; @@ -36,6 +37,7 @@ public class CredentialCreationProcessTypeExecutorTests private readonly CredentialCreationProcessTypeExecutor _sut; private readonly ICredentialCreationProcessHandler _credentialCreationProcessHandler; private readonly ICredentialRepository _credentialRepository; + private readonly ICredentialReissuanceProcessHandler _credentialReissuanceProcessHandler; public CredentialCreationProcessTypeExecutorTests() { @@ -46,12 +48,12 @@ public CredentialCreationProcessTypeExecutorTests() var issuerRepositories = A.Fake(); _credentialCreationProcessHandler = A.Fake(); - + _credentialReissuanceProcessHandler = A.Fake(); _credentialRepository = A.Fake(); A.CallTo(() => issuerRepositories.GetInstance()).Returns(_credentialRepository); - _sut = new CredentialCreationProcessTypeExecutor(issuerRepositories, _credentialCreationProcessHandler); + _sut = new CredentialCreationProcessTypeExecutor(issuerRepositories, _credentialCreationProcessHandler, _credentialReissuanceProcessHandler); } [Fact] @@ -68,13 +70,21 @@ public void IsExecutableStepTypeId_WithValid_ReturnsExpected() _sut.IsExecutableStepTypeId(ProcessStepTypeId.SIGN_CREDENTIAL).Should().BeTrue(); } + [Fact] + public void IsExecutableStepTypeId_Withdalid_RevokeReissuedCredential_ReturnsExpected() + { + // Assert + _sut.IsExecutableStepTypeId(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL).Should().BeTrue(); + } + [Fact] public void GetExecutableStepTypeIds_ReturnsExpected() { // Assert - _sut.GetExecutableStepTypeIds().Should().HaveCount(5).And.Satisfy( + _sut.GetExecutableStepTypeIds().Should().HaveCount(6).And.Satisfy( x => x == ProcessStepTypeId.CREATE_CREDENTIAL, x => x == ProcessStepTypeId.SIGN_CREDENTIAL, + x => x == ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, x => x == ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, x => x == ProcessStepTypeId.CREATE_CREDENTIAL_FOR_HOLDER, x => x == ProcessStepTypeId.TRIGGER_CALLBACK); @@ -232,5 +242,36 @@ public async Task ExecuteProcessStep_WithServiceException_ReturnsFailedAndRetrig result.SkipStepTypeIds.Should().BeNull(); } + [Fact] + public async Task ExecuteProcessStep_RevokeIssuedCredential_WithValidData_CallsExpected() + { + // Arrange InitializeProcess + var validProcessId = Guid.NewGuid(); + var credentialId = Guid.NewGuid(); + A.CallTo(() => _credentialRepository.GetDataForProcessId(validProcessId)) + .Returns((true, credentialId)); + + // Act InitializeProcess + var initializeResult = await _sut.InitializeProcess(validProcessId, Enumerable.Empty()); + + // Assert InitializeProcess + initializeResult.Modified.Should().BeFalse(); + initializeResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange + A.CallTo(() => _credentialReissuanceProcessHandler.RevokeReissuedCredential(credentialId)) + .Returns((null, ProcessStepStatusId.DONE, false, null)); + + // Act + var result = await _sut.ExecuteProcessStep(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, Enumerable.Empty(), CancellationToken.None); + + // Assert + result.Modified.Should().BeFalse(); + result.ScheduleStepTypeIds.Should().BeNull(); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.ProcessMessage.Should().BeNull(); + result.SkipStepTypeIds.Should().BeNull(); + } + #endregion } diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs new file mode 100644 index 00000000..5d7fb41d --- /dev/null +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs @@ -0,0 +1,121 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 FakeItEasy; +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Xunit; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Tests; + +public class CredentialReissuanceProcessHandlerTests +{ + private readonly ICredentialReissuanceProcessHandler _sut; + private readonly IIssuerRepositories _issuerRepositories; + private readonly IReissuanceRepository _reissuanceRepository; + private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; + private readonly IProcessStepRepository _processStepRepository; + private readonly ILogger _logger; + + public CredentialReissuanceProcessHandlerTests() + { + _issuerRepositories = A.Fake(); + _reissuanceRepository = A.Fake(); + _companySsiDetailsRepository = A.Fake(); + _processStepRepository = A.Fake(); + + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_processStepRepository); + + _logger = A.Fake>(); + _sut = new CredentialReissuanceProcessHandler(_issuerRepositories, _logger); + } + + [Fact] + public void RevokeReissuedCredential_isReissuedCredentialFalse_ReturnsExpected() + { + // Arrange + var credentialId = Guid.NewGuid(); + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(false); + + // Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + AssertSuccessResult(revokeCredentialResponse); + } + + [Fact] + public void RevokeReissuedCredential_CreateProcessStepThrowsException_ReturnsExpected() + { + // Arrage Ids + var credentialId = Guid.NewGuid(); + var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); + + // Arrange + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); + A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); + A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)) + .Throws(new Exception("not possible to create step process exception")); + + //Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + AssertSuccessResult(revokeCredentialResponse); + } + + [Fact] + public void RevokeReissuedCredential_CreateProcessStep_ReturnsExpected() + { + // Arrage Ids + var credentialId = Guid.NewGuid(); + var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); + var processStep = A.Fake(); + + // Arrange + A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); + A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); + A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)).Returns(processStep); + A.CallTo(() => _reissuanceRepository.GetCompanySsiDetailId(credentialId)).Returns(credentialId); + + //Act + var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + + // Assert + A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialId, A>._, A>._)).WithAnyArguments().MustHaveHappened(); + AssertSuccessResult(revokeCredentialResponse); + } + + private static void AssertSuccessResult(Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> revokeCredentialResponse) + { + var result = revokeCredentialResponse.Result; + result.nextStepTypeIds.Should().HaveCount(1).And.Satisfy( + x => x == ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT); + result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.modified.Should().BeFalse(); + result.processMessage.Should().BeNull(); + } +} From 31bd4837c0b826f289ad64f2e7deabad84834707 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Mon, 19 Aug 2024 13:33:23 +0200 Subject: [PATCH 17/26] feat: Added tests for Reissuance service and default value for reissueance settings --- src/SsiCredentialIssuer.sln | 7 + .../ReissuanceExpirySettings.cs | 2 +- .../Services/ReissuanceService.cs | 11 +- .../Handler/CredentialIssuerHandlerTests.cs | 125 ++++++++++++++ .../Services/ReissuanceServiceTests.cs | 155 ++++++++++++++++++ ...edentialIssuer.Reissuance.App.Tests.csproj | 31 ++++ 6 files changed, 323 insertions(+), 8 deletions(-) create mode 100644 tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs create mode 100644 tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs create mode 100644 tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/SsiCredentialIssuer.Reissuance.App.Tests.csproj diff --git a/src/SsiCredentialIssuer.sln b/src/SsiCredentialIssuer.sln index 19600845..fda5e2dd 100644 --- a/src/SsiCredentialIssuer.sln +++ b/src/SsiCredentialIssuer.sln @@ -66,6 +66,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Reissua EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "credentials\SsiCredentialIssuer.Credential.Library", "credentials\SsiCredentialIssuer.Credential.Library\SsiCredentialIssuer.Credential.Library.csproj", "{832CA2B5-E08D-4EB6-9C99-020E01A86A2C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SsiCredentialIssuer.Reissuance.App.Tests", "..\tests\credentials\SsiCredentialIssuer.Reissuance.App.Tests\SsiCredentialIssuer.Reissuance.App.Tests.csproj", "{677EC522-C102-4446-80E4-B98E6C527D33}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -176,6 +178,10 @@ Global {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU {832CA2B5-E08D-4EB6-9C99-020E01A86A2C}.Release|Any CPU.Build.0 = Release|Any CPU + {677EC522-C102-4446-80E4-B98E6C527D33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {677EC522-C102-4446-80E4-B98E6C527D33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {677EC522-C102-4446-80E4-B98E6C527D33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {677EC522-C102-4446-80E4-B98E6C527D33}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -207,5 +213,6 @@ Global {61DB2ADF-DBC1-4647-AAD2-A8E992E75B37} = {A2FC3E0F-5AFE-44FA-909B-B8016DD1EB44} {2757DB44-F658-420F-B00A-48EC6DBA6035} = {A79FF417-08E7-4175-8089-5F21054F5BDE} {832CA2B5-E08D-4EB6-9C99-020E01A86A2C} = {A79FF417-08E7-4175-8089-5F21054F5BDE} + {677EC522-C102-4446-80E4-B98E6C527D33} = {A2FC3E0F-5AFE-44FA-909B-B8016DD1EB44} EndGlobalSection EndGlobal diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs index ba8afa8a..43fcd8ba 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs @@ -30,5 +30,5 @@ public class ReissuanceExpirySettings /// Vcs which are about to expire in the next day(s). /// [Required] - public int ExpiredVcsToReissueInDays { get; init; } + public int ExpiredVcsToReissueInDays { get; init; } = 1; } diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index 118ab6e5..3aadf434 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -76,7 +76,6 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) var repositories = processServiceScope.ServiceProvider.GetRequiredService(); var expirationDate = dateTimeProvider.OffsetNow.AddDays(_settings.ExpiredVcsToReissueInDays); var companySsiDetailsRepository = repositories.GetInstance(); - var credentialIssuerHandler = processServiceScope.ServiceProvider.GetRequiredService(); var credentialsAboutToExpire = companySsiDetailsRepository.GetCredentialsAboutToExpire(expirationDate); await ProcessCredentials(credentialsAboutToExpire, dateTimeProvider); } @@ -114,19 +113,17 @@ await _credentialIssuerHandler.HandleCredentialProcessCreation(new IssuerCredent private static string CreateNewCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { - string schemaData; if (credential.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.BPN) { - schemaData = CreateBpnCredential(credential, credential.Schema, expirationDate); + return CreateBpnCredential(credential, expirationDate); } else { - schemaData = CreateMembershipCredential(credential, credential.Schema, expirationDate); + return CreateMembershipCredential(credential, expirationDate); } - return schemaData; } - private static string CreateBpnCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) + private static string CreateBpnCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { var bpnAboutToExpire = credential.Schema.Deserialize(); var bpnCredential = new BpnCredential( @@ -144,7 +141,7 @@ private static string CreateBpnCredential(CredentialAboutToExpireData credential return JsonSerializer.Serialize(bpnCredential, Options); } - private static string CreateMembershipCredential(CredentialAboutToExpireData credential, JsonDocument schema, DateTimeOffset expirationDate) + private static string CreateMembershipCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { var membershipAboutToExpire = credential.Schema.Deserialize(); var membershipCredential = new MembershipCredential( diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs new file mode 100644 index 00000000..d7ee4729 --- /dev/null +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs @@ -0,0 +1,125 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 FakeItEasy; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Xunit; +using System.Text.Json; +using AutoFixture; +using AutoFixture.AutoFakeItEasy; +using System.Text; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests.Handler; + +public class CredentialIssuerHandlerTests +{ + private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly IOptions _options; + private readonly IIssuerRepositories _issuerRepositories; + private readonly IDocumentRepository _documentRepository; + private readonly IReissuanceRepository _reissuanceRepository; + private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; + private readonly IServiceScope _serviceScope; + private readonly ICredentialIssuerHandler _credentialIssuerHandler; + private readonly IFixture _fixture; + + public CredentialIssuerHandlerTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + var serviceProvider = _fixture.Create(); + + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + _issuerRepositories = A.Fake(); + _documentRepository = A.Fake(); + _reissuanceRepository = A.Fake(); + _companySsiDetailsRepository = A.Fake(); + + _serviceScopeFactory = _fixture.Create(); + _serviceScope = _fixture.Create(); + _options = A.Fake>(); + + A.CallTo(() => _serviceScopeFactory.CreateScope()).Returns(_serviceScope); + A.CallTo(() => _serviceScope.ServiceProvider).Returns(serviceProvider); + A.CallTo(() => serviceProvider.GetService(typeof(IIssuerRepositories))).Returns(_issuerRepositories); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_documentRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); + + var credentialSettings = new CredentialSettings(); + credentialSettings.IssuerBpn = "BPNL000000000000"; + A.CallTo(() => _options.Value).Returns(credentialSettings); + + _credentialIssuerHandler = new CredentialIssuerHandler(_serviceScopeFactory, _options); + } + + [Fact] + public async void HandleCredentialProcessCreation_ValidateProcessCreation_NoErrorExpected() + { + // Arrange + var documentId = Guid.NewGuid(); + var schema = "{\"id\": \"21a1aa1f-b2f9-43bb-9c71-00b62bd1f8e0\", \"name\": \"BpnCredential\"}"; + var processStepRepository = A.Fake(); + var process = new Process(Guid.NewGuid(), ProcessTypeId.CREATE_CREDENTIAL, Guid.NewGuid()); + var companySsiDetail = new CompanySsiDetail(Guid.NewGuid(), null!, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, CompanySsiDetailStatusId.ACTIVE, _options.Value.IssuerBpn, Guid.NewGuid().ToString(), DateTimeOffset.UtcNow);; + var request = new IssuerCredentialRequest( + Guid.NewGuid(), + "BPNL000000000000", + VerifiedCredentialTypeKindId.BPN, + VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, + DateTimeOffset.Now, + "BPNL000000000000", + schema, + "holderWalletUrl", + Guid.NewGuid(), + "example.callback.cofinity" + ); + var documentContent = Encoding.ASCII.GetBytes("document content"); + var hash = Encoding.ASCII.GetBytes(documentContent.GetHashCode().ToString()); + var document = new Document(documentId, documentContent, hash, "document", MediaTypeId.JSON, DateTimeOffset.Now, DocumentStatusId.ACTIVE, DocumentTypeId.PRESENTATION); + + A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, MediaTypeId.JSON, DocumentTypeId.PRESENTATION, A?>._)).Returns(document); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(processStepRepository); + A.CallTo(() => processStepRepository.CreateProcess(ProcessTypeId.CREATE_CREDENTIAL)).Returns(process); + A.CallTo(() => _companySsiDetailsRepository.CreateSsiDetails( + request.Bpnl, + request.TypeId, + CompanySsiDetailStatusId.ACTIVE, + _options.Value.IssuerBpn, + request.IdentiyId, + A?>._)).Returns(companySsiDetail); + + // Act + await _credentialIssuerHandler.HandleCredentialProcessCreation(request); + + // Assert + A.CallTo(() => _documentRepository.AssignDocumentToCompanySsiDetails(A._, companySsiDetail.Id)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _reissuanceRepository.CreateReissuanceProcess(request.Id, companySsiDetail.Id)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _companySsiDetailsRepository.CreateProcessData(companySsiDetail.Id, A._, A._, A?>._)).MustHaveHappenedOnceExactly(); + A.CallTo(() => _issuerRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + } +} diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs new file mode 100644 index 00000000..9c4eecaa --- /dev/null +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs @@ -0,0 +1,155 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 AutoFixture; +using AutoFixture.AutoFakeItEasy; +using FakeItEasy; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; +using Xunit; +using System.Text; +using System.Text.Json; +using FluentAssertions; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests.Services; + +public class ReissuanceServiceTests +{ + private readonly ICredentialIssuerHandler _credentialIssuerHandler; + private readonly IReissuanceService _reissuanceService; + private readonly IIssuerRepositories _issuerRepositories; + private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; + private readonly IDateTimeProvider _dateTimeProvider; + private readonly ILogger _logger; + + public ReissuanceServiceTests() + { + var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + fixture.Behaviors.OfType().ToList() + .ForEach(b => fixture.Behaviors.Remove(b)); + fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + var serviceScopeFactory = fixture.Create(); + var serviceScope = fixture.Create(); + var options = A.Fake>(); + _logger = A.Fake>(); + var settings = new ReissuanceExpirySettings(); + var serviceProvider = fixture.Create(); + _dateTimeProvider = A.Fake(); + + _credentialIssuerHandler = A.Fake(); + _issuerRepositories = A.Fake(); + _companySsiDetailsRepository = A.Fake(); + _credentialIssuerHandler = A.Fake(); + + A.CallTo(() => options.Value).Returns(settings); + A.CallTo(() => serviceProvider.GetService(typeof(IDateTimeProvider))).Returns(_dateTimeProvider); + A.CallTo(() => serviceProvider.GetService(typeof(IIssuerRepositories))).Returns(_issuerRepositories); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); + A.CallTo(() => serviceScope.ServiceProvider).Returns(serviceProvider); + A.CallTo(() => serviceScopeFactory.CreateScope()).Returns(serviceScope); + A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(DateTimeOffset.UtcNow); + + _reissuanceService = new ReissuanceService(serviceScopeFactory, _credentialIssuerHandler, options, _logger); + } + + [Fact] + public async void ExecuteAsync_ProcessCredentials_NoCredentialsAboutToExpire() + { + // Act + await _reissuanceService.ExecuteAsync(CancellationToken.None); + + // Assert + A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)).MustNotHaveHappened(); + } + + [Fact] + public async void ExecuteAsync_ProcessCredentials_CreateBpnCredential() + { + // Arrange + var schema = "{\"id\":\"6f05cac6-c073-4562-8540-8fc883807808\",\"name\":\"BpnCredential\",\"type\":[\"VerifiableCredential\",\"BpnCredential\"],\"issuer\":\"did:web:localhost:BPNL000000000000\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://w3id.org/catenax/credentials/v1.0.0\"],\"description\":\"BpnCredential\",\"issuanceDate\":\"2024-08-19T07:32:37.598099+00:00\",\"expirationDate\":\"2025-08-19T07:32:37.598079+00:00\",\"credentialStatus\":{\"id\":\"example.com\",\"type\":\"StatusList2021\"},\"credentialSubject\":{\"id\":\"did:web:localhost:BPNL000000000000\",\"bpn\":\"BPNL000000000000\",\"holderIdentifier\":\"BPNL000000000000\"}}"; + IssuerCredentialRequest? issuerCredentialRequest = null; + var credentialsAboutToExpire = new CredentialAboutToExpireData( + Guid.NewGuid(), + "BPNL000000000000", + Entities.Enums.VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, + Entities.Enums.VerifiedCredentialTypeKindId.BPN, + JsonDocument.Parse(schema), + "BPNL000000000000", + "http://localhost", + Guid.NewGuid(), + "callback.com" + ); + + A.CallTo(() => _companySsiDetailsRepository.GetCredentialsAboutToExpire(A._)).Returns((new[] { credentialsAboutToExpire }.ToAsyncEnumerable())); + A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)) + .Invokes((IssuerCredentialRequest credentialRequest) => + { + issuerCredentialRequest = credentialRequest; + }); + + // Act + await _reissuanceService.ExecuteAsync(CancellationToken.None); + + // Assert + A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)).MustHaveHappenedOnceExactly(); + Assert.NotNull(issuerCredentialRequest); + issuerCredentialRequest.Id.Should().Be(credentialsAboutToExpire.Id); + issuerCredentialRequest.Bpnl.Should().Be(credentialsAboutToExpire.HolderBpn); + issuerCredentialRequest.TypeId.Should().Be(credentialsAboutToExpire.VerifiedCredentialTypeId); + } + + [Fact] + public async void ExecuteAsync_ProcessCredentials_HandleException() + { + // Arrange + var schema = "{\"id\":\"6f05cac6-c073-4562-8540-8fc883807808\",\"name\":\"BpnCredential\",\"type\":[\"VerifiableCredential\",\"BpnCredential\"],\"issuer\":\"did:web:localhost:BPNL000000000000\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://w3id.org/catenax/credentials/v1.0.0\"],\"description\":\"BpnCredential\",\"issuanceDate\":\"2024-08-19T07:32:37.598099+00:00\",\"expirationDate\":\"2025-08-19T07:32:37.598079+00:00\",\"credentialStatus\":{\"id\":\"example.com\",\"type\":\"StatusList2021\"},\"credentialSubject\":{\"id\":\"did:web:localhost:BPNL000000000000\",\"bpn\":\"BPNL000000000000\",\"holderIdentifier\":\"BPNL000000000000\"}}"; + IssuerCredentialRequest? issuerCredentialRequest = null; + + var credentialsAboutToExpire = new CredentialAboutToExpireData( + Guid.NewGuid(), + "BPNL000000000000", + Entities.Enums.VerifiedCredentialTypeId.MEMBERSHIP, + Entities.Enums.VerifiedCredentialTypeKindId.MEMBERSHIP, + JsonDocument.Parse(schema), + "BPNL000000000000", + "http://localhost", + Guid.NewGuid(), + "callback.com" + ); + + A.CallTo(() => _companySsiDetailsRepository.GetCredentialsAboutToExpire(A._)).Returns((new[] { credentialsAboutToExpire }.ToAsyncEnumerable())); + A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)).Throws(new Exception()); + + // Act + await _reissuanceService.ExecuteAsync(CancellationToken.None); + + // Assert + A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)).MustHaveHappenedOnceExactly(); + A.CallTo(_logger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Error).MustHaveHappened(1, Times.Exactly); + + } +} diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/SsiCredentialIssuer.Reissuance.App.Tests.csproj b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/SsiCredentialIssuer.Reissuance.App.Tests.csproj new file mode 100644 index 00000000..6d00864b --- /dev/null +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/SsiCredentialIssuer.Reissuance.App.Tests.csproj @@ -0,0 +1,31 @@ + + + + Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests + Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests + net8.0 + enable + enable + false + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + From 60c8945e0d860410f19afb4eec1a344a0f3643c4 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 14 Aug 2024 17:15:49 +0200 Subject: [PATCH 18/26] feat: Added process work tests for credential reissuance --- .../CredentialReissuanceProcessHandlerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs index 5d7fb41d..136553fb 100644 --- a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs @@ -105,7 +105,7 @@ public void RevokeReissuedCredential_CreateProcessStep_ReturnsExpected() var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); // Assert - A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialId, A>._, A>._)).WithAnyArguments().MustHaveHappened(); + A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialId, null, null)).WithAnyArguments().MustHaveHappened(); AssertSuccessResult(revokeCredentialResponse); } From b9692e913c2fc5b7a62c92a006e16054d7d1a4ce Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Tue, 20 Aug 2024 17:49:51 +0200 Subject: [PATCH 19/26] feat: added notification trigger for reissuanse when credential is revoked --- .../Program.cs | 4 +- .../Repositories/IReissuanceRepository.cs | 2 + .../Repositories/ReissuanceRepository.cs | 7 +++ ...edential_type_assigned_external_types.json | 8 ++++ .../Models/NotificationTypeId.cs | 7 ++- .../Expiry/CredentialExpiryProcessHandler.cs | 34 +++++++++++--- .../CredentialProcessCollectionExtensions.cs | 1 - .../CredentialCreationProcessHandlerTests.cs | 2 +- .../CredentialExpiryProcessHandlerTests.cs | 47 ++++++++++++++++++- 9 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs index b4588a2c..d0e1edd1 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs @@ -30,7 +30,7 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; LoggingExtensions.EnsureInitialized(); -Log.Information("Building worker"); +Log.Information("Building Reissuance App"); try { var host = Host @@ -47,7 +47,7 @@ }) .AddLogging() .Build(); - Log.Information("Building worker completed"); + Log.Information("Building Reissuance App completed"); using var tokenSource = new CancellationTokenSource(); Console.CancelKeyPress += (s, e) => diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs index b2e469e9..1388a216 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs @@ -28,4 +28,6 @@ public interface IReissuanceRepository Guid GetCompanySsiDetailId(Guid companySsiDetaillId); bool IsReissuedCredential(Guid companySsiDetaillId); + + bool IsCredentialRevokedByReissuance(Guid companySsiDetaillId); } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs index 47427283..a4c9cc30 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs @@ -52,4 +52,11 @@ public bool IsReissuedCredential(Guid companySsiDetaillId) .Where(ssi => ssi.ReissuedCredentialId == companySsiDetaillId) .Select(ssi => true).SingleOrDefault(); } + + public bool IsCredentialRevokedByReissuance(Guid companySsiDetaillId) + { + return _dbContext.Reissuances + .Where(ssi => ssi.Id == companySsiDetaillId) + .Select(ssi => true).SingleOrDefault(); + } } diff --git a/src/database/SsiCredentialIssuer.Migrations/Seeder/Data/verified_credential_type_assigned_external_types.json b/src/database/SsiCredentialIssuer.Migrations/Seeder/Data/verified_credential_type_assigned_external_types.json index b4e48a92..cfa667b2 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Seeder/Data/verified_credential_type_assigned_external_types.json +++ b/src/database/SsiCredentialIssuer.Migrations/Seeder/Data/verified_credential_type_assigned_external_types.json @@ -23,6 +23,10 @@ "verified_credential_external_type_id": 6, "verified_credential_type_id": 6 }, + { + "verified_credential_external_type_id": 7, + "verified_credential_type_id": 7 + }, { "verified_credential_external_type_id": 8, "verified_credential_type_id": 8 @@ -35,6 +39,10 @@ "verified_credential_external_type_id": 10, "verified_credential_type_id": 10 }, + { + "verified_credential_external_type_id": 11, + "verified_credential_type_id": 11 + }, { "verified_credential_external_type_id": 12, "verified_credential_type_id": 12 diff --git a/src/externalservices/Portal.Service/Models/NotificationTypeId.cs b/src/externalservices/Portal.Service/Models/NotificationTypeId.cs index e6d3409d..e334f8ca 100644 --- a/src/externalservices/Portal.Service/Models/NotificationTypeId.cs +++ b/src/externalservices/Portal.Service/Models/NotificationTypeId.cs @@ -152,5 +152,10 @@ public enum NotificationTypeId /// /// Notification when a credential got rejected /// - CREDENTIAL_EXPIRY = 26 + CREDENTIAL_EXPIRY = 26, + + /// + /// Notification when a credential got Reissued + /// + CREDENTIAL_RENEWAL = 27 } diff --git a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs index 1660e571..3f0be8ed 100644 --- a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs @@ -83,10 +83,12 @@ public CredentialExpiryProcessHandler(IIssuerRepositories repositories, IWalletS public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerNotification(Guid credentialId, CancellationToken cancellationToken) { var (typeId, requesterId) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); + var notificationTypeId = await GetNotificationTypeId(credentialId); + if (Guid.TryParse(requesterId, out var companyUserId)) { var content = JsonSerializer.Serialize(new { Type = typeId, CredentialId = credentialId }, Options); - await _portalService.AddNotification(content, companyUserId, NotificationTypeId.CREDENTIAL_REJECTED, cancellationToken); + await _portalService.AddNotification(content, companyUserId, notificationTypeId, cancellationToken); } return ( @@ -96,18 +98,30 @@ public CredentialExpiryProcessHandler(IIssuerRepositories repositories, IWalletS null); } + private Task GetNotificationTypeId(Guid credentialId) + { + var isRevokedByReissuance = _repositories.GetInstance().IsCredentialRevokedByReissuance(credentialId); + return Task.FromResult(isRevokedByReissuance ? NotificationTypeId.CREDENTIAL_RENEWAL : NotificationTypeId.CREDENTIAL_REJECTED); + } + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerMail(Guid credentialId, CancellationToken cancellationToken) { var (typeId, requesterId) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); - var typeValue = typeId.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {typeId} does not exists"); + var isRevokedByReissuance = _repositories.GetInstance().IsCredentialRevokedByReissuance(credentialId); + if (Guid.TryParse(requesterId, out var companyUserId)) { - var mailParameters = new MailParameter[] + if (isRevokedByReissuance) + { + var mailParameters = CreateEmailParameters(typeValue, "The credential about to expiry is revoked and new credential was reissued"); + await _portalService.TriggerMail("CredentialRenewal", companyUserId, mailParameters, cancellationToken); + } + else { - new("requestName", typeValue), new("reason", "The credential is already expired") - }; - await _portalService.TriggerMail("CredentialRejected", companyUserId, mailParameters, cancellationToken); + var mailParameters = CreateEmailParameters(typeValue, "The credential is already expired"); + await _portalService.TriggerMail("CredentialRejected", companyUserId, mailParameters, cancellationToken); + } } return ( @@ -116,4 +130,12 @@ public CredentialExpiryProcessHandler(IIssuerRepositories repositories, IWalletS false, null); } + + private static MailParameter[] CreateEmailParameters(string typeValue, string reason) + { + return + [ + new("requestName", typeValue), new("reason", reason) + ]; + } } diff --git a/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs b/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs index f8c254a1..b6732f70 100644 --- a/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs +++ b/src/processes/CredentialProcess.Worker/DependencyInjection/CredentialProcessCollectionExtensions.cs @@ -18,7 +18,6 @@ ********************************************************************************/ using Microsoft.Extensions.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Expiry; using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library; diff --git a/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs b/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs index 57862757..c3da8b46 100644 --- a/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs @@ -125,7 +125,7 @@ public async Task SignCredential_WithValidData_ReturnsExpected() result.modified.Should().BeFalse(); result.processMessage.Should().BeNull(); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); - result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL); } #endregion diff --git a/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs b/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs index 56f95cb7..1155ee66 100644 --- a/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs @@ -42,6 +42,7 @@ public class CredentialExpiryProcessHandlerTests private readonly IWalletService _walletService; private readonly IIssuerRepositories _issuerRepositories; private readonly ICredentialRepository _credentialRepository; + private readonly IReissuanceRepository _reissuanceRepository; private readonly IPortalService _portalService; private readonly CredentialExpiryProcessHandler _sut; @@ -58,9 +59,11 @@ public CredentialExpiryProcessHandlerTests() _issuerRepositories = A.Fake(); _credentialRepository = A.Fake(); _documentRepository = A.Fake(); + _reissuanceRepository = A.Fake(); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_credentialRepository); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_documentRepository); + A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); _walletService = A.Fake(); _portalService = A.Fake(); @@ -162,7 +165,7 @@ public async Task RevokeCredential_WithEmptyExternalCredentialId_ThrowsConflictE #region TriggerNotification [Fact] - public async Task TriggerNotification_WithValid_CallsExpected() + public async Task TriggerNotification_CredentialRejected_WithValid_CallsExpected() { // Arrange var requesterId = Guid.NewGuid(); @@ -181,12 +184,32 @@ public async Task TriggerNotification_WithValid_CallsExpected() result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.TRIGGER_MAIL); } + [Fact] + public async Task TriggerNotification_CredentialRenewal_WithValid_CallsExpected() + { + // Arrange + var requesterId = Guid.NewGuid(); + A.CallTo(() => _reissuanceRepository.IsCredentialRevokedByReissuance(_credentialId)).Returns(true); + A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) + .Returns((VerifiedCredentialExternalTypeId.BUSINESS_PARTNER_NUMBER, requesterId.ToString())); + + // Act + var result = await _sut.TriggerNotification(_credentialId, CancellationToken.None); + + // Assert + A.CallTo(() => _portalService.AddNotification(A._, requesterId, NotificationTypeId.CREDENTIAL_RENEWAL, A._)) + .MustHaveHappenedOnceExactly(); + result.modified.Should().BeFalse(); + result.processMessage.Should().BeNull(); + result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.TRIGGER_MAIL); + } #endregion #region TriggerMail [Fact] - public async Task TriggerMail_WithValid_CallsExpected() + public async Task TriggerMail_CredentialRejected_WithValid_CallsExpected() { // Arrange var requesterId = Guid.NewGuid(); @@ -205,5 +228,25 @@ public async Task TriggerMail_WithValid_CallsExpected() result.nextStepTypeIds.Should().BeNull(); } + [Fact] + public async Task TriggerMail_CredentialRenewal_WithValid_CallsExpected() + { + // Arrange + var requesterId = Guid.NewGuid(); + A.CallTo(() => _reissuanceRepository.IsCredentialRevokedByReissuance(_credentialId)).Returns(true); + A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) + .Returns((VerifiedCredentialExternalTypeId.MEMBERSHIP_CREDENTIAL, requesterId.ToString())); + + // Act + var result = await _sut.TriggerMail(_credentialId, CancellationToken.None); + + // Assert + A.CallTo(() => _portalService.TriggerMail("CredentialRenewal", requesterId, A>._, A._)) + .MustHaveHappenedOnceExactly(); + result.modified.Should().BeFalse(); + result.processMessage.Should().BeNull(); + result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); + result.nextStepTypeIds.Should().BeNull(); + } #endregion } From 5c1f484c7c3b454188e00549c41a71068d93fd71 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Tue, 20 Aug 2024 18:42:22 +0200 Subject: [PATCH 20/26] feat: fixed the format style --- .../SsiCredentialIssuer.Entities/IssuerDbContext.cs | 1 - .../Handler/CredentialIssuerHandlerTests.cs | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs index 751305cd..0a60277b 100644 --- a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs +++ b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs @@ -192,7 +192,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(d => d.ProcessTypeId) .OnDelete(DeleteBehavior.ClientSetNull); - modelBuilder.Entity() .HasOne(d => d.Process) .WithMany(p => p!.ProcessSteps) diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs index d7ee4729..13da04fa 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs @@ -85,7 +85,15 @@ public async void HandleCredentialProcessCreation_ValidateProcessCreation_NoErro var schema = "{\"id\": \"21a1aa1f-b2f9-43bb-9c71-00b62bd1f8e0\", \"name\": \"BpnCredential\"}"; var processStepRepository = A.Fake(); var process = new Process(Guid.NewGuid(), ProcessTypeId.CREATE_CREDENTIAL, Guid.NewGuid()); - var companySsiDetail = new CompanySsiDetail(Guid.NewGuid(), null!, VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, CompanySsiDetailStatusId.ACTIVE, _options.Value.IssuerBpn, Guid.NewGuid().ToString(), DateTimeOffset.UtcNow);; + var companySsiDetail = new CompanySsiDetail( + Guid.NewGuid(), + null!, + VerifiedCredentialTypeId.BUSINESS_PARTNER_NUMBER, + CompanySsiDetailStatusId.ACTIVE, + _options.Value.IssuerBpn, + Guid.NewGuid().ToString(), + DateTimeOffset.UtcNow); + var request = new IssuerCredentialRequest( Guid.NewGuid(), "BPNL000000000000", From e823e3cd100413b3124ab9664993e49e13cf32a6 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Tue, 20 Aug 2024 18:46:09 +0200 Subject: [PATCH 21/26] fix: removed unused imports --- .../Services/ReissuanceServiceTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs index 9c4eecaa..6d224a8b 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs @@ -31,7 +31,6 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; using Xunit; -using System.Text; using System.Text.Json; using FluentAssertions; From 8744628ab85716d840f861947b66fe786191630e Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Tue, 20 Aug 2024 19:11:44 +0200 Subject: [PATCH 22/26] fix: fixed style of the source files --- .../Context/CredentialContext.cs | 2 +- .../CredentialServiceExtensions.cs | 2 +- .../Entities/ReissuanceProcess.cs | 2 +- .../20240812093252_ReissuanceChanges.cs | 20 ++++++++++++++++++- .../Expiry/CredentialExpiryProcessHandler.cs | 5 +---- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs index 491a8094..de27bf4f 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs @@ -23,4 +23,4 @@ public class CredentialContext private static readonly IEnumerable _context = ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0"]; public static IEnumerable Context => _context; -} \ No newline at end of file +} diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs index 434db62d..5e6b20ef 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs @@ -33,7 +33,7 @@ public static class CredentialServiceExtensions /// /// the services /// the enriched service collection - public static IServiceCollection AddICredentialServiceExtensions(this IServiceCollection services, IConfiguration config) => + public static IServiceCollection AddICredentialServiceExtensions(this IServiceCollection services, IConfiguration config) => services .ConfigureCredentialSettings(config.GetSection("Credential")); } diff --git a/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs b/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs index a1d46621..f265c4c4 100644 --- a/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs +++ b/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs @@ -33,4 +33,4 @@ public ReissuanceProcess(Guid id, Guid reissuedCredentialId) // Navigation properties public virtual CompanySsiDetail? CompanySsiDetail { get; private set; } -} \ No newline at end of file +} diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs index 97450f9e..d3a62535 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs @@ -1,4 +1,22 @@ -using System; +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs index 3f0be8ed..d0a72933 100644 --- a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs @@ -133,9 +133,6 @@ private Task GetNotificationTypeId(Guid credentialId) private static MailParameter[] CreateEmailParameters(string typeValue, string reason) { - return - [ - new("requestName", typeValue), new("reason", reason) - ]; + return [new("requestName", typeValue), new("reason", reason)]; } } From 90ca8414a69efcd005076bd4e57b08077a445228 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 21 Aug 2024 10:43:17 +0200 Subject: [PATCH 23/26] fix: changed the format of source --- .../CredentialServiceExtensions.cs | 2 +- .../Handler/CredentialIssuerHandler.cs | 8 ++++---- .../Handler/ICredentialIssuerHandler.cs | 2 +- .../Handler/IssuerCredentialRequest.cs | 2 +- .../SsiCredentialIssuer.Reissuance.App/Program.cs | 10 +++++----- .../Services/IReissuanceService.cs | 2 +- .../Services/ReissuanceService.cs | 14 +++++++------- .../Repositories/IReissuanceRepository.cs | 2 +- .../Repositories/ReissuanceRepository.cs | 2 +- .../Migrations/20240812093252_ReissuanceChanges.cs | 2 +- .../BusinessLogic/IssuerBusinessLogic.cs | 2 +- .../CredentialReissuanceProcessHandler.cs | 2 +- .../ICredentialReissuanceProcessHandler.cs | 2 +- .../Handler/CredentialIssuerHandlerTests.cs | 10 +++++----- .../Services/ReissuanceServiceTests.cs | 6 +++--- .../BusinessLogic/IssuerBusinessLogicTests.cs | 2 +- 16 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs index 5e6b20ef..914c5b28 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs @@ -17,9 +17,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; -using Microsoft.Extensions.Configuration; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs index d647b29c..a951ec2c 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -18,14 +18,14 @@ ********************************************************************************/ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using System.Security.Cryptography; using System.Text; using System.Text.Json; -using Microsoft.Extensions.Options; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs index 2b17d162..78e6df1c 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs index 2724ebdc..a0690283 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs index d0e1edd1..0bc82dcc 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -21,13 +21,13 @@ using Microsoft.Extensions.Hosting; using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; using Serilog; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; LoggingExtensions.EnsureInitialized(); Log.Information("Building Reissuance App"); diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs index 10e8587f..fcf81a79 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/IReissuanceService.cs @@ -1,4 +1,4 @@ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; public interface IReissuanceService { diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index 3aadf434..858a6664 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional @@ -19,17 +19,17 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; -using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; -using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Text.Json; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; -using Microsoft.Extensions.Options; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs index 1388a216..00c37906 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs index a4c9cc30..d325c912 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs index d3a62535..5848b962 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs index c24a5cc9..3d5a77dd 100644 --- a/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs +++ b/src/issuer/SsiCredentialIssuer.Service/BusinessLogic/IssuerBusinessLogic.cs @@ -24,6 +24,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; @@ -34,7 +35,6 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Identity; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Models; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Globalization; using System.Security.Cryptography; using System.Text; diff --git a/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs index 2412ced2..9a6f993a 100644 --- a/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs index 6ee1d05c..851b3cd5 100644 --- a/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * Copyright (c) 2024 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs index 13da04fa..e536ce66 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs @@ -17,20 +17,20 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using AutoFixture; +using AutoFixture.AutoFakeItEasy; using FakeItEasy; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; -using Xunit; -using System.Text.Json; -using AutoFixture; -using AutoFixture.AutoFakeItEasy; using System.Text; +using System.Text.Json; +using Xunit; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests.Handler; diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs index 6d224a8b..031fc4a0 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs @@ -20,19 +20,19 @@ using AutoFixture; using AutoFixture.AutoFakeItEasy; using FakeItEasy; +using FluentAssertions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; -using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; +using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; -using Xunit; using System.Text.Json; -using FluentAssertions; +using Xunit; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests.Services; diff --git a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs index 991b73b1..2f0bcf0c 100644 --- a/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs +++ b/tests/issuer/SsiCredentialIssuer.Service.Tests/BusinessLogic/IssuerBusinessLogicTests.cs @@ -21,6 +21,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; @@ -32,7 +33,6 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Identity; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Models; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; using System.Net; using System.Security.Cryptography; using System.Text.Json; From a8823ae0bad870e65d2ce3c070335eec31b45c2e Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 21 Aug 2024 10:58:52 +0200 Subject: [PATCH 24/26] fix: removed unused variable --- .../Services/ReissuanceServiceTests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs index 031fc4a0..36ac2d7a 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs @@ -126,8 +126,6 @@ public async void ExecuteAsync_ProcessCredentials_HandleException() { // Arrange var schema = "{\"id\":\"6f05cac6-c073-4562-8540-8fc883807808\",\"name\":\"BpnCredential\",\"type\":[\"VerifiableCredential\",\"BpnCredential\"],\"issuer\":\"did:web:localhost:BPNL000000000000\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://w3id.org/catenax/credentials/v1.0.0\"],\"description\":\"BpnCredential\",\"issuanceDate\":\"2024-08-19T07:32:37.598099+00:00\",\"expirationDate\":\"2025-08-19T07:32:37.598079+00:00\",\"credentialStatus\":{\"id\":\"example.com\",\"type\":\"StatusList2021\"},\"credentialSubject\":{\"id\":\"did:web:localhost:BPNL000000000000\",\"bpn\":\"BPNL000000000000\",\"holderIdentifier\":\"BPNL000000000000\"}}"; - IssuerCredentialRequest? issuerCredentialRequest = null; - var credentialsAboutToExpire = new CredentialAboutToExpireData( Guid.NewGuid(), "BPNL000000000000", From c0182456fd4484aeb9a528835cf048a957197563 Mon Sep 17 00:00:00 2001 From: leandro-cavalcante Date: Wed, 21 Aug 2024 11:04:44 +0200 Subject: [PATCH 25/26] fix: added ternary response --- .../Services/ReissuanceService.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index 858a6664..a33b1184 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -113,14 +113,7 @@ await _credentialIssuerHandler.HandleCredentialProcessCreation(new IssuerCredent private static string CreateNewCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { - if (credential.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.BPN) - { - return CreateBpnCredential(credential, expirationDate); - } - else - { - return CreateMembershipCredential(credential, expirationDate); - } + return credential.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.BPN ? CreateBpnCredential(credential, expirationDate) : CreateMembershipCredential(credential, expirationDate); } private static string CreateBpnCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) From fce37a151a4c06fbe52f2cf74af934f71222908f Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Mon, 2 Sep 2024 14:21:25 +0200 Subject: [PATCH 26/26] feat(reissuance): adjust reissuance app Refs: #291 --- .github/workflows/chart-test.yml | 9 + .../credential-reissuance-app-docker.yml | 88 +++++++++ .github/workflows/owasp-zap.yml | 11 +- .github/workflows/release.yml | 3 + .github/workflows/release_candidate.yml | 3 + .github/workflows/trivy-main.yml | 33 ++++ .github/workflows/trivy.yml | 32 ++++ charts/ssi-credential-issuer/README.md | 8 + .../templates/cronjob-reissuance-app.yaml | 42 +---- docker/Dockerfile-credential-reissuance-app | 2 +- .../Configuration/CredentialSettings.cs | 65 ------- .../Context/CredentialContext.cs | 9 +- .../CredentialServiceExtensions.cs | 39 ---- ...CredentialIssuer.Credential.Library.csproj | 24 ++- .../ReissuanceServiceExtensions.cs | 14 +- ...xpirySettings.cs => ReissuanceSettings.cs} | 7 +- .../Handler/CredentialIssuerHandler.cs | 51 ++---- .../Handler/ICredentialIssuerHandler.cs | 2 +- .../Handler/IssuerCredentialRequest.cs | 38 ++-- .../Models/CredentialData.cs | 2 +- .../Program.cs | 6 +- .../Services/ReissuanceService.cs | 51 ++---- .../SsiCredentialIssuer.Reissuance.App.csproj | 38 ++-- .../appsettings.json | 30 +--- .../IssuerRepositories.cs | 1 - .../CompanySsiDetailsRepository.cs | 11 +- .../Repositories/CredentialRepository.cs | 14 +- .../ICompanySsiDetailsRepository.cs | 2 + .../Repositories/ICredentialRepository.cs | 4 +- .../Repositories/IReissuanceRepository.cs | 33 ---- .../Repositories/ReissuanceRepository.cs | 62 ------- .../AuditCompanySsiDetail20240902.cs | 59 ++++++ .../Entities/CompanySsiDetail.cs | 5 +- .../Entities/ReissuanceProcess.cs | 36 ---- .../IssuerDbContext.cs | 19 +- .../20240812093252_ReissuanceChanges.cs | 73 -------- ...40902130619_291-AddReissuance.Designer.cs} | 166 +++++++++++++---- .../20240902130619_291-AddReissuance.cs | 139 +++++++++++++++ .../IssuerDbContextModelSnapshot.cs | 168 ++++++++++++++---- .../CredentialCreationProcessHandler.cs | 4 +- .../CredentialHandlerExtensions.cs | 1 + .../Expiry/CredentialExpiryProcessHandler.cs | 16 +- .../CredentialReissuanceProcessHandler.cs | 58 ++---- .../ICredentialReissuanceProcessHandler.cs | 2 +- .../CredentialCreationProcessTypeExecutor.cs | 1 + .../Handler/CredentialIssuerHandlerTests.cs | 51 +++--- .../Services/ReissuanceServiceTests.cs | 27 ++- .../CredentialRepositoryTests.cs | 9 +- .../IssuerDbContextTests.cs | 6 +- .../MandatoryIdentityClaimHandlerTests.cs | 2 +- .../CredentialCreationProcessHandlerTests.cs | 23 +-- .../CredentialExpiryProcessHandlerTests.cs | 14 +- ...dentialCreationProcessTypeExecutorTests.cs | 1 + ...CredentialReissuanceProcessHandlerTests.cs | 63 +++---- .../MockLogger.cs | 2 +- .../ProcessExecutionServiceTests.cs | 1 - 56 files changed, 894 insertions(+), 786 deletions(-) create mode 100644 .github/workflows/credential-reissuance-app-docker.yml delete mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs delete mode 100644 src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs rename src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/{ReissuanceExpirySettings.cs => ReissuanceSettings.cs} (87%) rename src/credentials/{SsiCredentialIssuer.Credential.Library => SsiCredentialIssuer.Reissuance.App}/Models/CredentialData.cs (98%) delete mode 100644 src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs delete mode 100644 src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs create mode 100644 src/database/SsiCredentialIssuer.Entities/AuditEntities/AuditCompanySsiDetail20240902.cs delete mode 100644 src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs delete mode 100644 src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs rename src/database/SsiCredentialIssuer.Migrations/Migrations/{20240812093252_ReissuanceChanges.Designer.cs => 20240902130619_291-AddReissuance.Designer.cs} (90%) create mode 100644 src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.cs diff --git a/.github/workflows/chart-test.yml b/.github/workflows/chart-test.yml index d90e1a36..a39ece31 100644 --- a/.github/workflows/chart-test.yml +++ b/.github/workflows/chart-test.yml @@ -96,6 +96,15 @@ jobs: push: true tags: kind-registry:5000/credential-issuer-processes-worker:testing + - name: Build reissuance app + id: build-reissuance-app-image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile-credential-reissuance-app + push: true + tags: kind-registry:5000/credential-reissuance-app:testing + - name: Set up Helm uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4 with: diff --git a/.github/workflows/credential-reissuance-app-docker.yml b/.github/workflows/credential-reissuance-app-docker.yml new file mode 100644 index 00000000..888407ea --- /dev/null +++ b/.github/workflows/credential-reissuance-app-docker.yml @@ -0,0 +1,88 @@ +############################################################### +# Copyright (c) 2024 Contributors to the Eclipse Foundation +# +# 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 +############################################################### + +name: Build Credential Reissuance App Image + +on: + push: + paths: + # service and transitive paths + - 'src/**' + # workflow file + - '.github/workflows/credential-reissuance-app-docker.yml' + # dockerfile + - 'docker/Dockerfile-credential-reissuance-app' + + branches: + - 'main' + workflow_dispatch: + +env: + IMAGE_NAMESPACE: "tractusx" + IMAGE_NAME: "ssi-credential-reissuance-app" + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3.4.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=main + type=raw,value=${{ github.sha }} + + - name: Build and push Docker image + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c # v6.3.0 + with: + context: . + file: ./docker/Dockerfile-credential-reissuance-app + platforms: linux/amd64, linux/arm64 + pull: true + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + # https://github.com/peter-evans/dockerhub-description + - name: Update Docker Hub description + if: github.event_name != 'pull_request' + uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4.0.0 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} + readme-filepath: ./docker/notice-credential-reissuance-app.md diff --git a/.github/workflows/owasp-zap.yml b/.github/workflows/owasp-zap.yml index 497b2538..cb5a6b0c 100644 --- a/.github/workflows/owasp-zap.yml +++ b/.github/workflows/owasp-zap.yml @@ -95,7 +95,16 @@ jobs: file: ./docker/Dockerfile-credential-expiry-app push: true tags: kind-registry:5000/credential-expiry-app:testing - + + - name: Build Reissuance image + id: build-reissuance-image + uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c # v6.3.0 + with: + context: . + file: ./docker/Dockerfile-credential-reissuance-app + push: true + tags: kind-registry:5000/credential-reissuance-app:testing + - name: Add bitnami repo run: | helm repo add bitnami https://charts.bitnami.com/bitnami diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f895bd52..1a609bb1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,6 +103,9 @@ jobs: - image: tractusx/ssi-credential-expiry-app dockerfile: ./docker/Dockerfile-credential-expiry-app dockernotice: ./docker/notice-credential-expiry-app.md + - image: tractusx/ssi-credential-reissuance-app + dockerfile: ./docker/Dockerfile-credential-reissuance-app + dockernotice: ./docker/notice-credential-reissuance-app.md outputs: app-version: ${{ steps.app-version.outputs.current }} version-check: ${{ steps.version-check.outputs.exists }} diff --git a/.github/workflows/release_candidate.yml b/.github/workflows/release_candidate.yml index 04e61a57..901c924a 100644 --- a/.github/workflows/release_candidate.yml +++ b/.github/workflows/release_candidate.yml @@ -45,6 +45,9 @@ jobs: - image: tractusx/ssi-credential-expiry-app dockerfile: ./docker/Dockerfile-credential-expiry-app dockernotice: ./docker/notice-credential-expiry-app.md + - image: tractusx/ssi-credential-reissuance-app + dockerfile: ./docker/Dockerfile-credential-reissuance-app + dockernotice: ./docker/notice-credential-reissuance-app.md steps: - name: Checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 diff --git a/.github/workflows/trivy-main.yml b/.github/workflows/trivy-main.yml index addc9c5f..4ba3c2b8 100644 --- a/.github/workflows/trivy-main.yml +++ b/.github/workflows/trivy-main.yml @@ -198,3 +198,36 @@ jobs: uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 with: sarif_file: "trivy-results5.sarif" + + analyze-ssi-credential-issuer-reissuance-app: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # It's also possible to scan your private registry with Trivy's built-in image scan. + # All you have to do is set ENV vars. + # Docker Hub needs TRIVY_USERNAME and TRIVY_PASSWORD. + # You don't need to set ENV vars when downloading from a public repository. + # For public images, no ENV vars must be set. + - name: Run Trivy vulnerability scanner + if: always() + uses: aquasecurity/trivy-action@7c2007bcb556501da015201bcba5aa14069b74e2 # v0.23.0 + with: + # Path to Docker image + image-ref: "${{ env.IMAGE_NAMESPACE }}/ssi-credential-issuer-reissuance-app:main" + format: "sarif" + output: "trivy-results6.sarif" + vuln-type: "os,library" + skip-dirs: "docs/" + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + with: + sarif_file: "trivy-results6.sarif" diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 250e3ee6..3dedec55 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -196,3 +196,35 @@ jobs: uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 with: sarif_file: "trivy-results5.sarif" + + analyze-ssi-credential-reissuance-app: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # It's also possible to scan your private registry with Trivy's built-in image scan. + # All you have to do is set ENV vars. + # Docker Hub needs TRIVY_USERNAME and TRIVY_PASSWORD. + # You don't need to set ENV vars when downloading from a public repository. + # For public images, no ENV vars must be set. + - name: Run Trivy vulnerability scanner + if: always() + uses: aquasecurity/trivy-action@7c2007bcb556501da015201bcba5aa14069b74e2 # v0.23.0 + with: + # Path to Docker image + image-ref: "${{ env.IMAGE_NAMESPACE }}/ssi-credential-reissuance-app:latest" + format: "sarif" + output: "trivy-results6.sarif" + vuln-type: "os,library" + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + with: + sarif_file: "trivy-results6.sarif" diff --git a/charts/ssi-credential-issuer/README.md b/charts/ssi-credential-issuer/README.md index fd984e47..ae6b77ab 100644 --- a/charts/ssi-credential-issuer/README.md +++ b/charts/ssi-credential-issuer/README.md @@ -107,6 +107,14 @@ dependencies: | credentialExpiry.logging.default | string | `"Information"` | | | credentialExpiry.expiry.expiredVcsToDeleteInMonth | int | `12` | | | credentialExpiry.expiry.inactiveVcsToDeleteInWeeks | int | `12` | | +| credentialReissuance.name | string | `"reissuance"` | | +| credentialReissuance.image.name | string | `"docker.io/tractusx/ssi-credential-reissuance-app"` | | +| credentialReissuance.image.tag | string | `""` | | +| credentialReissuance.imagePullPolicy | string | `"IfNotPresent"` | | +| credentialReissuance.resources | object | `{"limits":{"cpu":"45m","memory":"105M"},"requests":{"cpu":"15m","memory":"105M"}}` | We recommend to review the default resource limits as this should a conscious choice. | +| credentialReissuance.processIdentity.identityId | string | `"23db9ff3-20c7-476c-ba70-6bdfe5c97104"` | | +| credentialReissuance.logging.default | string | `"Information"` | | +| credentialReissuance.expiry.expiredVcsToReissueInDays | int | `1` | | | existingSecret | string | `""` | Secret containing the client-secrets for the connection to portal and wallet as well as encryptionKeys for issuer.credential and processesworker.wallet | | dotnetEnvironment | string | `"Production"` | | | dbConnection.schema | string | `"issuer"` | | diff --git a/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml index 174ed091..cf032599 100644 --- a/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml +++ b/charts/ssi-credential-issuer/templates/cronjob-reissuance-app.yaml @@ -25,7 +25,7 @@ metadata: labels: {{- include "issuer.labels" . | nindent 4 }} spec: - schedule: "0 23 * * *" + schedule: "0 0 * * *" concurrencyPolicy: Forbid jobTemplate: metadata: @@ -66,46 +66,10 @@ spec: - name: "CONNECTIONSTRINGS__ISSUERDB" value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(ISSUER_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" {{- end }} - - name: "EXPIRY__EXPIREDVCSTOREISSUEINDAYS" + - name: "REISSUANCE__EXPIREDVCSTOREISSUEINDAYS" value: "{{ .Values.credentialReissuance.expiry.expiredVcsToReissueInDays }}" - - name: "PORTAL__CLIENTID" - value: "{{ .Values.service.portal.clientId }}" - - name: "PORTAL__CLIENTSECRET" - valueFrom: - secretKeyRef: - name: "{{ template "issuer.secretName" . }}" - key: "portal-client-secret" - - name: "PORTAL__GRANTTYPE" - value: "{{ .Values.processesworker.portal.grantType }}" - - name: "PORTAL__TOKENADDRESS" - value: "{{ .Values.centralidp.address }}{{ .Values.centralidp.tokenPath }}" - - name: "PORTAL__BASEADDRESS" - value: "{{ .Values.portalBackendAddress }}" - - name: "PORTAL__PASSWORD" - value: "empty" - - name: "PORTAL__SCOPE" - value: "{{ .Values.processesworker.portal.scope }}" - - name: "PORTAL__USERNAME" - value: "empty" - - name: "CREDENTIAL__ISSUERDID" - value: "{{ .Values.service.credential.issuerDid }}" - - name: "CREDENTIAL__ISSUERBPN" + - name: "REISSUANCE__ISSUERBPN" value: "{{ .Values.service.credential.issuerBpn }}" - - name: "CREDENTIAL__STATUSLISTURL" - value: "{{ .Values.service.credential.statusListUrl }}" - - name: "CREDENTIAL__ENCRYPTIONCONFIG__ENCRYPTIONCONFIGINDEX" - value: "{{ .Values.service.credential.encryptionConfigIndex }}" - - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__INDEX" - value: "{{ .Values.service.credential.encryptionConfigs.index0.index}}" - - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__CIPHERMODE" - value: "{{ .Values.service.credential.encryptionConfigs.index0.cipherMode}}" - - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__PADDINGMODE" - value: "{{ .Values.service.credential.encryptionConfigs.index0.paddingMode}}" - - name: "CREDENTIAL__ENCRYPTIONCONFIGS__0__ENCRYPTIONKEY" - valueFrom: - secretKeyRef: - name: "{{ template "issuer.secretName" . }}" - key: "credential-encryption-key0" ports: - name: http containerPort: {{ .Values.portContainer }} diff --git a/docker/Dockerfile-credential-reissuance-app b/docker/Dockerfile-credential-reissuance-app index 86d1e483..d9bd295c 100644 --- a/docker/Dockerfile-credential-reissuance-app +++ b/docker/Dockerfile-credential-reissuance-app @@ -32,4 +32,4 @@ WORKDIR /app COPY --from=publish /app/publish . RUN chown -R 1000:3000 /app USER 1000:3000 -ENTRYPOINT ["dotnet", "Org.Eclipse.TractusX.SsiCredentialIssuer.reissuance.App.dll"] +ENTRYPOINT ["dotnet", "Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.dll"] diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs deleted file mode 100644 index a44ac6df..00000000 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/Configuration/CredentialSettings.cs +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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 - ********************************************************************************/ - -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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 Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Validation; -using System.ComponentModel.DataAnnotations; - -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; - -public class CredentialSettings -{ - [Required(AllowEmptyStrings = false)] - public string IssuerBpn { get; set; } = null!; -} - -public static class CompanyDataSettingsExtensions -{ - public static IServiceCollection ConfigureCredentialSettings( - this IServiceCollection services, - IConfigurationSection section) - { - services.AddOptions() - .Bind(section) - .ValidateDataAnnotations() - .ValidateDistinctValues(section) - .ValidateEnumEnumeration(section) - .ValidateOnStart(); - return services; - } -} diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs index de27bf4f..40bec1c3 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/Context/CredentialContext.cs @@ -17,10 +17,11 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using System.Collections.Immutable; + namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; -public class CredentialContext -{ - private static readonly IEnumerable _context = ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0"]; - public static IEnumerable Context => _context; +public static class CredentialContext +{ + public static ImmutableArray Context => ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/catenax/credentials/v1.0.0"]; } diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs deleted file mode 100644 index 914c5b28..00000000 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/DependencyInjection/CredentialServiceExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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 Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; - -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; - -/// -/// Extension method to register the credential settings and dependent services -/// -public static class CredentialServiceExtensions -{ - /// - /// Adds the renewal service - /// - /// the services - /// the enriched service collection - public static IServiceCollection AddICredentialServiceExtensions(this IServiceCollection services, IConfiguration config) => - services - .ConfigureCredentialSettings(config.GetSection("Credential")); -} diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj b/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj index 2e295e63..e1b3b608 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj +++ b/src/credentials/SsiCredentialIssuer.Credential.Library/SsiCredentialIssuer.Credential.Library.csproj @@ -1,27 +1,23 @@ + + Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library + Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library + net8.0 + enable + enable + + - - - - - - + + - - Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library - Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library - net8.0 - enable - enable - - diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs index 2d71b730..f3e04f75 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceServiceExtensions.cs @@ -20,7 +20,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; @@ -38,16 +38,16 @@ public static class ReissuanceServiceExtensions /// the enriched service collection public static IServiceCollection AddReissuanceService(this IServiceCollection services, IConfigurationSection section) { - services.AddOptions().Bind(section); + services + .AddOptions() + .ValidateOnStart() + .ValidateDataAnnotations() + .Bind(section); services .AddTransient() .AddTransient() - .AddCredentialIssuerHandlerService(); + .AddTransient(); return services; } - - private static IServiceCollection AddCredentialIssuerHandlerService(this IServiceCollection services) => - services - .AddTransient(); } diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceSettings.cs similarity index 87% rename from src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceSettings.cs index 43fcd8ba..712c2c11 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceExpirySettings.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/DependencyInjection/ReissuanceSettings.cs @@ -24,11 +24,14 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInje /// /// Settings for the ReissuanceExpirySettings /// -public class ReissuanceExpirySettings +public class ReissuanceSettings { + [Required(AllowEmptyStrings = false)] + public string IssuerBpn { get; set; } = null!; + /// /// Vcs which are about to expire in the next day(s). /// [Required] - public int ExpiredVcsToReissueInDays { get; init; } = 1; + public int ExpiredVcsToReissueInDays { get; init; } } diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs index a951ec2c..19f27b45 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/CredentialIssuerHandler.cs @@ -17,79 +17,64 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; using System.Security.Cryptography; using System.Text; using System.Text.Json; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; /// -public class CredentialIssuerHandler : ICredentialIssuerHandler +public class CredentialIssuerHandler(IIssuerRepositories repositories, IOptions options) : ICredentialIssuerHandler { - private readonly CredentialSettings _settings; - private readonly IServiceScopeFactory _serviceScopeFactory; - /// - /// Constructor - /// - /// - /// - public CredentialIssuerHandler(IServiceScopeFactory serviceScopeFactory, IOptions options) - { - _serviceScopeFactory = serviceScopeFactory; - _settings = options.Value; - } + private readonly ReissuanceSettings _settings = options.Value; /// - public async Task HandleCredentialProcessCreation(IssuerCredentialRequest credentialRequest) + public async Task HandleCredentialProcessCreation(IssuerCredentialRequest issuerCredentialRequest) { - var documentContent = Encoding.UTF8.GetBytes(credentialRequest.Schema); + var documentContent = Encoding.UTF8.GetBytes(issuerCredentialRequest.Schema); var hash = SHA512.HashData(documentContent); - using var processServiceScope = _serviceScopeFactory.CreateScope(); - var repositories = processServiceScope.ServiceProvider.GetRequiredService(); var documentRepository = repositories.GetInstance(); - var reissuanceRepository = repositories.GetInstance(); var companyCredentialDetailsRepository = repositories.GetInstance(); - var docId = documentRepository.CreateDocument($"{credentialRequest.TypeId}.json", documentContent, + var docId = documentRepository.CreateDocument($"{issuerCredentialRequest.TypeId}.json", documentContent, hash, MediaTypeId.JSON, DocumentTypeId.PRESENTATION, x => { - x.IdentityId = credentialRequest.IdentiyId; + x.IdentityId = issuerCredentialRequest.IdentiyId; x.DocumentStatusId = DocumentStatusId.ACTIVE; }).Id; Guid? processId = CreateProcess(repositories); var ssiDetailId = companyCredentialDetailsRepository.CreateSsiDetails( - credentialRequest.Bpnl, - credentialRequest.TypeId, + issuerCredentialRequest.Bpnl, + issuerCredentialRequest.TypeId, CompanySsiDetailStatusId.ACTIVE, _settings.IssuerBpn, - credentialRequest.IdentiyId, + issuerCredentialRequest.IdentiyId, c => { - c.VerifiedCredentialExternalTypeDetailVersionId = credentialRequest.DetailVersionId; + c.VerifiedCredentialExternalTypeDetailVersionId = issuerCredentialRequest.DetailVersionId; c.ProcessId = processId; - c.ExpiryDate = credentialRequest.ExpiryDate; + c.ExpiryDate = issuerCredentialRequest.ExpiryDate; + c.ReissuedCredentialId = issuerCredentialRequest.Id; }).Id; documentRepository.AssignDocumentToCompanySsiDetails(docId, ssiDetailId); - reissuanceRepository.CreateReissuanceProcess(credentialRequest.Id, ssiDetailId); - - companyCredentialDetailsRepository.CreateProcessData(ssiDetailId, JsonDocument.Parse(credentialRequest.Schema), credentialRequest.KindId, + companyCredentialDetailsRepository.CreateProcessData(ssiDetailId, JsonDocument.Parse(issuerCredentialRequest.Schema), issuerCredentialRequest.KindId, c => { - c.HolderWalletUrl = credentialRequest.HolderWalletUrl; - c.CallbackUrl = credentialRequest.CallbackUrl; + c.HolderWalletUrl = issuerCredentialRequest.HolderWalletUrl; + c.CallbackUrl = issuerCredentialRequest.CallbackUrl; }); await repositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); } + private static Guid CreateProcess(IIssuerRepositories repositories) { var processStepRepository = repositories.GetInstance(); diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs index 78e6df1c..8b72603d 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/ICredentialIssuerHandler.cs @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; /// /// Handles the re-issuance of a new credential then creates a new create credential process diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs index a0690283..07d05013 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Handler/IssuerCredentialRequest.cs @@ -17,30 +17,18 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; - using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -public class IssuerCredentialRequest( - Guid id, - string bpnl, - VerifiedCredentialTypeKindId kindId, - VerifiedCredentialTypeId typeId, - DateTimeOffset expiryDate, - string identiyId, - string schema, - string? holderWalletUrl, - Guid? detailVersionId, - string? callbackUrl) -{ - public Guid Id { get; } = id; - public string Bpnl { get; } = bpnl; - public VerifiedCredentialTypeKindId KindId { get; } = kindId; - public VerifiedCredentialTypeId TypeId { get; } = typeId; - public DateTimeOffset ExpiryDate { get; } = expiryDate; - public string IdentiyId { get; } = identiyId; - public string Schema { get; } = schema; - public string? HolderWalletUrl { get; } = holderWalletUrl; - public Guid? DetailVersionId { get; } = detailVersionId; - public string? CallbackUrl { get; } = callbackUrl; -} +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; + +public record IssuerCredentialRequest( + Guid Id, + string Bpnl, + VerifiedCredentialTypeKindId KindId, + VerifiedCredentialTypeId TypeId, + DateTimeOffset ExpiryDate, + string IdentiyId, + string Schema, + string? HolderWalletUrl, + Guid? DetailVersionId, + string? CallbackUrl); diff --git a/src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Models/CredentialData.cs similarity index 98% rename from src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs rename to src/credentials/SsiCredentialIssuer.Reissuance.App/Models/CredentialData.cs index 1694b634..18d5408e 100644 --- a/src/credentials/SsiCredentialIssuer.Credential.Library/Models/CredentialData.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Models/CredentialData.cs @@ -19,7 +19,7 @@ using System.Text.Json.Serialization; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Models; public record FrameworkCredential( [property: JsonPropertyName("id")] Guid Id, diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs index 0bc82dcc..1e4c82ce 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Program.cs @@ -21,7 +21,6 @@ using Microsoft.Extensions.Hosting; using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; using Org.Eclipse.TractusX.Portal.Backend.Framework.Token; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.DependencyInjection; @@ -38,12 +37,9 @@ .ConfigureServices((hostContext, services) => { services - .AddTransient() .AddProcessIdentity(hostContext.Configuration.GetSection("ProcessIdentity")) .AddIssuerRepositories(hostContext.Configuration) - .AddPortalService(hostContext.Configuration.GetSection("Portal")) - .AddICredentialServiceExtensions(hostContext.Configuration) - .AddReissuanceService(hostContext.Configuration.GetSection("Expiry")); + .AddReissuanceService(hostContext.Configuration.GetSection("Reissuance")); }) .AddLogging() .Build(); diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs index a33b1184..a936d258 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/Services/ReissuanceService.cs @@ -22,13 +22,13 @@ using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Context; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Models; using System.Text.Json; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; @@ -36,42 +36,25 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; /// /// Service to re-issue credentials that will expire in the day after. /// -public class ReissuanceService : IReissuanceService +public class ReissuanceService(IServiceScopeFactory serviceScopeFactory, + ICredentialIssuerHandler credentialIssuerHandler, + IOptions options, + ILogger logger) : IReissuanceService { private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - private readonly IServiceScopeFactory _serviceScopeFactory; - private readonly ILogger _logger; - private readonly ICredentialIssuerHandler _credentialIssuerHandler; - private readonly ReissuanceExpirySettings _settings; - /// - /// Creates a new instance of - /// - /// access to the services - /// access to the credential issuer handler service - /// access to the expiry section settings - /// the logger - public ReissuanceService(IServiceScopeFactory serviceScopeFactory, - ICredentialIssuerHandler credentialIssuerHandler, - IOptions options, - ILogger logger) - { - _serviceScopeFactory = serviceScopeFactory; - _credentialIssuerHandler = credentialIssuerHandler; - _settings = options.Value; - _logger = logger; - } + private readonly ReissuanceSettings _settings = options.Value; /// /// Handles the process of re-issuing new verifiable credentias /// - /// Cancellation Tokenpublic async Task ExecuteAsync(CancellationToken stoppingToken) + /// Cancellation Token public async Task ExecuteAsync(CancellationToken stoppingToken) { if (!stoppingToken.IsCancellationRequested) { try { - using var processServiceScope = _serviceScopeFactory.CreateScope(); + using var processServiceScope = serviceScopeFactory.CreateScope(); var dateTimeProvider = processServiceScope.ServiceProvider.GetRequiredService(); var repositories = processServiceScope.ServiceProvider.GetRequiredService(); var expirationDate = dateTimeProvider.OffsetNow.AddDays(_settings.ExpiredVcsToReissueInDays); @@ -82,7 +65,7 @@ public async Task ExecuteAsync(CancellationToken stoppingToken) catch (Exception ex) { Environment.ExitCode = 1; - _logger.LogError("Verified Credential re-issuance check failed with error: {Errors}", ex.Message); + logger.LogError(ex, "Verified Credential re-issuance check failed with error: {Errors}", ex.Message); } } } @@ -95,7 +78,7 @@ private async Task ProcessCredentials(IAsyncEnumerable + credential.VerifiedCredentialTypeKindId switch + { + VerifiedCredentialTypeKindId.BPN => CreateBpnCredential(credential, expirationDate), + VerifiedCredentialTypeKindId.MEMBERSHIP => CreateMembershipCredential(credential, expirationDate), + var _ => throw new NotSupportedException("Only BPN or MEMBERSHIP credentials can be reissued") + }; private static string CreateBpnCredential(CredentialAboutToExpireData credential, DateTimeOffset expirationDate) { diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj b/src/credentials/SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj index b17c047f..b68b90a6 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/SsiCredentialIssuer.Reissuance.App.csproj @@ -19,12 +19,19 @@ - - - - - - + + Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App + Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App + Exe + net8.0 + enable + enable + 47895ab5-89cb-4818-9b08-570588b6aaf3 + Linux + ..\..\.. + True + CS1591 + @@ -42,21 +49,10 @@ - + + + + - - Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App - Org.Eclipse.TractusX.SsiCredentialIssuer.Renewal.App - Exe - net8.0 - enable - enable - 47895ab5-89cb-4818-9b08-570588b6aaf3 - Linux - ..\..\.. - True - CS1591 - - diff --git a/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json b/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json index fffd6a79..fb6e7583 100644 --- a/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json +++ b/src/credentials/SsiCredentialIssuer.Reissuance.App/appsettings.json @@ -26,32 +26,8 @@ "ProcessIdentity": { "IdentityId": "" }, - "Portal": { - "Username": "", - "Password": "", - "ClientId": "", - "GrantType": "", - "ClientSecret": "", - "Scope": "", - "TokenAddress": "", - "BaseAddress": "" - }, - "Expiry": { - "ExpiredVcsToReissueInDays": 1 - }, - "Credential": { - "IssuerDid": "", - "IssuerBpn": "", - "StatusListUrl": "", - "MaxPageSize": 0, - "EncryptionConfigIndex": 0, - "EncryptionConfigs": [ - { - "Index": 0, - "EncryptionKey": "", - "CipherMode": "", - "PaddingMode": "" - } - ] + "Reissuance": { + "ExpiredVcsToReissueInDays": 1, + "IssuerBpn": "" } } diff --git a/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs b/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs index b02fda94..20699e59 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/IssuerRepositories.cs @@ -34,7 +34,6 @@ public class IssuerRepositories : IIssuerRepositories { typeof(ICredentialRepository), context => new CredentialRepository(context) }, { typeof(IDocumentRepository), context => new DocumentRepository(context) }, { typeof(IProcessStepRepository), context => new ProcessStepRepository(context) }, - { typeof(IReissuanceRepository), context => new ReissuanceRepository(context) }, }.ToImmutableDictionary(); public IssuerRepositories(IssuerDbContext dbContext) diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs index 6c065fd6..2ad706fc 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CompanySsiDetailsRepository.cs @@ -303,7 +303,7 @@ public IAsyncEnumerable GetCredentialsAboutToExpire IsDateAboutToExpire = x.ExpiryDate != null && x.ExpiryDate.Value.Date.CompareTo(expirationDate.Date) == 0, IsSsiStatusIdActive = x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE, IsValidCredendialType = x.CompanySsiProcessData != null && (x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.BPN || x.CompanySsiProcessData.CredentialTypeKindId == VerifiedCredentialTypeKindId.MEMBERSHIP), - IsCredentialNotReissued = x.ReissuanceProcess == null + IsCredentialNotReissued = x.ReissuedCredentialId == null }) .Where(ssi => ssi.IsSsiStatusIdActive && ssi.IsDateAboutToExpire && ssi.IsValidCredendialType && ssi.IsCredentialNotReissued) .Select(x => new CredentialAboutToExpireData( @@ -319,4 +319,13 @@ public IAsyncEnumerable GetCredentialsAboutToExpire )) .AsAsyncEnumerable(); } + + public Task IsCredentialRevokedByReissuance(Guid credentialId) => + context.CompanySsiDetails.AnyAsync(x => x.Id == credentialId && x.ReissuedCredentialId != null); + + public Task GetCredentialToRevoke(Guid credentialId) => + context.CompanySsiDetails + .Where(x => x.Id == credentialId) + .Select(x => x.ReissuedCredentialId) + .SingleOrDefaultAsync(); } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CredentialRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CredentialRepository.cs index 370d0f47..abd444ce 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/CredentialRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/CredentialRepository.cs @@ -28,9 +28,10 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; public class CredentialRepository(IssuerDbContext dbContext) : ICredentialRepository { - public Task GetWalletCredentialId(Guid credentialId) => - dbContext.CompanySsiDetails.Where(x => x.Id == credentialId) - .Select(x => x.ExternalCredentialId) + public Task<(Guid? ExternalCredentialId, bool IsReissuance)> GetSigningData(Guid credentialId) => + dbContext.CompanySsiDetails + .Where(x => x.Id == credentialId) + .Select(x => new ValueTuple(x.ExternalCredentialId, x.ReissuedCredentialId != null)) .SingleOrDefaultAsync(); public Task<(HolderWalletData HolderWalletData, string? Credential, EncryptionTransformationData EncryptionInformation, string? CallbackUrl)> GetCredentialData(Guid credentialId) => @@ -91,10 +92,13 @@ public void AttachAndModifyCredential(Guid credentialId, Action GetCredentialNotificationData(Guid credentialId) => + public Task<(VerifiedCredentialExternalTypeId ExternalTypeId, string RequesterId, bool isReissuance)> GetCredentialNotificationData(Guid credentialId) => dbContext.CompanySsiDetails .Where(x => x.Id == credentialId) - .Select(x => new ValueTuple(x.VerifiedCredentialType!.VerifiedCredentialTypeAssignedExternalType!.VerifiedCredentialExternalTypeId, x.CreatorUserId)) + .Select(x => new ValueTuple( + x.VerifiedCredentialType!.VerifiedCredentialTypeAssignedExternalType!.VerifiedCredentialExternalTypeId, + x.CreatorUserId, + x.ReissuedCredentialId != null)) .SingleOrDefaultAsync(); public Task<(bool Exists, bool IsSameCompany, IEnumerable<(DocumentStatusId StatusId, byte[] Content)> Documents)> GetSignedCredentialForCredentialId(Guid credentialId, string bpnl) => diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs index b8d62555..8836ba67 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICompanySsiDetailsRepository.cs @@ -104,4 +104,6 @@ public interface ICompanySsiDetailsRepository void CreateProcessData(Guid companySsiDetailId, JsonDocument schema, VerifiedCredentialTypeKindId credentialTypeKindId, Action? setOptionalFields); void AttachAndModifyProcessData(Guid companySsiDetailId, Action? initialize, Action setOptionalFields); IAsyncEnumerable GetCredentialsAboutToExpire(DateTimeOffset expirationDate); + Task IsCredentialRevokedByReissuance(Guid credentialId); + Task GetCredentialToRevoke(Guid credentialId); } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICredentialRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICredentialRepository.cs index 0f66e489..857487fd 100644 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICredentialRepository.cs +++ b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ICredentialRepository.cs @@ -26,7 +26,7 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; public interface ICredentialRepository { - Task GetWalletCredentialId(Guid credentialId); + Task<(Guid? ExternalCredentialId, bool IsReissuance)> GetSigningData(Guid credentialId); Task<(HolderWalletData HolderWalletData, string? Credential, EncryptionTransformationData EncryptionInformation, string? CallbackUrl)> GetCredentialData(Guid credentialId); Task<(bool Exists, Guid CredentialId)> GetDataForProcessId(Guid processId); Task<(VerifiedCredentialTypeKindId CredentialTypeKindId, JsonDocument Schema)> GetCredentialStorageInformationById(Guid credentialId); @@ -34,7 +34,7 @@ public interface ICredentialRepository Task<(string Bpn, string? CallbackUrl)> GetCallbackUrl(Guid credentialId); Task<(bool Exists, bool IsSameBpnl, Guid? ExternalCredentialId, CompanySsiDetailStatusId StatusId, IEnumerable<(Guid DocumentId, DocumentStatusId DocumentStatusId)> Documents)> GetRevocationDataById(Guid credentialId, string bpnl); void AttachAndModifyCredential(Guid credentialId, Action? initialize, Action modify); - Task<(VerifiedCredentialExternalTypeId ExternalTypeId, string RequesterId)> GetCredentialNotificationData(Guid credentialId); + Task<(VerifiedCredentialExternalTypeId ExternalTypeId, string RequesterId, bool isReissuance)> GetCredentialNotificationData(Guid credentialId); Task<(bool Exists, bool IsSameCompany, IEnumerable<(DocumentStatusId StatusId, byte[] Content)> Documents)> GetSignedCredentialForCredentialId(Guid credentialId, string bpnl); Task<(bool Exists, bool IsSameCompany, string FileName, DocumentStatusId StatusId, byte[] Content, MediaTypeId MediaTypeId)> GetDocumentById(Guid documentId, string bpnl); } diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs deleted file mode 100644 index 00c37906..00000000 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/IReissuanceRepository.cs +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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.SsiCredentialIssuer.Entities.Entities; - -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; - -public interface IReissuanceRepository -{ - void CreateReissuanceProcess(Guid id, Guid reissuedCredentialId); - - Guid GetCompanySsiDetailId(Guid companySsiDetaillId); - - bool IsReissuedCredential(Guid companySsiDetaillId); - - bool IsCredentialRevokedByReissuance(Guid companySsiDetaillId); -} diff --git a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs b/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs deleted file mode 100644 index d325c912..00000000 --- a/src/database/SsiCredentialIssuer.DbAccess/Repositories/ReissuanceRepository.cs +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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.SsiCredentialIssuer.Entities; - -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; - -public class ReissuanceRepository : IReissuanceRepository -{ - private readonly IssuerDbContext _dbContext; - - /// - /// Constructor. - /// - /// IssuerDbContext context. - public ReissuanceRepository(IssuerDbContext dbContext) - { - _dbContext = dbContext; - } - public void CreateReissuanceProcess(Guid id, Guid reissuedCredentialId) - { - var reissuanceProcess = new ReissuanceProcess(id, reissuedCredentialId); - _dbContext.Reissuances.Add(reissuanceProcess); - } - - public Guid GetCompanySsiDetailId(Guid companySsiDetaillId) - { - return _dbContext.Reissuances - .Where(ssi => ssi.ReissuedCredentialId == companySsiDetaillId) - .Select(ssi => ssi.Id).SingleOrDefault(); - } - - public bool IsReissuedCredential(Guid companySsiDetaillId) - { - return _dbContext.Reissuances - .Where(ssi => ssi.ReissuedCredentialId == companySsiDetaillId) - .Select(ssi => true).SingleOrDefault(); - } - - public bool IsCredentialRevokedByReissuance(Guid companySsiDetaillId) - { - return _dbContext.Reissuances - .Where(ssi => ssi.Id == companySsiDetaillId) - .Select(ssi => true).SingleOrDefault(); - } -} diff --git a/src/database/SsiCredentialIssuer.Entities/AuditEntities/AuditCompanySsiDetail20240902.cs b/src/database/SsiCredentialIssuer.Entities/AuditEntities/AuditCompanySsiDetail20240902.cs new file mode 100644 index 00000000..7b1941fb --- /dev/null +++ b/src/database/SsiCredentialIssuer.Entities/AuditEntities/AuditCompanySsiDetail20240902.cs @@ -0,0 +1,59 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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.SsiCredentialIssuer.Entities.Auditing; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Auditing.Enums; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; +using System.ComponentModel.DataAnnotations; + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities; + +public class AuditCompanySsiDetail20240902 : IAuditEntityV2 +{ + /// + [Key] + public Guid AuditV2Id { get; set; } + + public Guid Id { get; set; } + public string Bpnl { get; set; } = null!; + public string IssuerBpn { get; set; } = null!; + public VerifiedCredentialTypeId VerifiedCredentialTypeId { get; set; } + public CompanySsiDetailStatusId CompanySsiDetailStatusId { get; set; } + public DateTimeOffset DateCreated { get; private set; } + public string CreatorUserId { get; set; } = null!; + public DateTimeOffset? ExpiryDate { get; set; } + public Guid? VerifiedCredentialExternalTypeDetailVersionId { get; set; } + + public ExpiryCheckTypeId? ExpiryCheckTypeId { get; set; } + public Guid? ProcessId { get; set; } + public Guid? ExternalCredentialId { get; set; } + public string? Credential { get; set; } + public Guid? ReissuedCredentialId { get; set; } + public DateTimeOffset? DateLastChanged { get; set; } + public string? LastEditorId { get; set; } + + /// + public string? AuditV2LastEditorId { get; set; } + + /// + public AuditOperationId AuditV2OperationId { get; set; } + + /// + public DateTimeOffset AuditV2DateLastChanged { get; set; } +} diff --git a/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs b/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs index ced344bc..457a3075 100644 --- a/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs +++ b/src/database/SsiCredentialIssuer.Entities/Entities/CompanySsiDetail.cs @@ -24,7 +24,7 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; -[AuditEntityV2(typeof(AuditCompanySsiDetail20240419))] +[AuditEntityV2(typeof(AuditCompanySsiDetail20240902))] public class CompanySsiDetail : IAuditableV2, IBaseEntity { private CompanySsiDetail() @@ -61,6 +61,7 @@ public CompanySsiDetail(Guid id, string bpnl, VerifiedCredentialTypeId verifiedC public Guid? ProcessId { get; set; } public Guid? ExternalCredentialId { get; set; } public string? Credential { get; set; } + public Guid? ReissuedCredentialId { get; set; } [LastChangedV2] public DateTimeOffset? DateLastChanged { get; set; } @@ -73,7 +74,7 @@ public CompanySsiDetail(Guid id, string bpnl, VerifiedCredentialTypeId verifiedC public virtual ExpiryCheckType? ExpiryCheckType { get; set; } public virtual CompanySsiDetailStatus? CompanySsiDetailStatus { get; set; } public virtual Process? Process { get; set; } - public virtual ReissuanceProcess? ReissuanceProcess { get; set; } + public virtual CompanySsiDetail? ReissuedCredential { get; set; } public virtual VerifiedCredentialExternalTypeDetailVersion? VerifiedCredentialExternalTypeDetailVersion { get; set; } public virtual CompanySsiProcessData? CompanySsiProcessData { get; set; } public virtual ICollection Documents { get; private set; } diff --git a/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs b/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs deleted file mode 100644 index f265c4c4..00000000 --- a/src/database/SsiCredentialIssuer.Entities/Entities/ReissuanceProcess.cs +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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.SsiCredentialIssuer.Entities.Auditing; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; - -public class ReissuanceProcess : IBaseEntity -{ - public ReissuanceProcess(Guid id, Guid reissuedCredentialId) - { - Id = id; - ReissuedCredentialId = reissuedCredentialId; - } - - public Guid Id { get; private set; } - public Guid ReissuedCredentialId { get; private set; } - - // Navigation properties - public virtual CompanySsiDetail? CompanySsiDetail { get; private set; } -} diff --git a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs index 0a60277b..337a078c 100644 --- a/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs +++ b/src/database/SsiCredentialIssuer.Entities/IssuerDbContext.cs @@ -44,8 +44,9 @@ public IssuerDbContext(DbContextOptions options, IAuditHandler } public virtual DbSet AuditCompanySsiDetail20240228 { get; set; } = default!; - public virtual DbSet AuditDocument20240305 { get; set; } = default!; public virtual DbSet AuditCompanySsiDetail20240419 { get; set; } = default!; + public virtual DbSet AuditCompanySsiDetail20240902 { get; set; } = default!; + public virtual DbSet AuditDocument20240305 { get; set; } = default!; public virtual DbSet AuditDocument20240419 { get; set; } = default!; public virtual DbSet CompanySsiDetails { get; set; } = default!; public virtual DbSet CompanySsiDetailAssignedDocuments { get; set; } = default!; @@ -61,7 +62,6 @@ public IssuerDbContext(DbContextOptions options, IAuditHandler public virtual DbSet ProcessStepStatuses { get; set; } = default!; public virtual DbSet ProcessStepTypes { get; set; } = default!; public virtual DbSet ProcessTypes { get; set; } = default!; - public virtual DbSet Reissuances { get; set; } = default!; public virtual DbSet UseCases { get; set; } = default!; public virtual DbSet VerifiedCredentialExternalTypes { get; set; } = default!; public virtual DbSet VerifiedCredentialExternalTypeDetailVersions { get; set; } = default!; @@ -103,6 +103,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(t => t.VerifiedCredentialExternalTypeDetailVersionId) .OnDelete(DeleteBehavior.ClientSetNull); + entity.HasOne(c => c.ReissuedCredential) + .WithOne() + .HasForeignKey(c => c.ReissuedCredentialId); + entity.HasMany(t => t.Documents) .WithMany(o => o.CompanySsiDetails) .UsingEntity( @@ -121,7 +125,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) j.HasKey(e => new { e.DocumentId, e.CompanySsiDetailId }); }); - entity.HasAuditV2Triggers(); + entity.HasAuditV2Triggers(); }); modelBuilder.Entity() @@ -144,15 +148,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(x => x.CredentialTypeKindId); }); - modelBuilder.Entity(e => - { - e.HasKey(x => x.Id); - - e.HasOne(x => x.CompanySsiDetail) - .WithOne(x => x.ReissuanceProcess) - .HasForeignKey(x => x.Id); - }); - modelBuilder.Entity(entity => { entity.HasAuditV2Triggers(); diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs deleted file mode 100644 index 5848b962..00000000 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.cs +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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 Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations -{ - /// - public partial class ReissuanceChanges : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "reissuances", - schema: "issuer", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - reissued_credential_id = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("pk_reissuances", x => x.id); - table.ForeignKey( - name: "fk_reissuances_company_ssi_details_id", - column: x => x.id, - principalSchema: "issuer", - principalTable: "company_ssi_details", - principalColumn: "id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.InsertData( - schema: "issuer", - table: "process_step_types", - columns: new[] { "id", "label" }, - values: new object[] { 6, "REVOKE_REISSUED_CREDENTIAL" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "reissuances", - schema: "issuer"); - - migrationBuilder.DeleteData( - schema: "issuer", - table: "process_step_types", - keyColumn: "id", - keyValue: 6); - } - } -} diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.Designer.cs similarity index 90% rename from src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs rename to src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.Designer.cs index dc4dedf5..6798ac75 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240812093252_ReissuanceChanges.Designer.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.Designer.cs @@ -1,4 +1,23 @@ -// +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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; using System.Text.Json; using Microsoft.EntityFrameworkCore; @@ -13,8 +32,8 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations { [DbContext(typeof(IssuerDbContext))] - [Migration("20240812093252_ReissuanceChanges")] - partial class ReissuanceChanges + [Migration("20240902130619_291-AddReissuance")] + partial class _291AddReissuance { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -203,6 +222,98 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("audit_company_ssi_detail20240419", "issuer"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditCompanySsiDetail20240902", b => + { + b.Property("AuditV2Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v2id"); + + b.Property("AuditV2DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v2date_last_changed"); + + b.Property("AuditV2LastEditorId") + .HasColumnType("text") + .HasColumnName("audit_v2last_editor_id"); + + b.Property("AuditV2OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v2operation_id"); + + b.Property("Bpnl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpnl"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("creator_user_id"); + + b.Property("Credential") + .HasColumnType("text") + .HasColumnName("credential"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("ExpiryCheckTypeId") + .HasColumnType("integer") + .HasColumnName("expiry_check_type_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("ExternalCredentialId") + .HasColumnType("uuid") + .HasColumnName("external_credential_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IssuerBpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("issuer_bpn"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + + b.Property("VerifiedCredentialExternalTypeDetailVersionId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_detail_version_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("AuditV2Id") + .HasName("pk_audit_company_ssi_detail20240902"); + + b.ToTable("audit_company_ssi_detail20240902", "issuer"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditDocument20240305", b => { b.Property("AuditV1Id") @@ -399,6 +510,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("process_id"); + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + b.Property("VerifiedCredentialExternalTypeDetailVersionId") .HasColumnType("uuid") .HasColumnName("verified_credential_external_type_detail_version_id"); @@ -419,6 +534,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("ProcessId") .HasDatabaseName("ix_company_ssi_details_process_id"); + b.HasIndex("ReissuedCredentialId") + .IsUnique() + .HasDatabaseName("ix_company_ssi_details_reissued_credential_id"); + b.HasIndex("VerifiedCredentialExternalTypeDetailVersionId") .HasDatabaseName("ix_company_ssi_details_verified_credential_external_type_detai"); @@ -433,8 +552,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) }); b - .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") - .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); }); modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailAssignedDocument", b => @@ -1334,22 +1453,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) }); }); - modelBuilder.Entity("ReissuanceProcess", b => - { - b.Property("Id") - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("ReissuedCredentialId") - .HasColumnType("uuid") - .HasColumnName("reissued_credential_id"); - - b.HasKey("Id") - .HasName("pk_reissuances"); - - b.ToTable("reissuances", "issuer"); - }); - modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", "CompanySsiDetailStatus") @@ -1368,6 +1471,11 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasForeignKey("ProcessId") .HasConstraintName("fk_company_ssi_details_processes_process_id"); + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "ReissuedCredential") + .WithOne() + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "ReissuedCredentialId") + .HasConstraintName("fk_company_ssi_details_company_ssi_details_reissued_credential"); + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", "VerifiedCredentialExternalTypeDetailVersion") .WithMany("CompanySsiDetails") .HasForeignKey("VerifiedCredentialExternalTypeDetailVersionId") @@ -1385,6 +1493,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Process"); + b.Navigation("ReissuedCredential"); + b.Navigation("VerifiedCredentialExternalTypeDetailVersion"); b.Navigation("VerifiedCredentialType"); @@ -1570,23 +1680,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("VerifiedCredentialType"); }); - modelBuilder.Entity("ReissuanceProcess", b => - { - b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") - .WithOne("ReissuanceProcess") - .HasForeignKey("ReissuanceProcess", "Id") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_reissuances_company_ssi_details_id"); - - b.Navigation("CompanySsiDetail"); - }); - modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.Navigation("CompanySsiProcessData"); - - b.Navigation("ReissuanceProcess"); }); modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", b => diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.cs new file mode 100644 index 00000000..a00af888 --- /dev/null +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/20240902130619_291-AddReissuance.cs @@ -0,0 +1,139 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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 Microsoft.EntityFrameworkCore.Migrations; +using System; + +#nullable disable + +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations +{ + /// + public partial class _291AddReissuance : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("DROP FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() CASCADE;"); + + migrationBuilder.Sql("DROP FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() CASCADE;"); + + migrationBuilder.AddColumn( + name: "reissued_credential_id", + schema: "issuer", + table: "company_ssi_details", + type: "uuid", + nullable: true); + + migrationBuilder.CreateTable( + name: "audit_company_ssi_detail20240902", + schema: "issuer", + columns: table => new + { + audit_v2id = table.Column(type: "uuid", nullable: false), + id = table.Column(type: "uuid", nullable: false), + bpnl = table.Column(type: "text", nullable: false), + issuer_bpn = table.Column(type: "text", nullable: false), + verified_credential_type_id = table.Column(type: "integer", nullable: false), + company_ssi_detail_status_id = table.Column(type: "integer", nullable: false), + date_created = table.Column(type: "timestamp with time zone", nullable: false), + creator_user_id = table.Column(type: "text", nullable: false), + expiry_date = table.Column(type: "timestamp with time zone", nullable: true), + verified_credential_external_type_detail_version_id = table.Column(type: "uuid", nullable: true), + expiry_check_type_id = table.Column(type: "integer", nullable: true), + process_id = table.Column(type: "uuid", nullable: true), + external_credential_id = table.Column(type: "uuid", nullable: true), + credential = table.Column(type: "text", nullable: true), + reissued_credential_id = table.Column(type: "uuid", nullable: true), + date_last_changed = table.Column(type: "timestamp with time zone", nullable: true), + last_editor_id = table.Column(type: "text", nullable: true), + audit_v2last_editor_id = table.Column(type: "text", nullable: true), + audit_v2operation_id = table.Column(type: "integer", nullable: false), + audit_v2date_last_changed = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_audit_company_ssi_detail20240902", x => x.audit_v2id); + }); + + migrationBuilder.InsertData( + schema: "issuer", + table: "process_step_types", + columns: new[] { "id", "label" }, + values: new object[] { 6, "REVOKE_REISSUED_CREDENTIAL" }); + + migrationBuilder.CreateIndex( + name: "ix_company_ssi_details_reissued_credential_id", + schema: "issuer", + table: "company_ssi_details", + column: "reissued_credential_id", + unique: true); + + migrationBuilder.AddForeignKey( + name: "fk_company_ssi_details_company_ssi_details_reissued_credential", + schema: "issuer", + table: "company_ssi_details", + column: "reissued_credential_id", + principalSchema: "issuer", + principalTable: "company_ssi_details", + principalColumn: "id"); + + migrationBuilder.Sql("CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();"); + + migrationBuilder.Sql("CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql("DROP FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() CASCADE;"); + + migrationBuilder.Sql("DROP FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() CASCADE;"); + + migrationBuilder.DropForeignKey( + name: "fk_company_ssi_details_company_ssi_details_reissued_credential", + schema: "issuer", + table: "company_ssi_details"); + + migrationBuilder.DropTable( + name: "audit_company_ssi_detail20240902", + schema: "issuer"); + + migrationBuilder.DropIndex( + name: "ix_company_ssi_details_reissued_credential_id", + schema: "issuer", + table: "company_ssi_details"); + + migrationBuilder.DeleteData( + schema: "issuer", + table: "process_step_types", + keyColumn: "id", + keyValue: 6); + + migrationBuilder.DropColumn( + name: "reissued_credential_id", + schema: "issuer", + table: "company_ssi_details"); + + migrationBuilder.Sql("CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();"); + + migrationBuilder.Sql("CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + } + } +} diff --git a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs index ba54338a..98e865ee 100644 --- a/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs +++ b/src/database/SsiCredentialIssuer.Migrations/Migrations/IssuerDbContextModelSnapshot.cs @@ -1,14 +1,29 @@ -// -using System; +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities; -#nullable disable - namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Migrations.Migrations { [DbContext(typeof(IssuerDbContext))] @@ -200,6 +215,98 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("audit_company_ssi_detail20240419", "issuer"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditCompanySsiDetail20240902", b => + { + b.Property("AuditV2Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("audit_v2id"); + + b.Property("AuditV2DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("audit_v2date_last_changed"); + + b.Property("AuditV2LastEditorId") + .HasColumnType("text") + .HasColumnName("audit_v2last_editor_id"); + + b.Property("AuditV2OperationId") + .HasColumnType("integer") + .HasColumnName("audit_v2operation_id"); + + b.Property("Bpnl") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpnl"); + + b.Property("CompanySsiDetailStatusId") + .HasColumnType("integer") + .HasColumnName("company_ssi_detail_status_id"); + + b.Property("CreatorUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("creator_user_id"); + + b.Property("Credential") + .HasColumnType("text") + .HasColumnName("credential"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("ExpiryCheckTypeId") + .HasColumnType("integer") + .HasColumnName("expiry_check_type_id"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiry_date"); + + b.Property("ExternalCredentialId") + .HasColumnType("uuid") + .HasColumnName("external_credential_id"); + + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("IssuerBpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("issuer_bpn"); + + b.Property("LastEditorId") + .HasColumnType("text") + .HasColumnName("last_editor_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + + b.Property("VerifiedCredentialExternalTypeDetailVersionId") + .HasColumnType("uuid") + .HasColumnName("verified_credential_external_type_detail_version_id"); + + b.Property("VerifiedCredentialTypeId") + .HasColumnType("integer") + .HasColumnName("verified_credential_type_id"); + + b.HasKey("AuditV2Id") + .HasName("pk_audit_company_ssi_detail20240902"); + + b.ToTable("audit_company_ssi_detail20240902", "issuer"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.AuditEntities.AuditDocument20240305", b => { b.Property("AuditV1Id") @@ -396,6 +503,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("process_id"); + b.Property("ReissuedCredentialId") + .HasColumnType("uuid") + .HasColumnName("reissued_credential_id"); + b.Property("VerifiedCredentialExternalTypeDetailVersionId") .HasColumnType("uuid") .HasColumnName("verified_credential_external_type_detail_version_id"); @@ -416,6 +527,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ProcessId") .HasDatabaseName("ix_company_ssi_details_process_id"); + b.HasIndex("ReissuedCredentialId") + .IsUnique() + .HasDatabaseName("ix_company_ssi_details_reissued_credential_id"); + b.HasIndex("VerifiedCredentialExternalTypeDetailVersionId") .HasDatabaseName("ix_company_ssi_details_verified_credential_external_type_detai"); @@ -430,8 +545,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) }); b - .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") - .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240419\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); + .HasAnnotation("LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 1, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL AFTER INSERT\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_INSERT_COMPANYSSIDETAIL\"();") + .HasAnnotation("LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL", "CREATE FUNCTION \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"() RETURNS trigger as $LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$\r\nBEGIN\r\n INSERT INTO \"issuer\".\"audit_company_ssi_detail20240902\" (\"id\", \"bpnl\", \"issuer_bpn\", \"verified_credential_type_id\", \"company_ssi_detail_status_id\", \"date_created\", \"creator_user_id\", \"expiry_date\", \"verified_credential_external_type_detail_version_id\", \"expiry_check_type_id\", \"process_id\", \"external_credential_id\", \"credential\", \"reissued_credential_id\", \"date_last_changed\", \"last_editor_id\", \"audit_v2id\", \"audit_v2operation_id\", \"audit_v2date_last_changed\", \"audit_v2last_editor_id\") SELECT NEW.\"id\", \r\n NEW.\"bpnl\", \r\n NEW.\"issuer_bpn\", \r\n NEW.\"verified_credential_type_id\", \r\n NEW.\"company_ssi_detail_status_id\", \r\n NEW.\"date_created\", \r\n NEW.\"creator_user_id\", \r\n NEW.\"expiry_date\", \r\n NEW.\"verified_credential_external_type_detail_version_id\", \r\n NEW.\"expiry_check_type_id\", \r\n NEW.\"process_id\", \r\n NEW.\"external_credential_id\", \r\n NEW.\"credential\", \r\n NEW.\"reissued_credential_id\", \r\n NEW.\"date_last_changed\", \r\n NEW.\"last_editor_id\", \r\n gen_random_uuid(), \r\n 2, \r\n CURRENT_TIMESTAMP, \r\n NEW.\"last_editor_id\";\r\nRETURN NEW;\r\nEND;\r\n$LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL$ LANGUAGE plpgsql;\r\nCREATE TRIGGER LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL AFTER UPDATE\r\nON \"issuer\".\"company_ssi_details\"\r\nFOR EACH ROW EXECUTE PROCEDURE \"issuer\".\"LC_TRIGGER_AFTER_UPDATE_COMPANYSSIDETAIL\"();"); }); modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailAssignedDocument", b => @@ -1331,22 +1446,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) }); }); - modelBuilder.Entity("ReissuanceProcess", b => - { - b.Property("Id") - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("ReissuedCredentialId") - .HasColumnType("uuid") - .HasColumnName("reissued_credential_id"); - - b.HasKey("Id") - .HasName("pk_reissuances"); - - b.ToTable("reissuances", "issuer"); - }); - modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", "CompanySsiDetailStatus") @@ -1365,6 +1464,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("ProcessId") .HasConstraintName("fk_company_ssi_details_processes_process_id"); + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "ReissuedCredential") + .WithOne() + .HasForeignKey("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "ReissuedCredentialId") + .HasConstraintName("fk_company_ssi_details_company_ssi_details_reissued_credential"); + b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.VerifiedCredentialExternalTypeDetailVersion", "VerifiedCredentialExternalTypeDetailVersion") .WithMany("CompanySsiDetails") .HasForeignKey("VerifiedCredentialExternalTypeDetailVersionId") @@ -1382,6 +1486,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Process"); + b.Navigation("ReissuedCredential"); + b.Navigation("VerifiedCredentialExternalTypeDetailVersion"); b.Navigation("VerifiedCredentialType"); @@ -1567,23 +1673,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("VerifiedCredentialType"); }); - modelBuilder.Entity("ReissuanceProcess", b => - { - b.HasOne("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", "CompanySsiDetail") - .WithOne("ReissuanceProcess") - .HasForeignKey("ReissuanceProcess", "Id") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_reissuances_company_ssi_details_id"); - - b.Navigation("CompanySsiDetail"); - }); - modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetail", b => { b.Navigation("CompanySsiProcessData"); - - b.Navigation("ReissuanceProcess"); }); modelBuilder.Entity("Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities.CompanySsiDetailStatus", b => diff --git a/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs b/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs index 590cdc00..3b9a01d3 100644 --- a/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Creation/CredentialCreationProcessHandler.cs @@ -54,7 +54,7 @@ public CredentialCreationProcessHandler(IIssuerRepositories issuerRepositories, public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SignCredential(Guid credentialId, CancellationToken cancellationToken) { - var externalCredentialId = await _issuerRepositories.GetInstance().GetWalletCredentialId(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); + var (externalCredentialId, isReissuance) = await _issuerRepositories.GetInstance().GetSigningData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); if (externalCredentialId is null) { throw new ConflictException("ExternalCredentialId must be set here"); @@ -62,7 +62,7 @@ public CredentialCreationProcessHandler(IIssuerRepositories issuerRepositories, await _walletBusinessLogic.SignCredential(credentialId, externalCredentialId!.Value, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); return ( - Enumerable.Repeat(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL, 1), + Enumerable.Repeat(isReissuance ? ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL : ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, 1), ProcessStepStatusId.DONE, false, null); diff --git a/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs b/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs index a0b5da2f..95634a06 100644 --- a/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs +++ b/src/processes/CredentialProcess.Library/DependencyInjection/CredentialHandlerExtensions.cs @@ -20,6 +20,7 @@ using Microsoft.Extensions.DependencyInjection; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Expiry; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.DependencyInjection; diff --git a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs index d0a72933..40c8d81b 100644 --- a/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Expiry/CredentialExpiryProcessHandler.cs @@ -82,13 +82,12 @@ public CredentialExpiryProcessHandler(IIssuerRepositories repositories, IWalletS public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerNotification(Guid credentialId, CancellationToken cancellationToken) { - var (typeId, requesterId) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); - var notificationTypeId = await GetNotificationTypeId(credentialId); + var (typeId, requesterId, isReissuance) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); if (Guid.TryParse(requesterId, out var companyUserId)) { var content = JsonSerializer.Serialize(new { Type = typeId, CredentialId = credentialId }, Options); - await _portalService.AddNotification(content, companyUserId, notificationTypeId, cancellationToken); + await _portalService.AddNotification(content, companyUserId, isReissuance ? NotificationTypeId.CREDENTIAL_RENEWAL : NotificationTypeId.CREDENTIAL_REJECTED, cancellationToken); } return ( @@ -98,21 +97,14 @@ public CredentialExpiryProcessHandler(IIssuerRepositories repositories, IWalletS null); } - private Task GetNotificationTypeId(Guid credentialId) - { - var isRevokedByReissuance = _repositories.GetInstance().IsCredentialRevokedByReissuance(credentialId); - return Task.FromResult(isRevokedByReissuance ? NotificationTypeId.CREDENTIAL_RENEWAL : NotificationTypeId.CREDENTIAL_REJECTED); - } - public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerMail(Guid credentialId, CancellationToken cancellationToken) { - var (typeId, requesterId) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); + var (typeId, requesterId, isReissuance) = await _repositories.GetInstance().GetCredentialNotificationData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); var typeValue = typeId.GetEnumValue() ?? throw new UnexpectedConditionException($"VerifiedCredentialType {typeId} does not exists"); - var isRevokedByReissuance = _repositories.GetInstance().IsCredentialRevokedByReissuance(credentialId); if (Guid.TryParse(requesterId, out var companyUserId)) { - if (isRevokedByReissuance) + if (isReissuance) { var mailParameters = CreateEmailParameters(typeValue, "The credential about to expiry is revoked and new credential was reissued"); await _portalService.TriggerMail("CredentialRenewal", companyUserId, mailParameters, cancellationToken); diff --git a/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs index 9a6f993a..5f71fa60 100644 --- a/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Reissuance/CredentialReissuanceProcessHandler.cs @@ -17,53 +17,30 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -using Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; -public class CredentialReissuanceProcessHandler : ICredentialReissuanceProcessHandler +public class CredentialReissuanceProcessHandler(IIssuerRepositories issuerRepositories) + : ICredentialReissuanceProcessHandler { - private readonly IIssuerRepositories _issuerRepositories; - private readonly ILogger _logger; - - public CredentialReissuanceProcessHandler(IIssuerRepositories issuerRepositories, ILogger logger) - { - _issuerRepositories = issuerRepositories; - _logger = logger; - } - - public Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> RevokeReissuedCredential(Guid credentialId) + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> RevokeReissuedCredential(Guid credentialId) { - var isReissuedCredential = _issuerRepositories.GetInstance().IsReissuedCredential(credentialId); + var companySsiRepository = issuerRepositories.GetInstance(); + var processStepRepository = issuerRepositories.GetInstance(); + var credentialToRevokeId = await issuerRepositories.GetInstance().GetCredentialToRevoke(credentialId).ConfigureAwait(ConfigureAwaitOptions.None); - if (isReissuedCredential) + if (credentialToRevokeId == null) { - CreateRevokeCredentialProcess(credentialId); + throw new ConflictException("Id of the credential to revoke should always be set here"); } - (IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage) result = ( - Enumerable.Repeat(ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, 1), - ProcessStepStatusId.DONE, - false, - null); - - return Task.FromResult(result); - } - - private void CreateRevokeCredentialProcess(Guid credentialId) - { - var companySsiRepository = _issuerRepositories.GetInstance(); - var processStepRepository = _issuerRepositories.GetInstance(); var processId = processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL).Id; - var credentialToRevokeId = _issuerRepositories.GetInstance().GetCompanySsiDetailId(credentialId); - - try - { - processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, processId); - companySsiRepository.AttachAndModifyCompanySsiDetails(credentialToRevokeId, c => + processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, processId); + companySsiRepository.AttachAndModifyCompanySsiDetails(credentialToRevokeId.Value, c => { c.ProcessId = null; }, @@ -71,11 +48,12 @@ private void CreateRevokeCredentialProcess(Guid credentialId) { c.ProcessId = processId; }); - } - catch (Exception ex) - { - _logger.LogError("The revokation of the reissued credential failed with error: {Errors}", ex.Message); - } + + return ( + Enumerable.Repeat(ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT, 1), + ProcessStepStatusId.DONE, + false, + null); } } diff --git a/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs index 851b3cd5..36c578a5 100644 --- a/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs +++ b/src/processes/CredentialProcess.Library/Reissuance/ICredentialReissuanceProcessHandler.cs @@ -19,7 +19,7 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; public interface ICredentialReissuanceProcessHandler { diff --git a/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs b/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs index 70978ec0..5bc5ce68 100644 --- a/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs +++ b/src/processes/CredentialProcess.Worker/Creation/CredentialCreationProcessTypeExecutor.cs @@ -20,6 +20,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs index e536ce66..a5ec2fec 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Handler/CredentialIssuerHandlerTests.cs @@ -20,14 +20,15 @@ using AutoFixture; using AutoFixture.AutoFakeItEasy; using FakeItEasy; +using FluentAssertions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Credential.Library.Configuration; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; using System.Text; using System.Text.Json; using Xunit; @@ -36,52 +37,40 @@ namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Tests.Handler; public class CredentialIssuerHandlerTests { - private readonly IServiceScopeFactory _serviceScopeFactory; - private readonly IOptions _options; + private readonly IOptions _options; private readonly IIssuerRepositories _issuerRepositories; private readonly IDocumentRepository _documentRepository; - private readonly IReissuanceRepository _reissuanceRepository; private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; - private readonly IServiceScope _serviceScope; private readonly ICredentialIssuerHandler _credentialIssuerHandler; - private readonly IFixture _fixture; public CredentialIssuerHandlerTests() { - _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); - _fixture.Behaviors.OfType().ToList() - .ForEach(b => _fixture.Behaviors.Remove(b)); - var serviceProvider = _fixture.Create(); + var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + fixture.Behaviors.OfType().ToList() + .ForEach(b => fixture.Behaviors.Remove(b)); - _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _issuerRepositories = A.Fake(); _documentRepository = A.Fake(); - _reissuanceRepository = A.Fake(); _companySsiDetailsRepository = A.Fake(); - _serviceScopeFactory = _fixture.Create(); - _serviceScope = _fixture.Create(); - _options = A.Fake>(); + _options = A.Fake>(); - A.CallTo(() => _serviceScopeFactory.CreateScope()).Returns(_serviceScope); - A.CallTo(() => _serviceScope.ServiceProvider).Returns(serviceProvider); - A.CallTo(() => serviceProvider.GetService(typeof(IIssuerRepositories))).Returns(_issuerRepositories); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_documentRepository); - A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); - var credentialSettings = new CredentialSettings(); - credentialSettings.IssuerBpn = "BPNL000000000000"; + var credentialSettings = new ReissuanceSettings { IssuerBpn = "BPNL000000000000" }; A.CallTo(() => _options.Value).Returns(credentialSettings); - _credentialIssuerHandler = new CredentialIssuerHandler(_serviceScopeFactory, _options); + _credentialIssuerHandler = new CredentialIssuerHandler(_issuerRepositories, _options); } [Fact] - public async void HandleCredentialProcessCreation_ValidateProcessCreation_NoErrorExpected() + public async Task HandleCredentialProcessCreation_ValidateProcessCreation_NoErrorExpected() { // Arrange var documentId = Guid.NewGuid(); + var ssiCredentialDetails = new List(); var schema = "{\"id\": \"21a1aa1f-b2f9-43bb-9c71-00b62bd1f8e0\", \"name\": \"BpnCredential\"}"; var processStepRepository = A.Fake(); var process = new Process(Guid.NewGuid(), ProcessTypeId.CREATE_CREDENTIAL, Guid.NewGuid()); @@ -119,14 +108,24 @@ public async void HandleCredentialProcessCreation_ValidateProcessCreation_NoErro CompanySsiDetailStatusId.ACTIVE, _options.Value.IssuerBpn, request.IdentiyId, - A?>._)).Returns(companySsiDetail); + A?>._)) + .Invokes((string bpnl, VerifiedCredentialTypeId verifiedCredentialTypeId, + CompanySsiDetailStatusId companySsiDetailStatusId, string issuerBpn, string userId, + Action? setOptionalFields) => + { + var detail = new CompanySsiDetail(Guid.NewGuid(), bpnl, verifiedCredentialTypeId, companySsiDetailStatusId, issuerBpn, userId, DateTimeOffset.UtcNow); + setOptionalFields?.Invoke(detail); + ssiCredentialDetails.Add(detail); + }) + .Returns(companySsiDetail); // Act await _credentialIssuerHandler.HandleCredentialProcessCreation(request); // Assert + ssiCredentialDetails.Should().ContainSingle().And.Satisfy( + c => c.ReissuedCredentialId == request.Id); A.CallTo(() => _documentRepository.AssignDocumentToCompanySsiDetails(A._, companySsiDetail.Id)).MustHaveHappenedOnceExactly(); - A.CallTo(() => _reissuanceRepository.CreateReissuanceProcess(request.Id, companySsiDetail.Id)).MustHaveHappenedOnceExactly(); A.CallTo(() => _companySsiDetailsRepository.CreateProcessData(companySsiDetail.Id, A._, A._, A?>._)).MustHaveHappenedOnceExactly(); A.CallTo(() => _issuerRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); } diff --git a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs index 36ac2d7a..3c73e89d 100644 --- a/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs +++ b/tests/credentials/SsiCredentialIssuer.Reissuance.App.Tests/Services/ReissuanceServiceTests.cs @@ -29,7 +29,7 @@ using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.DependencyInjection; -using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handlers; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Handler; using Org.Eclipse.TractusX.SsiCredentialIssuer.Reissuance.App.Services; using System.Text.Json; using Xunit; @@ -40,9 +40,7 @@ public class ReissuanceServiceTests { private readonly ICredentialIssuerHandler _credentialIssuerHandler; private readonly IReissuanceService _reissuanceService; - private readonly IIssuerRepositories _issuerRepositories; private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; - private readonly IDateTimeProvider _dateTimeProvider; private readonly ILogger _logger; public ReissuanceServiceTests() @@ -53,30 +51,30 @@ public ReissuanceServiceTests() fixture.Behaviors.Add(new OmitOnRecursionBehavior()); var serviceScopeFactory = fixture.Create(); var serviceScope = fixture.Create(); - var options = A.Fake>(); + var options = A.Fake>(); _logger = A.Fake>(); - var settings = new ReissuanceExpirySettings(); + var settings = new ReissuanceSettings(); var serviceProvider = fixture.Create(); - _dateTimeProvider = A.Fake(); + var dateTimeProvider = A.Fake(); _credentialIssuerHandler = A.Fake(); - _issuerRepositories = A.Fake(); + var issuerRepositories = A.Fake(); _companySsiDetailsRepository = A.Fake(); _credentialIssuerHandler = A.Fake(); A.CallTo(() => options.Value).Returns(settings); - A.CallTo(() => serviceProvider.GetService(typeof(IDateTimeProvider))).Returns(_dateTimeProvider); - A.CallTo(() => serviceProvider.GetService(typeof(IIssuerRepositories))).Returns(_issuerRepositories); - A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); + A.CallTo(() => serviceProvider.GetService(typeof(IDateTimeProvider))).Returns(dateTimeProvider); + A.CallTo(() => serviceProvider.GetService(typeof(IIssuerRepositories))).Returns(issuerRepositories); + A.CallTo(() => issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); A.CallTo(() => serviceScope.ServiceProvider).Returns(serviceProvider); A.CallTo(() => serviceScopeFactory.CreateScope()).Returns(serviceScope); - A.CallTo(() => _dateTimeProvider.OffsetNow).Returns(DateTimeOffset.UtcNow); + A.CallTo(() => dateTimeProvider.OffsetNow).Returns(DateTimeOffset.UtcNow); _reissuanceService = new ReissuanceService(serviceScopeFactory, _credentialIssuerHandler, options, _logger); } [Fact] - public async void ExecuteAsync_ProcessCredentials_NoCredentialsAboutToExpire() + public async Task ExecuteAsync_ProcessCredentials_NoCredentialsAboutToExpire() { // Act await _reissuanceService.ExecuteAsync(CancellationToken.None); @@ -86,7 +84,7 @@ public async void ExecuteAsync_ProcessCredentials_NoCredentialsAboutToExpire() } [Fact] - public async void ExecuteAsync_ProcessCredentials_CreateBpnCredential() + public async Task ExecuteAsync_ProcessCredentials_CreateBpnCredential() { // Arrange var schema = "{\"id\":\"6f05cac6-c073-4562-8540-8fc883807808\",\"name\":\"BpnCredential\",\"type\":[\"VerifiableCredential\",\"BpnCredential\"],\"issuer\":\"did:web:localhost:BPNL000000000000\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://w3id.org/catenax/credentials/v1.0.0\"],\"description\":\"BpnCredential\",\"issuanceDate\":\"2024-08-19T07:32:37.598099+00:00\",\"expirationDate\":\"2025-08-19T07:32:37.598079+00:00\",\"credentialStatus\":{\"id\":\"example.com\",\"type\":\"StatusList2021\"},\"credentialSubject\":{\"id\":\"did:web:localhost:BPNL000000000000\",\"bpn\":\"BPNL000000000000\",\"holderIdentifier\":\"BPNL000000000000\"}}"; @@ -122,7 +120,7 @@ public async void ExecuteAsync_ProcessCredentials_CreateBpnCredential() } [Fact] - public async void ExecuteAsync_ProcessCredentials_HandleException() + public async Task ExecuteAsync_ProcessCredentials_HandleException() { // Arrange var schema = "{\"id\":\"6f05cac6-c073-4562-8540-8fc883807808\",\"name\":\"BpnCredential\",\"type\":[\"VerifiableCredential\",\"BpnCredential\"],\"issuer\":\"did:web:localhost:BPNL000000000000\",\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://w3id.org/catenax/credentials/v1.0.0\"],\"description\":\"BpnCredential\",\"issuanceDate\":\"2024-08-19T07:32:37.598099+00:00\",\"expirationDate\":\"2025-08-19T07:32:37.598079+00:00\",\"credentialStatus\":{\"id\":\"example.com\",\"type\":\"StatusList2021\"},\"credentialSubject\":{\"id\":\"did:web:localhost:BPNL000000000000\",\"bpn\":\"BPNL000000000000\",\"holderIdentifier\":\"BPNL000000000000\"}}"; @@ -147,6 +145,5 @@ public async void ExecuteAsync_ProcessCredentials_HandleException() // Assert A.CallTo(() => _credentialIssuerHandler.HandleCredentialProcessCreation(A._)).MustHaveHappenedOnceExactly(); A.CallTo(_logger).Where(call => call.Method.Name == "Log" && call.GetArgument(0) == LogLevel.Error).MustHaveHappened(1, Times.Exactly); - } } diff --git a/tests/database/SsiCredentialIssuer.DbAccess.Tests/CredentialRepositoryTests.cs b/tests/database/SsiCredentialIssuer.DbAccess.Tests/CredentialRepositoryTests.cs index a87e85a5..775cda56 100644 --- a/tests/database/SsiCredentialIssuer.DbAccess.Tests/CredentialRepositoryTests.cs +++ b/tests/database/SsiCredentialIssuer.DbAccess.Tests/CredentialRepositoryTests.cs @@ -85,19 +85,20 @@ public async Task GetCredentialData_ReturnsExpectedDocument() #endregion - #region GetWalletCredentialId + #region GetSigningData [Fact] - public async Task GetWalletCredentialId_ReturnsExpectedDocument() + public async Task GetSigningData_ReturnsExpectedDocument() { // Arrange var sut = await CreateSut(); // Act - var result = await sut.GetWalletCredentialId(new Guid("9f5b9934-4014-4099-91e9-7b1aee696b03")); + var result = await sut.GetSigningData(new Guid("9f5b9934-4014-4099-91e9-7b1aee696b03")); // Assert - result.Should().Be(new Guid("bd474c60-e7ce-450f-bdf4-73604546fc5e")); + result.ExternalCredentialId.Should().Be(new Guid("bd474c60-e7ce-450f-bdf4-73604546fc5e")); + result.IsReissuance.Should().BeFalse(); } #endregion diff --git a/tests/database/SsiCredentialIssuer.DbAccess.Tests/IssuerDbContextTests.cs b/tests/database/SsiCredentialIssuer.DbAccess.Tests/IssuerDbContextTests.cs index 0acb8021..4e43c22e 100644 --- a/tests/database/SsiCredentialIssuer.DbAccess.Tests/IssuerDbContextTests.cs +++ b/tests/database/SsiCredentialIssuer.DbAccess.Tests/IssuerDbContextTests.cs @@ -73,8 +73,8 @@ public async Task SaveCreatedAuditableEntity_SetsLastEditorId() // Assert ca.LastEditorId.Should().NotBeNull().And.Be("ac1cf001-7fbc-1f2f-817f-bce058020001"); ca.DateLastChanged.Should().Be(now); - var auditEntries = await sut.AuditCompanySsiDetail20240419.Where(x => x.Id == id).ToListAsync(); - auditEntries.Should().ContainSingle().Which.Should().Match( + var auditEntries = await sut.AuditCompanySsiDetail20240902.Where(x => x.Id == id).ToListAsync(); + auditEntries.Should().ContainSingle().Which.Should().Match( x => x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE && (x.DateCreated - before) < TimeSpan.FromSeconds(1) && x.AuditV2OperationId == AuditOperationId.INSERT && (x.AuditV2DateLastChanged - now) < TimeSpan.FromSeconds(1) && x.LastEditorId == "ac1cf001-7fbc-1f2f-817f-bce058020001"); await trans.RollbackAsync(); } @@ -103,7 +103,7 @@ public async Task SaveDeletedAuditableEntity_SetsLastEditorId() // Assert ca.LastEditorId.Should().NotBeNull().And.Be("ac1cf001-7fbc-1f2f-817f-bce058020001"); ca.DateLastChanged.Should().Be(later); - var auditEntries = await sut.AuditCompanySsiDetail20240419.Where(x => x.Id == id).ToListAsync(); + var auditEntries = await sut.AuditCompanySsiDetail20240902.Where(x => x.Id == id).ToListAsync(); auditEntries.Should().HaveCount(2).And.Satisfy( x => x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE && (x.DateCreated - before) < TimeSpan.FromSeconds(1) && x.AuditV2OperationId == AuditOperationId.INSERT && x.LastEditorId == "ac1cf001-7fbc-1f2f-817f-bce058020001", x => x.CompanySsiDetailStatusId == CompanySsiDetailStatusId.ACTIVE && (x.DateCreated - before) < TimeSpan.FromSeconds(1) && x.AuditV2OperationId == AuditOperationId.DELETE && (x.AuditV2DateLastChanged - later) < TimeSpan.FromSeconds(1) && x.LastEditorId == "ac1cf001-7fbc-1f2f-817f-bce058020001"); diff --git a/tests/issuer/SsiCredentialIssuer.Service.Tests/Identity/MandatoryIdentityClaimHandlerTests.cs b/tests/issuer/SsiCredentialIssuer.Service.Tests/Identity/MandatoryIdentityClaimHandlerTests.cs index 15d695e6..53eaf422 100644 --- a/tests/issuer/SsiCredentialIssuer.Service.Tests/Identity/MandatoryIdentityClaimHandlerTests.cs +++ b/tests/issuer/SsiCredentialIssuer.Service.Tests/Identity/MandatoryIdentityClaimHandlerTests.cs @@ -20,7 +20,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; -using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared; +using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.Tests; using Org.Eclipse.TractusX.SsiCredentialIssuer.Service.Identity; using System.Security.Claims; diff --git a/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs b/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs index c3da8b46..0cba7665 100644 --- a/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Library.Tests/CredentialCreationProcessHandlerTests.cs @@ -41,7 +41,6 @@ public class CredentialCreationProcessHandlerTests private readonly Guid _credentialId = Guid.NewGuid(); private readonly IWalletBusinessLogic _walletBusinessLogic; - private readonly IIssuerRepositories _issuerRepositories; private readonly ICredentialRepository _credentialRepository; private readonly CredentialCreationProcessHandler _sut; @@ -55,15 +54,15 @@ public CredentialCreationProcessHandlerTests() .ForEach(b => _fixture.Behaviors.Remove(b)); _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); - _issuerRepositories = A.Fake(); + var issuerRepositories = A.Fake(); _credentialRepository = A.Fake(); - A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_credentialRepository); + A.CallTo(() => issuerRepositories.GetInstance()).Returns(_credentialRepository); _walletBusinessLogic = A.Fake(); _callbackService = A.Fake(); - _sut = new CredentialCreationProcessHandler(_issuerRepositories, _walletBusinessLogic, _callbackService); + _sut = new CredentialCreationProcessHandler(issuerRepositories, _walletBusinessLogic, _callbackService); } #region CreateCredential @@ -96,8 +95,8 @@ public async Task CreateCredential_WithValidData_ReturnsExpected() public async Task SignCredential_WithNotExisting_ReturnsExpected() { // Arrange - A.CallTo(() => _credentialRepository.GetWalletCredentialId(_credentialId)) - .Returns(null); + A.CallTo(() => _credentialRepository.GetSigningData(_credentialId)) + .Returns(new ValueTuple(null, false)); Task Act() => _sut.SignCredential(_credentialId, CancellationToken.None); // Act @@ -107,13 +106,15 @@ public async Task SignCredential_WithNotExisting_ReturnsExpected() ex.Message.Should().Be("ExternalCredentialId must be set here"); } - [Fact] - public async Task SignCredential_WithValidData_ReturnsExpected() + [Theory] + [InlineData(true, ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL)] + [InlineData(false, ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT)] + public async Task SignCredential_WithValidData_ReturnsExpected(bool reissuanceProcess, ProcessStepTypeId nextStep) { // Arrange var externalCredentialId = Guid.NewGuid(); - A.CallTo(() => _credentialRepository.GetWalletCredentialId(_credentialId)) - .Returns(externalCredentialId); + A.CallTo(() => _credentialRepository.GetSigningData(_credentialId)) + .Returns(new ValueTuple(externalCredentialId, reissuanceProcess)); // Act var result = await _sut.SignCredential(_credentialId, CancellationToken.None); @@ -125,7 +126,7 @@ public async Task SignCredential_WithValidData_ReturnsExpected() result.modified.Should().BeFalse(); result.processMessage.Should().BeNull(); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); - result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.REVOKE_REISSUED_CREDENTIAL); + result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(nextStep); } #endregion diff --git a/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs b/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs index 1155ee66..1b0f8a7d 100644 --- a/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Library.Tests/CredentialExpiryProcessHandlerTests.cs @@ -42,7 +42,6 @@ public class CredentialExpiryProcessHandlerTests private readonly IWalletService _walletService; private readonly IIssuerRepositories _issuerRepositories; private readonly ICredentialRepository _credentialRepository; - private readonly IReissuanceRepository _reissuanceRepository; private readonly IPortalService _portalService; private readonly CredentialExpiryProcessHandler _sut; @@ -59,11 +58,9 @@ public CredentialExpiryProcessHandlerTests() _issuerRepositories = A.Fake(); _credentialRepository = A.Fake(); _documentRepository = A.Fake(); - _reissuanceRepository = A.Fake(); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_credentialRepository); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_documentRepository); - A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); _walletService = A.Fake(); _portalService = A.Fake(); @@ -170,7 +167,7 @@ public async Task TriggerNotification_CredentialRejected_WithValid_CallsExpected // Arrange var requesterId = Guid.NewGuid(); A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) - .Returns((VerifiedCredentialExternalTypeId.PCF_CREDENTIAL, requesterId.ToString())); + .Returns((VerifiedCredentialExternalTypeId.PCF_CREDENTIAL, requesterId.ToString(), false)); // Act var result = await _sut.TriggerNotification(_credentialId, CancellationToken.None); @@ -189,9 +186,8 @@ public async Task TriggerNotification_CredentialRenewal_WithValid_CallsExpected( { // Arrange var requesterId = Guid.NewGuid(); - A.CallTo(() => _reissuanceRepository.IsCredentialRevokedByReissuance(_credentialId)).Returns(true); A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) - .Returns((VerifiedCredentialExternalTypeId.BUSINESS_PARTNER_NUMBER, requesterId.ToString())); + .Returns((VerifiedCredentialExternalTypeId.BUSINESS_PARTNER_NUMBER, requesterId.ToString(), true)); // Act var result = await _sut.TriggerNotification(_credentialId, CancellationToken.None); @@ -204,6 +200,7 @@ public async Task TriggerNotification_CredentialRenewal_WithValid_CallsExpected( result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); result.nextStepTypeIds.Should().ContainSingle().Which.Should().Be(ProcessStepTypeId.TRIGGER_MAIL); } + #endregion #region TriggerMail @@ -214,7 +211,7 @@ public async Task TriggerMail_CredentialRejected_WithValid_CallsExpected() // Arrange var requesterId = Guid.NewGuid(); A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) - .Returns((VerifiedCredentialExternalTypeId.PCF_CREDENTIAL, requesterId.ToString())); + .Returns((VerifiedCredentialExternalTypeId.PCF_CREDENTIAL, requesterId.ToString(), false)); // Act var result = await _sut.TriggerMail(_credentialId, CancellationToken.None); @@ -233,9 +230,8 @@ public async Task TriggerMail_CredentialRenewal_WithValid_CallsExpected() { // Arrange var requesterId = Guid.NewGuid(); - A.CallTo(() => _reissuanceRepository.IsCredentialRevokedByReissuance(_credentialId)).Returns(true); A.CallTo(() => _credentialRepository.GetCredentialNotificationData(_credentialId)) - .Returns((VerifiedCredentialExternalTypeId.MEMBERSHIP_CREDENTIAL, requesterId.ToString())); + .Returns((VerifiedCredentialExternalTypeId.MEMBERSHIP_CREDENTIAL, requesterId.ToString(), true)); // Act var result = await _sut.TriggerMail(_credentialId, CancellationToken.None); diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs index 7a2f346f..e8886d63 100644 --- a/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialCreationProcessTypeExecutorTests.cs @@ -24,6 +24,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Creation; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Worker.Creation; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; diff --git a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs index 136553fb..4525b209 100644 --- a/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs +++ b/tests/processes/CredentialProcess.Worker.Tests/CredentialReissuanceProcessHandlerTests.cs @@ -20,7 +20,9 @@ using FakeItEasy; using FluentAssertions; using Microsoft.Extensions.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library; +using Org.Eclipse.TractusX.SsiCredentialIssuer.CredentialProcess.Library.Reissuance; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities; @@ -33,85 +35,62 @@ public class CredentialReissuanceProcessHandlerTests { private readonly ICredentialReissuanceProcessHandler _sut; private readonly IIssuerRepositories _issuerRepositories; - private readonly IReissuanceRepository _reissuanceRepository; private readonly ICompanySsiDetailsRepository _companySsiDetailsRepository; private readonly IProcessStepRepository _processStepRepository; - private readonly ILogger _logger; public CredentialReissuanceProcessHandlerTests() { _issuerRepositories = A.Fake(); - _reissuanceRepository = A.Fake(); _companySsiDetailsRepository = A.Fake(); _processStepRepository = A.Fake(); - A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_reissuanceRepository); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_companySsiDetailsRepository); A.CallTo(() => _issuerRepositories.GetInstance()).Returns(_processStepRepository); - _logger = A.Fake>(); - _sut = new CredentialReissuanceProcessHandler(_issuerRepositories, _logger); + _sut = new CredentialReissuanceProcessHandler(_issuerRepositories); } [Fact] - public void RevokeReissuedCredential_isReissuedCredentialFalse_ReturnsExpected() + public async Task RevokeReissuedCredential_WithNoCredentialFound_ThrowsConflictException() { // Arrange var credentialId = Guid.NewGuid(); - A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(false); + A.CallTo(() => _companySsiDetailsRepository.GetCredentialToRevoke(credentialId)).Returns(null); + Task Act() => _sut.RevokeReissuedCredential(credentialId); // Act - var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + var ex = await Assert.ThrowsAsync(Act); // Assert - AssertSuccessResult(revokeCredentialResponse); + ex.Message.Should().Be("Id of the credential to revoke should always be set here"); } [Fact] - public void RevokeReissuedCredential_CreateProcessStepThrowsException_ReturnsExpected() + public async Task RevokeReissuedCredential_CreateProcessStep_ReturnsExpected() { // Arrage Ids var credentialId = Guid.NewGuid(); - var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); - - // Arrange - A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); - A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); - A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)) - .Throws(new Exception("not possible to create step process exception")); - - //Act - var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); - - // Assert - AssertSuccessResult(revokeCredentialResponse); - } - - [Fact] - public void RevokeReissuedCredential_CreateProcessStep_ReturnsExpected() - { - // Arrage Ids - var credentialId = Guid.NewGuid(); - var process = new Entities.Entities.Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); + var credentialIdToRevoke = Guid.NewGuid(); + var process = new Process(Guid.NewGuid(), ProcessTypeId.DECLINE_CREDENTIAL, Guid.NewGuid()); var processStep = A.Fake(); + var companySsiDetail = new CompanySsiDetail(credentialIdToRevoke, "BPNL000001TEST", VerifiedCredentialTypeId.MEMBERSHIP, CompanySsiDetailStatusId.ACTIVE, "BPNL00001ISSUER", "test", DateTimeOffset.UtcNow); // Arrange - A.CallTo(() => _issuerRepositories.GetInstance().IsReissuedCredential(credentialId)).Returns(true); A.CallTo(() => _processStepRepository.CreateProcess(ProcessTypeId.DECLINE_CREDENTIAL)).Returns(process); A.CallTo(() => _processStepRepository.CreateProcessStep(ProcessStepTypeId.REVOKE_CREDENTIAL, ProcessStepStatusId.TODO, process.Id)).Returns(processStep); - A.CallTo(() => _reissuanceRepository.GetCompanySsiDetailId(credentialId)).Returns(credentialId); + A.CallTo(() => _companySsiDetailsRepository.GetCredentialToRevoke(credentialId)).Returns(credentialIdToRevoke); + A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialIdToRevoke, A>._, A>._)) + .Invokes((Guid _, Action? initialize, Action modify) => + { + initialize?.Invoke(companySsiDetail); + modify(companySsiDetail); + }); //Act - var revokeCredentialResponse = _sut.RevokeReissuedCredential(credentialId); + var result = await _sut.RevokeReissuedCredential(credentialId); // Assert - A.CallTo(() => _companySsiDetailsRepository.AttachAndModifyCompanySsiDetails(credentialId, null, null)).WithAnyArguments().MustHaveHappened(); - AssertSuccessResult(revokeCredentialResponse); - } - - private static void AssertSuccessResult(Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> revokeCredentialResponse) - { - var result = revokeCredentialResponse.Result; + companySsiDetail.ProcessId.Should().Be(process.Id); result.nextStepTypeIds.Should().HaveCount(1).And.Satisfy( x => x == ProcessStepTypeId.SAVE_CREDENTIAL_DOCUMENT); result.stepStatusId.Should().Be(ProcessStepStatusId.DONE); diff --git a/tests/processes/Processes.Worker.Library.Tests/MockLogger.cs b/tests/processes/Processes.Worker.Library.Tests/MockLogger.cs index 7db4706d..3ea9c3e4 100644 --- a/tests/processes/Processes.Worker.Library.Tests/MockLogger.cs +++ b/tests/processes/Processes.Worker.Library.Tests/MockLogger.cs @@ -19,7 +19,7 @@ using Microsoft.Extensions.Logging; -namespace Org.Eclipse.TractusX.Portal.Backend.Tests.Shared; +namespace Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Worker.Library.Tests; public interface IMockLogger { diff --git a/tests/processes/Processes.Worker.Library.Tests/ProcessExecutionServiceTests.cs b/tests/processes/Processes.Worker.Library.Tests/ProcessExecutionServiceTests.cs index c395fb96..77db80ac 100644 --- a/tests/processes/Processes.Worker.Library.Tests/ProcessExecutionServiceTests.cs +++ b/tests/processes/Processes.Worker.Library.Tests/ProcessExecutionServiceTests.cs @@ -21,7 +21,6 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider; -using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess; using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories; using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities;