From 08671e373144d334de3c3dc1863d5a467b617230 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 08:38:18 +0100 Subject: [PATCH 01/30] refactor: optimize SeedTestUsers --- .../ConsumerApi/src/DevicesDbContextSeeder.cs | 8 ++---- .../Users/Commands/SeedTestUsers/Handler.cs | 28 ++++++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/Applications/ConsumerApi/src/DevicesDbContextSeeder.cs b/Applications/ConsumerApi/src/DevicesDbContextSeeder.cs index 64305fcc65..a7fd2b3625 100644 --- a/Applications/ConsumerApi/src/DevicesDbContextSeeder.cs +++ b/Applications/ConsumerApi/src/DevicesDbContextSeeder.cs @@ -6,7 +6,6 @@ using Backbone.Modules.Devices.Domain.Aggregates.Tier; using Backbone.Modules.Devices.Infrastructure.Persistence.Database; using MediatR; -using Microsoft.EntityFrameworkCore; namespace Backbone.ConsumerApi; @@ -30,7 +29,7 @@ private async Task SeedEverything(DevicesDbContext context) await SeedBasicTier(context); await SeedQueuedForDeletionTier(); - await SeedApplicationUsers(context); + await SeedApplicationUsers(); } private static async Task GetBasicTier(DevicesDbContext context) @@ -38,11 +37,8 @@ private async Task SeedEverything(DevicesDbContext context) return await context.Tiers.GetBasicTier(CancellationToken.None); } - private async Task SeedApplicationUsers(DevicesDbContext context) + private async Task SeedApplicationUsers() { - if (await context.Users.AnyAsync()) - return; - await _mediator.Send(new SeedTestUsersCommand()); } diff --git a/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs b/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs index 81446d8519..90bf28ff95 100644 --- a/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs @@ -1,5 +1,6 @@ using Backbone.DevelopmentKit.Identity.ValueObjects; using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; using Backbone.Modules.Devices.Domain.Entities.Identities; using MediatR; using Microsoft.Extensions.Options; @@ -23,10 +24,29 @@ public async Task Handle(SeedTestUsersCommand request, CancellationToken cancell { var basicTier = await _tiersRepository.FindBasicTier(cancellationToken); - var identityA = Identity.CreateTestIdentity(IdentityAddress.Create([1, 1, 1, 1, 1], _applicationOptions.DidDomainName), [1, 1, 1, 1, 1], basicTier!.Id, "USRa"); - var identityB = Identity.CreateTestIdentity(IdentityAddress.Create([2, 2, 2, 2, 2], _applicationOptions.DidDomainName), [2, 2, 2, 2, 2], basicTier.Id, "USRb"); + await CreateIdentityAIfNecessary(basicTier!, cancellationToken); + await CreateIdentityBIfNecessary(basicTier!, cancellationToken); + } - await _identitiesRepository.Add(identityA, "Aaaaaaaa1!"); - await _identitiesRepository.Add(identityB, "Bbbbbbbb1!"); + private async Task CreateIdentityAIfNecessary(Tier basicTier, CancellationToken cancellationToken) + { + var addressOfIdentityA = IdentityAddress.Create([1, 1, 1, 1, 1], _applicationOptions.DidDomainName); + var identityA = await _identitiesRepository.FindByAddress(addressOfIdentityA, cancellationToken); + if (identityA == null) + { + identityA = Identity.CreateTestIdentity(addressOfIdentityA, [1, 1, 1, 1, 1], basicTier.Id, "USRa"); + await _identitiesRepository.Add(identityA, "Aaaaaaaa1!"); + } + } + + private async Task CreateIdentityBIfNecessary(Tier basicTier, CancellationToken cancellationToken) + { + var addressOfIdentityB = IdentityAddress.Create([2, 2, 2, 2, 2], _applicationOptions.DidDomainName); + var identityB = await _identitiesRepository.FindByAddress(addressOfIdentityB, cancellationToken); + if (identityB == null) + { + identityB = Identity.CreateTestIdentity(addressOfIdentityB, [2, 2, 2, 2, 2], basicTier.Id, "USRb"); + await _identitiesRepository.Add(identityB, "Bbbbbbbb1!"); + } } } From 268c98d93d3c91349b37df7d2cf273267cc50cbf Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:03:45 +0100 Subject: [PATCH 02/30] test: add integration test --- .../Features/Challenges/POST.feature | 2 +- .../Features/Identities/IsDeleted/GET.feature | 12 +++++++++ .../ChallengesStepDefinitions.cs | 2 +- .../IdentitiesStepDefinitions.cs | 26 +++++++++++++++++++ .../Endpoints/Common/EndpointClient.cs | 15 +++++++---- .../Identities/IdentitiesEndpoint.cs | 5 ++++ .../Types/Responses/IsDeletedResponse.cs | 7 +++++ 7 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Identities/IsDeleted/GET.feature create mode 100644 Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/Types/Responses/IsDeletedResponse.cs diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Challenges/POST.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Challenges/POST.feature index 68fbab1356..d4cf042591 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Challenges/POST.feature +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Challenges/POST.feature @@ -4,7 +4,7 @@ Feature: POST /Challenges User creates a Challenge Scenario: Creating a Challenge as an anonymous user - When an anonymous user sends a POST request is sent to the /Challenges endpoint + When an anonymous user sends a POST request to the /Challenges endpoint Then the response status code is 201 (Created) And the response contains a Challenge And the Challenge has an expiration date in the future diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Identities/IsDeleted/GET.feature b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Identities/IsDeleted/GET.feature new file mode 100644 index 0000000000..656071fd64 --- /dev/null +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/Features/Identities/IsDeleted/GET.feature @@ -0,0 +1,12 @@ +@Integration +Feature: GET /Identities/IsDeleted + +User wants to know whether its identity was deleted + + Scenario: Asking whether a not-yet-deleted identity was deleted + Given an Identity i with a Device d + And an active deletion process for i exists + When an anonymous user sends a GET request to the /Identities/IsDeleted endpoint with d.Username + Then the response status code is 200 (OK) + And the response says that the identity was not deleted + And the deletion date is not set diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/ChallengesStepDefinitions.cs b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/ChallengesStepDefinitions.cs index 51041aef7f..1ddfbbff7c 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/ChallengesStepDefinitions.cs +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/ChallengesStepDefinitions.cs @@ -48,7 +48,7 @@ public async Task GivenAChallengeCreatedByAnAnonymousUser(string challengeName) #region When - [When("an anonymous user sends a POST request is sent to the /Challenges endpoint")] + [When("an anonymous user sends a POST request to the /Challenges endpoint")] public async Task WhenAnAnonymousUserSendsAPostRequestIsSentToTheChallengesEndpoint() { var client = _clientPool.Anonymous; diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs index d98d291ff2..c0b3586d6b 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs @@ -1,8 +1,10 @@ using Backbone.BuildingBlocks.SDK.Crypto; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.ConsumerApi.Sdk; using Backbone.ConsumerApi.Sdk.Authentication; using Backbone.ConsumerApi.Sdk.Endpoints.Devices.Types; using Backbone.ConsumerApi.Sdk.Endpoints.Identities.Types.Requests; +using Backbone.ConsumerApi.Sdk.Endpoints.Identities.Types.Responses; using Backbone.ConsumerApi.Tests.Integration.Configuration; using Backbone.ConsumerApi.Tests.Integration.Contexts; using Backbone.ConsumerApi.Tests.Integration.Helpers; @@ -27,6 +29,8 @@ internal class IdentitiesStepDefinitions private readonly ChallengesContext _challengesContext; private readonly ClientPool _clientPool; + private ApiResponse? _isDeletedResponse; + public IdentitiesStepDefinitions(ResponseContext responseContext, ChallengesContext challengesContext, ClientPool clientPool, HttpClientFactory factory, IOptions httpConfiguration) { @@ -92,4 +96,26 @@ public async Task WhenAPostRequestIsSentToTheIdentitiesEndpointWithAValidSignatu } #endregion + + [When($@"an anonymous user sends a GET request to the /Identities/IsDeleted endpoint with {RegexFor.SINGLE_THING}.Username")] + public async Task WhenAnAnonymousUserSendsAGETRequestToTheIdentitiesIsDeletedEndpointWithDUsername(string deviceName) + { + var client = _clientPool.GetForDeviceName(deviceName); + + var device = await client.Devices.GetActiveDevice(); + + _responseContext.WhenResponse = _isDeletedResponse = await _clientPool.Anonymous.Identities.IsDeleted(device.Result!.Username); + } + + [Then(@"the response says that the identity was not deleted")] + public void ThenTheResponseSaysThatTheIdentityWasNotDeleted() + { + _isDeletedResponse!.Result!.IsDeleted.Should().BeFalse(); + } + + [Then(@"the deletion date is not set")] + public void ThenTheDeletionDateIsNotSet() + { + _isDeletedResponse!.Result!.DeletionDate.Should().BeNull(); + } } diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs index dbe4f23d4e..5e72720b3e 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs @@ -59,12 +59,17 @@ public async Task> Get(string url, object? requestContent = nu .Execute(); } - public async Task> GetUnauthenticated(string url, object? requestContent = null, PaginationFilter? pagination = null) + public async Task> GetUnauthenticated(string url, Dictionary? queryParameters = null, PaginationFilter? pagination = null) { - return await Request(HttpMethod.Get, url) - .WithPagination(pagination) - .WithJson(requestContent) - .Execute(); + var queryBuilder = Request(HttpMethod.Get, url) + .WithPagination(pagination); + + foreach (var (key, value) in queryParameters ?? []) + { + queryBuilder.AddQueryParameter(key, value); + } + + return await queryBuilder.Execute(); } public async Task> Put(string url, object? requestContent = null) diff --git a/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs index 59271de8d4..85cba80970 100644 --- a/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs +++ b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs @@ -37,4 +37,9 @@ public async Task> CancelDeletionProc { return await _client.Put($"api/{API_VERSION}/Identities/Self/DeletionProcesses/{id}/Cancel"); } + + public async Task> IsDeleted(string username) + { + return await _client.GetUnauthenticated($"api/{API_VERSION}/Identities/IsDeleted", new Dictionary { { "username", username } }); + } } diff --git a/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/Types/Responses/IsDeletedResponse.cs b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/Types/Responses/IsDeletedResponse.cs new file mode 100644 index 0000000000..5e41a153bf --- /dev/null +++ b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/Types/Responses/IsDeletedResponse.cs @@ -0,0 +1,7 @@ +namespace Backbone.ConsumerApi.Sdk.Endpoints.Identities.Types.Responses; + +public class IsDeletedResponse +{ + public bool IsDeleted { get; set; } + public DateTime? DeletionDate { get; set; } +} From daf9de66405f661aaf31a9b79ac246eebe5383f5 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:07:47 +0100 Subject: [PATCH 03/30] refactor: use generic Find method for audit log entries --- .../GetDeletionProcessesAuditLogs/Handler.cs | 5 ++++- .../Repository/IIdentitiesRepository.cs | 4 +++- .../Repository/IdentitiesRepository.cs | 18 ++++++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/GetDeletionProcessesAuditLogs/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/GetDeletionProcessesAuditLogs/Handler.cs index 1cf6d20517..029c697acc 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Queries/GetDeletionProcessesAuditLogs/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/GetDeletionProcessesAuditLogs/Handler.cs @@ -15,7 +15,10 @@ public Handler(IIdentitiesRepository identityRepository) public async Task Handle(GetDeletionProcessesAuditLogsQuery request, CancellationToken cancellationToken) { - var identityDeletionProcessAuditLogEntries = await _identityRepository.GetIdentityDeletionProcessAuditLogsByAddress(Hasher.HashUtf8(request.IdentityAddress), cancellationToken); + var addressHash = Hasher.HashUtf8(request.IdentityAddress); + + var identityDeletionProcessAuditLogEntries = await _identityRepository.GetIdentityDeletionProcessAuditLogs(l => l.IdentityAddressHash == addressHash, cancellationToken); + return new GetDeletionProcessesAuditLogsResponse(identityDeletionProcessAuditLogEntries.OrderBy(e => e.CreatedAt)); } } diff --git a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs index 3f829a38bc..824f23ecfc 100644 --- a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs @@ -34,7 +34,9 @@ public interface IIdentitiesRepository #region Deletion Process Audit Logs - Task> GetIdentityDeletionProcessAuditLogsByAddress(byte[] identityAddressHash, CancellationToken cancellationToken); + Task> GetIdentityDeletionProcessAuditLogs(Expression> filter, + CancellationToken cancellationToken, bool track = false); + Task AddDeletionProcessAuditLogEntry(IdentityDeletionProcessAuditLogEntry auditLogEntry); #endregion diff --git a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs index 4a23e9ab99..77b6dcc6a3 100644 --- a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs @@ -53,10 +53,20 @@ public async Task FindDevices(Expression> filter, Exp .ToArrayAsync(cancellationToken); } - public async Task> GetIdentityDeletionProcessAuditLogsByAddress(byte[] identityAddressHash, CancellationToken cancellationToken) - { - return await _readonlyIdentityDeletionProcessAuditLogs - .Where(auditLog => auditLog.IdentityAddressHash == identityAddressHash) + public async Task> GetIdentityDeletionProcessAuditLogs(Expression> filter, + CancellationToken cancellationToken, bool track = false) + { + // Clearing the change tracker needs to be done because in case of the actual identity deletion, the deletion + // process including all its audit log entries is read first. Then the deletion process is deleted without the + // change tracker being involved. This leads to auditLogEntry.ProcessId being set to null in the database (because + // of the foreign key configuration). But the change tracker does not know about that. + // Later on during the actual deletion we want to update all existing audit log entries to set the usernames. + // And when trying to save the updated audit log entries, EF Core tries to save the process id as well, which is + // impossible, because the deletion process was deleted already. + _dbContext.ChangeTracker.Clear(); + + return await (track ? _identityDeletionProcessAuditLogs : _readonlyIdentityDeletionProcessAuditLogs) + .Where(filter) .ToListAsync(cancellationToken); } From 09991db37b75612e22eae98c3f692edb99090866 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:13:00 +0100 Subject: [PATCH 04/30] feat: add DeletionCompleted audit log entry and associate usernames after finished deletion --- .../Workers/ActualDeletionWorker.cs | 8 +++++ .../DTOs/IdentityDeletionProcessDetailsDTO.cs | 2 +- .../HandleCompletedDeletionProcessCommand.cs | 16 +++++++++ .../HandleCompletedDeletionProcess/Handler.cs | 34 +++++++++++++++++++ .../Repository/IIdentitiesRepository.cs | 2 ++ .../IdentityDeletionProcessAuditLogEntry.cs | 27 +++++++++++++-- .../Repository/IdentitiesRepository.cs | 6 ++++ ...entityDeletionProcessAuditLogEntryTests.cs | 20 +++++++++++ 8 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs create mode 100644 Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs create mode 100644 Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs index b13819b9fc..fde4e85ac0 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs @@ -2,7 +2,9 @@ using Backbone.BuildingBlocks.Application.PushNotifications; using Backbone.BuildingBlocks.Domain.Errors; using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Application.Identities.Commands.HandleCompletedDeletionProcess; using Backbone.Modules.Devices.Application.Identities.Commands.TriggerRipeDeletionProcesses; +using Backbone.Modules.Devices.Application.Identities.Queries.GetIdentity; using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess; using CSharpFunctionalExtensions; using MediatR; @@ -78,10 +80,16 @@ await _pushNotificationSender.SendNotification( private async Task Delete(IdentityAddress identityAddress) { + var identity = await _mediator.Send(new GetIdentityQuery(identityAddress.Value)); + foreach (var identityDeleter in _identityDeleters) { await identityDeleter.Delete(identityAddress); } + + var usernames = identity.Devices.Select(d => d.Username); + + await _mediator.Send(new HandleCompletedDeletionProcessCommand(identityAddress, usernames)); } private void LogErroringDeletionTriggers(IEnumerable>> erroringDeletionTriggers) diff --git a/Modules/Devices/src/Devices.Application/DTOs/IdentityDeletionProcessDetailsDTO.cs b/Modules/Devices/src/Devices.Application/DTOs/IdentityDeletionProcessDetailsDTO.cs index e99e5df897..1a91cce51c 100644 --- a/Modules/Devices/src/Devices.Application/DTOs/IdentityDeletionProcessDetailsDTO.cs +++ b/Modules/Devices/src/Devices.Application/DTOs/IdentityDeletionProcessDetailsDTO.cs @@ -67,7 +67,7 @@ public IdentityDeletionProcessAuditLogEntryDTO(IdentityDeletionProcessAuditLogEn public string Id { get; set; } public DateTime CreatedAt { get; set; } public DeletionProcessStatus? OldStatus { get; set; } - public DeletionProcessStatus NewStatus { get; set; } + public DeletionProcessStatus? NewStatus { get; set; } public Dictionary AdditionalData { get; set; } public MessageKey MessageKey { get; set; } } diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs new file mode 100644 index 0000000000..c46f884ddf --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs @@ -0,0 +1,16 @@ +using Backbone.DevelopmentKit.Identity.ValueObjects; +using MediatR; + +namespace Backbone.Modules.Devices.Application.Identities.Commands.HandleCompletedDeletionProcess; + +public class HandleCompletedDeletionProcessCommand : IRequest +{ + public HandleCompletedDeletionProcessCommand(IdentityAddress identityAddress, IEnumerable usernames) + { + IdentityAddress = identityAddress; + Usernames = usernames; + } + + public IdentityAddress IdentityAddress { get; } + public IEnumerable Usernames { get; } +} diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs new file mode 100644 index 0000000000..50b6c1608d --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs @@ -0,0 +1,34 @@ +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using MediatR; + +namespace Backbone.Modules.Devices.Application.Identities.Commands.HandleCompletedDeletionProcess; + +public class Handler : IRequestHandler +{ + private readonly IIdentitiesRepository _identitiesRepository; + + public Handler(IIdentitiesRepository identitiesRepository) + { + _identitiesRepository = identitiesRepository; + } + + public async Task Handle(HandleCompletedDeletionProcessCommand request, CancellationToken cancellationToken) + { + await _identitiesRepository.AddDeletionProcessAuditLogEntry(IdentityDeletionProcessAuditLogEntry.DeletionCompleted(request.IdentityAddress)); + + var identityAddressHash = Hasher.HashUtf8(IdentityAddress.ParseUnsafe(request.IdentityAddress)); + + var auditLogEntries = await _identitiesRepository.GetIdentityDeletionProcessAuditLogs(l => l.IdentityAddressHash == identityAddressHash, CancellationToken.None, track: true); + + var auditLogEntriesArray = auditLogEntries as IdentityDeletionProcessAuditLogEntry[] ?? auditLogEntries.ToArray(); + + foreach (var auditLogEntry in auditLogEntriesArray) + { + auditLogEntry.AssociateUsernames(request.Usernames.Select(Username.Parse)); + } + + await _identitiesRepository.Update(auditLogEntriesArray, cancellationToken); + } +} diff --git a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs index 824f23ecfc..eaf5e14ce5 100644 --- a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs @@ -39,5 +39,7 @@ Task> GetIdentityDeletionProce Task AddDeletionProcessAuditLogEntry(IdentityDeletionProcessAuditLogEntry auditLogEntry); + Task Update(IEnumerable auditLogEntries, CancellationToken cancellationToken); + #endregion } diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index 23b3095389..649edc6c28 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -16,7 +16,7 @@ private IdentityDeletionProcessAuditLogEntry() } private IdentityDeletionProcessAuditLogEntry(IdentityDeletionProcessId? processId, MessageKey messageKey, byte[] identityAddressHash, byte[]? deviceIdHash, DeletionProcessStatus? oldStatus, - DeletionProcessStatus newStatus, Dictionary? additionalData = null) + DeletionProcessStatus? newStatus, Dictionary? additionalData = null) { Id = IdentityDeletionProcessAuditLogEntryId.Generate(); ProcessId = processId; @@ -38,6 +38,7 @@ private IdentityDeletionProcessAuditLogEntry(IdentityDeletionProcessId? processI public DeletionProcessStatus? OldStatus { get; } public DeletionProcessStatus NewStatus { get; } public Dictionary? AdditionalData { get; } + public string? UsernameHashesBase64 { get; private set; } public static IdentityDeletionProcessAuditLogEntry ProcessStartedByOwner(IdentityDeletionProcessId processId, IdentityAddress identityAddress, DeviceId deviceId) { @@ -209,6 +210,27 @@ public static IdentityDeletionProcessAuditLogEntry DataDeleted(IdentityAddress i } ); } + + public static IdentityDeletionProcessAuditLogEntry DeletionCompleted(IdentityAddress identityAddress) + { + return new IdentityDeletionProcessAuditLogEntry( + null, + MessageKey.DeletionCompleted, + Hasher.HashUtf8(identityAddress.Value), + null, + DeletionProcessStatus.Deleting, + null + ); + } + + public void AssociateUsernames(IEnumerable usernames) + { + var hashedUsernames = usernames.Select(u => Hasher.HashUtf8(u.Value.Trim())); + var hashedUsernamesInBase64 = hashedUsernames.Select(Convert.ToBase64String); + var concatenatedHashedUsernamesInBase64 = string.Join("", hashedUsernamesInBase64); + + UsernameHashesBase64 = concatenatedHashedUsernamesInBase64; + } } public enum MessageKey @@ -226,5 +248,6 @@ public enum MessageKey GracePeriodReminder1Sent = 11, GracePeriodReminder2Sent = 12, GracePeriodReminder3Sent = 13, - DataDeleted = 14 + DataDeleted = 14, + DeletionCompleted = 15 } diff --git a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs index 77b6dcc6a3..b82273a943 100644 --- a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs @@ -164,4 +164,10 @@ public async Task AddDeletionProcessAuditLogEntry(IdentityDeletionProcessAuditLo _identityDeletionProcessAuditLogs.Add(auditLogEntry); await _dbContext.SaveChangesAsync(); } + + public async Task Update(IEnumerable auditLogEntries, CancellationToken cancellationToken) + { + _identityDeletionProcessAuditLogs.UpdateRange(auditLogEntries); + await _dbContext.SaveChangesAsync(cancellationToken); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs new file mode 100644 index 0000000000..6e67b2c479 --- /dev/null +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -0,0 +1,20 @@ +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Entities.Identities; + +namespace Backbone.Modules.Devices.Domain.Tests.Identities; + +public class IdentityDeletionProcessAuditLogEntryTests +{ + [Fact] + public void AssociateUsernames_happy_path() + { + // Arrange + var auditLogEntry = IdentityDeletionProcessAuditLogEntry.DeletionCompleted(CreateRandomIdentityAddress()); + + // Act + auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); + + // Assert + auditLogEntry.UsernameHashesBase64.Should().NotBeEmpty(); + } +} From 14ee5c3a33c97e5bc8efba27212919a0b85d216d Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:15:58 +0100 Subject: [PATCH 05/30] feat: add migrations --- ...tyDeletionProcessAuditLogEntry.Designer.cs | 928 +++++++++++++++++ ...nToIdentityDeletionProcessAuditLogEntry.cs | 50 + .../DevicesDbContextModelSnapshot.cs | 7 +- ...tyDeletionProcessAuditLogEntry.Designer.cs | 931 ++++++++++++++++++ ...nToIdentityDeletionProcessAuditLogEntry.cs | 50 + .../DevicesDbContextModelSnapshot.cs | 7 +- 6 files changed, 1969 insertions(+), 4 deletions(-) create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs new file mode 100644 index 0000000000..7c30987cf7 --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs @@ -0,0 +1,928 @@ +// +using System; +using Backbone.Modules.Devices.Infrastructure.Persistence.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations +{ + [DbContext(typeof(DevicesDbContext))] + [Migration("20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry")] + partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Devices") + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => + { + b.Property("DeviceId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("AppId") + .IsRequired() + .HasColumnType("text"); + + b.Property("DevicePushIdentifier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("Environment") + .HasColumnType("integer"); + + b.Property("Handle") + .IsRequired() + .HasMaxLength(200) + .IsUnicode(true) + .HasColumnType("character varying(200)") + .IsFixedLength(false); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DeviceId"); + + b.ToTable("PnsRegistrations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CanBeManuallyAssigned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("CanBeUsedAsDefaultForClient") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .IsUnicode(true) + .HasColumnType("character varying(30)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tiers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Challenges", "Challenges", t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("LastLoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("UserName") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CommunicationLanguage") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(2) + .IsUnicode(false) + .HasColumnType("character(2)") + .HasDefaultValue("en") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByDevice") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.ToTable("Devices", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Property("Address") + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionGracePeriodEndsAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IdentityVersion") + .HasColumnType("smallint"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TierId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("TierIdBeforeDeletion") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.HasKey("Address"); + + b.HasIndex("ClientId"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("ClientId"), "hash"); + + b.HasIndex("TierId"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("TierId"), "hash"); + + b.ToTable("Identities", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("ApprovalReminder1SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovalReminder2SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovalReminder3SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CancelledAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CancelledByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionStartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodEndsAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder1SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder2SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder3SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("RejectedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RejectedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") + .IsUnique() + .HasFilter("\"Status\" = 1"); + + b.ToTable("IdentityDeletionProcesses", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("AdditionalData") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceIdHash") + .HasColumnType("bytea"); + + b.Property("IdentityAddressHash") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("IdentityDeletionProcessId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("MessageKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("NewStatus") + .HasColumnType("integer"); + + b.Property("OldStatus") + .HasColumnType("integer"); + + b.Property("UsernameHashesBase64") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("IdentityDeletionProcessId"); + + b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultTier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("MaxIdentities") + .HasColumnType("integer"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.HasIndex("DefaultTier"); + + b.ToTable("OpenIddictApplications", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("text"); + + b.Property("AuthorizationId") + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") + .WithOne("User") + .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") + .WithMany("Devices") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Identity"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) + .WithMany("DeletionProcesses") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) + .WithMany("AuditLog") + .HasForeignKey("IdentityDeletionProcessId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) + .WithMany() + .HasForeignKey("DefaultTier") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Navigation("User") + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Navigation("DeletionProcesses"); + + b.Navigation("Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Navigation("AuditLog"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs new file mode 100644 index 0000000000..a4f33677c5 --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations +{ + /// + public partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "integer", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AddColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog"); + + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "integer", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "integer", + oldNullable: true); + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs index afe4e7e765..2e3c11670f 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Devices") - .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -396,12 +396,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("integer"); b.Property("OldStatus") .HasColumnType("integer"); + b.Property("UsernameHashesBase64") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs new file mode 100644 index 0000000000..dc97bd5638 --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs @@ -0,0 +1,931 @@ +// +using System; +using Backbone.Modules.Devices.Infrastructure.Persistence.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations +{ + [DbContext(typeof(DevicesDbContext))] + [Migration("20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry")] + partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Devices") + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => + { + b.Property("DeviceId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("AppId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DevicePushIdentifier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("Environment") + .HasColumnType("int"); + + b.Property("Handle") + .IsRequired() + .HasMaxLength(200) + .IsUnicode(true) + .HasColumnType("nvarchar(200)") + .IsFixedLength(false); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("DeviceId"); + + b.ToTable("PnsRegistrations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CanBeManuallyAssigned") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("CanBeUsedAsDefaultForClient") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .IsUnicode(true) + .HasColumnType("nvarchar(30)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tiers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Challenges", "Challenges", t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("LastLoginAt") + .HasColumnType("datetime2"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CommunicationLanguage") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(2) + .IsUnicode(false) + .HasColumnType("char(2)") + .HasDefaultValue("en") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedByDevice") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DeletedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.ToTable("Devices", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Property("Address") + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletionGracePeriodEndsAt") + .HasColumnType("datetime2"); + + b.Property("IdentityVersion") + .HasColumnType("tinyint"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TierId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("TierIdBeforeDeletion") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.HasKey("Address"); + + b.HasIndex("ClientId") + .HasAnnotation("Npgsql:IndexMethod", "hash"); + + b.HasIndex("TierId") + .HasAnnotation("Npgsql:IndexMethod", "hash"); + + b.ToTable("Identities", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("ApprovalReminder1SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovalReminder2SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovalReminder3SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovedAt") + .HasColumnType("datetime2"); + + b.Property("ApprovedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CancelledAt") + .HasColumnType("datetime2"); + + b.Property("CancelledByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletionStartedAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodEndsAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder1SentAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder2SentAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder3SentAt") + .HasColumnType("datetime2"); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("RejectedAt") + .HasColumnType("datetime2"); + + b.Property("RejectedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") + .IsUnique() + .HasFilter("\"Status\" = 1"); + + b.ToTable("IdentityDeletionProcesses", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("AdditionalData") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeviceIdHash") + .HasColumnType("varbinary(max)"); + + b.Property("IdentityAddressHash") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("IdentityDeletionProcessId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("MessageKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NewStatus") + .HasColumnType("int"); + + b.Property("OldStatus") + .HasColumnType("int"); + + b.Property("UsernameHashesBase64") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("IdentityDeletionProcessId"); + + b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DefaultTier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("MaxIdentities") + .HasColumnType("int"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasFilter("[ClientId] IS NOT NULL"); + + b.HasIndex("DefaultTier"); + + b.ToTable("OpenIddictApplications", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasFilter("[Name] IS NOT NULL"); + + b.ToTable("OpenIddictScopes", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("AuthorizationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasFilter("[ReferenceId] IS NOT NULL"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") + .WithOne("User") + .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") + .WithMany("Devices") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Identity"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) + .WithMany("DeletionProcesses") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) + .WithMany("AuditLog") + .HasForeignKey("IdentityDeletionProcessId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) + .WithMany() + .HasForeignKey("DefaultTier") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Navigation("User") + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Navigation("DeletionProcesses"); + + b.Navigation("Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Navigation("AuditLog"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs new file mode 100644 index 0000000000..f6b01bfc74 --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations +{ + /// + public partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog"); + + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs index 021391f517..b3a953539e 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("Devices") - .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("ProductVersion", "9.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -395,12 +395,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("int"); b.Property("OldStatus") .HasColumnType("int"); + b.Property("UsernameHashesBase64") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); From 3fd84b1aa6614955008510d92984785bc7bb23ea Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:16:34 +0100 Subject: [PATCH 06/30] feat: add possibility to query whether an identity was deleted --- .../IsIdentityOfUserDeleted/Handler.cs | 27 +++++++++++++++ .../IsIdentityOfUserDeletedQuery.cs | 13 ++++++++ .../IsIdentityOfUserDeletedResponse.cs | 13 ++++++++ .../IsIdentityOfUserDeleted/Validator.cs | 13 ++++++++ .../Controllers/IdentitiesController.cs | 11 +++++++ .../IdentityDeletionProcessAuditLogEntry.cs | 10 ++++-- ...entityDeletionProcessAuditLogEntryTests.cs | 33 +++++++++++++++++++ 7 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs create mode 100644 Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs create mode 100644 Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedResponse.cs create mode 100644 Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Validator.cs diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs new file mode 100644 index 0000000000..3287b91ab6 --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs @@ -0,0 +1,27 @@ +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Application.Infrastructure.Persistence.Repository; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using MediatR; + +namespace Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUserDeleted; + +public class Handler : IRequestHandler +{ + private readonly IIdentitiesRepository _identitiesRepository; + + public Handler(IIdentitiesRepository identitiesRepository) + { + _identitiesRepository = identitiesRepository; + } + + public async Task Handle(IsIdentityOfUserDeletedQuery request, CancellationToken cancellationToken) + { + var auditLogEntries = await _identitiesRepository.GetIdentityDeletionProcessAuditLogs( + IdentityDeletionProcessAuditLogEntry.BelongsToUser(Username.Parse(request.Username)), + cancellationToken); + + var deletionCompletedAuditLogEntry = auditLogEntries.FirstOrDefault(l => l.MessageKey == MessageKey.DeletionCompleted); + + return new IsIdentityOfUserDeletedResponse(deletionCompletedAuditLogEntry != null, deletionCompletedAuditLogEntry?.CreatedAt); + } +} diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs new file mode 100644 index 0000000000..376bb5d350 --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs @@ -0,0 +1,13 @@ +using MediatR; + +namespace Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUserDeleted; + +public class IsIdentityOfUserDeletedQuery : IRequest +{ + public IsIdentityOfUserDeletedQuery(string username) + { + Username = username; + } + + public string Username { get; } +} diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedResponse.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedResponse.cs new file mode 100644 index 0000000000..d94fc90363 --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedResponse.cs @@ -0,0 +1,13 @@ +namespace Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUserDeleted; + +public class IsIdentityOfUserDeletedResponse +{ + public IsIdentityOfUserDeletedResponse(bool isDeleted, DateTime? deletionDate) + { + IsDeleted = isDeleted; + DeletionDate = deletionDate; + } + + public bool IsDeleted { get; set; } + public DateTime? DeletionDate { get; set; } +} diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Validator.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Validator.cs new file mode 100644 index 0000000000..7df6aabed5 --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Validator.cs @@ -0,0 +1,13 @@ +using Backbone.BuildingBlocks.Application.Extensions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using FluentValidation; + +namespace Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUserDeleted; + +public class Validator : AbstractValidator +{ + public Validator() + { + RuleFor(x => x.Username).ValidId(); + } +} diff --git a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs index 1638df6a3a..9a11f20dda 100644 --- a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs +++ b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs @@ -12,6 +12,7 @@ using Backbone.Modules.Devices.Application.Identities.Queries.GetDeletionProcessAsOwner; using Backbone.Modules.Devices.Application.Identities.Queries.GetDeletionProcessesAsOwner; using Backbone.Modules.Devices.Application.Identities.Queries.GetOwnIdentity; +using Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUserDeleted; using Backbone.Modules.Devices.Infrastructure.OpenIddict; using MediatR; using Microsoft.AspNetCore.Authorization; @@ -128,6 +129,16 @@ public async Task GetOwnIdentity(CancellationToken cancellationTo var response = await _mediator.Send(new GetOwnIdentityQuery(), cancellationToken); return Ok(response); } + + [HttpGet("IsDeleted")] + [ProducesResponseType(typeof(IsIdentityOfUserDeletedResponse), StatusCodes.Status200OK)] + [ProducesError(StatusCodes.Status200OK)] + [AllowAnonymous] + public async Task IsIdentityOfUserDeleted([FromQuery(Name = "username")] string username, CancellationToken cancellationToken) + { + var response = await _mediator.Send(new IsIdentityOfUserDeletedQuery(username), cancellationToken); + return Ok(response); + } } public class CreateIdentityRequest diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index 649edc6c28..c197f860fb 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -1,4 +1,5 @@ -using Backbone.BuildingBlocks.Domain; +using System.Linq.Expressions; +using Backbone.BuildingBlocks.Domain; using Backbone.DevelopmentKit.Identity.ValueObjects; using Backbone.Tooling; @@ -36,7 +37,7 @@ private IdentityDeletionProcessAuditLogEntry(IdentityDeletionProcessId? processI public byte[] IdentityAddressHash { get; } public byte[]? DeviceIdHash { get; } public DeletionProcessStatus? OldStatus { get; } - public DeletionProcessStatus NewStatus { get; } + public DeletionProcessStatus? NewStatus { get; } public Dictionary? AdditionalData { get; } public string? UsernameHashesBase64 { get; private set; } @@ -231,6 +232,11 @@ public void AssociateUsernames(IEnumerable usernames) UsernameHashesBase64 = concatenatedHashedUsernamesInBase64; } + + public static Expression> BelongsToUser(Username username) + { + return logEntry => logEntry.UsernameHashesBase64!.Contains(Convert.ToBase64String(Hasher.HashUtf8(username.Value.Trim()))); + } } public enum MessageKey diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index 6e67b2c479..24950f21cd 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -17,4 +17,37 @@ public void AssociateUsernames_happy_path() // Assert auditLogEntry.UsernameHashesBase64.Should().NotBeEmpty(); } + + [Fact] + public void BelongsToUser_returns_true_if_audit_log_entry_contains_username() + { + // Arrange + var username1 = Username.Parse("USR1111111111111111"); + var username2 = Username.Parse("USR2222222222222222"); + var auditLogEntry = IdentityDeletionProcessAuditLogEntry.DeletionCompleted(CreateRandomIdentityAddress()); + auditLogEntry.AssociateUsernames([username1, username2]); + + // Act + var resultForUsername1 = IdentityDeletionProcessAuditLogEntry.BelongsToUser(username1).Compile()(auditLogEntry); + var resultForUsername2 = IdentityDeletionProcessAuditLogEntry.BelongsToUser(username2).Compile()(auditLogEntry); + + // Assert + resultForUsername1.Should().BeTrue(); + resultForUsername2.Should().BeTrue(); + } + + [Fact] + public void BelongsToUser_returns_false_if_user_is_not_authorized() + { + // Arrange + var unauthorizedUsername = Username.Parse("USR3333333333333333"); + var auditLogEntry = IdentityDeletionProcessAuditLogEntry.DeletionCompleted(CreateRandomIdentityAddress()); + auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); + + // Act + var resultForUnauthorizedUsername = IdentityDeletionProcessAuditLogEntry.BelongsToUser(unauthorizedUsername).Compile()(auditLogEntry); + + // Assert + resultForUnauthorizedUsername.Should().BeFalse(); + } } From ec2e8fde3641c106a9a1389685bc33741a40d65d Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:19:43 +0100 Subject: [PATCH 07/30] chore: formatting --- .../StepDefinitions/IdentitiesStepDefinitions.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs index c0b3586d6b..698342500f 100644 --- a/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs +++ b/Applications/ConsumerApi/test/ConsumerApi.Tests.Integration/StepDefinitions/IdentitiesStepDefinitions.cs @@ -95,8 +95,6 @@ public async Task WhenAPostRequestIsSentToTheIdentitiesEndpointWithAValidSignatu _responseContext.WhenResponse = await _clientPool.Anonymous.Identities.CreateIdentity(createIdentityPayload); } - #endregion - [When($@"an anonymous user sends a GET request to the /Identities/IsDeleted endpoint with {RegexFor.SINGLE_THING}.Username")] public async Task WhenAnAnonymousUserSendsAGETRequestToTheIdentitiesIsDeletedEndpointWithDUsername(string deviceName) { @@ -107,6 +105,10 @@ public async Task WhenAnAnonymousUserSendsAGETRequestToTheIdentitiesIsDeletedEnd _responseContext.WhenResponse = _isDeletedResponse = await _clientPool.Anonymous.Identities.IsDeleted(device.Result!.Username); } + #endregion + + #region Then + [Then(@"the response says that the identity was not deleted")] public void ThenTheResponseSaysThatTheIdentityWasNotDeleted() { @@ -118,4 +120,6 @@ public void ThenTheDeletionDateIsNotSet() { _isDeletedResponse!.Result!.DeletionDate.Should().BeNull(); } + + #endregion } From f65d706a62466d479c7a1b2d9e792116328791b4 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:28:57 +0100 Subject: [PATCH 08/30] refactor: simplify Handler for SeedTestUsersCommand --- .../Users/Commands/SeedTestUsers/Handler.cs | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs b/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs index 90bf28ff95..f779f72f3f 100644 --- a/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Users/Commands/SeedTestUsers/Handler.cs @@ -12,6 +12,8 @@ public class Handler : IRequestHandler private readonly ApplicationOptions _applicationOptions; private readonly IIdentitiesRepository _identitiesRepository; private readonly ITiersRepository _tiersRepository; + private Tier? _basicTier; + private CancellationToken _cancellationToken; public Handler(IIdentitiesRepository identitiesRepository, ITiersRepository tiersRepository, IOptions applicationOptions) { @@ -22,31 +24,23 @@ public Handler(IIdentitiesRepository identitiesRepository, ITiersRepository tier public async Task Handle(SeedTestUsersCommand request, CancellationToken cancellationToken) { - var basicTier = await _tiersRepository.FindBasicTier(cancellationToken); + _cancellationToken = cancellationToken; + _basicTier = (await _tiersRepository.FindBasicTier(cancellationToken))!; - await CreateIdentityAIfNecessary(basicTier!, cancellationToken); - await CreateIdentityBIfNecessary(basicTier!, cancellationToken); + await CreateIdentityIfNecessary([1, 1, 1, 1, 1], "USRa", "Aaaaaaaa1!"); + await CreateIdentityIfNecessary([1, 1, 1, 1, 1], "USRa", "Bbbbbbbb1!"); } - private async Task CreateIdentityAIfNecessary(Tier basicTier, CancellationToken cancellationToken) + private async Task CreateIdentityIfNecessary(byte[] publicKey, string username, string password) { - var addressOfIdentityA = IdentityAddress.Create([1, 1, 1, 1, 1], _applicationOptions.DidDomainName); - var identityA = await _identitiesRepository.FindByAddress(addressOfIdentityA, cancellationToken); - if (identityA == null) - { - identityA = Identity.CreateTestIdentity(addressOfIdentityA, [1, 1, 1, 1, 1], basicTier.Id, "USRa"); - await _identitiesRepository.Add(identityA, "Aaaaaaaa1!"); - } - } + var address = IdentityAddress.Create(publicKey, _applicationOptions.DidDomainName); - private async Task CreateIdentityBIfNecessary(Tier basicTier, CancellationToken cancellationToken) - { - var addressOfIdentityB = IdentityAddress.Create([2, 2, 2, 2, 2], _applicationOptions.DidDomainName); - var identityB = await _identitiesRepository.FindByAddress(addressOfIdentityB, cancellationToken); - if (identityB == null) + var identityExists = await _identitiesRepository.Exists(address, _cancellationToken); + + if (!identityExists) { - identityB = Identity.CreateTestIdentity(addressOfIdentityB, [2, 2, 2, 2, 2], basicTier.Id, "USRb"); - await _identitiesRepository.Add(identityB, "Bbbbbbbb1!"); + var identity = Identity.CreateTestIdentity(address, publicKey, _basicTier!.Id, username); + await _identitiesRepository.Add(identity, password); } } } From 7e1c5eb74ecf1167e81341c7dbd41fdadcff7ebf Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 09:35:44 +0100 Subject: [PATCH 09/30] refactor: use NameValueCollection instead of Dictionary --- .../Endpoints/Common/EndpointClient.cs | 27 ++++++++++--------- .../Identities/IdentitiesEndpoint.cs | 5 ++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs index 5e72720b3e..1966ca585b 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs @@ -50,26 +50,21 @@ public async Task> PostUnauthenticated(string url, object? req .Execute(); } - public async Task> Get(string url, object? requestContent = null, PaginationFilter? pagination = null) + public async Task> Get(string url, NameValueCollection? queryParameters = null, PaginationFilter? pagination = null) { return await Request(HttpMethod.Get, url) .Authenticate() .WithPagination(pagination) - .WithJson(requestContent) + .AddQueryParameters(queryParameters) .Execute(); } - public async Task> GetUnauthenticated(string url, Dictionary? queryParameters = null, PaginationFilter? pagination = null) + public async Task> GetUnauthenticated(string url, NameValueCollection? queryParameters = null, PaginationFilter? pagination = null) { - var queryBuilder = Request(HttpMethod.Get, url) - .WithPagination(pagination); - - foreach (var (key, value) in queryParameters ?? []) - { - queryBuilder.AddQueryParameter(key, value); - } - - return await queryBuilder.Execute(); + return await Request(HttpMethod.Get, url) + .WithPagination(pagination) + .AddQueryParameters(queryParameters) + .Execute(); } public async Task> Put(string url, object? requestContent = null) @@ -242,6 +237,14 @@ public RequestBuilder AddQueryParameters(IQueryParameterStorage parameters) return this; } + public RequestBuilder AddQueryParameters(NameValueCollection? parameters) + { + if (parameters != null) + _queryParameters.Add(parameters); + + return this; + } + public RequestBuilder AddExtraHeader(string key, string value) { _extraHeaders.Add(key, value); diff --git a/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs index 85cba80970..626b200a20 100644 --- a/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs +++ b/Sdks/ConsumerApi.Sdk/src/Endpoints/Identities/IdentitiesEndpoint.cs @@ -1,4 +1,5 @@ -using Backbone.BuildingBlocks.SDK.Endpoints.Common; +using System.Collections.Specialized; +using Backbone.BuildingBlocks.SDK.Endpoints.Common; using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.ConsumerApi.Sdk.Endpoints.Identities.Types; using Backbone.ConsumerApi.Sdk.Endpoints.Identities.Types.Requests; @@ -40,6 +41,6 @@ public async Task> CancelDeletionProc public async Task> IsDeleted(string username) { - return await _client.GetUnauthenticated($"api/{API_VERSION}/Identities/IsDeleted", new Dictionary { { "username", username } }); + return await _client.GetUnauthenticated($"api/{API_VERSION}/Identities/IsDeleted", new NameValueCollection { { "username", username } }); } } From 0de5805ea379e3f601870a2c1bbcb06d26937a5d Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:12:42 +0100 Subject: [PATCH 10/30] refactor: rename BelongsTo method --- .../Queries/IsIdentityOfUserDeleted/Handler.cs | 2 +- .../IdentityDeletionProcessAuditLogEntry.cs | 2 +- .../IdentityDeletionProcessAuditLogEntryTests.cs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs index 3287b91ab6..0ec044d706 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs @@ -17,7 +17,7 @@ public Handler(IIdentitiesRepository identitiesRepository) public async Task Handle(IsIdentityOfUserDeletedQuery request, CancellationToken cancellationToken) { var auditLogEntries = await _identitiesRepository.GetIdentityDeletionProcessAuditLogs( - IdentityDeletionProcessAuditLogEntry.BelongsToUser(Username.Parse(request.Username)), + IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(Username.Parse(request.Username)), cancellationToken); var deletionCompletedAuditLogEntry = auditLogEntries.FirstOrDefault(l => l.MessageKey == MessageKey.DeletionCompleted); diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index c197f860fb..7bc6c4a3d0 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -233,7 +233,7 @@ public void AssociateUsernames(IEnumerable usernames) UsernameHashesBase64 = concatenatedHashedUsernamesInBase64; } - public static Expression> BelongsToUser(Username username) + public static Expression> IsAssociatedToUser(Username username) { return logEntry => logEntry.UsernameHashesBase64!.Contains(Convert.ToBase64String(Hasher.HashUtf8(username.Value.Trim()))); } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index 24950f21cd..c07e4e478e 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -3,7 +3,7 @@ namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class IdentityDeletionProcessAuditLogEntryTests +public class IdentityDeletionProcessAuditLogEntryTests : AbstractTestsBase { [Fact] public void AssociateUsernames_happy_path() @@ -19,7 +19,7 @@ public void AssociateUsernames_happy_path() } [Fact] - public void BelongsToUser_returns_true_if_audit_log_entry_contains_username() + public void IsAssociatedToUser_returns_true_if_audit_log_entry_contains_username() { // Arrange var username1 = Username.Parse("USR1111111111111111"); @@ -28,8 +28,8 @@ public void BelongsToUser_returns_true_if_audit_log_entry_contains_username() auditLogEntry.AssociateUsernames([username1, username2]); // Act - var resultForUsername1 = IdentityDeletionProcessAuditLogEntry.BelongsToUser(username1).Compile()(auditLogEntry); - var resultForUsername2 = IdentityDeletionProcessAuditLogEntry.BelongsToUser(username2).Compile()(auditLogEntry); + var resultForUsername1 = IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(username1).Compile()(auditLogEntry); + var resultForUsername2 = IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(username2).Compile()(auditLogEntry); // Assert resultForUsername1.Should().BeTrue(); @@ -37,7 +37,7 @@ public void BelongsToUser_returns_true_if_audit_log_entry_contains_username() } [Fact] - public void BelongsToUser_returns_false_if_user_is_not_authorized() + public void IsAssociatedToUser_returns_false_if_user_is_not_authorized() { // Arrange var unauthorizedUsername = Username.Parse("USR3333333333333333"); @@ -45,7 +45,7 @@ public void BelongsToUser_returns_false_if_user_is_not_authorized() auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); // Act - var resultForUnauthorizedUsername = IdentityDeletionProcessAuditLogEntry.BelongsToUser(unauthorizedUsername).Compile()(auditLogEntry); + var resultForUnauthorizedUsername = IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(unauthorizedUsername).Compile()(auditLogEntry); // Assert resultForUnauthorizedUsername.Should().BeFalse(); From 36dab577433382ec45887ca81e7b6631c7328221 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:13:06 +0100 Subject: [PATCH 11/30] chore: fix archunit test errors --- .../Job.IdentityDeletion/Workers/ActualDeletionWorker.cs | 2 +- .../HandleCompletedDeletionProcessCommand.cs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs index fde4e85ac0..78b72ba49a 100644 --- a/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs +++ b/Applications/IdentityDeletionJobs/src/Job.IdentityDeletion/Workers/ActualDeletionWorker.cs @@ -89,7 +89,7 @@ private async Task Delete(IdentityAddress identityAddress) var usernames = identity.Devices.Select(d => d.Username); - await _mediator.Send(new HandleCompletedDeletionProcessCommand(identityAddress, usernames)); + await _mediator.Send(new HandleCompletedDeletionProcessCommand(identityAddress.Value, usernames)); } private void LogErroringDeletionTriggers(IEnumerable>> erroringDeletionTriggers) diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs index c46f884ddf..8945bfed43 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/HandleCompletedDeletionProcessCommand.cs @@ -1,16 +1,15 @@ -using Backbone.DevelopmentKit.Identity.ValueObjects; -using MediatR; +using MediatR; namespace Backbone.Modules.Devices.Application.Identities.Commands.HandleCompletedDeletionProcess; public class HandleCompletedDeletionProcessCommand : IRequest { - public HandleCompletedDeletionProcessCommand(IdentityAddress identityAddress, IEnumerable usernames) + public HandleCompletedDeletionProcessCommand(string identityAddress, IEnumerable usernames) { IdentityAddress = identityAddress; Usernames = usernames; } - public IdentityAddress IdentityAddress { get; } + public string IdentityAddress { get; } public IEnumerable Usernames { get; } } From 270beb411fb853239bea694ebace4fe5aa1f6279 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:21:27 +0100 Subject: [PATCH 12/30] chore: formatting --- .../BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs index 1966ca585b..fa88533e00 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs @@ -201,7 +201,9 @@ public RequestBuilder WithMultipartForm(MultipartContent content) public RequestBuilder WithPagination(PaginationFilter? pagination) { - if (pagination != null) AddQueryParameters(pagination); + if (pagination != null) + AddQueryParameters(pagination); + return this; } @@ -233,8 +235,7 @@ public RequestBuilder AddQueryParameter(string key, object value) public RequestBuilder AddQueryParameters(IQueryParameterStorage parameters) { - _queryParameters.Add(parameters.ToQueryParameters()); - return this; + return AddQueryParameters(parameters.ToQueryParameters()); } public RequestBuilder AddQueryParameters(NameValueCollection? parameters) From a61e31f2851f8041eb9e293b6f0b29450980c68f Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:30:11 +0100 Subject: [PATCH 13/30] test: fix test by configuring fake --- .../Tests/ActualDeletionWorkerTests.cs | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs index feb5834646..7f4a1381bd 100644 --- a/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs +++ b/Applications/IdentityDeletionJobs/test/Job.IdentityDeletion.Tests/Tests/ActualDeletionWorkerTests.cs @@ -4,7 +4,10 @@ using Backbone.DevelopmentKit.Identity.ValueObjects; using Backbone.Job.IdentityDeletion.Workers; using Backbone.Modules.Devices.Application.Identities.Commands.TriggerRipeDeletionProcesses; +using Backbone.Modules.Devices.Application.Identities.Queries.GetIdentity; using Backbone.Modules.Devices.Application.Infrastructure.PushNotifications.DeletionProcess; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.Entities.Identities; using Backbone.Modules.Relationships.Application.Relationships.Queries.FindRelationshipsOfIdentity; using CSharpFunctionalExtensions; using FakeItEasy; @@ -37,9 +40,9 @@ public async Task Calls_Deleters_For_Each_Identity() { // Arrange var fakeMediator = A.Fake(); - var identityAddress1 = CreateRandomIdentityAddress(); - var identityAddress2 = CreateRandomIdentityAddress(); - SetupRipeDeletionProcessesCommand(fakeMediator, identityAddress1, identityAddress2); + var identity1 = CreateIdentity(); + var identity2 = CreateIdentity(); + SetupRipeDeletionProcessesCommand(fakeMediator, identity1.Address, identity2.Address); var mockIdentityDeleter = A.Fake(); var worker = CreateWorker(fakeMediator, [mockIdentityDeleter]); @@ -47,12 +50,18 @@ public async Task Calls_Deleters_For_Each_Identity() A.CallTo(() => fakeMediator.Send(A._, A._)) .Returns(new FindRelationshipsOfIdentityResponse([])); + A.CallTo(() => fakeMediator.Send(A.That.Matches(q => q.Address == identity1.Address.Value), A._)) + .Returns(new GetIdentityResponse(identity1)); + + A.CallTo(() => fakeMediator.Send(A.That.Matches(q => q.Address == identity2.Address.Value), A._)) + .Returns(new GetIdentityResponse(identity2)); + // Act await worker.StartProcessing(CancellationToken.None); // Assert - A.CallTo(() => mockIdentityDeleter.Delete(identityAddress1)).MustHaveHappenedOnceExactly(); - A.CallTo(() => mockIdentityDeleter.Delete(identityAddress2)).MustHaveHappenedOnceExactly(); + A.CallTo(() => mockIdentityDeleter.Delete(identity1.Address)).MustHaveHappenedOnceExactly(); + A.CallTo(() => mockIdentityDeleter.Delete(identity2.Address)).MustHaveHappenedOnceExactly(); } [Fact] @@ -60,12 +69,17 @@ public async Task Sends_push_notification_to_each_deleted_identity() { // Arrange var fakeMediator = A.Fake(); - var identityAddress1 = CreateRandomIdentityAddress(); - var identityAddress2 = CreateRandomIdentityAddress(); - var identityAddress3 = CreateRandomIdentityAddress(); - SetupRipeDeletionProcessesCommand(fakeMediator, identityAddress1, identityAddress2, identityAddress3); + var identity1 = CreateIdentity(); + var identity2 = CreateIdentity(); + SetupRipeDeletionProcessesCommand(fakeMediator, identity1.Address, identity2.Address); A.CallTo(() => fakeMediator.Send(A._, A._)).Returns(new FindRelationshipsOfIdentityResponse([])); + A.CallTo(() => fakeMediator.Send(A.That.Matches(q => q.Address == identity1.Address.Value), A._)) + .Returns(new GetIdentityResponse(identity1)); + + A.CallTo(() => fakeMediator.Send(A.That.Matches(q => q.Address == identity2.Address.Value), A._)) + .Returns(new GetIdentityResponse(identity2)); + var mockPushNotificationSender = A.Fake(); var worker = CreateWorker(fakeMediator, [], mockPushNotificationSender); @@ -73,7 +87,7 @@ public async Task Sends_push_notification_to_each_deleted_identity() await worker.StartProcessing(CancellationToken.None); // Assert - foreach (var identityAddress in new[] { identityAddress1, identityAddress2, identityAddress3 }) + foreach (var identityAddress in new[] { identity1.Address, identity2.Address }) { A.CallTo(() => mockPushNotificationSender.SendNotification( A._, @@ -99,4 +113,15 @@ private static ActualDeletionWorker CreateWorker(IMediator mediator, var logger = A.Dummy>(); return new ActualDeletionWorker(hostApplicationLifetime, identityDeleters, mediator, pushNotificationSender, logger); } + + private static Identity CreateIdentity() + { + return new Identity( + CreateRandomDeviceId(), + CreateRandomIdentityAddress(), + CreateRandomBytes(), + TierId.Generate(), + 1, + CommunicationLanguage.DEFAULT_LANGUAGE); + } } From cfe0350c84d1fdff250af829a5837478f019d89a Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:47:38 +0100 Subject: [PATCH 14/30] refactor: cleanup HandleCompletedDeletionProcessCommand Handler --- .../Commands/HandleCompletedDeletionProcess/Handler.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs index 50b6c1608d..4a3ba15670 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Handler.cs @@ -18,11 +18,16 @@ public async Task Handle(HandleCompletedDeletionProcessCommand request, Cancella { await _identitiesRepository.AddDeletionProcessAuditLogEntry(IdentityDeletionProcessAuditLogEntry.DeletionCompleted(request.IdentityAddress)); - var identityAddressHash = Hasher.HashUtf8(IdentityAddress.ParseUnsafe(request.IdentityAddress)); + await AssociateUsernames(request, cancellationToken); + } + + private async Task AssociateUsernames(HandleCompletedDeletionProcessCommand request, CancellationToken cancellationToken) + { + var identityAddressHash = Hasher.HashUtf8(request.IdentityAddress); var auditLogEntries = await _identitiesRepository.GetIdentityDeletionProcessAuditLogs(l => l.IdentityAddressHash == identityAddressHash, CancellationToken.None, track: true); - var auditLogEntriesArray = auditLogEntries as IdentityDeletionProcessAuditLogEntry[] ?? auditLogEntries.ToArray(); + var auditLogEntriesArray = auditLogEntries.ToArray(); foreach (var auditLogEntry in auditLogEntriesArray) { From fe771acad425219de4b946d98d604a1e0ba03ca9 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:47:58 +0100 Subject: [PATCH 15/30] feat: add validator for HandleCompletedDeletionProcessCommand --- .../HandleCompletedDeletionProcess/Validator.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Validator.cs diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Validator.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Validator.cs new file mode 100644 index 0000000000..9207e08229 --- /dev/null +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/HandleCompletedDeletionProcess/Validator.cs @@ -0,0 +1,15 @@ +using Backbone.BuildingBlocks.Application.Extensions; +using Backbone.BuildingBlocks.Application.FluentValidation; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using FluentValidation; + +namespace Backbone.Modules.Devices.Application.Identities.Commands.HandleCompletedDeletionProcess; + +public class Validator : AbstractValidator +{ + public Validator() + { + RuleFor(c => c.IdentityAddress).ValidId(); + RuleFor(c => c.Usernames).DetailedNotEmpty(); + } +} From 0265c72586c6d2f647bd183efeb44b1809891956 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 10:51:31 +0100 Subject: [PATCH 16/30] chore: formatting/cleanup --- .../Controllers/IdentitiesController.cs | 2 +- .../IdentityDeletionProcessAuditLogEntry.cs | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs index 9a11f20dda..cdf4cad8f7 100644 --- a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs +++ b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs @@ -131,9 +131,9 @@ public async Task GetOwnIdentity(CancellationToken cancellationTo } [HttpGet("IsDeleted")] + [AllowAnonymous] [ProducesResponseType(typeof(IsIdentityOfUserDeletedResponse), StatusCodes.Status200OK)] [ProducesError(StatusCodes.Status200OK)] - [AllowAnonymous] public async Task IsIdentityOfUserDeleted([FromQuery(Name = "username")] string username, CancellationToken cancellationToken) { var response = await _mediator.Send(new IsIdentityOfUserDeletedQuery(username), cancellationToken); diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index 7bc6c4a3d0..cfaaa84894 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -215,22 +215,20 @@ public static IdentityDeletionProcessAuditLogEntry DataDeleted(IdentityAddress i public static IdentityDeletionProcessAuditLogEntry DeletionCompleted(IdentityAddress identityAddress) { return new IdentityDeletionProcessAuditLogEntry( - null, - MessageKey.DeletionCompleted, - Hasher.HashUtf8(identityAddress.Value), - null, - DeletionProcessStatus.Deleting, - null + processId: null, + messageKey: MessageKey.DeletionCompleted, + identityAddressHash: Hasher.HashUtf8(identityAddress.Value), + deviceIdHash: null, + oldStatus: DeletionProcessStatus.Deleting, + newStatus: null ); } public void AssociateUsernames(IEnumerable usernames) { var hashedUsernames = usernames.Select(u => Hasher.HashUtf8(u.Value.Trim())); - var hashedUsernamesInBase64 = hashedUsernames.Select(Convert.ToBase64String); - var concatenatedHashedUsernamesInBase64 = string.Join("", hashedUsernamesInBase64); - - UsernameHashesBase64 = concatenatedHashedUsernamesInBase64; + var base64 = hashedUsernames.Select(Convert.ToBase64String); + UsernameHashesBase64 = string.Join("", base64); } public static Expression> IsAssociatedToUser(Username username) From 48ab1fef11352a5f00ba33ddcee08073e393f3fa Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 11:51:06 +0100 Subject: [PATCH 17/30] refactor: improve AssociateUsernames method --- .../Identities/IdentityDeletionProcessAuditLogEntry.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index cfaaa84894..b688d051aa 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -226,9 +226,10 @@ public static IdentityDeletionProcessAuditLogEntry DeletionCompleted(IdentityAdd public void AssociateUsernames(IEnumerable usernames) { - var hashedUsernames = usernames.Select(u => Hasher.HashUtf8(u.Value.Trim())); - var base64 = hashedUsernames.Select(Convert.ToBase64String); - UsernameHashesBase64 = string.Join("", base64); + UsernameHashesBase64 = usernames + .Select(u => Hasher.HashUtf8(u.Value.Trim())) + .Select(Convert.ToBase64String) + .Aggregate((result, current) => result + current); } public static Expression> IsAssociatedToUser(Username username) From 3fa3812bcad0f4c5641e6436fb4d60d0bbc4778b Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 11:51:17 +0100 Subject: [PATCH 18/30] refactor: extract variable --- .../Identities/IdentityDeletionProcessAuditLogEntry.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index b688d051aa..d65108a760 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -234,7 +234,8 @@ public void AssociateUsernames(IEnumerable usernames) public static Expression> IsAssociatedToUser(Username username) { - return logEntry => logEntry.UsernameHashesBase64!.Contains(Convert.ToBase64String(Hasher.HashUtf8(username.Value.Trim()))); + var usernameHashBase64 = Convert.ToBase64String(Hasher.HashUtf8(username.Value.Trim())); + return logEntry => logEntry.UsernameHashesBase64 != null && logEntry.UsernameHashesBase64.Contains(usernameHashBase64); } } From 939595cd070892d71bb61308e6403b4a74383faf Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 11:53:22 +0100 Subject: [PATCH 19/30] test: change test names --- .../Identities/IdentityDeletionProcessAuditLogEntryTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index c07e4e478e..c3abde7e13 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -19,7 +19,7 @@ public void AssociateUsernames_happy_path() } [Fact] - public void IsAssociatedToUser_returns_true_if_audit_log_entry_contains_username() + public void IsAssociatedToUser_returns_true_if_user_is_associated() { // Arrange var username1 = Username.Parse("USR1111111111111111"); @@ -37,7 +37,7 @@ public void IsAssociatedToUser_returns_true_if_audit_log_entry_contains_username } [Fact] - public void IsAssociatedToUser_returns_false_if_user_is_not_authorized() + public void IsAssociatedToUser_returns_false_if_user_is_not_associated() { // Arrange var unauthorizedUsername = Username.Parse("USR3333333333333333"); From 6f900b3ee0d2f6fd4308b38a5dd32648ffd9f7ed Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 11:57:48 +0100 Subject: [PATCH 20/30] chore: remove leftover comment --- .../Devices/src/Devices.Domain/Entities/Identities/Hasher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/Hasher.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/Hasher.cs index 0e67e7f10c..8bca59de43 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/Hasher.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/Hasher.cs @@ -40,9 +40,9 @@ public static void Reset() internal class HasherImpl : IHasher { private static readonly byte[] SALT = SHA256.HashData("enmeshed_identity_deletion_log"u8.ToArray()); + public byte[] HashUtf8(string input) { - // Salt: SHA128 von "enmeshed_identity_deletion_log" var hash = KeyDerivation.Pbkdf2(input, SALT, KeyDerivationPrf.HMACSHA256, 100_000, 32); return hash; } From f56dbfc841fa79c1c4769f8628ed3dd5d5c90502 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Tue, 26 Nov 2024 11:58:20 +0100 Subject: [PATCH 21/30] test: make AssociateUsernames test more concrete --- .../IdentityDeletionProcessAuditLogEntryTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index c3abde7e13..1a6e81346f 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -15,7 +15,7 @@ public void AssociateUsernames_happy_path() auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); // Assert - auditLogEntry.UsernameHashesBase64.Should().NotBeEmpty(); + auditLogEntry.UsernameHashesBase64.Should().Be("jj3azydpiPwK4iFxo/wpCP6pP5Yf5MStnu/hyzMUZ14=FQao/LArcVbFzRs4RgYCU5JycRx9zmJMxY5ApJ0Nk8E="); } [Fact] @@ -40,14 +40,14 @@ public void IsAssociatedToUser_returns_true_if_user_is_associated() public void IsAssociatedToUser_returns_false_if_user_is_not_associated() { // Arrange - var unauthorizedUsername = Username.Parse("USR3333333333333333"); + var unassociatedUsername = Username.Parse("USR3333333333333333"); var auditLogEntry = IdentityDeletionProcessAuditLogEntry.DeletionCompleted(CreateRandomIdentityAddress()); auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); // Act - var resultForUnauthorizedUsername = IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(unauthorizedUsername).Compile()(auditLogEntry); + var result = IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(unassociatedUsername).Compile()(auditLogEntry); // Assert - resultForUnauthorizedUsername.Should().BeFalse(); + result.Should().BeFalse(); } } From 3517a20567b4718f62103866f5fd4bad0eb38c81 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 07:17:02 +0100 Subject: [PATCH 22/30] refactor: use init property instead of constructor --- .../IsIdentityOfUserDeletedQuery.cs | 7 +------ .../Controllers/IdentitiesController.cs | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs index 376bb5d350..b5c22c92dc 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/IsIdentityOfUserDeletedQuery.cs @@ -4,10 +4,5 @@ namespace Backbone.Modules.Devices.Application.Identities.Queries.IsIdentityOfUs public class IsIdentityOfUserDeletedQuery : IRequest { - public IsIdentityOfUserDeletedQuery(string username) - { - Username = username; - } - - public string Username { get; } + public required string Username { get; init; } } diff --git a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs index cdf4cad8f7..11e76ef9e1 100644 --- a/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs +++ b/Modules/Devices/src/Devices.ConsumerApi/Controllers/IdentitiesController.cs @@ -136,7 +136,7 @@ public async Task GetOwnIdentity(CancellationToken cancellationTo [ProducesError(StatusCodes.Status200OK)] public async Task IsIdentityOfUserDeleted([FromQuery(Name = "username")] string username, CancellationToken cancellationToken) { - var response = await _mediator.Send(new IsIdentityOfUserDeletedQuery(username), cancellationToken); + var response = await _mediator.Send(new IsIdentityOfUserDeletedQuery { Username = username }, cancellationToken); return Ok(response); } } From 1180d000b99cd6b8bd6d96d068e470da434ded50 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 09:23:44 +0100 Subject: [PATCH 23/30] feat: remove migration --- ...tyDeletionProcessAuditLogEntry.Designer.cs | 928 ----------------- ...nToIdentityDeletionProcessAuditLogEntry.cs | 50 - .../DevicesDbContextModelSnapshot.cs | 5 +- ...tyDeletionProcessAuditLogEntry.Designer.cs | 931 ------------------ ...nToIdentityDeletionProcessAuditLogEntry.cs | 50 - .../DevicesDbContextModelSnapshot.cs | 5 +- 6 files changed, 2 insertions(+), 1967 deletions(-) delete mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs delete mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs delete mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs delete mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs deleted file mode 100644 index 7c30987cf7..0000000000 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs +++ /dev/null @@ -1,928 +0,0 @@ -// -using System; -using Backbone.Modules.Devices.Infrastructure.Persistence.Database; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations -{ - [DbContext(typeof(DevicesDbContext))] - [Migration("20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry")] - partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Devices") - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => - { - b.Property("DeviceId") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("AppId") - .IsRequired() - .HasColumnType("text"); - - b.Property("DevicePushIdentifier") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("Environment") - .HasColumnType("integer"); - - b.Property("Handle") - .IsRequired() - .HasMaxLength(200) - .IsUnicode(true) - .HasColumnType("character varying(200)") - .IsFixedLength(false); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("character varying(80)") - .IsFixedLength(false); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("DeviceId"); - - b.ToTable("PnsRegistrations", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("CanBeManuallyAssigned") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true); - - b.Property("CanBeUsedAsDefaultForClient") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true); - - b.Property("Name") - .IsRequired() - .HasMaxLength(30) - .IsUnicode(true) - .HasColumnType("character varying(30)") - .IsFixedLength(false); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("Tiers", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("Challenges", "Challenges", t => - { - t.ExcludeFromMigrations(); - }); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("text"); - - b.Property("AccessFailedCount") - .HasColumnType("integer"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("LastLoginAt") - .HasColumnType("timestamp with time zone"); - - b.Property("LockoutEnabled") - .HasColumnType("boolean"); - - b.Property("LockoutEnd") - .HasColumnType("timestamp with time zone"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("PasswordHash") - .HasColumnType("text"); - - b.Property("SecurityStamp") - .HasColumnType("text"); - - b.Property("UserName") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("AspNetUsers", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("CommunicationLanguage") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(2) - .IsUnicode(false) - .HasColumnType("character(2)") - .HasDefaultValue("en") - .IsFixedLength(); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedByDevice") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("character varying(80)") - .IsFixedLength(false); - - b.HasKey("Id"); - - b.HasIndex("IdentityAddress"); - - b.ToTable("Devices", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => - { - b.Property("Address") - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("character varying(80)") - .IsFixedLength(false); - - b.Property("ClientId") - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletionGracePeriodEndsAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IdentityVersion") - .HasColumnType("smallint"); - - b.Property("PublicKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("Status") - .HasColumnType("integer"); - - b.Property("TierId") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("TierIdBeforeDeletion") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.HasKey("Address"); - - b.HasIndex("ClientId"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("ClientId"), "hash"); - - b.HasIndex("TierId"); - - NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("TierId"), "hash"); - - b.ToTable("Identities", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("ApprovalReminder1SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ApprovalReminder2SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ApprovalReminder3SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ApprovedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ApprovedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("CancelledAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CancelledByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeletionStartedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("GracePeriodEndsAt") - .HasColumnType("timestamp with time zone"); - - b.Property("GracePeriodReminder1SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("GracePeriodReminder2SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("GracePeriodReminder3SentAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("character varying(80)") - .IsFixedLength(false); - - b.Property("RejectedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("RejectedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("Status") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("IdentityAddress"); - - b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") - .IsUnique() - .HasFilter("\"Status\" = 1"); - - b.ToTable("IdentityDeletionProcesses", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("AdditionalData") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceIdHash") - .HasColumnType("bytea"); - - b.Property("IdentityAddressHash") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("IdentityDeletionProcessId") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("MessageKey") - .IsRequired() - .HasColumnType("text"); - - b.Property("NewStatus") - .HasColumnType("integer"); - - b.Property("OldStatus") - .HasColumnType("integer"); - - b.Property("UsernameHashesBase64") - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("IdentityDeletionProcessId"); - - b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("text"); - - b.Property("ApplicationType") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("ClientId") - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("ClientSecret") - .HasColumnType("text"); - - b.Property("ClientType") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("ConsentType") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DefaultTier") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("character(20)") - .IsFixedLength(); - - b.Property("DisplayName") - .HasColumnType("text"); - - b.Property("DisplayNames") - .HasColumnType("text"); - - b.Property("JsonWebKeySet") - .HasColumnType("text"); - - b.Property("MaxIdentities") - .HasColumnType("integer"); - - b.Property("Permissions") - .HasColumnType("text"); - - b.Property("PostLogoutRedirectUris") - .HasColumnType("text"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("RedirectUris") - .HasColumnType("text"); - - b.Property("Requirements") - .HasColumnType("text"); - - b.Property("Settings") - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.HasIndex("DefaultTier"); - - b.ToTable("OpenIddictApplications", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("text"); - - b.Property("ApplicationId") - .HasColumnType("text"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CreationDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("Scopes") - .HasColumnType("text"); - - b.Property("Status") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Subject") - .HasMaxLength(400) - .HasColumnType("character varying(400)"); - - b.Property("Type") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - - b.ToTable("OpenIddictAuthorizations", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("text"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("Descriptions") - .HasColumnType("text"); - - b.Property("DisplayName") - .HasColumnType("text"); - - b.Property("DisplayNames") - .HasColumnType("text"); - - b.Property("Name") - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("Resources") - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("OpenIddictScopes", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("text"); - - b.Property("ApplicationId") - .HasColumnType("text"); - - b.Property("AuthorizationId") - .HasColumnType("text"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CreationDate") - .HasColumnType("timestamp with time zone"); - - b.Property("ExpirationDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Payload") - .HasColumnType("text"); - - b.Property("Properties") - .HasColumnType("text"); - - b.Property("RedemptionDate") - .HasColumnType("timestamp with time zone"); - - b.Property("ReferenceId") - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("Status") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("Subject") - .HasMaxLength(400) - .HasColumnType("character varying(400)"); - - b.Property("Type") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.HasKey("Id"); - - b.HasIndex("AuthorizationId"); - - b.HasIndex("ReferenceId") - .IsUnique(); - - b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - - b.ToTable("OpenIddictTokens", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("text"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("text"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex"); - - b.ToTable("AspNetRoles", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("text"); - - b.Property("ClaimValue") - .HasColumnType("text"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("text"); - - b.Property("ClaimValue") - .HasColumnType("text"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("text"); - - b.Property("ProviderKey") - .HasColumnType("text"); - - b.Property("ProviderDisplayName") - .HasColumnType("text"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("text"); - - b.Property("RoleId") - .HasColumnType("text"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("text"); - - b.Property("LoginProvider") - .HasColumnType("text"); - - b.Property("Name") - .HasColumnType("text"); - - b.Property("Value") - .HasColumnType("text"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") - .WithOne("User") - .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Device"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") - .WithMany("Devices") - .HasForeignKey("IdentityAddress") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Identity"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) - .WithMany("DeletionProcesses") - .HasForeignKey("IdentityAddress") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) - .WithMany("AuditLog") - .HasForeignKey("IdentityDeletionProcessId") - .OnDelete(DeleteBehavior.SetNull); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) - .WithMany() - .HasForeignKey("DefaultTier") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") - .WithMany("Authorizations") - .HasForeignKey("ApplicationId"); - - b.Navigation("Application"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => - { - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") - .WithMany("Tokens") - .HasForeignKey("ApplicationId"); - - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") - .WithMany("Tokens") - .HasForeignKey("AuthorizationId"); - - b.Navigation("Application"); - - b.Navigation("Authorization"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.Navigation("User") - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => - { - b.Navigation("DeletionProcesses"); - - b.Navigation("Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.Navigation("AuditLog"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.Navigation("Authorizations"); - - b.Navigation("Tokens"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.Navigation("Tokens"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs deleted file mode 100644 index a4f33677c5..0000000000 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241125144914_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations -{ - /// - public partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "NewStatus", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "integer", - nullable: true, - oldClrType: typeof(int), - oldType: "integer"); - - migrationBuilder.AddColumn( - name: "UsernameHashesBase64", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "text", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "UsernameHashesBase64", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog"); - - migrationBuilder.AlterColumn( - name: "NewStatus", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "integer", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "integer", - oldNullable: true); - } - } -} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs index 2e3c11670f..c81100d780 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs @@ -396,15 +396,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("integer"); b.Property("OldStatus") .HasColumnType("integer"); - b.Property("UsernameHashesBase64") - .HasColumnType("text"); - b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs deleted file mode 100644 index dc97bd5638..0000000000 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.Designer.cs +++ /dev/null @@ -1,931 +0,0 @@ -// -using System; -using Backbone.Modules.Devices.Infrastructure.Persistence.Database; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations -{ - [DbContext(typeof(DevicesDbContext))] - [Migration("20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry")] - partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("Devices") - .HasAnnotation("ProductVersion", "9.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => - { - b.Property("DeviceId") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("AppId") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DevicePushIdentifier") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("Environment") - .HasColumnType("int"); - - b.Property("Handle") - .IsRequired() - .HasMaxLength(200) - .IsUnicode(true) - .HasColumnType("nvarchar(200)") - .IsFixedLength(false); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("varchar(80)") - .IsFixedLength(false); - - b.Property("UpdatedAt") - .HasColumnType("datetime2"); - - b.HasKey("DeviceId"); - - b.ToTable("PnsRegistrations", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("CanBeManuallyAssigned") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(true); - - b.Property("CanBeUsedAsDefaultForClient") - .ValueGeneratedOnAdd() - .HasColumnType("bit") - .HasDefaultValue(true); - - b.Property("Name") - .IsRequired() - .HasMaxLength(30) - .IsUnicode(true) - .HasColumnType("nvarchar(30)") - .IsFixedLength(false); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("Tiers", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("ExpiresAt") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("Challenges", "Challenges", t => - { - t.ExcludeFromMigrations(); - }); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("LastLoginAt") - .HasColumnType("datetime2"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("UserName") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("CommunicationLanguage") - .IsRequired() - .ValueGeneratedOnAdd() - .HasMaxLength(2) - .IsUnicode(false) - .HasColumnType("char(2)") - .HasDefaultValue("en") - .IsFixedLength(); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedByDevice") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("DeletedAt") - .HasColumnType("datetime2"); - - b.Property("DeletedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("varchar(80)") - .IsFixedLength(false); - - b.HasKey("Id"); - - b.HasIndex("IdentityAddress"); - - b.ToTable("Devices", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => - { - b.Property("Address") - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("varchar(80)") - .IsFixedLength(false); - - b.Property("ClientId") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("DeletionGracePeriodEndsAt") - .HasColumnType("datetime2"); - - b.Property("IdentityVersion") - .HasColumnType("tinyint"); - - b.Property("PublicKey") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TierId") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("TierIdBeforeDeletion") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.HasKey("Address"); - - b.HasIndex("ClientId") - .HasAnnotation("Npgsql:IndexMethod", "hash"); - - b.HasIndex("TierId") - .HasAnnotation("Npgsql:IndexMethod", "hash"); - - b.ToTable("Identities", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("ApprovalReminder1SentAt") - .HasColumnType("datetime2"); - - b.Property("ApprovalReminder2SentAt") - .HasColumnType("datetime2"); - - b.Property("ApprovalReminder3SentAt") - .HasColumnType("datetime2"); - - b.Property("ApprovedAt") - .HasColumnType("datetime2"); - - b.Property("ApprovedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("CancelledAt") - .HasColumnType("datetime2"); - - b.Property("CancelledByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("DeletionStartedAt") - .HasColumnType("datetime2"); - - b.Property("GracePeriodEndsAt") - .HasColumnType("datetime2"); - - b.Property("GracePeriodReminder1SentAt") - .HasColumnType("datetime2"); - - b.Property("GracePeriodReminder2SentAt") - .HasColumnType("datetime2"); - - b.Property("GracePeriodReminder3SentAt") - .HasColumnType("datetime2"); - - b.Property("IdentityAddress") - .IsRequired() - .HasMaxLength(80) - .IsUnicode(false) - .HasColumnType("varchar(80)") - .IsFixedLength(false); - - b.Property("RejectedAt") - .HasColumnType("datetime2"); - - b.Property("RejectedByDevice") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("Status") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("IdentityAddress"); - - b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") - .IsUnique() - .HasFilter("\"Status\" = 1"); - - b.ToTable("IdentityDeletionProcesses", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => - { - b.Property("Id") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("AdditionalData") - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("DeviceIdHash") - .HasColumnType("varbinary(max)"); - - b.Property("IdentityAddressHash") - .IsRequired() - .HasColumnType("varbinary(max)"); - - b.Property("IdentityDeletionProcessId") - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("MessageKey") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NewStatus") - .HasColumnType("int"); - - b.Property("OldStatus") - .HasColumnType("int"); - - b.Property("UsernameHashesBase64") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("IdentityDeletionProcessId"); - - b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("ApplicationType") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ClientId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("ClientSecret") - .HasColumnType("nvarchar(max)"); - - b.Property("ClientType") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("ConsentType") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("DefaultTier") - .IsRequired() - .HasMaxLength(20) - .IsUnicode(false) - .HasColumnType("char(20)") - .IsFixedLength(); - - b.Property("DisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayNames") - .HasColumnType("nvarchar(max)"); - - b.Property("JsonWebKeySet") - .HasColumnType("nvarchar(max)"); - - b.Property("MaxIdentities") - .HasColumnType("int"); - - b.Property("Permissions") - .HasColumnType("nvarchar(max)"); - - b.Property("PostLogoutRedirectUris") - .HasColumnType("nvarchar(max)"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("RedirectUris") - .HasColumnType("nvarchar(max)"); - - b.Property("Requirements") - .HasColumnType("nvarchar(max)"); - - b.Property("Settings") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique() - .HasFilter("[ClientId] IS NOT NULL"); - - b.HasIndex("DefaultTier"); - - b.ToTable("OpenIddictApplications", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("ApplicationId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("CreationDate") - .HasColumnType("datetime2"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Scopes") - .HasColumnType("nvarchar(max)"); - - b.Property("Status") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("Subject") - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.Property("Type") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - - b.ToTable("OpenIddictAuthorizations", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("Descriptions") - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayNames") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("Resources") - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique() - .HasFilter("[Name] IS NOT NULL"); - - b.ToTable("OpenIddictScopes", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("ApplicationId") - .HasColumnType("nvarchar(450)"); - - b.Property("AuthorizationId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyToken") - .IsConcurrencyToken() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("CreationDate") - .HasColumnType("datetime2"); - - b.Property("ExpirationDate") - .HasColumnType("datetime2"); - - b.Property("Payload") - .HasColumnType("nvarchar(max)"); - - b.Property("Properties") - .HasColumnType("nvarchar(max)"); - - b.Property("RedemptionDate") - .HasColumnType("datetime2"); - - b.Property("ReferenceId") - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Status") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("Subject") - .HasMaxLength(400) - .HasColumnType("nvarchar(400)"); - - b.Property("Type") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.HasKey("Id"); - - b.HasIndex("AuthorizationId"); - - b.HasIndex("ReferenceId") - .IsUnique() - .HasFilter("[ReferenceId] IS NOT NULL"); - - b.HasIndex("ApplicationId", "Status", "Subject", "Type"); - - b.ToTable("OpenIddictTokens", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", "Devices"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", "Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") - .WithOne("User") - .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Device"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") - .WithMany("Devices") - .HasForeignKey("IdentityAddress") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Identity"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) - .WithMany("DeletionProcesses") - .HasForeignKey("IdentityAddress") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) - .WithMany("AuditLog") - .HasForeignKey("IdentityDeletionProcessId") - .OnDelete(DeleteBehavior.SetNull); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) - .WithMany() - .HasForeignKey("DefaultTier") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") - .WithMany("Authorizations") - .HasForeignKey("ApplicationId"); - - b.Navigation("Application"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => - { - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") - .WithMany("Tokens") - .HasForeignKey("ApplicationId"); - - b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") - .WithMany("Tokens") - .HasForeignKey("AuthorizationId"); - - b.Navigation("Application"); - - b.Navigation("Authorization"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => - { - b.Navigation("User") - .IsRequired(); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => - { - b.Navigation("DeletionProcesses"); - - b.Navigation("Devices"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => - { - b.Navigation("AuditLog"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => - { - b.Navigation("Authorizations"); - - b.Navigation("Tokens"); - }); - - modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => - { - b.Navigation("Tokens"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs deleted file mode 100644 index f6b01bfc74..0000000000 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241125144912_AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations -{ - /// - public partial class AddUsernameHashesBase64ColumnToIdentityDeletionProcessAuditLogEntry : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "NewStatus", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "int", - nullable: true, - oldClrType: typeof(int), - oldType: "int"); - - migrationBuilder.AddColumn( - name: "UsernameHashesBase64", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "nvarchar(max)", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "UsernameHashesBase64", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog"); - - migrationBuilder.AlterColumn( - name: "NewStatus", - schema: "Devices", - table: "IdentityDeletionProcessAuditLog", - type: "int", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "int", - oldNullable: true); - } - } -} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs index b3a953539e..ac81d9407b 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs @@ -395,15 +395,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("int"); b.Property("OldStatus") .HasColumnType("int"); - b.Property("UsernameHashesBase64") - .HasColumnType("nvarchar(max)"); - b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); From 704c9584798a0858e52ba9cc24f9124ea88ee9ac Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 10:27:08 +0100 Subject: [PATCH 24/30] refactor: use List instead of string as type for UsernameHashesBase64 column --- .../IdentityDeletionProcessAuditLogEntry.cs | 4 +- ..._AddUsernameHashesBase64Column.Designer.cs | 929 +++++++++++++++++ ...128082925_AddUsernameHashesBase64Column.cs | 51 + .../DevicesDbContextModelSnapshot.cs | 6 +- ..._AddUsernameHashesBase64Column.Designer.cs | 931 ++++++++++++++++++ ...128082923_AddUsernameHashesBase64Column.cs | 50 + .../DevicesDbContextModelSnapshot.cs | 5 +- ...entityDeletionProcessAuditLogEntryTests.cs | 2 +- 8 files changed, 1973 insertions(+), 5 deletions(-) create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.Designer.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.Designer.cs create mode 100644 Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.cs diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs index d65108a760..d3476a0d69 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/IdentityDeletionProcessAuditLogEntry.cs @@ -39,7 +39,7 @@ private IdentityDeletionProcessAuditLogEntry(IdentityDeletionProcessId? processI public DeletionProcessStatus? OldStatus { get; } public DeletionProcessStatus? NewStatus { get; } public Dictionary? AdditionalData { get; } - public string? UsernameHashesBase64 { get; private set; } + public List? UsernameHashesBase64 { get; private set; } public static IdentityDeletionProcessAuditLogEntry ProcessStartedByOwner(IdentityDeletionProcessId processId, IdentityAddress identityAddress, DeviceId deviceId) { @@ -229,7 +229,7 @@ public void AssociateUsernames(IEnumerable usernames) UsernameHashesBase64 = usernames .Select(u => Hasher.HashUtf8(u.Value.Trim())) .Select(Convert.ToBase64String) - .Aggregate((result, current) => result + current); + .ToList(); } public static Expression> IsAssociatedToUser(Username username) diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.Designer.cs new file mode 100644 index 0000000000..8cc5ace4da --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.Designer.cs @@ -0,0 +1,929 @@ +// +using System; +using System.Collections.Generic; +using Backbone.Modules.Devices.Infrastructure.Persistence.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations +{ + [DbContext(typeof(DevicesDbContext))] + [Migration("20241128082925_AddUsernameHashesBase64Column")] + partial class AddUsernameHashesBase64Column + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Devices") + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => + { + b.Property("DeviceId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("AppId") + .IsRequired() + .HasColumnType("text"); + + b.Property("DevicePushIdentifier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("Environment") + .HasColumnType("integer"); + + b.Property("Handle") + .IsRequired() + .HasMaxLength(200) + .IsUnicode(true) + .HasColumnType("character varying(200)") + .IsFixedLength(false); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("DeviceId"); + + b.ToTable("PnsRegistrations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CanBeManuallyAssigned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("CanBeUsedAsDefaultForClient") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .IsUnicode(true) + .HasColumnType("character varying(30)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tiers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Challenges", "Challenges", t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("LastLoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("UserName") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CommunicationLanguage") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(2) + .IsUnicode(false) + .HasColumnType("character(2)") + .HasDefaultValue("en") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedByDevice") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.ToTable("Devices", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Property("Address") + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionGracePeriodEndsAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IdentityVersion") + .HasColumnType("smallint"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TierId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("TierIdBeforeDeletion") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.HasKey("Address"); + + b.HasIndex("ClientId"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("ClientId"), "hash"); + + b.HasIndex("TierId"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("TierId"), "hash"); + + b.ToTable("Identities", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("ApprovalReminder1SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovalReminder2SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovalReminder3SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ApprovedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CancelledAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CancelledByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletionStartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodEndsAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder1SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder2SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GracePeriodReminder3SentAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("character varying(80)") + .IsFixedLength(false); + + b.Property("RejectedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("RejectedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("Status") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") + .IsUnique() + .HasFilter("\"Status\" = 1"); + + b.ToTable("IdentityDeletionProcesses", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("AdditionalData") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DeviceIdHash") + .HasColumnType("bytea"); + + b.Property("IdentityAddressHash") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("IdentityDeletionProcessId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("MessageKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("NewStatus") + .HasColumnType("integer"); + + b.Property("OldStatus") + .HasColumnType("integer"); + + b.PrimitiveCollection>("UsernameHashesBase64") + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.HasIndex("IdentityDeletionProcessId"); + + b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ClientSecret") + .HasColumnType("text"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DefaultTier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("character(20)") + .IsFixedLength(); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("JsonWebKeySet") + .HasColumnType("text"); + + b.Property("MaxIdentities") + .HasColumnType("integer"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedirectUris") + .HasColumnType("text"); + + b.Property("Requirements") + .HasColumnType("text"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.HasIndex("DefaultTier"); + + b.ToTable("OpenIddictApplications", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Descriptions") + .HasColumnType("text"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("DisplayNames") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("Resources") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("text"); + + b.Property("AuthorizationId") + .HasColumnType("text"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Payload") + .HasColumnType("text"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") + .WithOne("User") + .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") + .WithMany("Devices") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Identity"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) + .WithMany("DeletionProcesses") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) + .WithMany("AuditLog") + .HasForeignKey("IdentityDeletionProcessId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) + .WithMany() + .HasForeignKey("DefaultTier") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Navigation("User") + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Navigation("DeletionProcesses"); + + b.Navigation("Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Navigation("AuditLog"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.cs new file mode 100644 index 0000000000..bdb6aad9ef --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/20241128082925_AddUsernameHashesBase64Column.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.Postgres.Migrations +{ + /// + public partial class AddUsernameHashesBase64Column : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "integer", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AddColumn>( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "text[]", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog"); + + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "integer", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "integer", + oldNullable: true); + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs index c81100d780..c7b4ff6698 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Migrations/DevicesDbContextModelSnapshot.cs @@ -1,5 +1,6 @@ // using System; +using System.Collections.Generic; using Backbone.Modules.Devices.Infrastructure.Persistence.Database; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -396,12 +397,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("integer"); b.Property("OldStatus") .HasColumnType("integer"); + b.PrimitiveCollection>("UsernameHashesBase64") + .HasColumnType("text[]"); + b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.Designer.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.Designer.cs new file mode 100644 index 0000000000..4b7203f822 --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.Designer.cs @@ -0,0 +1,931 @@ +// +using System; +using Backbone.Modules.Devices.Infrastructure.Persistence.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations +{ + [DbContext(typeof(DevicesDbContext))] + [Migration("20241128082923_AddUsernameHashesBase64Column")] + partial class AddUsernameHashesBase64Column + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("Devices") + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.PushNotifications.PnsRegistration", b => + { + b.Property("DeviceId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("AppId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DevicePushIdentifier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("Environment") + .HasColumnType("int"); + + b.Property("Handle") + .IsRequired() + .HasMaxLength(200) + .IsUnicode(true) + .HasColumnType("nvarchar(200)") + .IsFixedLength(false); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("DeviceId"); + + b.ToTable("PnsRegistrations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CanBeManuallyAssigned") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("CanBeUsedAsDefaultForClient") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .IsUnicode(true) + .HasColumnType("nvarchar(30)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tiers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Challenge", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("ExpiresAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Challenges", "Challenges", t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("LastLoginAt") + .HasColumnType("datetime2"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.HasKey("Id"); + + b.HasIndex("DeviceId") + .IsUnique(); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CommunicationLanguage") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(2) + .IsUnicode(false) + .HasColumnType("char(2)") + .HasDefaultValue("en") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedByDevice") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("DeletedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.ToTable("Devices", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Property("Address") + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletionGracePeriodEndsAt") + .HasColumnType("datetime2"); + + b.Property("IdentityVersion") + .HasColumnType("tinyint"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TierId") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("TierIdBeforeDeletion") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.HasKey("Address"); + + b.HasIndex("ClientId") + .HasAnnotation("Npgsql:IndexMethod", "hash"); + + b.HasIndex("TierId") + .HasAnnotation("Npgsql:IndexMethod", "hash"); + + b.ToTable("Identities", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("ApprovalReminder1SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovalReminder2SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovalReminder3SentAt") + .HasColumnType("datetime2"); + + b.Property("ApprovedAt") + .HasColumnType("datetime2"); + + b.Property("ApprovedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CancelledAt") + .HasColumnType("datetime2"); + + b.Property("CancelledByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeletionStartedAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodEndsAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder1SentAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder2SentAt") + .HasColumnType("datetime2"); + + b.Property("GracePeriodReminder3SentAt") + .HasColumnType("datetime2"); + + b.Property("IdentityAddress") + .IsRequired() + .HasMaxLength(80) + .IsUnicode(false) + .HasColumnType("varchar(80)") + .IsFixedLength(false); + + b.Property("RejectedAt") + .HasColumnType("datetime2"); + + b.Property("RejectedByDevice") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("IdentityAddress"); + + b.HasIndex(new[] { "IdentityAddress" }, "IX_only_one_active_deletion_process") + .IsUnique() + .HasFilter("\"Status\" = 1"); + + b.ToTable("IdentityDeletionProcesses", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.Property("Id") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("AdditionalData") + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DeviceIdHash") + .HasColumnType("varbinary(max)"); + + b.Property("IdentityAddressHash") + .IsRequired() + .HasColumnType("varbinary(max)"); + + b.Property("IdentityDeletionProcessId") + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("MessageKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NewStatus") + .HasColumnType("int"); + + b.Property("OldStatus") + .HasColumnType("int"); + + b.PrimitiveCollection("UsernameHashesBase64") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("IdentityDeletionProcessId"); + + b.ToTable("IdentityDeletionProcessAuditLog", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("DefaultTier") + .IsRequired() + .HasMaxLength(20) + .IsUnicode(false) + .HasColumnType("char(20)") + .IsFixedLength(); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("MaxIdentities") + .HasColumnType("int"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasFilter("[ClientId] IS NOT NULL"); + + b.HasIndex("DefaultTier"); + + b.ToTable("OpenIddictApplications", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique() + .HasFilter("[Name] IS NOT NULL"); + + b.ToTable("OpenIddictScopes", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("ApplicationId") + .HasColumnType("nvarchar(450)"); + + b.Property("AuthorizationId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasFilter("[ReferenceId] IS NOT NULL"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", "Devices"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", "Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Device", "Device") + .WithOne("User") + .HasForeignKey("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", "DeviceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Device"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", "Identity") + .WithMany("Devices") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Identity"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", null) + .WithMany("DeletionProcesses") + .HasForeignKey("IdentityAddress") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcessAuditLogEntry", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", null) + .WithMany("AuditLog") + .HasForeignKey("IdentityDeletionProcessId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Aggregates.Tier.Tier", null) + .WithMany() + .HasForeignKey("DefaultTier") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreToken", b => + { + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Backbone.Modules.Devices.Domain.Entities.Identities.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Device", b => + { + b.Navigation("User") + .IsRequired(); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.Identity", b => + { + b.Navigation("DeletionProcesses"); + + b.Navigation("Devices"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Domain.Entities.Identities.IdentityDeletionProcess", b => + { + b.Navigation("AuditLog"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreApplication", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Backbone.Modules.Devices.Infrastructure.OpenIddict.CustomOpenIddictEntityFrameworkCoreAuthorization", b => + { + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.cs new file mode 100644 index 0000000000..169737415a --- /dev/null +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/20241128082923_AddUsernameHashesBase64Column.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Backbone.Modules.Devices.Infrastructure.Database.SqlServer.Migrations +{ + /// + public partial class AddUsernameHashesBase64Column : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "nvarchar(max)", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UsernameHashesBase64", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog"); + + migrationBuilder.AlterColumn( + name: "NewStatus", + schema: "Devices", + table: "IdentityDeletionProcessAuditLog", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + } + } +} diff --git a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs index ac81d9407b..61f4e9d039 100644 --- a/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs +++ b/Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Migrations/DevicesDbContextModelSnapshot.cs @@ -395,12 +395,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("NewStatus") + b.Property("NewStatus") .HasColumnType("int"); b.Property("OldStatus") .HasColumnType("int"); + b.PrimitiveCollection("UsernameHashesBase64") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("IdentityDeletionProcessId"); diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index 1a6e81346f..bc59833374 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -15,7 +15,7 @@ public void AssociateUsernames_happy_path() auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); // Assert - auditLogEntry.UsernameHashesBase64.Should().Be("jj3azydpiPwK4iFxo/wpCP6pP5Yf5MStnu/hyzMUZ14=FQao/LArcVbFzRs4RgYCU5JycRx9zmJMxY5ApJ0Nk8E="); + auditLogEntry.UsernameHashesBase64.Should().Contain("jj3azydpiPwK4iFxo/wpCP6pP5Yf5MStnu/hyzMUZ14=", "FQao/LArcVbFzRs4RgYCU5JycRx9zmJMxY5ApJ0Nk8E="); } [Fact] From 872ee33642d55846703392b441dc0eac7077c345 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 10:37:51 +0100 Subject: [PATCH 25/30] test: test for length of UsernameHashesBase64 --- .../Identities/IdentityDeletionProcessAuditLogEntryTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs index bc59833374..3afe98a1b2 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IdentityDeletionProcessAuditLogEntryTests.cs @@ -15,6 +15,7 @@ public void AssociateUsernames_happy_path() auditLogEntry.AssociateUsernames([Username.Parse("USR1111111111111111"), Username.Parse("USR2222222222222222")]); // Assert + auditLogEntry.UsernameHashesBase64.Should().HaveCount(2); auditLogEntry.UsernameHashesBase64.Should().Contain("jj3azydpiPwK4iFxo/wpCP6pP5Yf5MStnu/hyzMUZ14=", "FQao/LArcVbFzRs4RgYCU5JycRx9zmJMxY5ApJ0Nk8E="); } From c968c1e63ed15685459bc631e0597258870fb30f Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 13:59:14 +0100 Subject: [PATCH 26/30] test: check what happens if we remove all calls to Hasher.SetHasher --- .../DeletionGracePeriodReminderTests.cs | 282 +++++++++--------- .../DeletionProcessApprovalReminderTests.cs | 278 ++++++++--------- .../DeletionProcessGracePeriodTests.cs | 260 ++++++++-------- .../Identities/RejectDeletionProcessTests.cs | 214 ++++++------- .../StartDeletionProcessAsOwnerTests.cs | 270 ++++++++--------- .../StartDeletionProcessAsSupportTests.cs | 188 ++++++------ 6 files changed, 752 insertions(+), 740 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs index dc5ff06243..819b19b13d 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs @@ -1,142 +1,144 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionGracePeriodReminderTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder2Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// private static Identity CreateIdentityWithApprovedDeletionProcess() +// { +// var identity = CreateIdentity(); +// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); +// identity.Devices.Add(device); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// identity.StartDeletionProcessAsOwner(device.Id); +// +// return identity; +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionGracePeriodReminderTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder2Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - private static Identity CreateIdentityWithApprovedDeletionProcess() - { - var identity = CreateIdentity(); - var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); - identity.Devices.Add(device); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - identity.StartDeletionProcessAsOwner(device.Id); - - return identity; - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs index f3d3213049..dd8a846720 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs @@ -1,140 +1,142 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionProcessApprovalReminderTests : AbstractTestsBase +// { +// [Fact] +// public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder2Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// } +// +// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() +// { +// var identity = CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsSupport(); +// +// return identity; +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// +// [Fact] +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionProcessApprovalReminderTests : AbstractTestsBase -{ - [Fact] - public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder2Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - } - - private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() - { - var identity = CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsSupport(); - - return identity; - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } - - [Fact] - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs index 0719bd71c5..44e9fd27fd 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs @@ -1,131 +1,133 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionProcessGracePeriodTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder2Sent; +// +// // Asserterror +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// private static Identity CreateIdentityWithApprovedDeletionProcess() +// { +// var identity = TestDataGenerator.CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); +// +// return identity; +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionProcessGracePeriodTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder2Sent; - - // Asserterror - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - private static Identity CreateIdentityWithApprovedDeletionProcess() - { - var identity = TestDataGenerator.CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); - - return identity; - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs index f20e681f06..52a5415e44 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs @@ -1,108 +1,110 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class RejectDeletionProcessTests : AbstractTestsBase +// { +// [Fact] +// public void Reject_deletion_process_waiting_for_approval() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2020-01-01")); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// +// // Act +// identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// } +// +// [Fact] +// public void Throws_when_device_not_owned_by_identity() +// { +// // Arrange +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("Device"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_does_not_exist() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; +// +// // Act +// var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("IdentityDeletionProcess"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); +// +// // Act +// var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// exception.Message.Should().Contain("WaitingForApproval"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// +// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() +// { +// var identity = CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsSupport(); +// return identity; +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class RejectDeletionProcessTests : AbstractTestsBase -{ - [Fact] - public void Reject_deletion_process_waiting_for_approval() - { - // Arrange - SystemTime.Set(DateTime.Parse("2020-01-01")); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - - // Act - identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; - AssertAuditLogEntryWasCreated(deletionProcess); - } - - [Fact] - public void Throws_when_device_not_owned_by_identity() - { - // Arrange - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("Device"); - } - - [Fact] - public void Throws_when_deletion_process_does_not_exist() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; - - // Act - var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("IdentityDeletionProcess"); - } - - [Fact] - public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); - - // Act - var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - exception.Message.Should().Contain("WaitingForApproval"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } - - private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() - { - var identity = CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsSupport(); - return identity; - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs index 55076cc41a..d038fb9397 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs @@ -1,136 +1,138 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class StartDeletionProcessAsOwnerTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void Start_deletion_process() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var activeIdentity = CreateIdentity(); +// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); +// activeIdentity.Devices.Add(activeDevice); +// +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// // Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Assert +// activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); +// activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); +// activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); +// +// AssertDeletionProcessWasStarted(activeIdentity); +// deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); +// deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); +// deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); +// deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); +// +// AssertAuditLogEntryWasCreated(deletionProcess); +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); +// auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// [Fact] +// public void Throws_when_device_not_owned_by_identity() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2020-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); +// +// identity.Devices.Add(device); +// +// // Act +// var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("Device"); +// } +// +// [Fact] +// public void Only_one_active_deletion_process_is_allowed_when_started() +// { +// // Arrange +// var activeIdentity = CreateIdentity(); +// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); +// activeIdentity.Devices.Add(activeDevice); +// +// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Act +// var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); +// } +// +// [Fact] +// public void Raises_domain_events() +// { +// //Arrange +// var activeIdentity = TestDataGenerator.CreateIdentity(); +// var tierBeforeDeletion = activeIdentity.TierId; +// var activeDevice = activeIdentity.Devices[0]; +// +// //Act +// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// //Assert +// var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); +// +// tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); +// tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); +// +// identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// } +// +// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) +// { +// activeIdentity.DeletionProcesses.Should().HaveCount(1); +// var deletionProcess = activeIdentity.DeletionProcesses[0]; +// deletionProcess.Should().NotBeNull(); +// +// deletionProcess.Id.Should().NotBeNull(); +// deletionProcess.Id.Value.Should().HaveLength(20); +// +// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); +// +// deletionProcess.AuditLog.Should().HaveCount(1); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().BeNull(); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class StartDeletionProcessAsOwnerTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void Start_deletion_process() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var activeIdentity = CreateIdentity(); - var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); - activeIdentity.Devices.Add(activeDevice); - - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - // Act - var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Assert - activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); - activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); - activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); - - AssertDeletionProcessWasStarted(activeIdentity); - deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); - deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); - deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); - deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); - - AssertAuditLogEntryWasCreated(deletionProcess); - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); - auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - [Fact] - public void Throws_when_device_not_owned_by_identity() - { - // Arrange - SystemTime.Set(DateTime.Parse("2020-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); - - identity.Devices.Add(device); - - // Act - var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); - - // Assert - var exception = acting.Should().Throw().Which; - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("Device"); - } - - [Fact] - public void Only_one_active_deletion_process_is_allowed_when_started() - { - // Arrange - var activeIdentity = CreateIdentity(); - var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); - activeIdentity.Devices.Add(activeDevice); - - activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Act - var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); - } - - [Fact] - public void Raises_domain_events() - { - //Arrange - var activeIdentity = TestDataGenerator.CreateIdentity(); - var tierBeforeDeletion = activeIdentity.TierId; - var activeDevice = activeIdentity.Devices[0]; - - //Act - activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - //Assert - var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); - - tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); - tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); - - identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - } - - private static void AssertDeletionProcessWasStarted(Identity activeIdentity) - { - activeIdentity.DeletionProcesses.Should().HaveCount(1); - var deletionProcess = activeIdentity.DeletionProcesses[0]; - deletionProcess.Should().NotBeNull(); - - deletionProcess.Id.Should().NotBeNull(); - deletionProcess.Id.Value.Should().HaveLength(20); - - deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); - - deletionProcess.AuditLog.Should().HaveCount(1); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().BeNull(); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs index 4a4aa40a4d..ba647f4bdc 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs @@ -1,95 +1,97 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class StartDeletionProcessAsSupportTests : AbstractTestsBase +// { +// [Fact] +// public void Start_deletion_process() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var activeIdentity = CreateIdentity(); +// +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// // Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); +// +// // Assert +// AssertDeletionProcessWasStarted(activeIdentity); +// deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); +// +// AssertAuditLogEntryWasCreated(deletionProcess); +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); +// auditLogEntry.DeviceIdHash.Should().BeNull(); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// } +// +// [Fact] +// public void Only_one_active_deletion_process_is_allowed_when_started() +// { +// // Arrange +// var activeIdentity = CreateIdentity(); +// +// activeIdentity.StartDeletionProcessAsSupport(); +// +// // Act +// var acting = activeIdentity.StartDeletionProcessAsSupport; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); +// } +// +// [Fact] +// public void Raises_IdentityDeletionProcessStartedDomainEvent() +// { +// //Arrange +// var activeIdentity = CreateIdentity(); +// +// //Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); +// +// //Assert +// var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); +// domainEvent.Address.Should().Be(activeIdentity.Address); +// domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); +// domainEvent.Initiator.Should().Be(null); +// } +// +// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) +// { +// activeIdentity.DeletionProcesses.Should().HaveCount(1); +// var deletionProcess = activeIdentity.DeletionProcesses[0]; +// deletionProcess.Should().NotBeNull(); +// +// deletionProcess.Id.Should().NotBeNull(); +// deletionProcess.Id.Value.Should().HaveLength(20); +// +// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); +// +// deletionProcess.AuditLog.Should().HaveCount(1); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().BeNull(); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class StartDeletionProcessAsSupportTests : AbstractTestsBase -{ - [Fact] - public void Start_deletion_process() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var activeIdentity = CreateIdentity(); - - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - // Act - var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); - - // Assert - AssertDeletionProcessWasStarted(activeIdentity); - deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); - - AssertAuditLogEntryWasCreated(deletionProcess); - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); - auditLogEntry.DeviceIdHash.Should().BeNull(); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - } - - [Fact] - public void Only_one_active_deletion_process_is_allowed_when_started() - { - // Arrange - var activeIdentity = CreateIdentity(); - - activeIdentity.StartDeletionProcessAsSupport(); - - // Act - var acting = activeIdentity.StartDeletionProcessAsSupport; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); - } - - [Fact] - public void Raises_IdentityDeletionProcessStartedDomainEvent() - { - //Arrange - var activeIdentity = CreateIdentity(); - - //Act - var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); - - //Assert - var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); - domainEvent.Address.Should().Be(activeIdentity.Address); - domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); - domainEvent.Initiator.Should().Be(null); - } - - private static void AssertDeletionProcessWasStarted(Identity activeIdentity) - { - activeIdentity.DeletionProcesses.Should().HaveCount(1); - var deletionProcess = activeIdentity.DeletionProcesses[0]; - deletionProcess.Should().NotBeNull(); - - deletionProcess.Id.Should().NotBeNull(); - deletionProcess.Id.Value.Should().HaveLength(20); - - deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); - - deletionProcess.AuditLog.Should().HaveCount(1); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().BeNull(); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} From d3e03f99a1288527917f36f19d76ae2981ce5c71 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Thu, 28 Nov 2024 13:59:14 +0100 Subject: [PATCH 27/30] test: check what happens if we remove all calls to Hasher.SetHasher --- .../Identities/ApproveDeletionProcessTests.cs | 260 ++++++++-------- .../DeletionGracePeriodReminderTests.cs | 282 +++++++++--------- .../DeletionProcessApprovalReminderTests.cs | 278 ++++++++--------- .../DeletionProcessGracePeriodTests.cs | 260 ++++++++-------- .../Identities/RejectDeletionProcessTests.cs | 214 ++++++------- .../StartDeletionProcessAsOwnerTests.cs | 270 ++++++++--------- .../StartDeletionProcessAsSupportTests.cs | 188 ++++++------ 7 files changed, 883 insertions(+), 869 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs index 78f9a1c942..442dea73e9 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs @@ -1,131 +1,133 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class ApproveDeletionProcessTests : AbstractTestsBase +// { +// [Fact] +// public void Approve_deletion_process_waiting_for_approval() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// +// // Act +// identity.ApproveDeletionProcess(identity.GetDeletionProcessInStatus(DeletionProcessStatus.WaitingForApproval)!.Id, deviceId); +// +// // Assert +// identity.Status.Should().Be(IdentityStatus.ToBeDeleted); +// identity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); +// identity.TierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// } +// +// [Fact] +// public void Throws_when_device_not_owned_by_identity() +// { +// // Arrange +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// var acting = () => identity.ApproveDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); +// var exception = acting.Should().Throw().Which; +// +// // Assert +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("Device"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_does_not_exist() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; +// +// // Act +// var acting = () => identity.ApproveDeletionProcess(deletionProcessId, deviceId); +// var exception = acting.Should().Throw().Which; +// +// // Assert +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("IdentityDeletionProcess"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); +// +// // Act +// var acting = () => identity.ApproveDeletionProcess(deletionProcess.Id, deviceId); +// var exception = acting.Should().Throw().Which; +// +// // Assert +// exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// exception.Message.Should().Contain("WaitingForApproval"); +// } +// +// [Fact] +// public void Raises_domain_events() +// { +// //Arrange +// var activeIdentity = TestDataGenerator.CreateIdentity(); +// var activeDevice = activeIdentity.Devices[0]; +// var tierBeforeDeletion = activeIdentity.TierId; +// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); +// +// //Act +// activeIdentity.ApproveDeletionProcess(deletionProcess.Id, activeDevice.Id); +// +// //Assert +// var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); +// +// tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); +// tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); +// +// identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// +// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() +// { +// var identity = CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsSupport(); +// return identity; +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class ApproveDeletionProcessTests : AbstractTestsBase -{ - [Fact] - public void Approve_deletion_process_waiting_for_approval() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - - // Act - identity.ApproveDeletionProcess(identity.GetDeletionProcessInStatus(DeletionProcessStatus.WaitingForApproval)!.Id, deviceId); - - // Assert - identity.Status.Should().Be(IdentityStatus.ToBeDeleted); - identity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); - identity.TierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - } - - [Fact] - public void Throws_when_device_not_owned_by_identity() - { - // Arrange - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - var acting = () => identity.ApproveDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); - var exception = acting.Should().Throw().Which; - - // Assert - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("Device"); - } - - [Fact] - public void Throws_when_deletion_process_does_not_exist() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; - - // Act - var acting = () => identity.ApproveDeletionProcess(deletionProcessId, deviceId); - var exception = acting.Should().Throw().Which; - - // Assert - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("IdentityDeletionProcess"); - } - - [Fact] - public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); - - // Act - var acting = () => identity.ApproveDeletionProcess(deletionProcess.Id, deviceId); - var exception = acting.Should().Throw().Which; - - // Assert - exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - exception.Message.Should().Contain("WaitingForApproval"); - } - - [Fact] - public void Raises_domain_events() - { - //Arrange - var activeIdentity = TestDataGenerator.CreateIdentity(); - var activeDevice = activeIdentity.Devices[0]; - var tierBeforeDeletion = activeIdentity.TierId; - var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); - - //Act - activeIdentity.ApproveDeletionProcess(deletionProcess.Id, activeDevice.Id); - - //Assert - var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); - - tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); - tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); - - identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } - - private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() - { - var identity = CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsSupport(); - return identity; - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs index dc5ff06243..819b19b13d 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs @@ -1,142 +1,144 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionGracePeriodReminderTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder2Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// private static Identity CreateIdentityWithApprovedDeletionProcess() +// { +// var identity = CreateIdentity(); +// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); +// identity.Devices.Add(device); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// identity.StartDeletionProcessAsOwner(device.Id); +// +// return identity; +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionGracePeriodReminderTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder2Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - private static Identity CreateIdentityWithApprovedDeletionProcess() - { - var identity = CreateIdentity(); - var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); - identity.Devices.Add(device); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - identity.StartDeletionProcessAsOwner(device.Id); - - return identity; - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs index f3d3213049..dd8a846720 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs @@ -1,140 +1,142 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionProcessApprovalReminderTests : AbstractTestsBase +// { +// [Fact] +// public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder2Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// identity.DeletionProcessApprovalReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = CreateIdentity(); +// +// // Act +// var acting = identity.DeletionProcessApprovalReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// } +// +// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() +// { +// var identity = CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsSupport(); +// +// return identity; +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// +// [Fact] +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionProcessApprovalReminderTests : AbstractTestsBase -{ - [Fact] - public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder2Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - identity.DeletionProcessApprovalReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = CreateIdentity(); - - // Act - var acting = identity.DeletionProcessApprovalReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - } - - private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() - { - var identity = CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsSupport(); - - return identity; - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } - - [Fact] - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs index 0719bd71c5..44e9fd27fd 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs @@ -1,131 +1,133 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class DeletionProcessGracePeriodTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder1Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder1Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder2Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder2Sent; +// +// // Asserterror +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() +// { +// // Arrange +// var currentDateTime = DateTime.Parse("2000-01-01"); +// SystemTime.Set(currentDateTime); +// var identity = CreateIdentityWithApprovedDeletionProcess(); +// +// // Act +// identity.DeletionGracePeriodReminder3Sent(); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); +// } +// +// +// [Fact] +// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// +// // Act +// var acting = identity.DeletionGracePeriodReminder3Sent; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// private static Identity CreateIdentityWithApprovedDeletionProcess() +// { +// var identity = TestDataGenerator.CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); +// +// return identity; +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class DeletionProcessGracePeriodTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder1Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); - } - - [Fact] - public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder1Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder2Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder2Sent; - - // Asserterror - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - [Fact] - public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() - { - // Arrange - var currentDateTime = DateTime.Parse("2000-01-01"); - SystemTime.Set(currentDateTime); - var identity = CreateIdentityWithApprovedDeletionProcess(); - - // Act - identity.DeletionGracePeriodReminder3Sent(); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; - AssertAuditLogEntryWasCreated(deletionProcess); - deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); - } - - - [Fact] - public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - - // Act - var acting = identity.DeletionGracePeriodReminder3Sent; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - private static Identity CreateIdentityWithApprovedDeletionProcess() - { - var identity = TestDataGenerator.CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); - - return identity; - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs index f20e681f06..52a5415e44 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs @@ -1,108 +1,110 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class RejectDeletionProcessTests : AbstractTestsBase +// { +// [Fact] +// public void Reject_deletion_process_waiting_for_approval() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2020-01-01")); +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// +// // Act +// identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); +// +// // Assert +// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; +// AssertAuditLogEntryWasCreated(deletionProcess); +// } +// +// [Fact] +// public void Throws_when_device_not_owned_by_identity() +// { +// // Arrange +// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); +// +// // Act +// var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("Device"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_does_not_exist() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; +// +// // Act +// var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("IdentityDeletionProcess"); +// } +// +// [Fact] +// public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() +// { +// // Arrange +// var identity = CreateIdentity(); +// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); +// var deviceId = identity.Devices[0].Id; +// var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); +// +// // Act +// var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// +// exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); +// exception.Message.Should().Contain("WaitingForApproval"); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// deletionProcess.AuditLog.Should().HaveCount(2); +// +// var auditLogEntry = deletionProcess.AuditLog[1]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// +// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() +// { +// var identity = CreateIdentity(); +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// identity.StartDeletionProcessAsSupport(); +// return identity; +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class RejectDeletionProcessTests : AbstractTestsBase -{ - [Fact] - public void Reject_deletion_process_waiting_for_approval() - { - // Arrange - SystemTime.Set(DateTime.Parse("2020-01-01")); - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - - // Act - identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); - - // Assert - var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; - AssertAuditLogEntryWasCreated(deletionProcess); - } - - [Fact] - public void Throws_when_device_not_owned_by_identity() - { - // Arrange - var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); - - // Act - var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("Device"); - } - - [Fact] - public void Throws_when_deletion_process_does_not_exist() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; - - // Act - var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("IdentityDeletionProcess"); - } - - [Fact] - public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() - { - // Arrange - var identity = CreateIdentity(); - identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); - var deviceId = identity.Devices[0].Id; - var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); - - // Act - var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); - - // Assert - var exception = acting.Should().Throw().Which; - - exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); - exception.Message.Should().Contain("WaitingForApproval"); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - deletionProcess.AuditLog.Should().HaveCount(2); - - var auditLogEntry = deletionProcess.AuditLog[1]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } - - private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() - { - var identity = CreateIdentity(); - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - identity.StartDeletionProcessAsSupport(); - return identity; - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs index 55076cc41a..d038fb9397 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs @@ -1,136 +1,138 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class StartDeletionProcessAsOwnerTests : AbstractTestsBase +// { +// public override void Dispose() +// { +// Hasher.Reset(); +// base.Dispose(); +// } +// +// [Fact] +// public void Start_deletion_process() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var activeIdentity = CreateIdentity(); +// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); +// activeIdentity.Devices.Add(activeDevice); +// +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// // Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Assert +// activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); +// activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); +// activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); +// +// AssertDeletionProcessWasStarted(activeIdentity); +// deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); +// deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); +// deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); +// deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); +// +// AssertAuditLogEntryWasCreated(deletionProcess); +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); +// auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); +// } +// +// [Fact] +// public void Throws_when_device_not_owned_by_identity() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2020-01-01")); +// var identity = TestDataGenerator.CreateIdentity(); +// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); +// +// identity.Devices.Add(device); +// +// // Act +// var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); +// +// // Assert +// var exception = acting.Should().Throw().Which; +// exception.Code.Should().Be("error.platform.recordNotFound"); +// exception.Message.Should().Contain("Device"); +// } +// +// [Fact] +// public void Only_one_active_deletion_process_is_allowed_when_started() +// { +// // Arrange +// var activeIdentity = CreateIdentity(); +// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); +// activeIdentity.Devices.Add(activeDevice); +// +// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Act +// var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); +// } +// +// [Fact] +// public void Raises_domain_events() +// { +// //Arrange +// var activeIdentity = TestDataGenerator.CreateIdentity(); +// var tierBeforeDeletion = activeIdentity.TierId; +// var activeDevice = activeIdentity.Devices[0]; +// +// //Act +// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); +// +// //Assert +// var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); +// +// tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); +// tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); +// +// identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); +// } +// +// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) +// { +// activeIdentity.DeletionProcesses.Should().HaveCount(1); +// var deletionProcess = activeIdentity.DeletionProcesses[0]; +// deletionProcess.Should().NotBeNull(); +// +// deletionProcess.Id.Should().NotBeNull(); +// deletionProcess.Id.Value.Should().HaveLength(20); +// +// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); +// +// deletionProcess.AuditLog.Should().HaveCount(1); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().BeNull(); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class StartDeletionProcessAsOwnerTests : AbstractTestsBase -{ - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - - [Fact] - public void Start_deletion_process() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var activeIdentity = CreateIdentity(); - var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); - activeIdentity.Devices.Add(activeDevice); - - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - // Act - var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Assert - activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); - activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); - activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); - - AssertDeletionProcessWasStarted(activeIdentity); - deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); - deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); - deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); - deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); - - AssertAuditLogEntryWasCreated(deletionProcess); - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); - auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); - } - - [Fact] - public void Throws_when_device_not_owned_by_identity() - { - // Arrange - SystemTime.Set(DateTime.Parse("2020-01-01")); - var identity = TestDataGenerator.CreateIdentity(); - var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); - - identity.Devices.Add(device); - - // Act - var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); - - // Assert - var exception = acting.Should().Throw().Which; - exception.Code.Should().Be("error.platform.recordNotFound"); - exception.Message.Should().Contain("Device"); - } - - [Fact] - public void Only_one_active_deletion_process_is_allowed_when_started() - { - // Arrange - var activeIdentity = CreateIdentity(); - var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); - activeIdentity.Devices.Add(activeDevice); - - activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Act - var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); - } - - [Fact] - public void Raises_domain_events() - { - //Arrange - var activeIdentity = TestDataGenerator.CreateIdentity(); - var tierBeforeDeletion = activeIdentity.TierId; - var activeDevice = activeIdentity.Devices[0]; - - //Act - activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); - - //Assert - var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); - - tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); - tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); - - identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); - } - - private static void AssertDeletionProcessWasStarted(Identity activeIdentity) - { - activeIdentity.DeletionProcesses.Should().HaveCount(1); - var deletionProcess = activeIdentity.DeletionProcesses[0]; - deletionProcess.Should().NotBeNull(); - - deletionProcess.Id.Should().NotBeNull(); - deletionProcess.Id.Value.Should().HaveLength(20); - - deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); - - deletionProcess.AuditLog.Should().HaveCount(1); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().BeNull(); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs index 4a4aa40a4d..ba647f4bdc 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs @@ -1,95 +1,97 @@ -using Backbone.BuildingBlocks.Domain.Exceptions; -using Backbone.DevelopmentKit.Identity.ValueObjects; -using Backbone.Modules.Devices.Domain.Aggregates.Tier; -using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -using Backbone.Modules.Devices.Domain.Entities.Identities; -using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -using Backbone.Tooling; +// using Backbone.BuildingBlocks.Domain.Exceptions; +// using Backbone.DevelopmentKit.Identity.ValueObjects; +// using Backbone.Modules.Devices.Domain.Aggregates.Tier; +// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +// using Backbone.Modules.Devices.Domain.Entities.Identities; +// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +// using Backbone.Tooling; +// +// namespace Backbone.Modules.Devices.Domain.Tests.Identities; +// +// public class StartDeletionProcessAsSupportTests : AbstractTestsBase +// { +// [Fact] +// public void Start_deletion_process() +// { +// // Arrange +// SystemTime.Set(DateTime.Parse("2000-01-01")); +// var activeIdentity = CreateIdentity(); +// +// Hasher.SetHasher(new DummyHasher([1, 2, 3])); +// +// // Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); +// +// // Assert +// AssertDeletionProcessWasStarted(activeIdentity); +// deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); +// +// AssertAuditLogEntryWasCreated(deletionProcess); +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); +// auditLogEntry.DeviceIdHash.Should().BeNull(); +// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); +// } +// +// [Fact] +// public void Only_one_active_deletion_process_is_allowed_when_started() +// { +// // Arrange +// var activeIdentity = CreateIdentity(); +// +// activeIdentity.StartDeletionProcessAsSupport(); +// +// // Act +// var acting = activeIdentity.StartDeletionProcessAsSupport; +// +// // Assert +// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); +// } +// +// [Fact] +// public void Raises_IdentityDeletionProcessStartedDomainEvent() +// { +// //Arrange +// var activeIdentity = CreateIdentity(); +// +// //Act +// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); +// +// //Assert +// var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); +// domainEvent.Address.Should().Be(activeIdentity.Address); +// domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); +// domainEvent.Initiator.Should().Be(null); +// } +// +// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) +// { +// activeIdentity.DeletionProcesses.Should().HaveCount(1); +// var deletionProcess = activeIdentity.DeletionProcesses[0]; +// deletionProcess.Should().NotBeNull(); +// +// deletionProcess.Id.Should().NotBeNull(); +// deletionProcess.Id.Value.Should().HaveLength(20); +// +// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); +// +// deletionProcess.AuditLog.Should().HaveCount(1); +// } +// +// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) +// { +// var auditLogEntry = deletionProcess.AuditLog[0]; +// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); +// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); +// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); +// auditLogEntry.OldStatus.Should().BeNull(); +// } +// +// private static Identity CreateIdentity() +// { +// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); +// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); +// } +// } -namespace Backbone.Modules.Devices.Domain.Tests.Identities; -public class StartDeletionProcessAsSupportTests : AbstractTestsBase -{ - [Fact] - public void Start_deletion_process() - { - // Arrange - SystemTime.Set(DateTime.Parse("2000-01-01")); - var activeIdentity = CreateIdentity(); - - Hasher.SetHasher(new DummyHasher([1, 2, 3])); - - // Act - var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); - - // Assert - AssertDeletionProcessWasStarted(activeIdentity); - deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); - - AssertAuditLogEntryWasCreated(deletionProcess); - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); - auditLogEntry.DeviceIdHash.Should().BeNull(); - auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); - } - - [Fact] - public void Only_one_active_deletion_process_is_allowed_when_started() - { - // Arrange - var activeIdentity = CreateIdentity(); - - activeIdentity.StartDeletionProcessAsSupport(); - - // Act - var acting = activeIdentity.StartDeletionProcessAsSupport; - - // Assert - acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); - } - - [Fact] - public void Raises_IdentityDeletionProcessStartedDomainEvent() - { - //Arrange - var activeIdentity = CreateIdentity(); - - //Act - var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); - - //Assert - var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); - domainEvent.Address.Should().Be(activeIdentity.Address); - domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); - domainEvent.Initiator.Should().Be(null); - } - - private static void AssertDeletionProcessWasStarted(Identity activeIdentity) - { - activeIdentity.DeletionProcesses.Should().HaveCount(1); - var deletionProcess = activeIdentity.DeletionProcesses[0]; - deletionProcess.Should().NotBeNull(); - - deletionProcess.Id.Should().NotBeNull(); - deletionProcess.Id.Value.Should().HaveLength(20); - - deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); - - deletionProcess.AuditLog.Should().HaveCount(1); - } - - private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) - { - var auditLogEntry = deletionProcess.AuditLog[0]; - auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); - auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); - auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); - auditLogEntry.OldStatus.Should().BeNull(); - } - - private static Identity CreateIdentity() - { - var address = IdentityAddress.Create([], "prod.enmeshed.eu"); - return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); - } -} From 3cf7b0ce26c6505f86f6bb04de9ef13b3722c12f Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Mon, 2 Dec 2024 11:18:55 +0100 Subject: [PATCH 28/30] feat: IsDeleted returns true if grace period is over but identity is not deleted yet --- .../IsIdentityOfUserDeleted/Handler.cs | 5 +++ .../Repository/IIdentitiesRepository.cs | 1 + .../Entities/Identities/Identity.cs | 31 ++++++++++------ .../Repository/IdentitiesRepository.cs | 8 +++++ .../Identities/IsGracePeriodOverTests.cs | 35 +++++++++++++++++++ 5 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 Modules/Devices/test/Devices.Domain.Tests/Identities/IsGracePeriodOverTests.cs diff --git a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs index 0ec044d706..1b667b4b19 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Queries/IsIdentityOfUserDeleted/Handler.cs @@ -16,6 +16,11 @@ public Handler(IIdentitiesRepository identitiesRepository) public async Task Handle(IsIdentityOfUserDeletedQuery request, CancellationToken cancellationToken) { + var identity = await _identitiesRepository.FindSingle(Identity.HasUser(request.Username), cancellationToken); + + if (identity.IsGracePeriodOver) + return new IsIdentityOfUserDeletedResponse(true, identity.DeletionGracePeriodEndsAt); + var auditLogEntries = await _identitiesRepository.GetIdentityDeletionProcessAuditLogs( IdentityDeletionProcessAuditLogEntry.IsAssociatedToUser(Username.Parse(request.Username)), cancellationToken); diff --git a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs index eaf5e14ce5..98001dc17b 100644 --- a/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Application/Infrastructure/Persistence/Repository/IIdentitiesRepository.cs @@ -16,6 +16,7 @@ public interface IIdentitiesRepository Task> FindAllWithDeletionProcessInStatus(DeletionProcessStatus status, CancellationToken cancellationToken, bool track = false); Task CountByClientId(string clientId, CancellationToken cancellationToken); Task> Find(Expression> filter, CancellationToken cancellationToken, bool track = false); + Task FindSingle(Expression> filter, CancellationToken cancellationToken, bool track = false); Task Delete(Expression> filter, CancellationToken cancellationToken); Task Add(Identity identity, string password); diff --git a/Modules/Devices/src/Devices.Domain/Entities/Identities/Identity.cs b/Modules/Devices/src/Devices.Domain/Entities/Identities/Identity.cs index f60a8e6ce6..1f3fdd29aa 100644 --- a/Modules/Devices/src/Devices.Domain/Entities/Identities/Identity.cs +++ b/Modules/Devices/src/Devices.Domain/Entities/Identities/Identity.cs @@ -95,6 +95,8 @@ private set public IdentityStatus Status { get; private set; } + public bool IsGracePeriodOver => DeletionGracePeriodEndsAt != null && DeletionGracePeriodEndsAt < SystemTime.UtcNow; + public bool IsNew() { return Devices.Count < 1; @@ -278,16 +280,6 @@ public void DeletionGracePeriodReminder3Sent() return DeletionProcesses.FirstOrDefault(x => x.Status == deletionProcessStatus); } - public static Expression> HasAddress(IdentityAddress address) - { - return i => i.Address == address.ToString(); - } - - public static Expression> IsReadyForDeletion() - { - return i => i.Status == IdentityStatus.ToBeDeleted && i.DeletionGracePeriodEndsAt != null && i.DeletionGracePeriodEndsAt < SystemTime.UtcNow; - } - public IdentityDeletionProcess CancelDeletionProcessAsOwner(IdentityDeletionProcessId deletionProcessId, DeviceId cancelledByDeviceId) { EnsureIdentityOwnsDevice(cancelledByDeviceId); @@ -329,6 +321,25 @@ public static Identity CreateTestIdentity(IdentityAddress address, byte[] public { return new Identity("test", address, publicKey, tierId, 1, CommunicationLanguage.DEFAULT_LANGUAGE, username); } + + #region Expressions + + public static Expression> HasAddress(IdentityAddress address) + { + return i => i.Address == address.ToString(); + } + + public static Expression> IsReadyForDeletion() + { + return i => i.Status == IdentityStatus.ToBeDeleted && i.DeletionGracePeriodEndsAt != null && i.DeletionGracePeriodEndsAt < SystemTime.UtcNow; + } + + public static Expression> HasUser(string username) + { + return i => i.Devices.Any(d => d.User.UserName == username); + } + + #endregion } public enum DeletionProcessStatus diff --git a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs index b82273a943..bbb6c7e4ba 100644 --- a/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs +++ b/Modules/Devices/src/Devices.Infrastructure/Persistence/Repository/IdentitiesRepository.cs @@ -154,6 +154,14 @@ public async Task> Find(Expression> f .ToListAsync(cancellationToken); } + public async Task FindSingle(Expression> filter, CancellationToken cancellationToken, bool track = false) + { + return await (track ? _identities : _readonlyIdentities) + .IncludeAll(_dbContext) + .Where(filter) + .SingleAsync(cancellationToken); + } + public async Task Delete(Expression> filter, CancellationToken cancellationToken) { await _identities.Where(filter).ExecuteDeleteAsync(cancellationToken); diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/IsGracePeriodOverTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/IsGracePeriodOverTests.cs new file mode 100644 index 0000000000..214652bddd --- /dev/null +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/IsGracePeriodOverTests.cs @@ -0,0 +1,35 @@ +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Tooling; + +namespace Backbone.Modules.Devices.Domain.Tests.Identities; + +public class IsGracePeriodOverTests : AbstractTestsBase +{ + [Fact] + public void Returns_false_if_grace_period_is_not_over() + { + // Arrange + var identity = TestDataGenerator.CreateIdentityWithApprovedDeletionProcess(); + + // Act + var result = identity.IsGracePeriodOver; + + // Assert + result.Should().BeFalse(); + } + + [Fact] + public void Returns_true_if_grace_period_is_over() + { + // Arrange + var identity = TestDataGenerator.CreateIdentityWithApprovedDeletionProcess(); + + SystemTime.Set(SystemTime.UtcNow.AddDays(IdentityDeletionConfiguration.Instance.LengthOfGracePeriodInDays + 1)); + + // Act + var result = identity.IsGracePeriodOver; + + // Assert + result.Should().BeTrue(); + } +} From b957e40ccb42ae9084b852dbba74a3ebe4b1ead2 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Mon, 2 Dec 2024 11:23:33 +0100 Subject: [PATCH 29/30] Revert "test: check what happens if we remove all calls to Hasher.SetHasher" This reverts commit d3e03f99a1288527917f36f19d76ae2981ce5c71. --- .../Identities/ApproveDeletionProcessTests.cs | 260 ++++++++-------- .../DeletionGracePeriodReminderTests.cs | 282 +++++++++--------- .../DeletionProcessApprovalReminderTests.cs | 278 +++++++++-------- .../DeletionProcessGracePeriodTests.cs | 260 ++++++++-------- .../Identities/RejectDeletionProcessTests.cs | 214 +++++++------ .../StartDeletionProcessAsOwnerTests.cs | 270 +++++++++-------- .../StartDeletionProcessAsSupportTests.cs | 188 ++++++------ 7 files changed, 869 insertions(+), 883 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs index 442dea73e9..78f9a1c942 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs @@ -1,133 +1,131 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class ApproveDeletionProcessTests : AbstractTestsBase -// { -// [Fact] -// public void Approve_deletion_process_waiting_for_approval() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// -// // Act -// identity.ApproveDeletionProcess(identity.GetDeletionProcessInStatus(DeletionProcessStatus.WaitingForApproval)!.Id, deviceId); -// -// // Assert -// identity.Status.Should().Be(IdentityStatus.ToBeDeleted); -// identity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); -// identity.TierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// } -// -// [Fact] -// public void Throws_when_device_not_owned_by_identity() -// { -// // Arrange -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// -// // Act -// var acting = () => identity.ApproveDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); -// var exception = acting.Should().Throw().Which; -// -// // Assert -// exception.Code.Should().Be("error.platform.recordNotFound"); -// exception.Message.Should().Contain("Device"); -// } -// -// [Fact] -// public void Throws_when_deletion_process_does_not_exist() -// { -// // Arrange -// var identity = CreateIdentity(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; -// -// // Act -// var acting = () => identity.ApproveDeletionProcess(deletionProcessId, deviceId); -// var exception = acting.Should().Throw().Which; -// -// // Assert -// exception.Code.Should().Be("error.platform.recordNotFound"); -// exception.Message.Should().Contain("IdentityDeletionProcess"); -// } -// -// [Fact] -// public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() -// { -// // Arrange -// var identity = CreateIdentity(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); -// -// // Act -// var acting = () => identity.ApproveDeletionProcess(deletionProcess.Id, deviceId); -// var exception = acting.Should().Throw().Which; -// -// // Assert -// exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// exception.Message.Should().Contain("WaitingForApproval"); -// } -// -// [Fact] -// public void Raises_domain_events() -// { -// //Arrange -// var activeIdentity = TestDataGenerator.CreateIdentity(); -// var activeDevice = activeIdentity.Devices[0]; -// var tierBeforeDeletion = activeIdentity.TierId; -// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); -// -// //Act -// activeIdentity.ApproveDeletionProcess(deletionProcess.Id, activeDevice.Id); -// -// //Assert -// var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); -// -// tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); -// tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); -// tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); -// -// identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// deletionProcess.AuditLog.Should().HaveCount(2); -// -// var auditLogEntry = deletionProcess.AuditLog[1]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// -// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() -// { -// var identity = CreateIdentity(); -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// identity.StartDeletionProcessAsSupport(); -// return identity; -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class ApproveDeletionProcessTests : AbstractTestsBase +{ + [Fact] + public void Approve_deletion_process_waiting_for_approval() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + + // Act + identity.ApproveDeletionProcess(identity.GetDeletionProcessInStatus(DeletionProcessStatus.WaitingForApproval)!.Id, deviceId); + + // Assert + identity.Status.Should().Be(IdentityStatus.ToBeDeleted); + identity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); + identity.TierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + } + + [Fact] + public void Throws_when_device_not_owned_by_identity() + { + // Arrange + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + + // Act + var acting = () => identity.ApproveDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); + var exception = acting.Should().Throw().Which; + + // Assert + exception.Code.Should().Be("error.platform.recordNotFound"); + exception.Message.Should().Contain("Device"); + } + + [Fact] + public void Throws_when_deletion_process_does_not_exist() + { + // Arrange + var identity = CreateIdentity(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; + + // Act + var acting = () => identity.ApproveDeletionProcess(deletionProcessId, deviceId); + var exception = acting.Should().Throw().Which; + + // Assert + exception.Code.Should().Be("error.platform.recordNotFound"); + exception.Message.Should().Contain("IdentityDeletionProcess"); + } + + [Fact] + public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() + { + // Arrange + var identity = CreateIdentity(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); + + // Act + var acting = () => identity.ApproveDeletionProcess(deletionProcess.Id, deviceId); + var exception = acting.Should().Throw().Which; + + // Assert + exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + exception.Message.Should().Contain("WaitingForApproval"); + } + + [Fact] + public void Raises_domain_events() + { + //Arrange + var activeIdentity = TestDataGenerator.CreateIdentity(); + var activeDevice = activeIdentity.Devices[0]; + var tierBeforeDeletion = activeIdentity.TierId; + var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); + + //Act + activeIdentity.ApproveDeletionProcess(deletionProcess.Id, activeDevice.Id); + + //Assert + var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); + + tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); + tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); + tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); + + identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + deletionProcess.AuditLog.Should().HaveCount(2); + + var auditLogEntry = deletionProcess.AuditLog[1]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } + + private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() + { + var identity = CreateIdentity(); + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + identity.StartDeletionProcessAsSupport(); + return identity; + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs index 819b19b13d..dc5ff06243 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs @@ -1,144 +1,142 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class DeletionGracePeriodReminderTests : AbstractTestsBase -// { -// public override void Dispose() -// { -// Hasher.Reset(); -// base.Dispose(); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder1Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder1Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder2Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder2Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder3Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder3Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// deletionProcess.AuditLog.Should().HaveCount(2); -// -// var auditLogEntry = deletionProcess.AuditLog[1]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); -// } -// -// private static Identity CreateIdentityWithApprovedDeletionProcess() -// { -// var identity = CreateIdentity(); -// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); -// identity.Devices.Add(device); -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// -// identity.StartDeletionProcessAsOwner(device.Id); -// -// return identity; -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class DeletionGracePeriodReminderTests : AbstractTestsBase +{ + public override void Dispose() + { + Hasher.Reset(); + base.Dispose(); + } + + [Fact] + public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder1Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); + } + + [Fact] + public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder1Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder2Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder2Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder3Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder3Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + deletionProcess.AuditLog.Should().HaveCount(2); + + var auditLogEntry = deletionProcess.AuditLog[1]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); + } + + private static Identity CreateIdentityWithApprovedDeletionProcess() + { + var identity = CreateIdentity(); + var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); + identity.Devices.Add(device); + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + + identity.StartDeletionProcessAsOwner(device.Id); + + return identity; + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs index dd8a846720..f3d3213049 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs @@ -1,142 +1,140 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class DeletionProcessApprovalReminderTests : AbstractTestsBase -// { -// [Fact] -// public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// -// // Act -// identity.DeletionProcessApprovalReminder1Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); -// } -// -// [Fact] -// public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionProcessApprovalReminder1Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// -// // Act -// identity.DeletionProcessApprovalReminder2Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionProcessApprovalReminder2Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// -// // Act -// identity.DeletionProcessApprovalReminder3Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = CreateIdentity(); -// -// // Act -// var acting = identity.DeletionProcessApprovalReminder3Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// deletionProcess.AuditLog.Should().HaveCount(2); -// -// var auditLogEntry = deletionProcess.AuditLog[1]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); -// } -// -// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() -// { -// var identity = CreateIdentity(); -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// identity.StartDeletionProcessAsSupport(); -// -// return identity; -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// -// [Fact] -// public override void Dispose() -// { -// Hasher.Reset(); -// base.Dispose(); -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class DeletionProcessApprovalReminderTests : AbstractTestsBase +{ + [Fact] + public void DeletionProcessApprovalReminder1Sent_updates_ApprovalReminder1SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + + // Act + identity.DeletionProcessApprovalReminder1Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.ApprovalReminder1SentAt.Should().Be(currentDateTime); + } + + [Fact] + public void DeletionProcessApprovalReminder1Sent_fails_when_no_deletion_process_waiting_for_approval_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionProcessApprovalReminder1Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionProcessApprovalReminder2Sent_updates_ApprovalReminder2SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + + // Act + identity.DeletionProcessApprovalReminder2Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.ApprovalReminder2SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionProcessApprovalReminder2Sent_fails_when_no_deletion_process_waiting_for_approval_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionProcessApprovalReminder2Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionProcessApprovalReminder3Sent_updates_ApprovalReminder3SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + + // Act + identity.DeletionProcessApprovalReminder3Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.WaitingForApproval)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.ApprovalReminder3SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionProcessApprovalReminder3Sent_fails_when_no_deletion_process_waiting_for_approval_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = CreateIdentity(); + + // Act + var acting = identity.DeletionProcessApprovalReminder3Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + deletionProcess.AuditLog.Should().HaveCount(2); + + var auditLogEntry = deletionProcess.AuditLog[1]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); + } + + private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() + { + var identity = CreateIdentity(); + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + identity.StartDeletionProcessAsSupport(); + + return identity; + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } + + [Fact] + public override void Dispose() + { + Hasher.Reset(); + base.Dispose(); + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs index 44e9fd27fd..0719bd71c5 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs @@ -1,133 +1,131 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class DeletionProcessGracePeriodTests : AbstractTestsBase -// { -// public override void Dispose() -// { -// Hasher.Reset(); -// base.Dispose(); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder1Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = TestDataGenerator.CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder1Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder2Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = TestDataGenerator.CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder2Sent; -// -// // Asserterror -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// [Fact] -// public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() -// { -// // Arrange -// var currentDateTime = DateTime.Parse("2000-01-01"); -// SystemTime.Set(currentDateTime); -// var identity = CreateIdentityWithApprovedDeletionProcess(); -// -// // Act -// identity.DeletionGracePeriodReminder3Sent(); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); -// } -// -// -// [Fact] -// public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var identity = TestDataGenerator.CreateIdentity(); -// -// // Act -// var acting = identity.DeletionGracePeriodReminder3Sent; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// deletionProcess.AuditLog.Should().HaveCount(2); -// -// var auditLogEntry = deletionProcess.AuditLog[1]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); -// } -// -// private static Identity CreateIdentityWithApprovedDeletionProcess() -// { -// var identity = TestDataGenerator.CreateIdentity(); -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); -// -// return identity; -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class DeletionProcessGracePeriodTests : AbstractTestsBase +{ + public override void Dispose() + { + Hasher.Reset(); + base.Dispose(); + } + + [Fact] + public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder1Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder1SentAt.Should().Be(currentDateTime); + } + + [Fact] + public void DeletionGracePeriodReminder1Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = TestDataGenerator.CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder1Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionGracePeriodReminder2Sent_updates_GracePeriodReminder2SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder2Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder2SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionGracePeriodReminder2Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = TestDataGenerator.CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder2Sent; + + // Asserterror + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + [Fact] + public void DeletionGracePeriodReminder3Sent_updates_GracePeriodReminder3SentAt() + { + // Arrange + var currentDateTime = DateTime.Parse("2000-01-01"); + SystemTime.Set(currentDateTime); + var identity = CreateIdentityWithApprovedDeletionProcess(); + + // Act + identity.DeletionGracePeriodReminder3Sent(); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Approved)!; + AssertAuditLogEntryWasCreated(deletionProcess); + deletionProcess.GracePeriodReminder3SentAt.Should().Be(currentDateTime); + } + + + [Fact] + public void DeletionGracePeriodReminder3Sent_fails_when_no_approved_deletion_process_exists() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var identity = TestDataGenerator.CreateIdentity(); + + // Act + var acting = identity.DeletionGracePeriodReminder3Sent; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + deletionProcess.AuditLog.Should().HaveCount(2); + + var auditLogEntry = deletionProcess.AuditLog[1]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.Approved); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); + } + + private static Identity CreateIdentityWithApprovedDeletionProcess() + { + var identity = TestDataGenerator.CreateIdentity(); + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + identity.StartDeletionProcessAsOwner(identity.Devices.First().Id); + + return identity; + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs index 52a5415e44..f20e681f06 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs @@ -1,110 +1,108 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class RejectDeletionProcessTests : AbstractTestsBase -// { -// [Fact] -// public void Reject_deletion_process_waiting_for_approval() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2020-01-01")); -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// -// // Act -// identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); -// -// // Assert -// var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; -// AssertAuditLogEntryWasCreated(deletionProcess); -// } -// -// [Fact] -// public void Throws_when_device_not_owned_by_identity() -// { -// // Arrange -// var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); -// -// // Act -// var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); -// -// // Assert -// var exception = acting.Should().Throw().Which; -// -// exception.Code.Should().Be("error.platform.recordNotFound"); -// exception.Message.Should().Contain("Device"); -// } -// -// [Fact] -// public void Throws_when_deletion_process_does_not_exist() -// { -// // Arrange -// var identity = CreateIdentity(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; -// -// // Act -// var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); -// -// // Assert -// var exception = acting.Should().Throw().Which; -// -// exception.Code.Should().Be("error.platform.recordNotFound"); -// exception.Message.Should().Contain("IdentityDeletionProcess"); -// } -// -// [Fact] -// public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() -// { -// // Arrange -// var identity = CreateIdentity(); -// identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); -// var deviceId = identity.Devices[0].Id; -// var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); -// -// // Act -// var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); -// -// // Assert -// var exception = acting.Should().Throw().Which; -// -// exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); -// exception.Message.Should().Contain("WaitingForApproval"); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// deletionProcess.AuditLog.Should().HaveCount(2); -// -// var auditLogEntry = deletionProcess.AuditLog[1]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// -// private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() -// { -// var identity = CreateIdentity(); -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// identity.StartDeletionProcessAsSupport(); -// return identity; -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class RejectDeletionProcessTests : AbstractTestsBase +{ + [Fact] + public void Reject_deletion_process_waiting_for_approval() + { + // Arrange + SystemTime.Set(DateTime.Parse("2020-01-01")); + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + + // Act + identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, deviceId); + + // Assert + var deletionProcess = identity.DeletionProcesses.FirstOrDefault(d => d.Status == DeletionProcessStatus.Rejected)!; + AssertAuditLogEntryWasCreated(deletionProcess); + } + + [Fact] + public void Throws_when_device_not_owned_by_identity() + { + // Arrange + var identity = CreateIdentityWithDeletionProcessWaitingForApproval(); + + // Act + var acting = () => identity.RejectDeletionProcess(identity.DeletionProcesses[0].Id, DeviceId.Parse("DVC")); + + // Assert + var exception = acting.Should().Throw().Which; + + exception.Code.Should().Be("error.platform.recordNotFound"); + exception.Message.Should().Contain("Device"); + } + + [Fact] + public void Throws_when_deletion_process_does_not_exist() + { + // Arrange + var identity = CreateIdentity(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + var deletionProcessId = IdentityDeletionProcessId.Create("IDP00000000000000001").Value; + + // Act + var acting = () => identity.RejectDeletionProcess(deletionProcessId, deviceId); + + // Assert + var exception = acting.Should().Throw().Which; + + exception.Code.Should().Be("error.platform.recordNotFound"); + exception.Message.Should().Contain("IdentityDeletionProcess"); + } + + [Fact] + public void Throws_when_deletion_process_is_not_in_status_waiting_for_approval() + { + // Arrange + var identity = CreateIdentity(); + identity.Devices.Add(new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE)); + var deviceId = identity.Devices[0].Id; + var deletionProcess = identity.StartDeletionProcessAsOwner(deviceId); + + // Act + var acting = () => identity.RejectDeletionProcess(deletionProcess.Id, deviceId); + + // Assert + var exception = acting.Should().Throw().Which; + + exception.Code.Should().Be("error.platform.validation.device.deletionProcessIsNotInRequiredStatus"); + exception.Message.Should().Contain("WaitingForApproval"); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + deletionProcess.AuditLog.Should().HaveCount(2); + + var auditLogEntry = deletionProcess.AuditLog[1]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Rejected); + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } + + private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() + { + var identity = CreateIdentity(); + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + identity.StartDeletionProcessAsSupport(); + return identity; + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs index d038fb9397..55076cc41a 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs @@ -1,138 +1,136 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class StartDeletionProcessAsOwnerTests : AbstractTestsBase -// { -// public override void Dispose() -// { -// Hasher.Reset(); -// base.Dispose(); -// } -// -// [Fact] -// public void Start_deletion_process() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var activeIdentity = CreateIdentity(); -// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); -// activeIdentity.Devices.Add(activeDevice); -// -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// -// // Act -// var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); -// -// // Assert -// activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); -// activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); -// activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); -// -// AssertDeletionProcessWasStarted(activeIdentity); -// deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); -// deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); -// deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); -// deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); -// -// AssertAuditLogEntryWasCreated(deletionProcess); -// var auditLogEntry = deletionProcess.AuditLog[0]; -// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); -// auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); -// } -// -// [Fact] -// public void Throws_when_device_not_owned_by_identity() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2020-01-01")); -// var identity = TestDataGenerator.CreateIdentity(); -// var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); -// -// identity.Devices.Add(device); -// -// // Act -// var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); -// -// // Assert -// var exception = acting.Should().Throw().Which; -// exception.Code.Should().Be("error.platform.recordNotFound"); -// exception.Message.Should().Contain("Device"); -// } -// -// [Fact] -// public void Only_one_active_deletion_process_is_allowed_when_started() -// { -// // Arrange -// var activeIdentity = CreateIdentity(); -// var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); -// activeIdentity.Devices.Add(activeDevice); -// -// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); -// -// // Act -// var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); -// } -// -// [Fact] -// public void Raises_domain_events() -// { -// //Arrange -// var activeIdentity = TestDataGenerator.CreateIdentity(); -// var tierBeforeDeletion = activeIdentity.TierId; -// var activeDevice = activeIdentity.Devices[0]; -// -// //Act -// activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); -// -// //Assert -// var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); -// -// tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); -// tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); -// tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); -// -// identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); -// } -// -// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) -// { -// activeIdentity.DeletionProcesses.Should().HaveCount(1); -// var deletionProcess = activeIdentity.DeletionProcesses[0]; -// deletionProcess.Should().NotBeNull(); -// -// deletionProcess.Id.Should().NotBeNull(); -// deletionProcess.Id.Value.Should().HaveLength(20); -// -// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); -// -// deletionProcess.AuditLog.Should().HaveCount(1); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// var auditLogEntry = deletionProcess.AuditLog[0]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().BeNull(); -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class StartDeletionProcessAsOwnerTests : AbstractTestsBase +{ + public override void Dispose() + { + Hasher.Reset(); + base.Dispose(); + } + + [Fact] + public void Start_deletion_process() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var activeIdentity = CreateIdentity(); + var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); + activeIdentity.Devices.Add(activeDevice); + + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + + // Act + var deletionProcess = activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); + + // Assert + activeIdentity.DeletionGracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); + activeIdentity.TierId.Value.Should().Be(Tier.QUEUED_FOR_DELETION.Id.Value); + activeIdentity.Status.Should().Be(IdentityStatus.ToBeDeleted); + + AssertDeletionProcessWasStarted(activeIdentity); + deletionProcess.Status.Should().Be(DeletionProcessStatus.Approved); + deletionProcess.ApprovedAt.Should().Be(SystemTime.UtcNow); + deletionProcess.ApprovedByDevice.Should().Be(activeDevice.Id); + deletionProcess.GracePeriodEndsAt.Should().Be(DateTime.Parse("2000-01-15")); + + AssertAuditLogEntryWasCreated(deletionProcess); + var auditLogEntry = deletionProcess.AuditLog[0]; + auditLogEntry.MessageKey.Should().Be(MessageKey.StartedByOwner); + auditLogEntry.DeviceIdHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.Approved); + } + + [Fact] + public void Throws_when_device_not_owned_by_identity() + { + // Arrange + SystemTime.Set(DateTime.Parse("2020-01-01")); + var identity = TestDataGenerator.CreateIdentity(); + var device = new Device(identity, CommunicationLanguage.DEFAULT_LANGUAGE); + + identity.Devices.Add(device); + + // Act + var acting = () => identity.StartDeletionProcessAsOwner(DeviceId.Parse("DVC")); + + // Assert + var exception = acting.Should().Throw().Which; + exception.Code.Should().Be("error.platform.recordNotFound"); + exception.Message.Should().Contain("Device"); + } + + [Fact] + public void Only_one_active_deletion_process_is_allowed_when_started() + { + // Arrange + var activeIdentity = CreateIdentity(); + var activeDevice = new Device(activeIdentity, CommunicationLanguage.DEFAULT_LANGUAGE); + activeIdentity.Devices.Add(activeDevice); + + activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); + + // Act + var acting = () => activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); + } + + [Fact] + public void Raises_domain_events() + { + //Arrange + var activeIdentity = TestDataGenerator.CreateIdentity(); + var tierBeforeDeletion = activeIdentity.TierId; + var activeDevice = activeIdentity.Devices[0]; + + //Act + activeIdentity.StartDeletionProcessAsOwner(activeDevice.Id); + + //Assert + var (tierOfIdentityChangedDomainEvent, identityToBeDeletedDomainEvent) = activeIdentity.Should().HaveDomainEvents(); + + tierOfIdentityChangedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); + tierOfIdentityChangedDomainEvent.OldTierId.Should().Be(tierBeforeDeletion); + tierOfIdentityChangedDomainEvent.NewTierId.Should().Be(Tier.QUEUED_FOR_DELETION.Id); + + identityToBeDeletedDomainEvent.IdentityAddress.Should().Be(activeIdentity.Address); + } + + private static void AssertDeletionProcessWasStarted(Identity activeIdentity) + { + activeIdentity.DeletionProcesses.Should().HaveCount(1); + var deletionProcess = activeIdentity.DeletionProcesses[0]; + deletionProcess.Should().NotBeNull(); + + deletionProcess.Id.Should().NotBeNull(); + deletionProcess.Id.Value.Should().HaveLength(20); + + deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); + + deletionProcess.AuditLog.Should().HaveCount(1); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + var auditLogEntry = deletionProcess.AuditLog[0]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().BeNull(); + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } +} diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs index ba647f4bdc..4a4aa40a4d 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs @@ -1,97 +1,95 @@ -// using Backbone.BuildingBlocks.Domain.Exceptions; -// using Backbone.DevelopmentKit.Identity.ValueObjects; -// using Backbone.Modules.Devices.Domain.Aggregates.Tier; -// using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; -// using Backbone.Modules.Devices.Domain.Entities.Identities; -// using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; -// using Backbone.Tooling; -// -// namespace Backbone.Modules.Devices.Domain.Tests.Identities; -// -// public class StartDeletionProcessAsSupportTests : AbstractTestsBase -// { -// [Fact] -// public void Start_deletion_process() -// { -// // Arrange -// SystemTime.Set(DateTime.Parse("2000-01-01")); -// var activeIdentity = CreateIdentity(); -// -// Hasher.SetHasher(new DummyHasher([1, 2, 3])); -// -// // Act -// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); -// -// // Assert -// AssertDeletionProcessWasStarted(activeIdentity); -// deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); -// -// AssertAuditLogEntryWasCreated(deletionProcess); -// var auditLogEntry = deletionProcess.AuditLog[0]; -// auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); -// auditLogEntry.DeviceIdHash.Should().BeNull(); -// auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); -// } -// -// [Fact] -// public void Only_one_active_deletion_process_is_allowed_when_started() -// { -// // Arrange -// var activeIdentity = CreateIdentity(); -// -// activeIdentity.StartDeletionProcessAsSupport(); -// -// // Act -// var acting = activeIdentity.StartDeletionProcessAsSupport; -// -// // Assert -// acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); -// } -// -// [Fact] -// public void Raises_IdentityDeletionProcessStartedDomainEvent() -// { -// //Arrange -// var activeIdentity = CreateIdentity(); -// -// //Act -// var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); -// -// //Assert -// var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); -// domainEvent.Address.Should().Be(activeIdentity.Address); -// domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); -// domainEvent.Initiator.Should().Be(null); -// } -// -// private static void AssertDeletionProcessWasStarted(Identity activeIdentity) -// { -// activeIdentity.DeletionProcesses.Should().HaveCount(1); -// var deletionProcess = activeIdentity.DeletionProcesses[0]; -// deletionProcess.Should().NotBeNull(); -// -// deletionProcess.Id.Should().NotBeNull(); -// deletionProcess.Id.Value.Should().HaveLength(20); -// -// deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); -// -// deletionProcess.AuditLog.Should().HaveCount(1); -// } -// -// private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) -// { -// var auditLogEntry = deletionProcess.AuditLog[0]; -// auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); -// auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); -// auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); -// auditLogEntry.OldStatus.Should().BeNull(); -// } -// -// private static Identity CreateIdentity() -// { -// var address = IdentityAddress.Create([], "prod.enmeshed.eu"); -// return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); -// } -// } +using Backbone.BuildingBlocks.Domain.Exceptions; +using Backbone.DevelopmentKit.Identity.ValueObjects; +using Backbone.Modules.Devices.Domain.Aggregates.Tier; +using Backbone.Modules.Devices.Domain.DomainEvents.Outgoing; +using Backbone.Modules.Devices.Domain.Entities.Identities; +using Backbone.Modules.Devices.Domain.Tests.Identities.TestDoubles; +using Backbone.Tooling; +namespace Backbone.Modules.Devices.Domain.Tests.Identities; +public class StartDeletionProcessAsSupportTests : AbstractTestsBase +{ + [Fact] + public void Start_deletion_process() + { + // Arrange + SystemTime.Set(DateTime.Parse("2000-01-01")); + var activeIdentity = CreateIdentity(); + + Hasher.SetHasher(new DummyHasher([1, 2, 3])); + + // Act + var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); + + // Assert + AssertDeletionProcessWasStarted(activeIdentity); + deletionProcess.Status.Should().Be(DeletionProcessStatus.WaitingForApproval); + + AssertAuditLogEntryWasCreated(deletionProcess); + var auditLogEntry = deletionProcess.AuditLog[0]; + auditLogEntry.MessageKey.Should().Be(MessageKey.StartedBySupport); + auditLogEntry.DeviceIdHash.Should().BeNull(); + auditLogEntry.NewStatus.Should().Be(DeletionProcessStatus.WaitingForApproval); + } + + [Fact] + public void Only_one_active_deletion_process_is_allowed_when_started() + { + // Arrange + var activeIdentity = CreateIdentity(); + + activeIdentity.StartDeletionProcessAsSupport(); + + // Act + var acting = activeIdentity.StartDeletionProcessAsSupport; + + // Assert + acting.Should().Throw().Which.Code.Should().Be("error.platform.validation.device.onlyOneActiveDeletionProcessAllowed"); + } + + [Fact] + public void Raises_IdentityDeletionProcessStartedDomainEvent() + { + //Arrange + var activeIdentity = CreateIdentity(); + + //Act + var deletionProcess = activeIdentity.StartDeletionProcessAsSupport(); + + //Assert + var domainEvent = deletionProcess.Should().HaveASingleDomainEvent(); + domainEvent.Address.Should().Be(activeIdentity.Address); + domainEvent.DeletionProcessId.Should().Be(deletionProcess.Id); + domainEvent.Initiator.Should().Be(null); + } + + private static void AssertDeletionProcessWasStarted(Identity activeIdentity) + { + activeIdentity.DeletionProcesses.Should().HaveCount(1); + var deletionProcess = activeIdentity.DeletionProcesses[0]; + deletionProcess.Should().NotBeNull(); + + deletionProcess.Id.Should().NotBeNull(); + deletionProcess.Id.Value.Should().HaveLength(20); + + deletionProcess.CreatedAt.Should().Be(SystemTime.UtcNow); + + deletionProcess.AuditLog.Should().HaveCount(1); + } + + private static void AssertAuditLogEntryWasCreated(IdentityDeletionProcess deletionProcess) + { + var auditLogEntry = deletionProcess.AuditLog[0]; + auditLogEntry.ProcessId.Should().Be(deletionProcess.Id); + auditLogEntry.CreatedAt.Should().Be(SystemTime.UtcNow); + auditLogEntry.IdentityAddressHash.Should().BeEquivalentTo(new byte[] { 1, 2, 3 }); + auditLogEntry.OldStatus.Should().BeNull(); + } + + private static Identity CreateIdentity() + { + var address = IdentityAddress.Create([], "prod.enmeshed.eu"); + return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); + } +} From c68cb163e7bcd5818a4d6cdcdc56755ccd2fb1b4 Mon Sep 17 00:00:00 2001 From: Timo Notheisen Date: Mon, 2 Dec 2024 11:28:00 +0100 Subject: [PATCH 30/30] test: reset hasher after the tests have finished --- .../Identities/ApproveDeletionProcessTests.cs | 6 ++++++ .../Identities/DeletionGracePeriodReminderTests.cs | 12 ++++++------ .../DeletionProcessApprovalReminderTests.cs | 3 +-- .../Identities/DeletionProcessGracePeriodTests.cs | 12 ++++++------ .../Identities/RejectDeletionProcessTests.cs | 6 ++++++ .../Identities/StartDeletionProcessAsOwnerTests.cs | 12 ++++++------ .../Identities/StartDeletionProcessAsSupportTests.cs | 6 ++++++ 7 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs index 78f9a1c942..76cf470375 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/ApproveDeletionProcessTests.cs @@ -128,4 +128,10 @@ private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() identity.StartDeletionProcessAsSupport(); return identity; } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs index dc5ff06243..1b36894737 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionGracePeriodReminderTests.cs @@ -9,12 +9,6 @@ namespace Backbone.Modules.Devices.Domain.Tests.Identities; public class DeletionGracePeriodReminderTests : AbstractTestsBase { - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - [Fact] public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() { @@ -139,4 +133,10 @@ private static Identity CreateIdentity() var address = IdentityAddress.Create([], "prod.enmeshed.eu"); return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs index f3d3213049..15c211314e 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessApprovalReminderTests.cs @@ -131,10 +131,9 @@ private static Identity CreateIdentity() return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); } - [Fact] public override void Dispose() { - Hasher.Reset(); base.Dispose(); + Hasher.Reset(); } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs index 0719bd71c5..45ab6a6860 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/DeletionProcessGracePeriodTests.cs @@ -7,12 +7,6 @@ namespace Backbone.Modules.Devices.Domain.Tests.Identities; public class DeletionProcessGracePeriodTests : AbstractTestsBase { - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - [Fact] public void DeletionGracePeriodReminder1Sent_updates_GracePeriodReminder1SentAt() { @@ -128,4 +122,10 @@ private static Identity CreateIdentityWithApprovedDeletionProcess() return identity; } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs index f20e681f06..a73bfd09dd 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/RejectDeletionProcessTests.cs @@ -105,4 +105,10 @@ private static Identity CreateIdentityWithDeletionProcessWaitingForApproval() identity.StartDeletionProcessAsSupport(); return identity; } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs index 55076cc41a..2a1a8c6c2c 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsOwnerTests.cs @@ -10,12 +10,6 @@ namespace Backbone.Modules.Devices.Domain.Tests.Identities; public class StartDeletionProcessAsOwnerTests : AbstractTestsBase { - public override void Dispose() - { - Hasher.Reset(); - base.Dispose(); - } - [Fact] public void Start_deletion_process() { @@ -133,4 +127,10 @@ private static Identity CreateIdentity() var address = IdentityAddress.Create([], "prod.enmeshed.eu"); return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } } diff --git a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs index 4a4aa40a4d..437ccc09c3 100644 --- a/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs +++ b/Modules/Devices/test/Devices.Domain.Tests/Identities/StartDeletionProcessAsSupportTests.cs @@ -92,4 +92,10 @@ private static Identity CreateIdentity() var address = IdentityAddress.Create([], "prod.enmeshed.eu"); return new Identity("", address, [], TierId.Generate(), 1, CommunicationLanguage.DEFAULT_LANGUAGE); } + + public override void Dispose() + { + base.Dispose(); + Hasher.Reset(); + } }