From 23d3ccedc9fb53786e48509dd8a7a1f889ffa6ba Mon Sep 17 00:00:00 2001 From: Jezz Santos Date: Wed, 3 Apr 2024 16:33:48 +1300 Subject: [PATCH] Refactored all domain events into a shared library --- docs/design-principles/0130-multitenancy.md | 2 +- .../EmailDeliverRootSpec.cs | 11 +- src/AncillaryDomain/AncillaryDomain.csproj | 2 +- src/AncillaryDomain/AuditRoot.cs | 5 +- src/AncillaryDomain/EmailDeliveryRoot.cs | 21 +- src/AncillaryDomain/Events.cs | 165 ++---- .../Persistence/ReadModels/AuditProjection.cs | 3 +- .../ReadModels/EmailDeliveryProjection.cs | 11 +- .../BookingRootSpec.cs | 7 +- src/BookingsDomain.UnitTests/TripSpec.cs | 3 +- src/BookingsDomain/BookingRoot.cs | 21 +- src/BookingsDomain/BookingsDomain.csproj | 2 +- src/BookingsDomain/Events.cs | 187 ++----- src/BookingsDomain/Trip.cs | 11 +- .../CarsApplicationSpec.cs | 1 + .../Persistence/ReadModels/Unavailability.cs | 2 +- src/CarsDomain.UnitTests/CarRootSpec.cs | 40 +- src/CarsDomain.UnitTests/CausedBySpec.cs | 1 + .../UnavailabilitySpec.cs | 1 + src/CarsDomain/CarRoot.cs | 32 +- src/CarsDomain/CarsDomain.csproj | 2 +- src/CarsDomain/CausedBy.cs | 1 + src/CarsDomain/Events.cs | 195 ++----- src/CarsDomain/Unavailability.cs | 5 +- .../CarsApiSpec.cs | 1 + .../Persistence/ReadModels/CarProjection.cs | 13 +- .../Ancillary/Audits/Created.cs | 20 + .../Ancillary/EmailDelivery/Created.cs | 12 + .../EmailDelivery/DeliveryAttempted.cs | 12 + .../Ancillary/EmailDelivery/DeliveryFailed.cs | 12 + .../EmailDelivery/DeliverySucceeded.cs | 12 + .../EmailDelivery/EmailDetailsChanged.cs | 18 + .../Bookings/CarChanged.cs | 14 + src/Domain.Events.Shared/Bookings/Created.cs | 12 + .../Bookings/ReservationMade.cs | 20 + .../Bookings/TripAdded.cs | 26 + .../Bookings/TripBegan.cs | 20 + .../Bookings/TripEnded.cs | 22 + src/Domain.Events.Shared/Cars/Created.cs | 14 + .../Cars/ManufacturerChanged.cs | 18 + .../Cars/OwnershipChanged.cs | 16 + .../Cars/RegistrationChanged.cs | 18 + .../Cars/UnavailabilitySlotAdded.cs | 23 + .../Cars/UnavailabilitySlotRemoved.cs | 14 + .../Domain.Events.Shared.csproj | 18 + src/Domain.Events.Shared/EndUsers/Created.cs | 16 + .../EndUsers/GuestInvitationAccepted.cs | 14 + .../EndUsers/GuestInvitationCreated.cs | 16 + .../EndUsers/MembershipAdded.cs | 20 + .../EndUsers/MembershipDefaultChanged.cs | 14 + .../EndUsers/MembershipFeatureAssigned.cs | 16 + .../EndUsers/MembershipRoleAssigned.cs | 16 + .../EndUsers/PlatformFeatureAssigned.cs | 12 + .../EndUsers/PlatformRoleAssigned.cs | 12 + .../EndUsers/PlatformRoleUnassigned.cs | 12 + .../EndUsers/Registered.cs | 22 + .../Identities/APIKeys/Created.cs | 16 + .../Identities/APIKeys/KeyVerified.cs | 12 + .../Identities/APIKeys/ParametersChanged.cs | 14 + .../Identities/AuthTokens/Created.cs | 12 + .../Identities/AuthTokens/TokensChanged.cs | 20 + .../Identities/AuthTokens/TokensRefreshed.cs | 20 + .../Identities/AuthTokens/TokensRevoked.cs | 12 + .../PasswordCredentials/AccountLocked.cs | 10 + .../PasswordCredentials/AccountUnlocked.cs | 10 + .../Identities/PasswordCredentials/Created.cs | 12 + .../PasswordCredentials/CredentialsChanged.cs | 12 + .../PasswordResetCompleted.cs | 14 + .../PasswordResetInitiated.cs | 12 + .../PasswordCredentials/PasswordVerified.cs | 14 + .../RegistrationChanged.cs | 14 + .../RegistrationVerificationCreated.cs | 12 + .../RegistrationVerificationVerified.cs | 10 + .../Identities/SSOUsers/Created.cs | 14 + .../Identities/SSOUsers/TokensUpdated.cs | 22 + .../Organizations/Created.cs | 17 + .../Organizations/SettingCreated.cs | 19 + .../Organizations/SettingUpdated.cs | 23 + .../UserProfiles/ContactAddressChanged.cs | 26 + .../UserProfiles/Created.cs | 20 + .../UserProfiles/DisplayNameChanged.cs | 14 + .../UserProfiles/EmailAddressChanged.cs | 14 + .../UserProfiles/NameChanged.cs | 16 + .../UserProfiles/PhoneNumberChanged.cs | 14 + .../UserProfiles/TimezoneChanged.cs | 14 + .../DomainServices/ITokensService.cs | 2 +- .../Cars}/UnavailabilityCausedBy.cs | 2 +- .../{ => Identities}/APIKeyToken.cs | 2 +- .../Organizations/OrganizationOwnership.cs | 7 + .../Organizations/SettingValueType.cs | 8 + .../EndUserRootSpec.cs | 31 +- .../MembershipSpec.cs | 12 +- .../MembershipsSpec.cs | 2 +- src/EndUsersDomain/EndUserRoot.cs | 47 +- src/EndUsersDomain/EndUsersDomain.csproj | 3 +- src/EndUsersDomain/Events.cs | 328 ++++-------- src/EndUsersDomain/Membership.cs | 12 +- .../ReadModels/EndUserProjection.cs | 28 +- .../APIKeysApplicationSpec.cs | 2 +- .../APIKeyRootSpec.cs | 9 +- .../AuthTokensRootSpec.cs | 7 +- .../PasswordCredentialRootSpec.cs | 41 +- .../SSOUserRootSpec.cs | 3 +- src/IdentityDomain/APIKeyRoot.cs | 15 +- src/IdentityDomain/AuthTokensRoot.cs | 19 +- src/IdentityDomain/Events.cs | 499 ++++++------------ src/IdentityDomain/IdentityDomain.csproj | 13 +- src/IdentityDomain/PasswordCredentialRoot.cs | 43 +- src/IdentityDomain/SSOUserRoot.cs | 9 +- .../ReadModels/APIKeyProjection.cs | 7 +- .../ReadModels/AuthTokensProjection.cs | 9 +- .../PasswordCredentialProjection.cs | 21 +- .../ReadModels/SSOUserProjection.cs | 5 +- .../DomainServices/TokensService.cs | 2 +- .../OrganizationsApplicationSpec.cs | 29 +- .../OrganizationsApplication.cs | 13 +- .../Persistence/ReadModels/Organization.cs | 4 +- .../OrganizationRootSpec.cs | 12 +- .../SettingSpec.cs | 1 + src/OrganizationsDomain/Events.cs | 111 ++-- src/OrganizationsDomain/OrganizationRoot.cs | 21 +- .../OrganizationsDomain.csproj | 3 +- src/OrganizationsDomain/Ownership.cs | 7 - src/OrganizationsDomain/Setting.cs | 8 +- .../ReadModels/OrganizationProjection.cs | 5 +- src/SaaStack.sln | 9 + src/SaaStack.sln.DotSettings | 1 + .../DomainDrivenDesignAnalyzerSpec.cs | 22 - .../AnalyzerReleases.Shipped.md | 1 - .../DomainDrivenDesignAnalyzer.cs | 11 +- .../UserProfileRootSpec.cs | 15 +- src/UserProfilesDomain/Events.cs | 218 +++----- src/UserProfilesDomain/UserProfileRoot.cs | 29 +- .../UserProfilesDomain.csproj | 3 +- .../ReadModels/EndUserProjection.cs | 15 +- 135 files changed, 1818 insertions(+), 1583 deletions(-) create mode 100644 src/Domain.Events.Shared/Ancillary/Audits/Created.cs create mode 100644 src/Domain.Events.Shared/Ancillary/EmailDelivery/Created.cs create mode 100644 src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryAttempted.cs create mode 100644 src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryFailed.cs create mode 100644 src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliverySucceeded.cs create mode 100644 src/Domain.Events.Shared/Ancillary/EmailDelivery/EmailDetailsChanged.cs create mode 100644 src/Domain.Events.Shared/Bookings/CarChanged.cs create mode 100644 src/Domain.Events.Shared/Bookings/Created.cs create mode 100644 src/Domain.Events.Shared/Bookings/ReservationMade.cs create mode 100644 src/Domain.Events.Shared/Bookings/TripAdded.cs create mode 100644 src/Domain.Events.Shared/Bookings/TripBegan.cs create mode 100644 src/Domain.Events.Shared/Bookings/TripEnded.cs create mode 100644 src/Domain.Events.Shared/Cars/Created.cs create mode 100644 src/Domain.Events.Shared/Cars/ManufacturerChanged.cs create mode 100644 src/Domain.Events.Shared/Cars/OwnershipChanged.cs create mode 100644 src/Domain.Events.Shared/Cars/RegistrationChanged.cs create mode 100644 src/Domain.Events.Shared/Cars/UnavailabilitySlotAdded.cs create mode 100644 src/Domain.Events.Shared/Cars/UnavailabilitySlotRemoved.cs create mode 100644 src/Domain.Events.Shared/Domain.Events.Shared.csproj create mode 100644 src/Domain.Events.Shared/EndUsers/Created.cs create mode 100644 src/Domain.Events.Shared/EndUsers/GuestInvitationAccepted.cs create mode 100644 src/Domain.Events.Shared/EndUsers/GuestInvitationCreated.cs create mode 100644 src/Domain.Events.Shared/EndUsers/MembershipAdded.cs create mode 100644 src/Domain.Events.Shared/EndUsers/MembershipDefaultChanged.cs create mode 100644 src/Domain.Events.Shared/EndUsers/MembershipFeatureAssigned.cs create mode 100644 src/Domain.Events.Shared/EndUsers/MembershipRoleAssigned.cs create mode 100644 src/Domain.Events.Shared/EndUsers/PlatformFeatureAssigned.cs create mode 100644 src/Domain.Events.Shared/EndUsers/PlatformRoleAssigned.cs create mode 100644 src/Domain.Events.Shared/EndUsers/PlatformRoleUnassigned.cs create mode 100644 src/Domain.Events.Shared/EndUsers/Registered.cs create mode 100644 src/Domain.Events.Shared/Identities/APIKeys/Created.cs create mode 100644 src/Domain.Events.Shared/Identities/APIKeys/KeyVerified.cs create mode 100644 src/Domain.Events.Shared/Identities/APIKeys/ParametersChanged.cs create mode 100644 src/Domain.Events.Shared/Identities/AuthTokens/Created.cs create mode 100644 src/Domain.Events.Shared/Identities/AuthTokens/TokensChanged.cs create mode 100644 src/Domain.Events.Shared/Identities/AuthTokens/TokensRefreshed.cs create mode 100644 src/Domain.Events.Shared/Identities/AuthTokens/TokensRevoked.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/AccountLocked.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/AccountUnlocked.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/Created.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/CredentialsChanged.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetCompleted.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetInitiated.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordVerified.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationChanged.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationCreated.cs create mode 100644 src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationVerified.cs create mode 100644 src/Domain.Events.Shared/Identities/SSOUsers/Created.cs create mode 100644 src/Domain.Events.Shared/Identities/SSOUsers/TokensUpdated.cs create mode 100644 src/Domain.Events.Shared/Organizations/Created.cs create mode 100644 src/Domain.Events.Shared/Organizations/SettingCreated.cs create mode 100644 src/Domain.Events.Shared/Organizations/SettingUpdated.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/ContactAddressChanged.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/Created.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/DisplayNameChanged.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/EmailAddressChanged.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/NameChanged.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/PhoneNumberChanged.cs create mode 100644 src/Domain.Events.Shared/UserProfiles/TimezoneChanged.cs rename src/{CarsDomain => Domain.Shared/Cars}/UnavailabilityCausedBy.cs (77%) rename src/Domain.Shared/{ => Identities}/APIKeyToken.cs (85%) create mode 100644 src/Domain.Shared/Organizations/OrganizationOwnership.cs create mode 100644 src/Domain.Shared/Organizations/SettingValueType.cs delete mode 100644 src/OrganizationsDomain/Ownership.cs diff --git a/docs/design-principles/0130-multitenancy.md b/docs/design-principles/0130-multitenancy.md index 7af36186..826c60e8 100644 --- a/docs/design-principles/0130-multitenancy.md +++ b/docs/design-principles/0130-multitenancy.md @@ -311,7 +311,7 @@ For SaaS products that wish to provision physical infrastructure to implement "I Consider the following workflow: 1. A new customer signs up for the platform. They register a new user, and that will create a new `Personal` organization for them to use the product. This organization will have a billing subscription that gives them some [limited] access level to the product at this time (i.e., a trial). -2. At that time, or at some future time (like when they upgrade to a paid plan), a new event (e.g., `EndUsersDomain.Events.Registered`) can be subscribed to by adding a new `IEventNotificationRegistration` in one of the subdomains. +2. At that time, or at some future time (like when they upgrade to a paid plan), a new event (e.g., `Domain.Events.Shared.EndUsers.Registered`) can be subscribed to by adding a new `IEventNotificationRegistration` in one of the subdomains. 3. This event is then raised at runtime, which triggers an application (in some subdomain) to make some API call to some cloud-based process to provision some specific infrastructure (e.g., via queue message or direct via an API call to an Azure function or AWS Lambda - there are many integration options). Let's assume that this triggers Azure to create a new SQL database in a regional data center physically closer to where this specific customer is signing up. 4. Let's assume that this cloud provisioning process takes some time to complete (perhaps several minutes), and meanwhile, the customer is starting using the product and try it out for themselves (using their `Personal` organization, which we assume is using shared platform infrastructure at this time. 5. When the provisioning process is completed (a few minutes later), a new message [containing some data about the provisioning process] is created and dropped on the `provisioning` queue (in Azure or AWS). diff --git a/src/AncillaryDomain.UnitTests/EmailDeliverRootSpec.cs b/src/AncillaryDomain.UnitTests/EmailDeliverRootSpec.cs index 4b99fb48..02fb8f9d 100644 --- a/src/AncillaryDomain.UnitTests/EmailDeliverRootSpec.cs +++ b/src/AncillaryDomain.UnitTests/EmailDeliverRootSpec.cs @@ -3,6 +3,7 @@ using Domain.Common; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Ancillary.EmailDelivery; using Domain.Interfaces.Entities; using Domain.Shared; using FluentAssertions; @@ -35,7 +36,7 @@ public void WhenCreate_ThenReturnsAssigned() var result = EmailDeliveryRoot.Create(_recorder.Object, _idFactory.Object, messageId).Value; result.MessageId.Should().Be(messageId); - result.Events.Last().Should().BeOfType(); + result.Events.Last().Should().BeOfType(); } [Fact] @@ -73,7 +74,7 @@ public void WhenSetEmailDetails_ThenDetailsAssigned() result.Should().BeSuccess(); root.Recipient.Should().Be(recipient); - root.Events.Last().Should().BeOfType(); + root.Events.Last().Should().BeOfType(); } [Fact] @@ -103,7 +104,7 @@ public void WhenAttemptedDeliveryAndNotDelivered_ThenAddsAnAttempt() result.Value.Should().BeFalse(); root.Attempts.Attempts.Count.Should().Be(1); root.Attempts.Attempts[0].Should().BeNear(DateTime.UtcNow); - root.Events.Last().Should().BeOfType(); + root.Events.Last().Should().BeOfType(); } [Fact] @@ -141,7 +142,7 @@ public void WhenFailDelivery_ThenFails() var result = root.FailedDelivery(); result.Should().BeSuccess(); - root.Events.Last().Should().BeOfType(); + root.Events.Last().Should().BeOfType(); } [Fact] @@ -181,7 +182,7 @@ public void WhenSucceededDelivery_ThenDelivered() result.Should().BeSuccess(); root.IsDelivered.Should().BeTrue(); root.Delivered.Should().BeNear(DateTime.UtcNow); - root.Events.Last().Should().BeOfType(); + root.Events.Last().Should().BeOfType(); } private static QueuedMessageId CreateMessageId() diff --git a/src/AncillaryDomain/AncillaryDomain.csproj b/src/AncillaryDomain/AncillaryDomain.csproj index acbb7ad7..603c53c7 100644 --- a/src/AncillaryDomain/AncillaryDomain.csproj +++ b/src/AncillaryDomain/AncillaryDomain.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/AncillaryDomain/AuditRoot.cs b/src/AncillaryDomain/AuditRoot.cs index 3322ebba..9f0816d6 100644 --- a/src/AncillaryDomain/AuditRoot.cs +++ b/src/AncillaryDomain/AuditRoot.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Ancillary.Audits; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -16,7 +17,7 @@ public static Result Create(IRecorder recorder, IIdentifierFac TemplateArguments templateArguments) { var root = new AuditRoot(recorder, idFactory); - root.RaiseCreateEvent(AncillaryDomain.Events.Audits.Created.Create(root.Id, againstId, organizationId, + root.RaiseCreateEvent(AncillaryDomain.Events.Audits.Created(root.Id, againstId, organizationId, auditCode, messageTemplate, templateArguments)); return root; @@ -62,7 +63,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Audits.Created created: + case Created created: { OrganizationId = created.OrganizationId.HasValue() ? created.OrganizationId.ToId() diff --git a/src/AncillaryDomain/EmailDeliveryRoot.cs b/src/AncillaryDomain/EmailDeliveryRoot.cs index 8813c5a8..4cdfb47a 100644 --- a/src/AncillaryDomain/EmailDeliveryRoot.cs +++ b/src/AncillaryDomain/EmailDeliveryRoot.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Entities; using Domain.Common.Identity; +using Domain.Events.Shared.Ancillary.EmailDelivery; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -15,7 +16,7 @@ public static Result Create(IRecorder recorder, IIdent QueuedMessageId messageId) { var root = new EmailDeliveryRoot(recorder, idFactory); - root.RaiseCreateEvent(AncillaryDomain.Events.EmailDelivery.Created.Create(root.Id, messageId)); + root.RaiseCreateEvent(AncillaryDomain.Events.EmailDelivery.Created(root.Id, messageId)); return root; } @@ -62,7 +63,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.EmailDelivery.Created created: + case Created created: { var messageId = QueuedMessageId.Create(created.MessageId); if (!messageId.IsSuccessful) @@ -74,7 +75,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.EmailDelivery.EmailDetailsChanged changed: + case EmailDetailsChanged changed: { var emailAddress = EmailAddress.Create(changed.ToEmailAddress); if (!emailAddress.IsSuccessful) @@ -93,7 +94,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.EmailDelivery.DeliveryAttempted changed: + case DeliveryAttempted changed: { var attempted = Attempts.Attempt(changed.When); if (!attempted.IsSuccessful) @@ -106,13 +107,13 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.EmailDelivery.DeliveryFailed _: + case DeliveryFailed _: { Recorder.TraceDebug(null, "EmailDelivery {Id} failed a delivery", Id); return Result.Ok; } - case Events.EmailDelivery.DeliverySucceeded changed: + case DeliverySucceeded changed: { Delivered = changed.When; Recorder.TraceDebug(null, "EmailDelivery {Id} succeeded delivery", Id); @@ -132,7 +133,7 @@ public Result AttemptDelivery() } var when = DateTime.UtcNow; - var attempted = RaiseChangeEvent(AncillaryDomain.Events.EmailDelivery.DeliveryAttempted.Create(Id, when)); + var attempted = RaiseChangeEvent(AncillaryDomain.Events.EmailDelivery.DeliveryAttempted(Id, when)); if (!attempted.IsSuccessful) { return attempted.Error; @@ -155,7 +156,7 @@ public Result FailedDelivery() var when = DateTime.UtcNow; return RaiseChangeEvent( - AncillaryDomain.Events.EmailDelivery.DeliveryFailed.Create(Id, when)); + AncillaryDomain.Events.EmailDelivery.DeliveryFailed(Id, when)); } public Result SetEmailDetails(string? subject, string? body, EmailRecipient recipient) @@ -173,7 +174,7 @@ public Result SetEmailDetails(string? subject, string? body, EmailRecipie } return RaiseChangeEvent( - AncillaryDomain.Events.EmailDelivery.EmailDetailsChanged.Create(Id, subject!, body!, recipient)); + AncillaryDomain.Events.EmailDelivery.EmailDetailsChanged(Id, subject!, body!, recipient)); } public Result SucceededDelivery(Optional transactionId) @@ -190,7 +191,7 @@ public Result SucceededDelivery(Optional transactionId) var when = DateTime.UtcNow; return RaiseChangeEvent( - AncillaryDomain.Events.EmailDelivery.DeliverySucceeded.Create(Id, when)); + AncillaryDomain.Events.EmailDelivery.DeliverySucceeded(Id, when)); } #if TESTINGONLY diff --git a/src/AncillaryDomain/Events.cs b/src/AncillaryDomain/Events.cs index e9c9595e..f9d815b8 100644 --- a/src/AncillaryDomain/Events.cs +++ b/src/AncillaryDomain/Events.cs @@ -1,6 +1,7 @@ using Common; using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.Ancillary.EmailDelivery; +using Created = Domain.Events.Shared.Ancillary.Audits.Created; namespace AncillaryDomain; @@ -8,145 +9,79 @@ public static class Events { public static class EmailDelivery { - public sealed class Created : IDomainEvent + public static Domain.Events.Shared.Ancillary.EmailDelivery.Created Created(Identifier id, + QueuedMessageId messageId) { - public static Created Create(Identifier id, QueuedMessageId messageId) + return new Domain.Events.Shared.Ancillary.EmailDelivery.Created { - return new Created - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - MessageId = messageId - }; - } - - public required string MessageId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + MessageId = messageId + }; } - public sealed class EmailDetailsChanged : IDomainEvent + public static DeliveryAttempted DeliveryAttempted(Identifier id, DateTime when) { - public static EmailDetailsChanged Create(Identifier id, string subject, string body, EmailRecipient to) + return new DeliveryAttempted { - return new EmailDetailsChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Subject = subject, - Body = body, - ToEmailAddress = to.EmailAddress, - ToDisplayName = to.DisplayName - }; - } - - public required string Body { get; set; } - - public required string Subject { get; set; } - - public required string ToDisplayName { get; set; } - - public required string ToEmailAddress { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + When = when + }; } - public sealed class DeliveryAttempted : IDomainEvent + public static DeliveryFailed DeliveryFailed(Identifier id, DateTime when) { - public static DeliveryAttempted Create(Identifier id, DateTime when) + return new DeliveryFailed { - return new DeliveryAttempted - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - When = when - }; - } - - public required DateTime When { get; set; } - - public required DateTime OccurredUtc { get; set; } - - public required string RootId { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + When = when + }; } - public sealed class DeliveryFailed : IDomainEvent + public static DeliverySucceeded DeliverySucceeded(Identifier id, DateTime when) { - public static DeliveryFailed Create(Identifier id, DateTime when) + return new DeliverySucceeded { - return new DeliveryFailed - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - When = when - }; - } - - public required DateTime When { get; set; } - - public required DateTime OccurredUtc { get; set; } - - public required string RootId { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + When = when + }; } - public sealed class DeliverySucceeded : IDomainEvent + public static EmailDetailsChanged EmailDetailsChanged(Identifier id, string subject, string body, + EmailRecipient to) { - public static DeliverySucceeded Create(Identifier id, DateTime when) + return new EmailDetailsChanged { - return new DeliverySucceeded - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - When = when - }; - } - - public required DateTime When { get; set; } - - public required DateTime OccurredUtc { get; set; } - - public required string RootId { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Subject = subject, + Body = body, + ToEmailAddress = to.EmailAddress, + ToDisplayName = to.DisplayName + }; } } public static class Audits { - public sealed class Created : IDomainEvent + public static Created Created(Identifier id, Identifier againstId, Optional organizationId, + string auditCode, Optional messageTemplate, TemplateArguments templateArguments) { - public static Created Create(Identifier id, Identifier againstId, Optional organizationId, - string auditCode, Optional messageTemplate, TemplateArguments templateArguments) + return new Created { - return new Created - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - OrganizationId = organizationId.HasValue - ? organizationId.Value.Text - : null, - AgainstId = againstId, - AuditCode = auditCode, - MessageTemplate = messageTemplate.ValueOrDefault ?? string.Empty, - TemplateArguments = templateArguments.Items - }; - } - - public required string AgainstId { get; set; } - - public required string AuditCode { get; set; } - - public required string MessageTemplate { get; set; } - - public string? OrganizationId { get; set; } - - public required List TemplateArguments { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + OrganizationId = organizationId.HasValue + ? organizationId.Value.Text + : null, + AgainstId = againstId, + AuditCode = auditCode, + MessageTemplate = messageTemplate.ValueOrDefault ?? string.Empty, + TemplateArguments = templateArguments.Items + }; } } } \ No newline at end of file diff --git a/src/AncillaryInfrastructure/Persistence/ReadModels/AuditProjection.cs b/src/AncillaryInfrastructure/Persistence/ReadModels/AuditProjection.cs index f709daaa..9dc7e3c7 100644 --- a/src/AncillaryInfrastructure/Persistence/ReadModels/AuditProjection.cs +++ b/src/AncillaryInfrastructure/Persistence/ReadModels/AuditProjection.cs @@ -4,6 +4,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Ancillary.Audits; using Domain.Interfaces; using Domain.Interfaces.Entities; using Infrastructure.Persistence.Common; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.Audits.Created e: + case Created e: return await _audits.HandleCreateAsync(e.RootId.ToId(), dto => { dto.OrganizationId = e.OrganizationId; diff --git a/src/AncillaryInfrastructure/Persistence/ReadModels/EmailDeliveryProjection.cs b/src/AncillaryInfrastructure/Persistence/ReadModels/EmailDeliveryProjection.cs index d1d4453d..ee8ba0ce 100644 --- a/src/AncillaryInfrastructure/Persistence/ReadModels/EmailDeliveryProjection.cs +++ b/src/AncillaryInfrastructure/Persistence/ReadModels/EmailDeliveryProjection.cs @@ -4,6 +4,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Ancillary.EmailDelivery; using Domain.Interfaces; using Domain.Interfaces.Entities; using Infrastructure.Persistence.Common; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.EmailDelivery.Created e: + case Created e: return await _deliveries.HandleCreateAsync(e.RootId.ToId(), dto => { dto.MessageId = e.MessageId; @@ -38,7 +39,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven }, cancellationToken); - case Events.EmailDelivery.EmailDetailsChanged e: + case EmailDetailsChanged e: return await _deliveries.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Subject = e.Subject; @@ -47,7 +48,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.ToDisplayName = e.ToDisplayName; }, cancellationToken); - case Events.EmailDelivery.DeliveryAttempted e: + case DeliveryAttempted e: return await _deliveries.HandleUpdateAsync(e.RootId.ToId(), dto => { var attempts = dto.Attempts.HasValue @@ -65,11 +66,11 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.LastAttempted = e.When; }, cancellationToken); - case Events.EmailDelivery.DeliveryFailed e: + case DeliveryFailed e: return await _deliveries.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Failed = e.When; }, cancellationToken); - case Events.EmailDelivery.DeliverySucceeded e: + case DeliverySucceeded e: return await _deliveries.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Delivered = e.When; }, cancellationToken); diff --git a/src/BookingsDomain.UnitTests/BookingRootSpec.cs b/src/BookingsDomain.UnitTests/BookingRootSpec.cs index 1b0f8f35..d038ef5b 100644 --- a/src/BookingsDomain.UnitTests/BookingRootSpec.cs +++ b/src/BookingsDomain.UnitTests/BookingRootSpec.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Bookings; using Domain.Interfaces.Entities; using FluentAssertions; using Moq; @@ -40,7 +41,7 @@ public void WhenChangeCar_ThenAssigned() _booking.ChangeCar("acarid".ToId()); _booking.CarId.Should().Be("acarid".ToId()); - _booking.Events.Last().Should().BeOfType(); + _booking.Events.Last().Should().BeOfType(); } [Fact] @@ -103,7 +104,7 @@ public void WhenMakeReservation_ThenAssigned() _booking.BorrowerId.Should().Be("aborrowerid".ToId()); _booking.Start.Should().Be(start); _booking.End.Should().Be(end); - _booking.Events.Last().Should().BeOfType(); + _booking.Events.Last().Should().BeOfType(); } [Fact] @@ -123,6 +124,6 @@ public void WhenStartTrip_ThenAddsTrip() result.Should().BeSuccess(); _booking.Trips.Count().Should().Be(1); - _booking.Events.Last().Should().BeOfType(); + _booking.Events.Last().Should().BeOfType(); } } \ No newline at end of file diff --git a/src/BookingsDomain.UnitTests/TripSpec.cs b/src/BookingsDomain.UnitTests/TripSpec.cs index 084fd571..139ed65e 100644 --- a/src/BookingsDomain.UnitTests/TripSpec.cs +++ b/src/BookingsDomain.UnitTests/TripSpec.cs @@ -1,6 +1,7 @@ using Common; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Bookings; using FluentAssertions; using Moq; using UnitTesting.Common; @@ -20,7 +21,7 @@ public TripSpec() var idFactory = new FixedIdentifierFactory("anid"); _trip = Trip.Create(recorder.Object, idFactory, _ => Result.Ok).Value; - _trip.RaiseChangeEvent(Events.TripAdded.Create("arootid".ToId(), "anorganizationid".ToId())); + _trip.RaiseChangeEvent(TripAdded.Create("arootid".ToId(), "anorganizationid".ToId())); } [Fact] diff --git a/src/BookingsDomain/BookingRoot.cs b/src/BookingsDomain/BookingRoot.cs index 441ed94b..15f3a4ec 100644 --- a/src/BookingsDomain/BookingRoot.cs +++ b/src/BookingsDomain/BookingRoot.cs @@ -4,6 +4,7 @@ using Domain.Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Bookings; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.Services; @@ -19,7 +20,7 @@ public static Result Create(IRecorder recorder, IIdentifierF Identifier organizationId) { var root = new BookingRoot(recorder, idFactory); - root.RaiseCreateEvent(BookingsDomain.Events.Created.Create(root.Id, organizationId)); + root.RaiseCreateEvent(BookingsDomain.Events.Created(root.Id, organizationId)); return root; } @@ -91,13 +92,13 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Created created: + case Created created: { OrganizationId = created.OrganizationId.ToId(); return Result.Ok; } - case Events.ReservationMade changed: + case ReservationMade changed: { BorrowerId = changed.BorrowerId.ToId(); Start = changed.Start; @@ -105,13 +106,13 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.CarChanged changed: + case CarChanged changed: { CarId = changed.CarId.ToId(); return Result.Ok; } - case Events.TripAdded changed: + case TripAdded changed: { var trip = RaiseEventToChildEntity(isReconstituting, changed, idFactory => Trip.Create(Recorder, idFactory, RaiseChangeEvent), e => e.TripId!); @@ -125,14 +126,14 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.TripBegan changed: + case TripBegan changed: { Recorder.TraceDebug(null, "Booking {Id} has started trip {TripId} from {From}", Id, changed.TripId, changed.BeganFrom); return Result.Ok; } - case Events.TripEnded changed: + case TripEnded changed: { Recorder.TraceDebug(null, "Booking {Id} has ended trip {TripId} at {To}", Id, changed.TripId, changed.EndedTo); @@ -156,7 +157,7 @@ public Result Cancel() public Result ChangeCar(Identifier carId) { - return RaiseChangeEvent(BookingsDomain.Events.CarChanged.Create(Id, OrganizationId, carId)); + return RaiseChangeEvent(BookingsDomain.Events.CarChanged(Id, OrganizationId, carId)); } public Result MakeReservation(Identifier borrowerId, DateTime start, DateTime end) @@ -184,7 +185,7 @@ public Result MakeReservation(Identifier borrowerId, DateTime start, Date } return RaiseChangeEvent( - BookingsDomain.Events.ReservationMade.Create(Id, OrganizationId, borrowerId, start, end)); + BookingsDomain.Events.ReservationMade(Id, OrganizationId, borrowerId, start, end)); } public Result StartTrip(Location from) @@ -194,7 +195,7 @@ public Result StartTrip(Location from) return Error.RuleViolation(Resources.BookingRoot_ReservationRequiresCar); } - var added = RaiseChangeEvent(BookingsDomain.Events.TripAdded.Create(Id, OrganizationId)); + var added = RaiseChangeEvent(TripAdded.Create(Id, OrganizationId)); if (!added.IsSuccessful) { return added.Error; diff --git a/src/BookingsDomain/BookingsDomain.csproj b/src/BookingsDomain/BookingsDomain.csproj index 98374b83..603c53c7 100644 --- a/src/BookingsDomain/BookingsDomain.csproj +++ b/src/BookingsDomain/BookingsDomain.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/BookingsDomain/Events.cs b/src/BookingsDomain/Events.cs index aff0e435..f0af4d7c 100644 --- a/src/BookingsDomain/Events.cs +++ b/src/BookingsDomain/Events.cs @@ -1,167 +1,72 @@ using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.Bookings; namespace BookingsDomain; public static class Events { - public sealed class Created : IDomainEvent + public static CarChanged CarChanged(Identifier id, Identifier organizationId, Identifier carId) { - public static Created Create(Identifier id, Identifier organizationId) + return new CarChanged { - return new Created - { - RootId = id, - OrganizationId = organizationId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string OrganizationId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + CarId = carId, + OccurredUtc = DateTime.UtcNow + }; } -#pragma warning disable SAASDDD043 - public sealed class ReservationMade : IDomainEvent -#pragma warning restore SAASDDD043 + public static Created Created(Identifier id, Identifier organizationId) { - public static ReservationMade Create(Identifier id, Identifier organizationId, Identifier borrowerId, - DateTime start, DateTime end) + return new Created { - return new ReservationMade - { - RootId = id, - OrganizationId = organizationId, - BorrowerId = borrowerId, - Start = start, - End = end, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string BorrowerId { get; set; } - - public required DateTime End { get; set; } - - public required string OrganizationId { get; set; } - - public required DateTime Start { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class CarChanged : IDomainEvent + public static ReservationMade ReservationMade(Identifier id, Identifier organizationId, Identifier borrowerId, + DateTime start, DateTime end) { - public static CarChanged Create(Identifier id, Identifier organizationId, Identifier carId) + return new ReservationMade { - return new CarChanged - { - RootId = id, - OrganizationId = organizationId, - CarId = carId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string CarId { get; set; } - - public required string OrganizationId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + BorrowerId = borrowerId, + Start = start, + End = end, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class TripAdded : IDomainEvent + public static TripBegan TripBegan(Identifier id, Identifier organizationId, Identifier tripId, + DateTime beganAt, Location from) { - public static TripAdded Create(Identifier id, Identifier organizationId) + return new TripBegan { - return new TripAdded - { - RootId = id, - OrganizationId = organizationId, - TripId = null, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string OrganizationId { get; set; } - - public string? TripId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + TripId = tripId, + BeganAt = beganAt, + BeganFrom = from, + OccurredUtc = DateTime.UtcNow + }; } -#pragma warning disable SAASDDD043 - public sealed class TripBegan : IDomainEvent -#pragma warning restore SAASDDD043 + public static TripEnded TripEnded(Identifier id, Identifier organizationId, Identifier tripId, DateTime beganAt, + Location from, DateTime endedAt, Location to) { - public static TripBegan Create(Identifier id, Identifier organizationId, Identifier tripId, - DateTime beganAt, Location from) + return new TripEnded { - return new TripBegan - { - RootId = id, - OrganizationId = organizationId, - TripId = tripId, - BeganAt = beganAt, - BeganFrom = from, - OccurredUtc = DateTime.UtcNow - }; - } - - public required DateTime BeganAt { get; set; } - - public required string BeganFrom { get; set; } - - public required string OrganizationId { get; set; } - - public required string TripId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } - } - - public sealed class TripEnded : IDomainEvent - { - public static TripEnded Create(Identifier id, Identifier organizationId, Identifier tripId, DateTime beganAt, - Location from, DateTime endedAt, Location to) - { - return new TripEnded - { - RootId = id, - OrganizationId = organizationId, - TripId = tripId, - BeganAt = beganAt, - BeganFrom = from, - EndedAt = endedAt, - EndedTo = to, - OccurredUtc = DateTime.UtcNow - }; - } - - public required DateTime BeganAt { get; set; } - - public required string BeganFrom { get; set; } - - public required DateTime EndedAt { get; set; } - - public required string EndedTo { get; set; } - - public required string OrganizationId { get; set; } - - public required string TripId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + TripId = tripId, + BeganAt = beganAt, + BeganFrom = from, + EndedAt = endedAt, + EndedTo = to, + OccurredUtc = DateTime.UtcNow + }; } } \ No newline at end of file diff --git a/src/BookingsDomain/Trip.cs b/src/BookingsDomain/Trip.cs index ebfc3424..5daac665 100644 --- a/src/BookingsDomain/Trip.cs +++ b/src/BookingsDomain/Trip.cs @@ -3,6 +3,7 @@ using Domain.Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Bookings; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.Services; @@ -69,14 +70,14 @@ protected override Result OnStateChanged(IDomainEvent @event) { switch (@event) { - case Events.TripAdded added: + case TripAdded added: { RootId = added.RootId.ToId(); OrganizationId = added.OrganizationId.ToId(); return Result.Ok; } - case Events.TripBegan changed: + case TripBegan changed: { var from = Location.Create(changed.BeganFrom); if (!from.IsSuccessful) @@ -89,7 +90,7 @@ protected override Result OnStateChanged(IDomainEvent @event) return Result.Ok; } - case Events.TripEnded changed: + case TripEnded changed: { var to = Location.Create(changed.EndedTo); if (!to.IsSuccessful) @@ -141,7 +142,7 @@ public Result Begin(Location from) } var starts = DateTime.UtcNow; - return RaiseChangeEvent(Events.TripBegan.Create(RootId.Value, OrganizationId.Value, Id, starts, from)); + return RaiseChangeEvent(Events.TripBegan(RootId.Value, OrganizationId.Value, Id, starts, from)); } public Result End(Location to) @@ -157,7 +158,7 @@ public Result End(Location to) } var ends = DateTime.UtcNow; - return RaiseChangeEvent(Events.TripEnded.Create(RootId.Value, OrganizationId.Value, Id, BeganAt.Value, + return RaiseChangeEvent(Events.TripEnded(RootId.Value, OrganizationId.Value, Id, BeganAt.Value, From.Value, ends, to)); } diff --git a/src/CarsApplication.UnitTests/CarsApplicationSpec.cs b/src/CarsApplication.UnitTests/CarsApplicationSpec.cs index 5d8f0b77..26df4673 100644 --- a/src/CarsApplication.UnitTests/CarsApplicationSpec.cs +++ b/src/CarsApplication.UnitTests/CarsApplicationSpec.cs @@ -7,6 +7,7 @@ using Domain.Common.Identity; using Domain.Common.ValueObjects; using Domain.Interfaces.Entities; +using Domain.Shared.Cars; using FluentAssertions; using Moq; using UnitTesting.Common; diff --git a/src/CarsApplication/Persistence/ReadModels/Unavailability.cs b/src/CarsApplication/Persistence/ReadModels/Unavailability.cs index dbf60fc4..2c76b791 100644 --- a/src/CarsApplication/Persistence/ReadModels/Unavailability.cs +++ b/src/CarsApplication/Persistence/ReadModels/Unavailability.cs @@ -1,6 +1,6 @@ using Application.Persistence.Common; -using CarsDomain; using Common; +using Domain.Shared.Cars; using QueryAny; namespace CarsApplication.Persistence.ReadModels; diff --git a/src/CarsDomain.UnitTests/CarRootSpec.cs b/src/CarsDomain.UnitTests/CarRootSpec.cs index 684de66e..362fe925 100644 --- a/src/CarsDomain.UnitTests/CarRootSpec.cs +++ b/src/CarsDomain.UnitTests/CarRootSpec.cs @@ -3,7 +3,9 @@ using Domain.Common.Events; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Cars; using Domain.Interfaces.Entities; +using Domain.Shared.Cars; using FluentAssertions; using Moq; using UnitTesting.Common; @@ -50,7 +52,7 @@ public void WhenSetManufacturer_ThenManufactured() _car.SetManufacturer(manufacturer); _car.Manufacturer.Should().Be(manufacturer); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -61,7 +63,7 @@ public void WhenSetOwnership_ThenOwnedAndManaged() _car.Owner.Should().Be(VehicleOwner.Create(owner.OwnerId).Value); _car.Managers.Managers.Single().Should().Be("anownerid".ToId()); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -71,7 +73,7 @@ public void WhenChangeRegistration_ThenRegistered() _car.License.Should().Be(LicensePlate.Create(Jurisdiction.AllowedCountries[0], "aplate").Value); _car.Status.Should().Be(CarStatus.Registered); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -144,7 +146,7 @@ public void WhenTakeOfflineAndAvailable_ThenOffline() _car.Unavailabilities[0].Slot.Should().Be(slot); _car.Unavailabilities[0].CausedBy!.Reason.Should().Be(UnavailabilityCausedBy.Offline); _car.Unavailabilities[0].CausedBy!.Reference.Should().BeNull(); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -190,7 +192,7 @@ public void WhenScheduleMaintenanceAndAvailable_ThenOffline() _car.Unavailabilities[0].Slot.Should().Be(slot); _car.Unavailabilities[0].CausedBy!.Reason.Should().Be(UnavailabilityCausedBy.Maintenance); _car.Unavailabilities[0].CausedBy!.Reference.Should().BeNull(); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -249,7 +251,7 @@ public void WhenReserveIfAvailableAndAvailable_ThenReturnsTrue() _car.Unavailabilities[0].Slot.Should().Be(slot); _car.Unavailabilities[0].CausedBy!.Reason.Should().Be(UnavailabilityCausedBy.Reservation); _car.Unavailabilities[0].CausedBy!.Reference.Should().Be("areference"); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } [Fact] @@ -342,8 +344,8 @@ public void WhenAddUnavailability_ThenUnavailable() _car.Unavailabilities[0].Slot.Should().Be(slot); _car.Unavailabilities[0].CausedBy!.Reason.Should().Be(UnavailabilityCausedBy.Other); _car.Unavailabilities[0].CausedBy!.Reference.Should().BeNull(); - _car.Events.Last().Should().BeOfType(); - _car.Events.Last().As().UnavailabilityId.Should() + _car.Events.Last().Should().BeOfType(); + _car.Events.Last().As().UnavailabilityId.Should() .Be("anunavailbilityid1"); } #endif @@ -360,7 +362,7 @@ public void WhenAddUnavailableAndNotExist_ThenCreatesUnavailability() _car.Unavailabilities.Count.Should().Be(1); _car.Unavailabilities[0].Slot.Should().Be(slot); - _car.Events.Last().Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif @@ -378,8 +380,8 @@ public void WhenAddUnavailableWithIntersectingSlotWithSameCauseNoReference_ThenR _car.Unavailabilities.Count.Should().Be(1); _car.Unavailabilities[0].Slot.Should().Be(slot2); - _car.Events[4].Should().BeOfType(); - _car.Events.Last().Should().BeOfType(); + _car.Events[4].Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif @@ -397,8 +399,8 @@ public void WhenAddUnavailableWithIntersectingSlotWithSameCauseSameReference_The _car.Unavailabilities.Count.Should().Be(1); _car.Unavailabilities[0].Slot.Should().Be(slot2); - _car.Events[4].Should().BeOfType(); - _car.Events.Last().Should().BeOfType(); + _car.Events[4].Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif @@ -468,8 +470,8 @@ public void WhenAddUnavailableWithNotIntersectingSlotSameCause_ThenAddsUnavailab _car.Unavailabilities.Count.Should().Be(2); _car.Unavailabilities[0].Slot.Should().Be(slot1); _car.Unavailabilities[1].Slot.Should().Be(slot2); - _car.Events[4].Should().BeOfType(); - _car.Events.Last().Should().BeOfType(); + _car.Events[4].Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif @@ -488,8 +490,8 @@ public void WhenAddUnavailableWithNotIntersectingSlotDifferentCause_ThenAddsUnav _car.Unavailabilities.Count.Should().Be(2); _car.Unavailabilities[0].Slot.Should().Be(slot1); _car.Unavailabilities[1].Slot.Should().Be(slot2); - _car.Events[4].Should().BeOfType(); - _car.Events.Last().Should().BeOfType(); + _car.Events[4].Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif @@ -509,8 +511,8 @@ public void _car.Unavailabilities.Count.Should().Be(2); _car.Unavailabilities[0].Slot.Should().Be(slot1); _car.Unavailabilities[1].Slot.Should().Be(slot2); - _car.Events[4].Should().BeOfType(); - _car.Events.Last().Should().BeOfType(); + _car.Events[4].Should().BeOfType(); + _car.Events.Last().Should().BeOfType(); } #endif diff --git a/src/CarsDomain.UnitTests/CausedBySpec.cs b/src/CarsDomain.UnitTests/CausedBySpec.cs index 5cb2fe22..471bd58a 100644 --- a/src/CarsDomain.UnitTests/CausedBySpec.cs +++ b/src/CarsDomain.UnitTests/CausedBySpec.cs @@ -1,4 +1,5 @@ using Common; +using Domain.Shared.Cars; using FluentAssertions; using UnitTesting.Common; using Xunit; diff --git a/src/CarsDomain.UnitTests/UnavailabilitySpec.cs b/src/CarsDomain.UnitTests/UnavailabilitySpec.cs index ff8d9af2..f8db9b2f 100644 --- a/src/CarsDomain.UnitTests/UnavailabilitySpec.cs +++ b/src/CarsDomain.UnitTests/UnavailabilitySpec.cs @@ -3,6 +3,7 @@ using Domain.Common.Identity; using Domain.Common.ValueObjects; using Domain.Interfaces.Entities; +using Domain.Shared.Cars; using FluentAssertions; using Moq; using UnitTesting.Common; diff --git a/src/CarsDomain/CarRoot.cs b/src/CarsDomain/CarRoot.cs index e898763f..3ddb56cb 100644 --- a/src/CarsDomain/CarRoot.cs +++ b/src/CarsDomain/CarRoot.cs @@ -3,9 +3,11 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Cars; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; +using Domain.Shared.Cars; namespace CarsDomain; @@ -15,7 +17,7 @@ public static Result Create(IRecorder recorder, IIdentifierFacto Identifier organizationId) { var root = new CarRoot(recorder, idFactory); - root.RaiseCreateEvent(CarsDomain.Events.Created.Create(root.Id, organizationId)); + root.RaiseCreateEvent(CarsDomain.Events.Created(root.Id, organizationId)); return root; } @@ -87,14 +89,14 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Created created: + case Created created: { OrganizationId = created.OrganizationId.ToId(); Status = created.Status.ToEnum(); return Result.Ok; } - case Events.ManufacturerChanged changed: + case ManufacturerChanged changed: { var manufacturer = CarsDomain.Manufacturer.Create(changed.Year, changed.Make, changed.Model); return manufacturer.Match(manu => @@ -106,7 +108,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco }, error => error); } - case Events.OwnershipChanged changed: + case OwnershipChanged changed: { var owner = VehicleOwner.Create(changed.Owner); if (!owner.IsSuccessful) @@ -120,7 +122,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.RegistrationChanged changed: + case RegistrationChanged changed: { var jurisdiction = Jurisdiction.Create(changed.Jurisdiction); if (!jurisdiction.IsSuccessful) @@ -147,7 +149,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.UnavailabilitySlotAdded created: + case UnavailabilitySlotAdded created: { var unavailability = RaiseEventToChildEntity(isReconstituting, created, idFactory => Unavailability.Create(Recorder, idFactory, RaiseChangeEvent), e => e.UnavailabilityId!); @@ -162,7 +164,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.UnavailabilitySlotRemoved deleted: + case UnavailabilitySlotRemoved deleted: { Unavailabilities.Remove(deleted.UnavailabilityId.ToId()); Recorder.TraceDebug(null, "Car {Id} has had unavailability {UnavailabilityId} removed", Id, @@ -177,7 +179,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco public Result ChangeRegistration(LicensePlate plate) { - return RaiseChangeEvent(CarsDomain.Events.RegistrationChanged.Create(Id, OrganizationId, plate)); + return RaiseChangeEvent(CarsDomain.Events.RegistrationChanged(Id, OrganizationId, plate)); } public Result Delete(Identifier deleterId) @@ -201,7 +203,7 @@ public Result ReleaseUnavailability(TimeSlot slot) if (unavailability.Exists()) { return RaiseChangeEvent( - CarsDomain.Events.UnavailabilitySlotRemoved.Create(Id, OrganizationId, unavailability.Id)); + CarsDomain.Events.UnavailabilitySlotRemoved(Id, OrganizationId, unavailability.Id)); } return Result.Ok; @@ -234,7 +236,7 @@ public Result ReserveIfAvailable(TimeSlot slot, Optional re var raised = RaiseChangeEvent( - CarsDomain.Events.UnavailabilitySlotAdded.Create(Id, OrganizationId, slot, causedBy.Value)); + CarsDomain.Events.UnavailabilitySlotAdded(Id, OrganizationId, slot, causedBy.Value)); if (!raised.IsSuccessful) { return raised.Error; @@ -264,18 +266,18 @@ public Result ScheduleMaintenance(TimeSlot slot) return causedBy.Error; } - return RaiseChangeEvent(CarsDomain.Events.UnavailabilitySlotAdded.Create(Id, OrganizationId, slot, + return RaiseChangeEvent(CarsDomain.Events.UnavailabilitySlotAdded(Id, OrganizationId, slot, causedBy.Value)); } public Result SetManufacturer(Manufacturer manufacturer) { - return RaiseChangeEvent(CarsDomain.Events.ManufacturerChanged.Create(Id, OrganizationId, manufacturer)); + return RaiseChangeEvent(CarsDomain.Events.ManufacturerChanged(Id, OrganizationId, manufacturer)); } public Result SetOwnership(VehicleOwner owner) { - return RaiseChangeEvent(CarsDomain.Events.OwnershipChanged.Create(Id, OrganizationId, owner)); + return RaiseChangeEvent(CarsDomain.Events.OwnershipChanged(Id, OrganizationId, owner)); } public Result TakeOffline(TimeSlot slot) @@ -298,7 +300,7 @@ public Result TakeOffline(TimeSlot slot) } return RaiseChangeEvent( - CarsDomain.Events.UnavailabilitySlotAdded.Create(Id, OrganizationId, slot, causedBy.Value)); + CarsDomain.Events.UnavailabilitySlotAdded(Id, OrganizationId, slot, causedBy.Value)); } private bool IsAvailable(TimeSlot slot) @@ -309,7 +311,7 @@ private bool IsAvailable(TimeSlot slot) #if TESTINGONLY public Result TestingOnly_AddUnavailability(TimeSlot slot, CausedBy causedBy) { - return RaiseChangeEvent(CarsDomain.Events.UnavailabilitySlotAdded.Create(Id, OrganizationId, slot, + return RaiseChangeEvent(CarsDomain.Events.UnavailabilitySlotAdded(Id, OrganizationId, slot, causedBy)); } diff --git a/src/CarsDomain/CarsDomain.csproj b/src/CarsDomain/CarsDomain.csproj index acbb7ad7..603c53c7 100644 --- a/src/CarsDomain/CarsDomain.csproj +++ b/src/CarsDomain/CarsDomain.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/CarsDomain/CausedBy.cs b/src/CarsDomain/CausedBy.cs index db0e3870..d17f705f 100644 --- a/src/CarsDomain/CausedBy.cs +++ b/src/CarsDomain/CausedBy.cs @@ -3,6 +3,7 @@ using Domain.Common.Extensions; using Domain.Common.ValueObjects; using Domain.Interfaces; +using Domain.Shared.Cars; namespace CarsDomain; diff --git a/src/CarsDomain/Events.cs b/src/CarsDomain/Events.cs index ff5427cc..50fbb653 100644 --- a/src/CarsDomain/Events.cs +++ b/src/CarsDomain/Events.cs @@ -1,169 +1,86 @@ using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.Cars; namespace CarsDomain; public static class Events { - public sealed class Created : IDomainEvent + public static Created Created(Identifier id, Identifier organizationId) { - public static Created Create(Identifier id, Identifier organizationId) + return new Created { - return new Created - { - RootId = id, - OrganizationId = organizationId, - OccurredUtc = DateTime.UtcNow, - Status = CarStatus.Unregistered.ToString() - }; - } - - public required string OrganizationId { get; set; } - - public required string Status { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + OccurredUtc = DateTime.UtcNow, + Status = CarStatus.Unregistered.ToString() + }; } - public sealed class ManufacturerChanged : IDomainEvent + public static ManufacturerChanged ManufacturerChanged(Identifier id, Identifier organizationId, + Manufacturer manufacturer) { - public static ManufacturerChanged Create(Identifier id, Identifier organizationId, - Manufacturer manufacturer) + return new ManufacturerChanged { - return new ManufacturerChanged - { - RootId = id, - OrganizationId = organizationId, - Year = manufacturer.Year, - Make = manufacturer.Make, - Model = manufacturer.Model, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string Make { get; set; } - - public required string Model { get; set; } - - public required string OrganizationId { get; set; } - - public required int Year { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + Year = manufacturer.Year, + Make = manufacturer.Make, + Model = manufacturer.Model, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class OwnershipChanged : IDomainEvent + public static OwnershipChanged OwnershipChanged(Identifier id, Identifier organizationId, VehicleOwner owner) { - public static OwnershipChanged Create(Identifier id, Identifier organizationId, VehicleOwner owner) + return new OwnershipChanged { - return new OwnershipChanged - { - RootId = id, - OrganizationId = organizationId, - Owner = owner.OwnerId, - Managers = new List { owner.OwnerId }, - OccurredUtc = DateTime.UtcNow - }; - } - - public required List Managers { get; set; } - - public required string OrganizationId { get; set; } - - public required string Owner { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + Owner = owner.OwnerId, + Managers = new List { owner.OwnerId }, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class RegistrationChanged : IDomainEvent + public static RegistrationChanged RegistrationChanged(Identifier id, Identifier organizationId, LicensePlate plate) { - public static RegistrationChanged Create(Identifier id, Identifier organizationId, LicensePlate plate) + return new RegistrationChanged { - return new RegistrationChanged - { - RootId = id, - OrganizationId = organizationId, - Jurisdiction = plate.Jurisdiction, - Number = plate.Number, - Status = CarStatus.Registered.ToString(), - OccurredUtc = DateTime.UtcNow - }; - } - - public required string Jurisdiction { get; set; } - - public required string Number { get; set; } - - public required string OrganizationId { get; set; } - - public required string Status { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + Jurisdiction = plate.Jurisdiction, + Number = plate.Number, + Status = CarStatus.Registered.ToString(), + OccurredUtc = DateTime.UtcNow + }; } - public sealed class UnavailabilitySlotAdded : IDomainEvent + public static UnavailabilitySlotAdded UnavailabilitySlotAdded(Identifier id, Identifier organizationId, + TimeSlot slot, + CausedBy causedBy) { - public static UnavailabilitySlotAdded Create(Identifier id, Identifier organizationId, TimeSlot slot, - CausedBy causedBy) + return new UnavailabilitySlotAdded { - return new UnavailabilitySlotAdded - { - RootId = id, - OrganizationId = organizationId, - From = slot.From, - To = slot.To, - CausedByReason = causedBy.Reason, - CausedByReference = causedBy.Reference, - UnavailabilityId = null, - OccurredUtc = DateTime.UtcNow - }; - } - - public required UnavailabilityCausedBy CausedByReason { get; set; } - - public string? CausedByReference { get; set; } - - public required DateTime From { get; set; } - - public required string OrganizationId { get; set; } - - public required DateTime To { get; set; } - - public string? UnavailabilityId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + From = slot.From, + To = slot.To, + CausedByReason = causedBy.Reason, + CausedByReference = causedBy.Reference, + UnavailabilityId = null, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class UnavailabilitySlotRemoved : IDomainEvent + public static UnavailabilitySlotRemoved UnavailabilitySlotRemoved(Identifier id, Identifier organizationId, + Identifier unavailabilityId) { - public static UnavailabilitySlotRemoved Create(Identifier id, Identifier organizationId, - Identifier unavailabilityId) + return new UnavailabilitySlotRemoved { - return new UnavailabilitySlotRemoved - { - RootId = id, - OrganizationId = organizationId, - UnavailabilityId = unavailabilityId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string OrganizationId { get; set; } - - public required string UnavailabilityId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OrganizationId = organizationId, + UnavailabilityId = unavailabilityId, + OccurredUtc = DateTime.UtcNow + }; } } \ No newline at end of file diff --git a/src/CarsDomain/Unavailability.cs b/src/CarsDomain/Unavailability.cs index ef8387f6..081a2045 100644 --- a/src/CarsDomain/Unavailability.cs +++ b/src/CarsDomain/Unavailability.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Cars; using Domain.Interfaces.Entities; namespace CarsDomain; @@ -48,7 +49,7 @@ protected override Result OnStateChanged(IDomainEvent @event) { switch (@event) { - case Events.UnavailabilitySlotAdded added: + case UnavailabilitySlotAdded added: { var slot = TimeSlot.Create(added.From, added.To); if (!slot.IsSuccessful) @@ -109,7 +110,7 @@ public Result Overlaps(TimeSlot slot) public void TestingOnly_Assign(Identifier carId, Identifier organizationId, TimeSlot timeSlot, CausedBy causedBy) { - RaiseChangeEvent(Events.UnavailabilitySlotAdded.Create(carId, organizationId, timeSlot, causedBy)); + RaiseChangeEvent(Events.UnavailabilitySlotAdded(carId, organizationId, timeSlot, causedBy)); } #endif } \ No newline at end of file diff --git a/src/CarsInfrastructure.IntegrationTests/CarsApiSpec.cs b/src/CarsInfrastructure.IntegrationTests/CarsApiSpec.cs index 99c41d28..4f07879c 100644 --- a/src/CarsInfrastructure.IntegrationTests/CarsApiSpec.cs +++ b/src/CarsInfrastructure.IntegrationTests/CarsApiSpec.cs @@ -2,6 +2,7 @@ using ApiHost1; using Application.Resources.Shared; using CarsDomain; +using Domain.Shared.Cars; using FluentAssertions; using Infrastructure.Web.Api.Common.Extensions; using Infrastructure.Web.Api.Operations.Shared.Cars; diff --git a/src/CarsInfrastructure/Persistence/ReadModels/CarProjection.cs b/src/CarsInfrastructure/Persistence/ReadModels/CarProjection.cs index 88afb40a..14c826ad 100644 --- a/src/CarsInfrastructure/Persistence/ReadModels/CarProjection.cs +++ b/src/CarsInfrastructure/Persistence/ReadModels/CarProjection.cs @@ -4,6 +4,7 @@ using CarsDomain; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Cars; using Domain.Interfaces; using Domain.Interfaces.Entities; using Infrastructure.Persistence.Common; @@ -30,14 +31,14 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.Created e: + case Created e: return await _cars.HandleCreateAsync(e.RootId.ToId(), dto => { dto.OrganizationId = e.OrganizationId; dto.Status = e.Status; }, cancellationToken); - case Events.ManufacturerChanged e: + case ManufacturerChanged e: return await _cars.HandleUpdateAsync(e.RootId, dto => { dto.ManufactureYear = e.Year; @@ -45,14 +46,14 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.ManufactureModel = e.Model; }, cancellationToken); - case Events.OwnershipChanged e: + case OwnershipChanged e: return await _cars.HandleUpdateAsync(e.RootId, dto => { dto.VehicleOwnerId = e.Owner; dto.ManagerIds = VehicleManagers.Create(e.Owner).Value; }, cancellationToken); - case Events.RegistrationChanged e: + case RegistrationChanged e: return await _cars.HandleUpdateAsync(e.RootId, dto => { dto.LicenseJurisdiction = e.Jurisdiction; @@ -60,7 +61,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Status = e.Status; }, cancellationToken); - case Events.UnavailabilitySlotAdded e: + case UnavailabilitySlotAdded e: return await _unavailabilities.HandleCreateAsync(e.UnavailabilityId!, dto => { dto.OrganizationId = e.OrganizationId; @@ -71,7 +72,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.CausedByReference = e.CausedByReference!; }, cancellationToken); - case Events.UnavailabilitySlotRemoved e: + case UnavailabilitySlotRemoved e: return await _unavailabilities.HandleDeleteAsync(e.UnavailabilityId, cancellationToken); default: diff --git a/src/Domain.Events.Shared/Ancillary/Audits/Created.cs b/src/Domain.Events.Shared/Ancillary/Audits/Created.cs new file mode 100644 index 00000000..cd25f570 --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/Audits/Created.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.Audits; + +public sealed class Created : IDomainEvent +{ + public required string AgainstId { get; set; } + + public required string AuditCode { get; set; } + + public required string MessageTemplate { get; set; } + + public string? OrganizationId { get; set; } + + public required List TemplateArguments { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Ancillary/EmailDelivery/Created.cs b/src/Domain.Events.Shared/Ancillary/EmailDelivery/Created.cs new file mode 100644 index 00000000..142d5392 --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/EmailDelivery/Created.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.EmailDelivery; + +public sealed class Created : IDomainEvent +{ + public required string MessageId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryAttempted.cs b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryAttempted.cs new file mode 100644 index 00000000..05dc3fbb --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryAttempted.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.EmailDelivery; + +public sealed class DeliveryAttempted : IDomainEvent +{ + public required DateTime When { get; set; } + + public required DateTime OccurredUtc { get; set; } + + public required string RootId { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryFailed.cs b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryFailed.cs new file mode 100644 index 00000000..5339e65a --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliveryFailed.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.EmailDelivery; + +public sealed class DeliveryFailed : IDomainEvent +{ + public required DateTime When { get; set; } + + public required DateTime OccurredUtc { get; set; } + + public required string RootId { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliverySucceeded.cs b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliverySucceeded.cs new file mode 100644 index 00000000..f13df0b6 --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/EmailDelivery/DeliverySucceeded.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.EmailDelivery; + +public sealed class DeliverySucceeded : IDomainEvent +{ + public required DateTime When { get; set; } + + public required DateTime OccurredUtc { get; set; } + + public required string RootId { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Ancillary/EmailDelivery/EmailDetailsChanged.cs b/src/Domain.Events.Shared/Ancillary/EmailDelivery/EmailDetailsChanged.cs new file mode 100644 index 00000000..194d69ae --- /dev/null +++ b/src/Domain.Events.Shared/Ancillary/EmailDelivery/EmailDetailsChanged.cs @@ -0,0 +1,18 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Ancillary.EmailDelivery; + +public sealed class EmailDetailsChanged : IDomainEvent +{ + public required string Body { get; set; } + + public required string Subject { get; set; } + + public required string ToDisplayName { get; set; } + + public required string ToEmailAddress { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/CarChanged.cs b/src/Domain.Events.Shared/Bookings/CarChanged.cs new file mode 100644 index 00000000..d073ad6c --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/CarChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +public sealed class CarChanged : IDomainEvent +{ + public required string CarId { get; set; } + + public required string OrganizationId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/Created.cs b/src/Domain.Events.Shared/Bookings/Created.cs new file mode 100644 index 00000000..dca639f9 --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/Created.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +public sealed class Created : IDomainEvent +{ + public required string OrganizationId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/ReservationMade.cs b/src/Domain.Events.Shared/Bookings/ReservationMade.cs new file mode 100644 index 00000000..3e257ba7 --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/ReservationMade.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +#pragma warning disable SAASDDD043 +public sealed class ReservationMade : IDomainEvent +#pragma warning restore SAASDDD043 +{ + public required string BorrowerId { get; set; } + + public required DateTime End { get; set; } + + public required string OrganizationId { get; set; } + + public required DateTime Start { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/TripAdded.cs b/src/Domain.Events.Shared/Bookings/TripAdded.cs new file mode 100644 index 00000000..79cca4c3 --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/TripAdded.cs @@ -0,0 +1,26 @@ +using Domain.Common.ValueObjects; +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +public sealed class TripAdded : IDomainEvent +{ + public static TripAdded Create(Identifier id, Identifier organizationId) + { + return new TripAdded + { + RootId = id, + OrganizationId = organizationId, + TripId = null, + OccurredUtc = DateTime.UtcNow + }; + } + + public required string OrganizationId { get; set; } + + public string? TripId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/TripBegan.cs b/src/Domain.Events.Shared/Bookings/TripBegan.cs new file mode 100644 index 00000000..7f3fea0e --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/TripBegan.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +#pragma warning disable SAASDDD043 +public sealed class TripBegan : IDomainEvent +#pragma warning restore SAASDDD043 +{ + public required DateTime BeganAt { get; set; } + + public required string BeganFrom { get; set; } + + public required string OrganizationId { get; set; } + + public required string TripId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Bookings/TripEnded.cs b/src/Domain.Events.Shared/Bookings/TripEnded.cs new file mode 100644 index 00000000..2215c618 --- /dev/null +++ b/src/Domain.Events.Shared/Bookings/TripEnded.cs @@ -0,0 +1,22 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Bookings; + +public sealed class TripEnded : IDomainEvent +{ + public required DateTime BeganAt { get; set; } + + public required string BeganFrom { get; set; } + + public required DateTime EndedAt { get; set; } + + public required string EndedTo { get; set; } + + public required string OrganizationId { get; set; } + + public required string TripId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/Created.cs b/src/Domain.Events.Shared/Cars/Created.cs new file mode 100644 index 00000000..dacbc524 --- /dev/null +++ b/src/Domain.Events.Shared/Cars/Created.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Cars; + +public sealed class Created : IDomainEvent +{ + public required string OrganizationId { get; set; } + + public required string Status { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/ManufacturerChanged.cs b/src/Domain.Events.Shared/Cars/ManufacturerChanged.cs new file mode 100644 index 00000000..62de6340 --- /dev/null +++ b/src/Domain.Events.Shared/Cars/ManufacturerChanged.cs @@ -0,0 +1,18 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Cars; + +public sealed class ManufacturerChanged : IDomainEvent +{ + public required string Make { get; set; } + + public required string Model { get; set; } + + public required string OrganizationId { get; set; } + + public required int Year { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/OwnershipChanged.cs b/src/Domain.Events.Shared/Cars/OwnershipChanged.cs new file mode 100644 index 00000000..ef2211ac --- /dev/null +++ b/src/Domain.Events.Shared/Cars/OwnershipChanged.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Cars; + +public sealed class OwnershipChanged : IDomainEvent +{ + public required List Managers { get; set; } + + public required string OrganizationId { get; set; } + + public required string Owner { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/RegistrationChanged.cs b/src/Domain.Events.Shared/Cars/RegistrationChanged.cs new file mode 100644 index 00000000..79d62301 --- /dev/null +++ b/src/Domain.Events.Shared/Cars/RegistrationChanged.cs @@ -0,0 +1,18 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Cars; + +public sealed class RegistrationChanged : IDomainEvent +{ + public required string Jurisdiction { get; set; } + + public required string Number { get; set; } + + public required string OrganizationId { get; set; } + + public required string Status { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/UnavailabilitySlotAdded.cs b/src/Domain.Events.Shared/Cars/UnavailabilitySlotAdded.cs new file mode 100644 index 00000000..4621c9e4 --- /dev/null +++ b/src/Domain.Events.Shared/Cars/UnavailabilitySlotAdded.cs @@ -0,0 +1,23 @@ +using Domain.Interfaces.Entities; +using Domain.Shared.Cars; + +namespace Domain.Events.Shared.Cars; + +public sealed class UnavailabilitySlotAdded : IDomainEvent +{ + public required UnavailabilityCausedBy CausedByReason { get; set; } + + public string? CausedByReference { get; set; } + + public required DateTime From { get; set; } + + public required string OrganizationId { get; set; } + + public required DateTime To { get; set; } + + public string? UnavailabilityId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Cars/UnavailabilitySlotRemoved.cs b/src/Domain.Events.Shared/Cars/UnavailabilitySlotRemoved.cs new file mode 100644 index 00000000..01c302b0 --- /dev/null +++ b/src/Domain.Events.Shared/Cars/UnavailabilitySlotRemoved.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Cars; + +public sealed class UnavailabilitySlotRemoved : IDomainEvent +{ + public required string OrganizationId { get; set; } + + public required string UnavailabilityId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Domain.Events.Shared.csproj b/src/Domain.Events.Shared/Domain.Events.Shared.csproj new file mode 100644 index 00000000..3ac942a6 --- /dev/null +++ b/src/Domain.Events.Shared/Domain.Events.Shared.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + + + + + + + + + + <_Parameter1>$(AssemblyName).UnitTests + + + + diff --git a/src/Domain.Events.Shared/EndUsers/Created.cs b/src/Domain.Events.Shared/EndUsers/Created.cs new file mode 100644 index 00000000..9c838918 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/Created.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class Created : IDomainEvent +{ + public required string Access { get; set; } + + public required string Classification { get; set; } + + public required string Status { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/GuestInvitationAccepted.cs b/src/Domain.Events.Shared/EndUsers/GuestInvitationAccepted.cs new file mode 100644 index 00000000..ba4dc3cb --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/GuestInvitationAccepted.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class GuestInvitationAccepted : IDomainEvent +{ + public required DateTime AcceptedAtUtc { get; set; } + + public required string AcceptedEmailAddress { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/GuestInvitationCreated.cs b/src/Domain.Events.Shared/EndUsers/GuestInvitationCreated.cs new file mode 100644 index 00000000..aa2f8bec --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/GuestInvitationCreated.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class GuestInvitationCreated : IDomainEvent +{ + public required string EmailAddress { get; set; } + + public required string InvitedById { get; set; } + + public required string Token { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/MembershipAdded.cs b/src/Domain.Events.Shared/EndUsers/MembershipAdded.cs new file mode 100644 index 00000000..5b677c78 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/MembershipAdded.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class MembershipAdded : IDomainEvent +{ + public required List Features { get; set; } + + public required bool IsDefault { get; set; } + + public string? MembershipId { get; set; } + + public required string OrganizationId { get; set; } + + public required List Roles { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/MembershipDefaultChanged.cs b/src/Domain.Events.Shared/EndUsers/MembershipDefaultChanged.cs new file mode 100644 index 00000000..0c75f3e2 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/MembershipDefaultChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class MembershipDefaultChanged : IDomainEvent +{ + public required string FromMembershipId { get; set; } + + public required string ToMembershipId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/MembershipFeatureAssigned.cs b/src/Domain.Events.Shared/EndUsers/MembershipFeatureAssigned.cs new file mode 100644 index 00000000..b9a5cb73 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/MembershipFeatureAssigned.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class MembershipFeatureAssigned : IDomainEvent +{ + public required string Feature { get; set; } + + public required string MembershipId { get; set; } + + public required string OrganizationId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/MembershipRoleAssigned.cs b/src/Domain.Events.Shared/EndUsers/MembershipRoleAssigned.cs new file mode 100644 index 00000000..81485346 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/MembershipRoleAssigned.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class MembershipRoleAssigned : IDomainEvent +{ + public required string MembershipId { get; set; } + + public required string OrganizationId { get; set; } + + public required string Role { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/PlatformFeatureAssigned.cs b/src/Domain.Events.Shared/EndUsers/PlatformFeatureAssigned.cs new file mode 100644 index 00000000..1e953762 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/PlatformFeatureAssigned.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class PlatformFeatureAssigned : IDomainEvent +{ + public required string Feature { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/PlatformRoleAssigned.cs b/src/Domain.Events.Shared/EndUsers/PlatformRoleAssigned.cs new file mode 100644 index 00000000..41bdce85 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/PlatformRoleAssigned.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class PlatformRoleAssigned : IDomainEvent +{ + public required string Role { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/PlatformRoleUnassigned.cs b/src/Domain.Events.Shared/EndUsers/PlatformRoleUnassigned.cs new file mode 100644 index 00000000..c535d3d0 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/PlatformRoleUnassigned.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class PlatformRoleUnassigned : IDomainEvent +{ + public required string Role { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/EndUsers/Registered.cs b/src/Domain.Events.Shared/EndUsers/Registered.cs new file mode 100644 index 00000000..2304bf35 --- /dev/null +++ b/src/Domain.Events.Shared/EndUsers/Registered.cs @@ -0,0 +1,22 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.EndUsers; + +public sealed class Registered : IDomainEvent +{ + public required string Access { get; set; } + + public required string Classification { get; set; } + + public required List Features { get; set; } + + public required List Roles { get; set; } + + public required string Status { get; set; } + + public string? Username { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/APIKeys/Created.cs b/src/Domain.Events.Shared/Identities/APIKeys/Created.cs new file mode 100644 index 00000000..79c344ea --- /dev/null +++ b/src/Domain.Events.Shared/Identities/APIKeys/Created.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.APIKeys; + +public sealed class Created : IDomainEvent +{ + public required string KeyHash { get; set; } + + public required string KeyToken { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/APIKeys/KeyVerified.cs b/src/Domain.Events.Shared/Identities/APIKeys/KeyVerified.cs new file mode 100644 index 00000000..1919a516 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/APIKeys/KeyVerified.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.APIKeys; + +public sealed class KeyVerified : IDomainEvent +{ + public required bool IsVerified { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/APIKeys/ParametersChanged.cs b/src/Domain.Events.Shared/Identities/APIKeys/ParametersChanged.cs new file mode 100644 index 00000000..6af5ffc7 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/APIKeys/ParametersChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.APIKeys; + +public sealed class ParametersChanged : IDomainEvent +{ + public required string Description { get; set; } + + public required DateTime ExpiresOn { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/AuthTokens/Created.cs b/src/Domain.Events.Shared/Identities/AuthTokens/Created.cs new file mode 100644 index 00000000..5c8bd04f --- /dev/null +++ b/src/Domain.Events.Shared/Identities/AuthTokens/Created.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.AuthTokens; + +public sealed class Created : IDomainEvent +{ + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/AuthTokens/TokensChanged.cs b/src/Domain.Events.Shared/Identities/AuthTokens/TokensChanged.cs new file mode 100644 index 00000000..3df89691 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/AuthTokens/TokensChanged.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.AuthTokens; + +public sealed class TokensChanged : IDomainEvent +{ + public required string AccessToken { get; set; } + + public required DateTime AccessTokenExpiresOn { get; set; } + + public required string RefreshToken { get; set; } + + public required DateTime RefreshTokenExpiresOn { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/AuthTokens/TokensRefreshed.cs b/src/Domain.Events.Shared/Identities/AuthTokens/TokensRefreshed.cs new file mode 100644 index 00000000..654b018a --- /dev/null +++ b/src/Domain.Events.Shared/Identities/AuthTokens/TokensRefreshed.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.AuthTokens; + +public sealed class TokensRefreshed : IDomainEvent +{ + public required string AccessToken { get; set; } + + public required DateTime AccessTokenExpiresOn { get; set; } + + public required string RefreshToken { get; set; } + + public required DateTime RefreshTokenExpiresOn { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/AuthTokens/TokensRevoked.cs b/src/Domain.Events.Shared/Identities/AuthTokens/TokensRevoked.cs new file mode 100644 index 00000000..e68bcfa3 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/AuthTokens/TokensRevoked.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.AuthTokens; + +public sealed class TokensRevoked : IDomainEvent +{ + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountLocked.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountLocked.cs new file mode 100644 index 00000000..31ebbb83 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountLocked.cs @@ -0,0 +1,10 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class AccountLocked : IDomainEvent +{ + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountUnlocked.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountUnlocked.cs new file mode 100644 index 00000000..31dc3fb9 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/AccountUnlocked.cs @@ -0,0 +1,10 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class AccountUnlocked : IDomainEvent +{ + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/Created.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/Created.cs new file mode 100644 index 00000000..bd5c3c33 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/Created.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class Created : IDomainEvent +{ + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/CredentialsChanged.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/CredentialsChanged.cs new file mode 100644 index 00000000..b4e8802e --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/CredentialsChanged.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class CredentialsChanged : IDomainEvent +{ + public required string PasswordHash { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetCompleted.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetCompleted.cs new file mode 100644 index 00000000..c13a466c --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetCompleted.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class PasswordResetCompleted : IDomainEvent +{ + public required string PasswordHash { get; set; } + + public required string Token { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetInitiated.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetInitiated.cs new file mode 100644 index 00000000..cdab4996 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordResetInitiated.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class PasswordResetInitiated : IDomainEvent +{ + public required string Token { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordVerified.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordVerified.cs new file mode 100644 index 00000000..7033d830 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/PasswordVerified.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class PasswordVerified : IDomainEvent +{ + public required bool AuditAttempt { get; set; } + + public required bool IsVerified { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationChanged.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationChanged.cs new file mode 100644 index 00000000..1d339d5e --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class RegistrationChanged : IDomainEvent +{ + public required string EmailAddress { get; set; } + + public required string Name { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationCreated.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationCreated.cs new file mode 100644 index 00000000..55a46fc0 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationCreated.cs @@ -0,0 +1,12 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class RegistrationVerificationCreated : IDomainEvent +{ + public required string Token { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationVerified.cs b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationVerified.cs new file mode 100644 index 00000000..dfbec156 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/PasswordCredentials/RegistrationVerificationVerified.cs @@ -0,0 +1,10 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.PasswordCredentials; + +public sealed class RegistrationVerificationVerified : IDomainEvent +{ + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/SSOUsers/Created.cs b/src/Domain.Events.Shared/Identities/SSOUsers/Created.cs new file mode 100644 index 00000000..b7956520 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/SSOUsers/Created.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.SSOUsers; + +public sealed class Created : IDomainEvent +{ + public required string ProviderName { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Identities/SSOUsers/TokensUpdated.cs b/src/Domain.Events.Shared/Identities/SSOUsers/TokensUpdated.cs new file mode 100644 index 00000000..2136f743 --- /dev/null +++ b/src/Domain.Events.Shared/Identities/SSOUsers/TokensUpdated.cs @@ -0,0 +1,22 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.Identities.SSOUsers; + +public sealed class TokensUpdated : IDomainEvent +{ + public required string CountryCode { get; set; } + + public required string EmailAddress { get; set; } + + public required string FirstName { get; set; } + + public string? LastName { get; set; } + + public required string Timezone { get; set; } + + public required string Tokens { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Organizations/Created.cs b/src/Domain.Events.Shared/Organizations/Created.cs new file mode 100644 index 00000000..7bd9907d --- /dev/null +++ b/src/Domain.Events.Shared/Organizations/Created.cs @@ -0,0 +1,17 @@ +using Domain.Interfaces.Entities; +using Domain.Shared.Organizations; + +namespace Domain.Events.Shared.Organizations; + +public sealed class Created : IDomainEvent +{ + public required string CreatedById { get; set; } + + public required string Name { get; set; } + + public required OrganizationOwnership Ownership { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Organizations/SettingCreated.cs b/src/Domain.Events.Shared/Organizations/SettingCreated.cs new file mode 100644 index 00000000..61e40d02 --- /dev/null +++ b/src/Domain.Events.Shared/Organizations/SettingCreated.cs @@ -0,0 +1,19 @@ +using Domain.Interfaces.Entities; +using Domain.Shared.Organizations; + +namespace Domain.Events.Shared.Organizations; + +public sealed class SettingCreated : IDomainEvent +{ + public required bool IsEncrypted { get; set; } + + public required string Name { get; set; } + + public required string StringValue { get; set; } + + public required SettingValueType ValueType { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/Organizations/SettingUpdated.cs b/src/Domain.Events.Shared/Organizations/SettingUpdated.cs new file mode 100644 index 00000000..c8a5c299 --- /dev/null +++ b/src/Domain.Events.Shared/Organizations/SettingUpdated.cs @@ -0,0 +1,23 @@ +using Domain.Interfaces.Entities; +using Domain.Shared.Organizations; + +namespace Domain.Events.Shared.Organizations; + +public sealed class SettingUpdated : IDomainEvent +{ + public required string From { get; set; } + + public required SettingValueType FromType { get; set; } + + public required bool IsEncrypted { get; set; } + + public required string Name { get; set; } + + public required string To { get; set; } + + public required SettingValueType ToType { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/ContactAddressChanged.cs b/src/Domain.Events.Shared/UserProfiles/ContactAddressChanged.cs new file mode 100644 index 00000000..8f79a4fc --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/ContactAddressChanged.cs @@ -0,0 +1,26 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class ContactAddressChanged : IDomainEvent +{ + public string? City { get; set; } + + public required string CountryCode { get; set; } + + public string? Line1 { get; set; } + + public string? Line2 { get; set; } + + public string? Line3 { get; set; } + + public string? State { get; set; } + + public required string UserId { get; set; } + + public string? Zip { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/Created.cs b/src/Domain.Events.Shared/UserProfiles/Created.cs new file mode 100644 index 00000000..f28d432e --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/Created.cs @@ -0,0 +1,20 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class Created : IDomainEvent +{ + public required string DisplayName { get; set; } + + public required string FirstName { get; set; } + + public string? LastName { get; set; } + + public required string Type { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/DisplayNameChanged.cs b/src/Domain.Events.Shared/UserProfiles/DisplayNameChanged.cs new file mode 100644 index 00000000..fc23dadf --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/DisplayNameChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class DisplayNameChanged : IDomainEvent +{ + public required string DisplayName { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/EmailAddressChanged.cs b/src/Domain.Events.Shared/UserProfiles/EmailAddressChanged.cs new file mode 100644 index 00000000..4c8910fa --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/EmailAddressChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class EmailAddressChanged : IDomainEvent +{ + public required string EmailAddress { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/NameChanged.cs b/src/Domain.Events.Shared/UserProfiles/NameChanged.cs new file mode 100644 index 00000000..24911fd2 --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/NameChanged.cs @@ -0,0 +1,16 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class NameChanged : IDomainEvent +{ + public required string FirstName { get; set; } + + public string? LastName { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/PhoneNumberChanged.cs b/src/Domain.Events.Shared/UserProfiles/PhoneNumberChanged.cs new file mode 100644 index 00000000..9a1d92a3 --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/PhoneNumberChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class PhoneNumberChanged : IDomainEvent +{ + public required string Number { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Events.Shared/UserProfiles/TimezoneChanged.cs b/src/Domain.Events.Shared/UserProfiles/TimezoneChanged.cs new file mode 100644 index 00000000..1d4cdb23 --- /dev/null +++ b/src/Domain.Events.Shared/UserProfiles/TimezoneChanged.cs @@ -0,0 +1,14 @@ +using Domain.Interfaces.Entities; + +namespace Domain.Events.Shared.UserProfiles; + +public sealed class TimezoneChanged : IDomainEvent +{ + public required string Timezone { get; set; } + + public required string UserId { get; set; } + + public required string RootId { get; set; } + + public required DateTime OccurredUtc { get; set; } +} \ No newline at end of file diff --git a/src/Domain.Services.Shared/DomainServices/ITokensService.cs b/src/Domain.Services.Shared/DomainServices/ITokensService.cs index e25fb310..10907a7c 100644 --- a/src/Domain.Services.Shared/DomainServices/ITokensService.cs +++ b/src/Domain.Services.Shared/DomainServices/ITokensService.cs @@ -1,5 +1,5 @@ using Common; -using Domain.Shared; +using Domain.Shared.Identities; namespace Domain.Services.Shared.DomainServices; diff --git a/src/CarsDomain/UnavailabilityCausedBy.cs b/src/Domain.Shared/Cars/UnavailabilityCausedBy.cs similarity index 77% rename from src/CarsDomain/UnavailabilityCausedBy.cs rename to src/Domain.Shared/Cars/UnavailabilityCausedBy.cs index 4c7a345f..e0b59a64 100644 --- a/src/CarsDomain/UnavailabilityCausedBy.cs +++ b/src/Domain.Shared/Cars/UnavailabilityCausedBy.cs @@ -1,4 +1,4 @@ -namespace CarsDomain; +namespace Domain.Shared.Cars; public enum UnavailabilityCausedBy { diff --git a/src/Domain.Shared/APIKeyToken.cs b/src/Domain.Shared/Identities/APIKeyToken.cs similarity index 85% rename from src/Domain.Shared/APIKeyToken.cs rename to src/Domain.Shared/Identities/APIKeyToken.cs index 3110f392..f412807c 100644 --- a/src/Domain.Shared/APIKeyToken.cs +++ b/src/Domain.Shared/Identities/APIKeyToken.cs @@ -1,4 +1,4 @@ -namespace Domain.Shared; +namespace Domain.Shared.Identities; public class APIKeyToken { diff --git a/src/Domain.Shared/Organizations/OrganizationOwnership.cs b/src/Domain.Shared/Organizations/OrganizationOwnership.cs new file mode 100644 index 00000000..c213d5aa --- /dev/null +++ b/src/Domain.Shared/Organizations/OrganizationOwnership.cs @@ -0,0 +1,7 @@ +namespace Domain.Shared.Organizations; + +public enum OrganizationOwnership +{ + Shared = 0, + Personal = 1 +} \ No newline at end of file diff --git a/src/Domain.Shared/Organizations/SettingValueType.cs b/src/Domain.Shared/Organizations/SettingValueType.cs new file mode 100644 index 00000000..a0f7654a --- /dev/null +++ b/src/Domain.Shared/Organizations/SettingValueType.cs @@ -0,0 +1,8 @@ +namespace Domain.Shared.Organizations; + +public enum SettingValueType +{ + String = 0, + Number = 1, + Boolean = 2 +} \ No newline at end of file diff --git a/src/EndUsersDomain.UnitTests/EndUserRootSpec.cs b/src/EndUsersDomain.UnitTests/EndUserRootSpec.cs index 459b1ae4..a81b0f57 100644 --- a/src/EndUsersDomain.UnitTests/EndUserRootSpec.cs +++ b/src/EndUsersDomain.UnitTests/EndUserRootSpec.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.EndUsers; using Domain.Interfaces; using Domain.Interfaces.Authorization; using Domain.Interfaces.Entities; @@ -71,8 +72,8 @@ await _user.InviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), emailA _user.Features.Items.Should().ContainInOrder(Feature.Create(PlatformFeatures.Basic.Name).Value); _user.GuestInvitation.IsAccepted.Should().BeTrue(); _user.GuestInvitation.AcceptedEmailAddress.Should().Be(emailAddress); - _user.Events[2].Should().BeOfType(); - _user.Events.Last().Should().BeOfType(); + _user.Events[2].Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } [Fact] @@ -87,7 +88,7 @@ public void WhenRegister_ThenRegistered() _user.Classification.Should().Be(UserClassification.Person); _user.Roles.Items.Should().ContainInOrder(Role.Create(PlatformRoles.Standard.Name).Value); _user.Features.Items.Should().ContainInOrder(Feature.Create(PlatformFeatures.Basic.Name).Value); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } [Fact] @@ -170,7 +171,7 @@ public void WhenAddMembership_ThenAddsMembershipAsDefaultWithRolesAndFeatures() && ms.IsDefault && ms.Roles == roles && ms.Features == features); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } [Fact] @@ -196,7 +197,7 @@ public void WhenAddMembershipAndHasMembership_ThenChangesNextToDefaultMembership && ms.IsDefault && ms.Roles == roles && ms.Features == features); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #if TESTINGONLY @@ -260,7 +261,7 @@ public void WhenAssignMembershipFeatures_ThenAssigns() _user.Memberships[0].Roles.Should().Be(Roles.Create(TenantRoles.Member.Name).Value); _user.Memberships[0].Features.Should() .Be(Features.Create(TenantFeatures.Basic.Name, TenantFeatures.TestingOnly.Name).Value); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #endif @@ -313,7 +314,7 @@ public void WhenAssignMembershipRoles_ThenAssigns() .Be(Roles.Create(TenantRoles.Member.Name, TenantRoles.TestingOnly.Name).Value); _user.Memberships[0].Features.Should() .Be(Features.Create(TenantFeatures.Basic.Name).Value); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #endif @@ -351,7 +352,7 @@ public void WhenAssignPlatformFeatures_ThenAssigns() result.Should().BeSuccess(); _user.Roles.HasNone().Should().BeTrue(); _user.Features.Should().Be(Features.Create(PlatformFeatures.TestingOnly.Name).Value); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #endif @@ -389,7 +390,7 @@ public void WhenAssignPlatformRoles_ThenAssigns() result.Should().BeSuccess(); _user.Roles.Should().Be(Roles.Create(PlatformRoles.TestingOnly.Name).Value); _user.Features.HasNone().Should().BeTrue(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #endif @@ -454,7 +455,7 @@ public void WhenUnassignPlatformRoles_ThenUnassigns() result.Should().BeSuccess(); _user.Roles.HasNone().Should().BeTrue(); _user.Features.HasNone().Should().BeTrue(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } #endif @@ -473,7 +474,7 @@ await _user.InviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), emailA }); wasCallbackCalled.Should().BeFalse(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); _user.GuestInvitation.IsInvited.Should().BeFalse(); _user.GuestInvitation.IsAccepted.Should().BeFalse(); } @@ -494,7 +495,7 @@ await _user.InviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), emailA }); wasCallbackCalled.Should().BeTrue(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); _user.GuestInvitation.IsInvited.Should().BeTrue(); _user.GuestInvitation.IsAccepted.Should().BeFalse(); } @@ -513,7 +514,7 @@ await _user.InviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), emailA }); wasCallbackCalled.Should().BeTrue(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); _user.GuestInvitation.IsInvited.Should().BeTrue(); _user.GuestInvitation.IsAccepted.Should().BeFalse(); } @@ -572,7 +573,7 @@ await _user.ReInviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), }); wasCallbackCalled.Should().BeTrue(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); _user.GuestInvitation.IsInvited.Should().BeTrue(); _user.GuestInvitation.IsAccepted.Should().BeFalse(); } @@ -680,7 +681,7 @@ await _user.InviteGuestAsync(_tokensService.Object, "aninviterid".ToId(), emailA var result = _user.AcceptGuestInvitation(CallerConstants.AnonymousUserId.ToId(), emailAddress); result.Should().BeSuccess(); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); _user.GuestInvitation.IsAccepted.Should().BeTrue(); _user.GuestInvitation.AcceptedEmailAddress.Should().Be(emailAddress); } diff --git a/src/EndUsersDomain.UnitTests/MembershipSpec.cs b/src/EndUsersDomain.UnitTests/MembershipSpec.cs index 23e0c59f..59d77c09 100644 --- a/src/EndUsersDomain.UnitTests/MembershipSpec.cs +++ b/src/EndUsersDomain.UnitTests/MembershipSpec.cs @@ -44,7 +44,7 @@ public void WhenMembershipAddedEventRaised_ThenAssigned() var features = Features.Create(); _membership.As() - .RaiseEvent(Events.MembershipAdded.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipAdded("arootid".ToId(), "anorganizationid".ToId(), true, roles, features), true); _membership.IsDefault.Should().BeTrue(); @@ -60,7 +60,7 @@ public void WhenMembershipRoleAssignedEventRaised_ThenAssigned() var role = Role.Create(TenantRoles.Member).Value; _membership.As() - .RaiseEvent(Events.MembershipRoleAssigned.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipRoleAssigned("arootid".ToId(), "anorganizationid".ToId(), "amembershipid".ToId(), role), true); _membership.Roles.HasRole(role).Should(); @@ -72,7 +72,7 @@ public void WhenMembershipFeatureAssignedEventRaised_ThenAssigned() var feature = Feature.Create(TenantFeatures.Basic).Value; _membership.As() - .RaiseEvent(Events.MembershipFeatureAssigned.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipFeatureAssigned("arootid".ToId(), "anorganizationid".ToId(), "amembershipid".ToId(), feature), true); _membership.Features.HasFeature(feature).Should(); @@ -82,7 +82,7 @@ public void WhenMembershipFeatureAssignedEventRaised_ThenAssigned() public void WhenEnsureInvariantsAndMissingDefaultRole_ThenReturnsError() { _membership.As() - .RaiseEvent(Events.MembershipFeatureAssigned.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipFeatureAssigned("arootid".ToId(), "anorganizationid".ToId(), "amembershipid".ToId(), Feature.Create(Membership.DefaultFeature).Value), true); @@ -96,9 +96,9 @@ public void WhenEnsureInvariantsAndMissingDefaultRole_ThenReturnsError() public void WhenEnsureInvariantsAndMissingDefaultFeature_ThenReturnsError() { _membership.As() - .RaiseEvent(Events.MembershipRoleAssigned.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipRoleAssigned("arootid".ToId(), "anorganizationid".ToId(), "amembershipid".ToId(), Role.Create(Membership.DefaultRole).Value), true); - + var result = _membership.EnsureInvariants(); result.Should().BeError(ErrorCode.RuleViolation, diff --git a/src/EndUsersDomain.UnitTests/MembershipsSpec.cs b/src/EndUsersDomain.UnitTests/MembershipsSpec.cs index 1e639a7f..53858361 100644 --- a/src/EndUsersDomain.UnitTests/MembershipsSpec.cs +++ b/src/EndUsersDomain.UnitTests/MembershipsSpec.cs @@ -167,7 +167,7 @@ private Membership CreateMembership(string organizationId = "anorganizationid", var features = Features.Create(Membership.DefaultFeature).Value; var membership = Membership.Create(_recorder.Object, _idFactory.Object, _ => Result.Ok).Value; membership.As() - .RaiseEvent(Events.MembershipAdded.Create("arootid".ToId(), + .RaiseEvent(Events.MembershipAdded("arootid".ToId(), organizationId.ToId(), isDefault, roles, features), true); return membership; } diff --git a/src/EndUsersDomain/EndUserRoot.cs b/src/EndUsersDomain/EndUserRoot.cs index 34cb5afd..5df9aa3e 100644 --- a/src/EndUsersDomain/EndUserRoot.cs +++ b/src/EndUsersDomain/EndUserRoot.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.EndUsers; using Domain.Interfaces; using Domain.Interfaces.Authorization; using Domain.Interfaces.Entities; @@ -20,7 +21,7 @@ public static Result Create(IRecorder recorder, IIdentifierF UserClassification classification) { var root = new EndUserRoot(recorder, idFactory); - root.RaiseCreateEvent(EndUsersDomain.Events.Created.Create(root.Id, classification)); + root.RaiseCreateEvent(EndUsersDomain.Events.Created(root.Id, classification)); return root; } @@ -103,7 +104,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Created created: + case Created created: { Access = created.Access.ToEnumOrDefault(UserAccess.Enabled); Status = created.Status.ToEnumOrDefault(UserStatus.Unregistered); @@ -113,7 +114,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.Registered changed: + case Registered changed: { Access = changed.Access.ToEnumOrDefault(UserAccess.Enabled); Status = changed.Status.ToEnumOrDefault(UserStatus.Unregistered); @@ -137,7 +138,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.MembershipAdded added: + case MembershipAdded added: { var membership = RaiseEventToChildEntity(isReconstituting, added, idFactory => Membership.Create(Recorder, idFactory, RaiseChangeEvent), e => e.MembershipId); @@ -153,7 +154,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.MembershipDefaultChanged changed: + case MembershipDefaultChanged changed: { var fromMembership = Memberships.FindByMembershipId(changed.FromMembershipId.ToId()); if (!fromMembership.HasValue) @@ -186,7 +187,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.MembershipRoleAssigned added: + case MembershipRoleAssigned added: { var membershipId = added.MembershipId.ToId(); var membership = Memberships.FindByMembershipId(membershipId); @@ -206,7 +207,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.MembershipFeatureAssigned added: + case MembershipFeatureAssigned added: { var membershipId = added.MembershipId.ToId(); var membership = Memberships.FindByMembershipId(membershipId); @@ -226,7 +227,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PlatformRoleAssigned added: + case PlatformRoleAssigned added: { var roles = Roles.Add(added.Role); if (!roles.IsSuccessful) @@ -239,7 +240,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PlatformRoleUnassigned added: + case PlatformRoleUnassigned added: { var roles = Roles.Remove(added.Role); Roles = roles; @@ -247,7 +248,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PlatformFeatureAssigned added: + case PlatformFeatureAssigned added: { var features = Features.Add(added.Feature); if (!features.IsSuccessful) @@ -260,7 +261,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.GuestInvitationCreated added: + case GuestInvitationCreated added: { var inviteeEmailAddress = EmailAddress.Create(added.EmailAddress); if (!inviteeEmailAddress.IsSuccessful) @@ -281,7 +282,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.GuestInvitationAccepted changed: + case GuestInvitationAccepted changed: { var acceptedEmailAddress = EmailAddress.Create(changed.AcceptedEmailAddress); if (!acceptedEmailAddress.IsSuccessful) @@ -318,7 +319,7 @@ public Result AcceptGuestInvitation(Identifier acceptedById, EmailAddress return verified.Error; } - return RaiseChangeEvent(EndUsersDomain.Events.GuestInvitationAccepted.Create(Id, emailAddress)); + return RaiseChangeEvent(EndUsersDomain.Events.GuestInvitationAccepted(Id, emailAddress)); } public Result AddMembership(Identifier organizationId, Roles tenantRoles, Features tenantFeatures) @@ -333,7 +334,7 @@ public Result AddMembership(Identifier organizationId, Roles tenantRoles, var isDefault = Memberships.HasNone(); var added = RaiseChangeEvent( - EndUsersDomain.Events.MembershipAdded.Create(Id, organizationId, isDefault, tenantRoles, tenantFeatures)); + EndUsersDomain.Events.MembershipAdded(Id, organizationId, isDefault, tenantRoles, tenantFeatures)); if (!added.IsSuccessful) { return added.Error; @@ -344,7 +345,7 @@ public Result AddMembership(Identifier organizationId, Roles tenantRoles, var defaultMembership = Memberships.DefaultMembership; var addedMembership = Memberships.FindByOrganizationId(organizationId); return RaiseChangeEvent( - EndUsersDomain.Events.MembershipDefaultChanged.Create(Id, defaultMembership.Id, + EndUsersDomain.Events.MembershipDefaultChanged(Id, defaultMembership.Id, addedMembership.Value.Id)); } @@ -377,7 +378,7 @@ public Result AssignMembershipFeatures(EndUserRoot assigner, Identifier o var addedFeature = RaiseChangeEvent( - EndUsersDomain.Events.MembershipFeatureAssigned.Create(Id, organizationId, membership.Value.Id, + EndUsersDomain.Events.MembershipFeatureAssigned(Id, organizationId, membership.Value.Id, feature)); if (!addedFeature.IsSuccessful) { @@ -414,7 +415,7 @@ public Result AssignMembershipRoles(EndUserRoot assigner, Ide var addedRole = RaiseChangeEvent( - EndUsersDomain.Events.MembershipRoleAssigned.Create(Id, organizationId, membership.Value.Id, + EndUsersDomain.Events.MembershipRoleAssigned(Id, organizationId, membership.Value.Id, role)); if (!addedRole.IsSuccessful) { @@ -445,7 +446,7 @@ public Result AssignPlatformFeatures(EndUserRoot assigner, Features platf var addedFeature = RaiseChangeEvent( - EndUsersDomain.Events.PlatformFeatureAssigned.Create(Id, feature)); + EndUsersDomain.Events.PlatformFeatureAssigned(Id, feature)); if (!addedFeature.IsSuccessful) { return addedFeature.Error; @@ -474,7 +475,7 @@ public Result AssignPlatformRoles(EndUserRoot assigner, Roles platformRol var addedRole = RaiseChangeEvent( - EndUsersDomain.Events.PlatformRoleAssigned.Create(Id, role)); + EndUsersDomain.Events.PlatformRoleAssigned(Id, role)); if (!addedRole.IsSuccessful) { return addedRole.Error; @@ -566,7 +567,7 @@ public async Task> InviteGuestAsync(ITokensService tokensService, var token = tokensService.CreateGuestInvitationToken(); var raised = RaiseChangeEvent( - EndUsersDomain.Events.GuestInvitationCreated.Create(Id, token, inviteeEmailAddress, inviterId)); + EndUsersDomain.Events.GuestInvitationCreated(Id, token, inviteeEmailAddress, inviterId)); if (!raised.IsSuccessful) { return raised.Error; @@ -586,7 +587,7 @@ public Result Register(Roles roles, Features levels, Optional Register(Roles roles, Features levels, Optional UnassignPlatformRoles(EndUserRoot assigner, Roles platformR var removedRole = RaiseChangeEvent( - EndUsersDomain.Events.PlatformRoleUnassigned.Create(Id, role)); + EndUsersDomain.Events.PlatformRoleUnassigned(Id, role)); if (!removedRole.IsSuccessful) { return removedRole.Error; diff --git a/src/EndUsersDomain/EndUsersDomain.csproj b/src/EndUsersDomain/EndUsersDomain.csproj index 7d8c1a78..28e34843 100644 --- a/src/EndUsersDomain/EndUsersDomain.csproj +++ b/src/EndUsersDomain/EndUsersDomain.csproj @@ -5,9 +5,8 @@ - - + diff --git a/src/EndUsersDomain/Events.cs b/src/EndUsersDomain/Events.cs index af0b07a8..ff570c10 100644 --- a/src/EndUsersDomain/Events.cs +++ b/src/EndUsersDomain/Events.cs @@ -1,284 +1,148 @@ using Common; using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.EndUsers; using Domain.Shared; namespace EndUsersDomain; public static class Events { - public sealed class Created : IDomainEvent + public static Created Created(Identifier id, UserClassification classification) { - public static Created Create(Identifier id, UserClassification classification) + return new Created { - return new Created - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Classification = classification.ToString(), - Access = UserAccess.Enabled.ToString(), - Status = UserStatus.Unregistered.ToString() - }; - } - - public required string Access { get; set; } - - public required string Classification { get; set; } - - public required string Status { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Classification = classification.ToString(), + Access = UserAccess.Enabled.ToString(), + Status = UserStatus.Unregistered.ToString() + }; } - public sealed class Registered : IDomainEvent + public static GuestInvitationAccepted GuestInvitationAccepted(Identifier id, EmailAddress emailAddress) { - public static Registered Create(Identifier id, Optional username, - UserClassification classification, - UserAccess access, UserStatus status, - Roles roles, - Features features) + return new GuestInvitationAccepted { - return new Registered - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Username = username.ValueOrDefault!, - Classification = classification.ToString(), - Access = access.ToString(), - Status = status.ToString(), - Roles = roles.ToList(), - Features = features.ToList() - }; - } - - public required string Access { get; set; } - - public required string Classification { get; set; } - - public required List Features { get; set; } - - public required List Roles { get; set; } - - public required string Status { get; set; } - - public string? Username { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + AcceptedEmailAddress = emailAddress, + AcceptedAtUtc = DateTime.UtcNow + }; } - public sealed class MembershipAdded : IDomainEvent + public static GuestInvitationCreated GuestInvitationCreated(Identifier id, string token, EmailAddress invitee, + Identifier invitedBy) { - public static MembershipAdded Create(Identifier id, Identifier organizationId, bool isDefault, Roles roles, - Features features) + return new GuestInvitationCreated { - return new MembershipAdded - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - MembershipId = null, - IsDefault = isDefault, - OrganizationId = organizationId, - Roles = roles.ToList(), - Features = features.ToList() - }; - } - - public required List Features { get; set; } - - public required bool IsDefault { get; set; } - - public string? MembershipId { get; set; } - - public required string OrganizationId { get; set; } - - public required List Roles { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + EmailAddress = invitee, + InvitedById = invitedBy, + Token = token + }; } - public sealed class MembershipDefaultChanged : IDomainEvent + public static MembershipAdded MembershipAdded(Identifier id, Identifier organizationId, bool isDefault, Roles roles, + Features features) { - public static MembershipDefaultChanged Create(Identifier id, Identifier fromMembershipId, - Identifier toMembershipId) + return new MembershipAdded { - return new MembershipDefaultChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - FromMembershipId = fromMembershipId, - ToMembershipId = toMembershipId - }; - } - - public required string FromMembershipId { get; set; } - - public required string ToMembershipId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + MembershipId = null, + IsDefault = isDefault, + OrganizationId = organizationId, + Roles = roles.ToList(), + Features = features.ToList() + }; } - public sealed class MembershipRoleAssigned : IDomainEvent + public static MembershipDefaultChanged MembershipDefaultChanged(Identifier id, Identifier fromMembershipId, + Identifier toMembershipId) { - public static MembershipRoleAssigned Create(Identifier id, Identifier organizationId, Identifier membershipId, - Role role) + return new MembershipDefaultChanged { - return new MembershipRoleAssigned - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - OrganizationId = organizationId, - MembershipId = membershipId, - Role = role.Identifier - }; - } - - public required string MembershipId { get; set; } - - public required string OrganizationId { get; set; } - - public required string Role { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + FromMembershipId = fromMembershipId, + ToMembershipId = toMembershipId + }; } - public sealed class MembershipFeatureAssigned : IDomainEvent + public static MembershipFeatureAssigned MembershipFeatureAssigned(Identifier id, Identifier organizationId, + Identifier membershipId, Feature feature) { - public static MembershipFeatureAssigned Create(Identifier id, Identifier organizationId, - Identifier membershipId, Feature feature) + return new MembershipFeatureAssigned { - return new MembershipFeatureAssigned - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - OrganizationId = organizationId, - MembershipId = membershipId, - Feature = feature.Identifier - }; - } - - public required string Feature { get; set; } - - public required string MembershipId { get; set; } - - public required string OrganizationId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + OrganizationId = organizationId, + MembershipId = membershipId, + Feature = feature.Identifier + }; } - public sealed class PlatformRoleAssigned : IDomainEvent + public static MembershipRoleAssigned MembershipRoleAssigned(Identifier id, Identifier organizationId, + Identifier membershipId, + Role role) { - public static PlatformRoleAssigned Create(Identifier id, Role role) + return new MembershipRoleAssigned { - return new PlatformRoleAssigned - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Role = role.Identifier - }; - } - - public required string Role { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + OrganizationId = organizationId, + MembershipId = membershipId, + Role = role.Identifier + }; } - public sealed class PlatformRoleUnassigned : IDomainEvent + public static PlatformFeatureAssigned PlatformFeatureAssigned(Identifier id, Feature feature) { - public static PlatformRoleUnassigned Create(Identifier id, Role role) + return new PlatformFeatureAssigned { - return new PlatformRoleUnassigned - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Role = role.Identifier - }; - } - - public required string Role { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Feature = feature.Identifier + }; } - public sealed class PlatformFeatureAssigned : IDomainEvent + public static PlatformRoleAssigned PlatformRoleAssigned(Identifier id, Role role) { - public static PlatformFeatureAssigned Create(Identifier id, Feature feature) + return new PlatformRoleAssigned { - return new PlatformFeatureAssigned - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - Feature = feature.Identifier - }; - } - - public required string Feature { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Role = role.Identifier + }; } - public sealed class GuestInvitationCreated : IDomainEvent + public static PlatformRoleUnassigned PlatformRoleUnassigned(Identifier id, Role role) { - public static GuestInvitationCreated Create(Identifier id, string token, EmailAddress invitee, - Identifier invitedBy) + return new PlatformRoleUnassigned { - return new GuestInvitationCreated - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - EmailAddress = invitee, - InvitedById = invitedBy, - Token = token - }; - } - - public required string EmailAddress { get; set; } - - public required string InvitedById { get; set; } - - public required string Token { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Role = role.Identifier + }; } - public sealed class GuestInvitationAccepted : IDomainEvent + public static Registered Registered(Identifier id, Optional username, + UserClassification classification, + UserAccess access, UserStatus status, + Roles roles, + Features features) { - public static GuestInvitationAccepted Create(Identifier id, EmailAddress emailAddress) + return new Registered { - return new GuestInvitationAccepted - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - AcceptedEmailAddress = emailAddress, - AcceptedAtUtc = DateTime.UtcNow - }; - } - - public required DateTime AcceptedAtUtc { get; set; } - - public required string AcceptedEmailAddress { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + Username = username.ValueOrDefault!, + Classification = classification.ToString(), + Access = access.ToString(), + Status = status.ToString(), + Roles = roles.ToList(), + Features = features.ToList() + }; } } \ No newline at end of file diff --git a/src/EndUsersDomain/Membership.cs b/src/EndUsersDomain/Membership.cs index 6ab5203a..e1acc682 100644 --- a/src/EndUsersDomain/Membership.cs +++ b/src/EndUsersDomain/Membership.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.EndUsers; using Domain.Interfaces.Authorization; using Domain.Interfaces.Entities; using Domain.Shared; @@ -11,8 +12,8 @@ namespace EndUsersDomain; public sealed class Membership : EntityBase { - internal static readonly RoleLevel DefaultRole = TenantRoles.Member; internal static readonly FeatureLevel DefaultFeature = TenantFeatures.Basic; + internal static readonly RoleLevel DefaultRole = TenantRoles.Member; public static Result Create(IRecorder recorder, IIdentifierFactory idFactory, RootEventHandler rootEventHandler) @@ -39,7 +40,7 @@ protected override Result OnStateChanged(IDomainEvent @event) { switch (@event) { - case Events.MembershipAdded added: + case MembershipAdded added: { RootId = added.RootId.ToId(); OrganizationId = added.OrganizationId.ToId(); @@ -61,7 +62,7 @@ protected override Result OnStateChanged(IDomainEvent @event) return Result.Ok; } - case Events.MembershipDefaultChanged changed: + case MembershipDefaultChanged changed: { if (changed.FromMembershipId == Id) { @@ -76,7 +77,7 @@ protected override Result OnStateChanged(IDomainEvent @event) return Result.Ok; } - case Events.MembershipRoleAssigned added: + case MembershipRoleAssigned added: { var role = Roles.Add(added.Role); if (!role.IsSuccessful) @@ -88,7 +89,7 @@ protected override Result OnStateChanged(IDomainEvent @event) return Result.Ok; } - case Events.MembershipFeatureAssigned added: + case MembershipFeatureAssigned added: { var feature = Features.Add(added.Feature); if (!feature.IsSuccessful) @@ -117,6 +118,7 @@ public override Result EnsureInvariants() { return Error.RuleViolation(Resources.Membership_MissingDefaultRole.Format(DefaultRole.Name)); } + if (!Features.HasFeature(DefaultFeature)) { return Error.RuleViolation(Resources.Membership_MissingDefaultFeature.Format(DefaultFeature.Name)); diff --git a/src/EndUsersInfrastructure/Persistence/ReadModels/EndUserProjection.cs b/src/EndUsersInfrastructure/Persistence/ReadModels/EndUserProjection.cs index 0188587d..cefc777f 100644 --- a/src/EndUsersInfrastructure/Persistence/ReadModels/EndUserProjection.cs +++ b/src/EndUsersInfrastructure/Persistence/ReadModels/EndUserProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.EndUsers; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Shared; @@ -35,20 +36,17 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.Created e: + case Created e: return await Tasks.WhenAllAsync(_users.HandleCreateAsync(e.RootId.ToId(), dto => { dto.Classification = e.Classification; dto.Access = e.Access; dto.Status = e.Status; }, cancellationToken), - _invitations.HandleCreateAsync(e.RootId.ToId(), dto => - { - dto.Status = e.Status; - }, + _invitations.HandleCreateAsync(e.RootId.ToId(), dto => { dto.Status = e.Status; }, cancellationToken)); - case Events.Registered e: + case Registered e: return await Tasks.WhenAllAsync(_users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Classification = e.Classification; @@ -61,7 +59,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven _invitations.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Status = e.Status; }, cancellationToken)); - case Events.MembershipAdded e: + case MembershipAdded e: return await _memberships.HandleCreateAsync(e.MembershipId.ToId(), dto => { dto.IsDefault = e.IsDefault; @@ -71,7 +69,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Features = Features.Create(e.Features.ToArray()).Value; }, cancellationToken); - case Events.MembershipDefaultChanged e: + case MembershipDefaultChanged e: { var from = await _memberships.HandleUpdateAsync(e.FromMembershipId.ToId(), dto => { dto.IsDefault = false; }, cancellationToken); @@ -90,7 +88,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven return to; } - case Events.MembershipRoleAssigned e: + case MembershipRoleAssigned e: return await _memberships.HandleUpdateAsync(e.RootId.ToId(), dto => { var roles = dto.Roles.HasValue @@ -104,7 +102,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Roles = roles.Value; }, cancellationToken); - case Events.MembershipFeatureAssigned e: + case MembershipFeatureAssigned e: return await _memberships.HandleUpdateAsync(e.RootId.ToId(), dto => { var features = dto.Features.HasValue @@ -118,7 +116,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Features = features.Value; }, cancellationToken); - case Events.PlatformRoleAssigned e: + case PlatformRoleAssigned e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { var roles = dto.Roles.HasValue @@ -132,7 +130,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Roles = roles.Value; }, cancellationToken); - case Events.PlatformRoleUnassigned e: + case PlatformRoleUnassigned e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { var roles = dto.Roles.HasValue @@ -146,7 +144,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Roles = roles.Value; }, cancellationToken); - case Events.PlatformFeatureAssigned e: + case PlatformFeatureAssigned e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { var features = dto.Features.HasValue @@ -160,7 +158,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.Features = features.Value; }, cancellationToken); - case Events.GuestInvitationCreated e: + case GuestInvitationCreated e: return await _invitations.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.InvitedEmailAddress = e.EmailAddress; @@ -168,7 +166,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.InvitedById = e.InvitedById; }, cancellationToken); - case Events.GuestInvitationAccepted e: + case GuestInvitationAccepted e: return await _invitations.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Token = Optional.None; diff --git a/src/IdentityApplication.UnitTests/APIKeysApplicationSpec.cs b/src/IdentityApplication.UnitTests/APIKeysApplicationSpec.cs index 43927667..ce1a1a89 100644 --- a/src/IdentityApplication.UnitTests/APIKeysApplicationSpec.cs +++ b/src/IdentityApplication.UnitTests/APIKeysApplicationSpec.cs @@ -7,7 +7,7 @@ using Domain.Common.ValueObjects; using Domain.Interfaces.Entities; using Domain.Services.Shared.DomainServices; -using Domain.Shared; +using Domain.Shared.Identities; using FluentAssertions; using IdentityApplication.Persistence; using IdentityDomain; diff --git a/src/IdentityDomain.UnitTests/APIKeyRootSpec.cs b/src/IdentityDomain.UnitTests/APIKeyRootSpec.cs index db507c97..a1f60f23 100644 --- a/src/IdentityDomain.UnitTests/APIKeyRootSpec.cs +++ b/src/IdentityDomain.UnitTests/APIKeyRootSpec.cs @@ -2,8 +2,9 @@ using Domain.Common.Events; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.APIKeys; using Domain.Interfaces.Entities; -using Domain.Shared; +using Domain.Shared.Identities; using FluentAssertions; using IdentityDomain.DomainServices; using Moq; @@ -83,7 +84,7 @@ public void WhenSetParametersWithNoExpiresOn_ThenAssigns() _apiKey.Description.Should().BeSome("adescription"); _apiKey.ExpiresOn.Should().BeSome(expires); _apiKey.UserId.Should().Be("auserid".ToId()); - _apiKey.Events.Last().Should().BeOfType(); + _apiKey.Events.Last().Should().BeOfType(); } [Fact] @@ -98,7 +99,7 @@ public void WhenSetParametersWithExpiresOn_ThenAssigns() _apiKey.Description.Should().BeSome("adescription"); _apiKey.ExpiresOn.Should().BeSome(expiresOn); _apiKey.UserId.Should().Be("auserid".ToId()); - _apiKey.Events.Last().Should().BeOfType(); + _apiKey.Events.Last().Should().BeOfType(); } [Fact] @@ -119,7 +120,7 @@ public void WhenVerifyKey_ThenReturnsTrue() result.Should().BeSuccess(); result.Value.Should().BeTrue(); - _apiKey.Events.Last().Should().BeOfType(); + _apiKey.Events.Last().Should().BeOfType(); } [Fact] diff --git a/src/IdentityDomain.UnitTests/AuthTokensRootSpec.cs b/src/IdentityDomain.UnitTests/AuthTokensRootSpec.cs index 15b26d61..9a7993ac 100644 --- a/src/IdentityDomain.UnitTests/AuthTokensRootSpec.cs +++ b/src/IdentityDomain.UnitTests/AuthTokensRootSpec.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.AuthTokens; using Domain.Interfaces.Entities; using FluentAssertions; using Moq; @@ -45,7 +46,7 @@ public void WhenSetTokens_ThenSetsTokens() _authTokens.RefreshToken.Should().BeSome("arefreshtoken"); _authTokens.AccessTokenExpiresOn.Should().BeSome(accessTokenExpiresOn); _authTokens.RefreshTokenExpiresOn.Should().BeSome(refreshTokenExpiresOn); - _authTokens.Events.Last().Should().BeOfType(); + _authTokens.Events.Last().Should().BeOfType(); } [Fact] @@ -106,7 +107,7 @@ public void WhenRenewTokens_ThenUpdatesTokens() _authTokens.RefreshToken.Should().BeSome("arefreshtoken2"); _authTokens.AccessTokenExpiresOn.Should().BeSome(accessTokenExpiresOn2); _authTokens.RefreshTokenExpiresOn.Should().BeSome(refreshTokenExpiresOn2); - _authTokens.Events.Last().Should().BeOfType(); + _authTokens.Events.Last().Should().BeOfType(); } [Fact] @@ -144,6 +145,6 @@ public void WhenRevoke_ThenDeletesTokens() _authTokens.RefreshToken.Should().BeNone(); _authTokens.AccessTokenExpiresOn.Should().BeNone(); _authTokens.RefreshTokenExpiresOn.Should().BeNone(); - _authTokens.Events.Last().Should().BeOfType(); + _authTokens.Events.Last().Should().BeOfType(); } } \ No newline at end of file diff --git a/src/IdentityDomain.UnitTests/PasswordCredentialRootSpec.cs b/src/IdentityDomain.UnitTests/PasswordCredentialRootSpec.cs index 271e0ea6..1725b49f 100644 --- a/src/IdentityDomain.UnitTests/PasswordCredentialRootSpec.cs +++ b/src/IdentityDomain.UnitTests/PasswordCredentialRootSpec.cs @@ -2,6 +2,7 @@ using Common.Configuration; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.PasswordCredentials; using Domain.Interfaces.Entities; using Domain.Services.Shared.DomainServices; using Domain.Shared; @@ -81,7 +82,7 @@ public void WhenInitiateRegistrationVerificationAndNotVerified_ThenInitiates() _credential.Verification.IsStillVerifying.Should().BeTrue(); _credential.Events.Last().Should() - .BeOfType(); + .BeOfType(); } [Fact] @@ -101,7 +102,7 @@ public void WhenSetCredentials_ThenSetsCredentials() _credential.SetCredential("apassword"); _credential.Password.PasswordHash.Should().Be("apasswordhash"); - _credential.Events.Last().Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -112,7 +113,7 @@ public void WhenSetRegistrationDetails_ThenSetsRegistration() _credential.Registration.Value.EmailAddress.Should().Be(EmailAddress.Create("auser@company.com").Value); _credential.Registration.Value.Name.Should().Be(PersonDisplayName.Create("adisplayname").Value); - _credential.Events.Last().Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -127,7 +128,7 @@ public void WhenVerifyPasswordWithInvalidPassword_ThenReturnsError() _credential.Login.FailedPasswordAttempts.Should().Be(0); _credential.Login.IsLocked.Should().BeFalse(); _credential.Login.ToggledLocked.Should().BeFalse(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -145,8 +146,8 @@ public void WhenVerifyPasswordAndWrongPasswordAndAudit_ThenAuditsFailedLogin() _credential.Login.FailedPasswordAttempts.Should().Be(1); _credential.Login.IsLocked.Should().BeFalse(); _credential.Login.ToggledLocked.Should().BeFalse(); - _credential.Events[1].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[1].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -162,8 +163,8 @@ public void WhenVerifyPasswordAndAndAudit_ThenResetsLoginMonitor() _credential.Login.FailedPasswordAttempts.Should().Be(0); _credential.Login.IsLocked.Should().BeFalse(); _credential.Login.ToggledLocked.Should().BeFalse(); - _credential.Events[1].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[1].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); _passwordHasherService.Verify(ph => ph.ValidatePassword("apassword", false)); } @@ -180,9 +181,9 @@ public void WhenVerifyPasswordAndFailsAndLocksAccount_ThenLocksLogin() .Be(Validations.Credentials.Login.DefaultMaxFailedPasswordAttempts); _credential.Login.IsLocked.Should().BeTrue(); _credential.Login.ToggledLocked.Should().BeTrue(); - _credential.Events[1].Should().BeOfType(); - _credential.Events[2].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[1].Should().BeOfType(); + _credential.Events[2].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -202,9 +203,9 @@ public void WhenVerifyPasswordAndSucceedsAfterCooldown_ThenUnlocksCredentials() _credential.Login.FailedPasswordAttempts.Should().Be(0); _credential.Login.IsLocked.Should().BeFalse(); _credential.Login.ToggledLocked.Should().BeTrue(); - _credential.Events[1].Should().BeOfType(); - _credential.Events[2].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[1].Should().BeOfType(); + _credential.Events[2].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -241,7 +242,7 @@ public void WhenVerifyRegistration_ThenVerified() _credential.VerifyRegistration(); _credential.Verification.IsVerified.Should().BeTrue(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -285,9 +286,9 @@ public void WhenInitiatePasswordReset_ThenInitiated() _credential.InitiatePasswordReset(); _credential.Password.IsInitiating.Should().BeTrue(); - _credential.Events[1].Should().BeOfType(); - _credential.Events[2].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[1].Should().BeOfType(); + _credential.Events[2].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] @@ -376,8 +377,8 @@ public void WhenResetPasswordAndCredentialsLocked_ThenResetsPasswordAndUnlocks() _passwordHasherService.Verify(ph => ph.ValidatePassword("anewpassword", false)); _credential.Login.IsLocked.Should().BeFalse(); _credential.Login.ToggledLocked.Should().BeTrue(); - _credential.Events[12].Should().BeOfType(); - _credential.Events.Last().Should().BeOfType(); + _credential.Events[12].Should().BeOfType(); + _credential.Events.Last().Should().BeOfType(); } [Fact] diff --git a/src/IdentityDomain.UnitTests/SSOUserRootSpec.cs b/src/IdentityDomain.UnitTests/SSOUserRootSpec.cs index 6c3ea990..195f98ae 100644 --- a/src/IdentityDomain.UnitTests/SSOUserRootSpec.cs +++ b/src/IdentityDomain.UnitTests/SSOUserRootSpec.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.SSOUsers; using Domain.Interfaces.Entities; using Domain.Services.Shared.DomainServices; using Domain.Shared; @@ -57,6 +58,6 @@ public void WhenUpdateDetails_ThenUpdates() _user.Name.Value.LastName.Should().BeNone(); _user.Timezone.Value.Code.Should().Be(Timezones.Default); _user.Address.Value.CountryCode.Should().Be(CountryCodes.Default); - _user.Events.Last().Should().BeOfType(); + _user.Events.Last().Should().BeOfType(); } } \ No newline at end of file diff --git a/src/IdentityDomain/APIKeyRoot.cs b/src/IdentityDomain/APIKeyRoot.cs index 2db6f903..4f1ddde6 100644 --- a/src/IdentityDomain/APIKeyRoot.cs +++ b/src/IdentityDomain/APIKeyRoot.cs @@ -4,10 +4,11 @@ using Domain.Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.APIKeys; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; -using Domain.Shared; +using Domain.Shared.Identities; using IdentityDomain.DomainServices; namespace IdentityDomain; @@ -20,7 +21,7 @@ public static Result Create(IRecorder recorder, IIdentifierFa IAPIKeyHasherService apiKeyHasherService, Identifier userId, APIKeyToken keyToken) { var root = new APIKeyRoot(recorder, idFactory, apiKeyHasherService); - root.RaiseCreateEvent(IdentityDomain.Events.APIKeys.Created.Create(root.Id, userId, keyToken.Token, + root.RaiseCreateEvent(IdentityDomain.Events.APIKeys.Created(root.Id, userId, keyToken.Token, apiKeyHasherService.HashAPIKey(keyToken.Key))); return root; } @@ -70,7 +71,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.APIKeys.Created created: + case Created created: { UserId = created.UserId.ToId(); @@ -84,7 +85,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.APIKeys.ParametersChanged changed: + case ParametersChanged changed: { Description = changed.Description; ExpiresOn = changed.ExpiresOn; @@ -92,7 +93,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.APIKeys.KeyVerified _: + case KeyVerified _: { Recorder.TraceDebug(null, "ApiKey {Id} verified", Id); return Result.Ok; @@ -136,7 +137,7 @@ public Result SetParameters(string description, DateTime expiresOn) return error3; } - return RaiseChangeEvent(IdentityDomain.Events.APIKeys.ParametersChanged.Create(Id, description, expiresOn)); + return RaiseChangeEvent(IdentityDomain.Events.APIKeys.ParametersChanged(Id, description, expiresOn)); } public Result VerifyKey(string key) @@ -164,7 +165,7 @@ public Result VerifyKey(string key) } var isVerified = verified.Value; - var raised = RaiseChangeEvent(IdentityDomain.Events.APIKeys.KeyVerified.Create(Id, isVerified)); + var raised = RaiseChangeEvent(IdentityDomain.Events.APIKeys.KeyVerified(Id, isVerified)); if (!raised.IsSuccessful) { return raised.Error; diff --git a/src/IdentityDomain/AuthTokensRoot.cs b/src/IdentityDomain/AuthTokensRoot.cs index c52c82d4..0b633b2a 100644 --- a/src/IdentityDomain/AuthTokensRoot.cs +++ b/src/IdentityDomain/AuthTokensRoot.cs @@ -2,6 +2,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.AuthTokens; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -14,7 +15,7 @@ public static Result Create(IRecorder recorder, IIdentifi Identifier userId) { var root = new AuthTokensRoot(recorder, idFactory); - root.RaiseCreateEvent(IdentityDomain.Events.AuthTokens.Created.Create(root.Id, userId)); + root.RaiseCreateEvent(IdentityDomain.Events.AuthTokens.Created(root.Id, userId)); return root; } @@ -64,13 +65,13 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.AuthTokens.Created created: + case Created created: { UserId = created.UserId.ToId(); return Result.Ok; } - case Events.AuthTokens.TokensChanged changed: + case TokensChanged changed: { AccessToken = changed.AccessToken; RefreshToken = changed.RefreshToken; @@ -80,7 +81,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.AuthTokens.TokensRefreshed changed: + case TokensRefreshed changed: { AccessToken = changed.AccessToken; RefreshToken = changed.RefreshToken; @@ -90,7 +91,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.AuthTokens.TokensRevoked changed: + case TokensRevoked changed: { AccessToken = Optional.None; RefreshToken = Optional.None; @@ -124,7 +125,7 @@ public Result RenewTokens(string refreshTokenToRenew, string accessToken, } return RaiseChangeEvent( - IdentityDomain.Events.AuthTokens.TokensRefreshed.Create(Id, UserId, accessToken, accessTokenExpiresOn, + IdentityDomain.Events.AuthTokens.TokensRefreshed(Id, UserId, accessToken, accessTokenExpiresOn, refreshToken, refreshTokenExpiresOn)); } @@ -141,7 +142,7 @@ public Result Revoke(string refreshToken) } return RaiseChangeEvent( - IdentityDomain.Events.AuthTokens.TokensRevoked.Create(Id, UserId)); + IdentityDomain.Events.AuthTokens.TokensRevoked(Id, UserId)); } public Result SetTokens(string accessToken, string refreshToken, DateTime accessTokenExpiresOn, @@ -154,7 +155,7 @@ public Result SetTokens(string accessToken, string refreshToken, DateTime } return RaiseChangeEvent( - IdentityDomain.Events.AuthTokens.TokensChanged.Create(Id, UserId, accessToken, accessTokenExpiresOn, + IdentityDomain.Events.AuthTokens.TokensChanged(Id, UserId, accessToken, accessTokenExpiresOn, refreshToken, refreshTokenExpiresOn)); } @@ -163,7 +164,7 @@ public Result TestingOnly_SetTokens(string accessToken, string refreshTok DateTime refreshTokenExpiresOn) { return RaiseChangeEvent( - IdentityDomain.Events.AuthTokens.TokensChanged.Create(Id, UserId, accessToken, accessTokenExpiresOn, + IdentityDomain.Events.AuthTokens.TokensChanged(Id, UserId, accessToken, accessTokenExpiresOn, refreshToken, refreshTokenExpiresOn)); } #endif diff --git a/src/IdentityDomain/Events.cs b/src/IdentityDomain/Events.cs index fd2fb6df..42b6a3ac 100644 --- a/src/IdentityDomain/Events.cs +++ b/src/IdentityDomain/Events.cs @@ -1,439 +1,242 @@ using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.Identities.APIKeys; +using Domain.Events.Shared.Identities.AuthTokens; +using Domain.Events.Shared.Identities.PasswordCredentials; +using Domain.Events.Shared.Identities.SSOUsers; using Domain.Shared; +using Created = Domain.Events.Shared.Identities.AuthTokens.Created; namespace IdentityDomain; public static class Events { - public static class PasswordCredentials + public static class AuthTokens { - public sealed class Created : IDomainEvent + public static Created Created(Identifier id, Identifier userId) { - public static Created Create(Identifier id, Identifier userId) + return new Created { - return new Created - { - RootId = id, - UserId = userId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class CredentialsChanged : IDomainEvent + public static TokensChanged TokensChanged(Identifier id, Identifier userId, string accessToken, + DateTime accessTokenExpiresOn, + string refreshToken, DateTime refreshTokenExpiresOn) { - public static CredentialsChanged Create(Identifier id, string passwordHash) + return new TokensChanged { - return new CredentialsChanged - { - RootId = id, - PasswordHash = passwordHash, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string PasswordHash { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + AccessToken = accessToken, + RefreshToken = refreshToken, + AccessTokenExpiresOn = accessTokenExpiresOn, + RefreshTokenExpiresOn = refreshTokenExpiresOn, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class RegistrationChanged : IDomainEvent + public static TokensRefreshed TokensRefreshed(Identifier id, Identifier userId, string accessToken, + DateTime accessTokenExpiresOn, + string refreshToken, DateTime refreshTokenExpiresOn) { - public static RegistrationChanged Create(Identifier id, EmailAddress emailAddress, PersonDisplayName name) + return new TokensRefreshed { - return new RegistrationChanged - { - RootId = id, - EmailAddress = emailAddress, - Name = name, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string EmailAddress { get; set; } - - public required string Name { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + AccessToken = accessToken, + RefreshToken = refreshToken, + AccessTokenExpiresOn = accessTokenExpiresOn, + RefreshTokenExpiresOn = refreshTokenExpiresOn, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class PasswordVerified : IDomainEvent + public static TokensRevoked TokensRevoked(Identifier id, Identifier userId) { - public static PasswordVerified Create(Identifier id, bool isVerified, - bool auditAttempt) + return new TokensRevoked { - return new PasswordVerified - { - RootId = id, - IsVerified = isVerified, - AuditAttempt = auditAttempt, - OccurredUtc = DateTime.UtcNow - }; - } - - public required bool AuditAttempt { get; set; } - - public required bool IsVerified { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + OccurredUtc = DateTime.UtcNow + }; } + } - public sealed class AccountLocked : IDomainEvent + public static class PasswordCredentials + { + public static AccountLocked AccountLocked(Identifier id) { - public static AccountLocked Create(Identifier id) + return new AccountLocked { - return new AccountLocked - { - RootId = id, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class AccountUnlocked : IDomainEvent + public static AccountUnlocked AccountUnlocked(Identifier id) { - public static AccountUnlocked Create(Identifier id) + return new AccountUnlocked { - return new AccountUnlocked - { - RootId = id, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class RegistrationVerificationCreated : IDomainEvent + public static Domain.Events.Shared.Identities.PasswordCredentials.Created Created(Identifier id, + Identifier userId) { - public static RegistrationVerificationCreated Create(Identifier id, string token) + return new Domain.Events.Shared.Identities.PasswordCredentials.Created { - return new RegistrationVerificationCreated - { - RootId = id, - Token = token, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string Token { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class RegistrationVerificationVerified : IDomainEvent + public static CredentialsChanged CredentialsChanged(Identifier id, string passwordHash) { - public static RegistrationVerificationVerified Create(Identifier id) + return new CredentialsChanged { - return new RegistrationVerificationVerified - { - RootId = id, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + PasswordHash = passwordHash, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class PasswordResetInitiated : IDomainEvent + public static PasswordResetCompleted PasswordResetCompleted(Identifier id, string token, string passwordHash) { - public static PasswordResetInitiated Create(Identifier id, string token) + return new PasswordResetCompleted { - return new PasswordResetInitiated - { - RootId = id, - Token = token, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string Token { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Token = token, + PasswordHash = passwordHash, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class PasswordResetCompleted : IDomainEvent + public static PasswordResetInitiated PasswordResetInitiated(Identifier id, string token) { - public static PasswordResetCompleted Create(Identifier id, string token, string passwordHash) + return new PasswordResetInitiated { - return new PasswordResetCompleted - { - RootId = id, - Token = token, - PasswordHash = passwordHash, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string PasswordHash { get; set; } - - public required string Token { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Token = token, + OccurredUtc = DateTime.UtcNow + }; } - } - public static class AuthTokens - { - public sealed class Created : IDomainEvent + public static PasswordVerified PasswordVerified(Identifier id, bool isVerified, + bool auditAttempt) { - public static Created Create(Identifier id, Identifier userId) + return new PasswordVerified { - return new Created - { - RootId = id, - UserId = userId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + IsVerified = isVerified, + AuditAttempt = auditAttempt, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class TokensChanged : IDomainEvent + public static RegistrationChanged RegistrationChanged(Identifier id, EmailAddress emailAddress, + PersonDisplayName name) { - public static TokensChanged Create(Identifier id, Identifier userId, string accessToken, - DateTime accessTokenExpiresOn, - string refreshToken, DateTime refreshTokenExpiresOn) + return new RegistrationChanged { - return new TokensChanged - { - RootId = id, - UserId = userId, - AccessToken = accessToken, - RefreshToken = refreshToken, - AccessTokenExpiresOn = accessTokenExpiresOn, - RefreshTokenExpiresOn = refreshTokenExpiresOn, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string AccessToken { get; set; } - - public required DateTime AccessTokenExpiresOn { get; set; } - - public required string RefreshToken { get; set; } - - public required DateTime RefreshTokenExpiresOn { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + EmailAddress = emailAddress, + Name = name, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class TokensRefreshed : IDomainEvent + public static RegistrationVerificationCreated RegistrationVerificationCreated(Identifier id, string token) { - public static TokensRefreshed Create(Identifier id, Identifier userId, string accessToken, - DateTime accessTokenExpiresOn, - string refreshToken, DateTime refreshTokenExpiresOn) + return new RegistrationVerificationCreated { - return new TokensRefreshed - { - RootId = id, - UserId = userId, - AccessToken = accessToken, - RefreshToken = refreshToken, - AccessTokenExpiresOn = accessTokenExpiresOn, - RefreshTokenExpiresOn = refreshTokenExpiresOn, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string AccessToken { get; set; } - - public required DateTime AccessTokenExpiresOn { get; set; } - - public required string RefreshToken { get; set; } - - public required DateTime RefreshTokenExpiresOn { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Token = token, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class TokensRevoked : IDomainEvent + public static RegistrationVerificationVerified RegistrationVerificationVerified(Identifier id) { - public static TokensRevoked Create(Identifier id, Identifier userId) + return new RegistrationVerificationVerified { - return new TokensRevoked - { - RootId = id, - UserId = userId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow + }; } } public static class APIKeys { - public sealed class Created : IDomainEvent + public static Domain.Events.Shared.Identities.APIKeys.Created Created(Identifier id, Identifier userId, + string keyToken, string keyHash) { - public static Created Create(Identifier id, Identifier userId, string keyToken, string keyHash) + return new Domain.Events.Shared.Identities.APIKeys.Created { - return new Created - { - RootId = id, - UserId = userId, - KeyToken = keyToken, - KeyHash = keyHash, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string KeyHash { get; set; } - - public required string KeyToken { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + UserId = userId, + KeyToken = keyToken, + KeyHash = keyHash, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class ParametersChanged : IDomainEvent + public static KeyVerified KeyVerified(Identifier id, bool isVerified) { - public static ParametersChanged Create(Identifier id, string description, - DateTime expiresOn) + return new KeyVerified { - return new ParametersChanged - { - RootId = id, - Description = description, - ExpiresOn = expiresOn, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string Description { get; set; } - - public required DateTime ExpiresOn { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + IsVerified = isVerified, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class KeyVerified : IDomainEvent + public static ParametersChanged ParametersChanged(Identifier id, string description, + DateTime expiresOn) { - public static KeyVerified Create(Identifier id, bool isVerified) + return new ParametersChanged { - return new KeyVerified - { - RootId = id, - IsVerified = isVerified, - OccurredUtc = DateTime.UtcNow - }; - } - - public required bool IsVerified { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Description = description, + ExpiresOn = expiresOn, + OccurredUtc = DateTime.UtcNow + }; } } public static class SSOUsers { - public sealed class Created : IDomainEvent + public static Domain.Events.Shared.Identities.SSOUsers.Created Created(Identifier id, string providerName, + Identifier userId) { - public static Created Create(Identifier id, string providerName, Identifier userId) + return new Domain.Events.Shared.Identities.SSOUsers.Created { - return new Created - { - RootId = id, - ProviderName = providerName, - UserId = userId, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string ProviderName { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + ProviderName = providerName, + UserId = userId, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class TokensUpdated : IDomainEvent + public static TokensUpdated TokensUpdated(Identifier id, string tokens, EmailAddress emailAddress, + PersonName name, Timezone timezone, Address address) { - public static TokensUpdated Create(Identifier id, string tokens, EmailAddress emailAddress, - PersonName name, Timezone timezone, Address address) + return new TokensUpdated { - return new TokensUpdated - { - RootId = id, - Tokens = tokens, - EmailAddress = emailAddress, - FirstName = name.FirstName, - LastName = name.LastName.ValueOrDefault?.Text, - Timezone = timezone.Code.ToString(), - CountryCode = address.CountryCode.ToString(), - OccurredUtc = DateTime.UtcNow - }; - } - - public required string CountryCode { get; set; } - - public required string EmailAddress { get; set; } - - public required string FirstName { get; set; } - - public string? LastName { get; set; } - - public required string Timezone { get; set; } - - public required string Tokens { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Tokens = tokens, + EmailAddress = emailAddress, + FirstName = name.FirstName, + LastName = name.LastName.ValueOrDefault?.Text, + Timezone = timezone.Code.ToString(), + CountryCode = address.CountryCode.ToString(), + OccurredUtc = DateTime.UtcNow + }; } } } \ No newline at end of file diff --git a/src/IdentityDomain/IdentityDomain.csproj b/src/IdentityDomain/IdentityDomain.csproj index e9296282..d0bc6074 100644 --- a/src/IdentityDomain/IdentityDomain.csproj +++ b/src/IdentityDomain/IdentityDomain.csproj @@ -5,18 +5,15 @@ - - <_Parameter1>$(AssemblyName).UnitTests - + + - - - - + + <_Parameter1>$(AssemblyName).UnitTests + - ResXFileCodeGenerator diff --git a/src/IdentityDomain/PasswordCredentialRoot.cs b/src/IdentityDomain/PasswordCredentialRoot.cs index dc2cc21f..e11536d0 100644 --- a/src/IdentityDomain/PasswordCredentialRoot.cs +++ b/src/IdentityDomain/PasswordCredentialRoot.cs @@ -4,6 +4,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.PasswordCredentials; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -27,7 +28,7 @@ public static Result Create(IRecorder recorder, I { var root = new PasswordCredentialRoot(recorder, idFactory, settings, emailAddressService, tokensService, passwordHasherService); - root.RaiseCreateEvent(IdentityDomain.Events.PasswordCredentials.Created.Create(root.Id, userId)); + root.RaiseCreateEvent(IdentityDomain.Events.PasswordCredentials.Created(root.Id, userId)); return root; } @@ -117,14 +118,14 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.PasswordCredentials.Created created: + case Created created: { UserId = created.UserId.ToId(); Recorder.TraceDebug(null, "Password credential {Id} was created for {UserId}", Id, created.UserId); return Result.Ok; } - case Events.PasswordCredentials.CredentialsChanged changed: + case CredentialsChanged changed: { var set = Password.SetPassword(_passwordHasherService, changed.PasswordHash); if (!set.IsSuccessful) @@ -137,7 +138,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PasswordCredentials.RegistrationChanged changed: + case RegistrationChanged changed: { var registration = IdentityDomain.Registration.Create(changed.EmailAddress, changed.Name); if (!registration.IsSuccessful) @@ -150,7 +151,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PasswordCredentials.PasswordVerified changed: + case PasswordVerified changed: { if (changed.AuditAttempt) { @@ -163,33 +164,33 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PasswordCredentials.AccountLocked _: + case AccountLocked _: { Recorder.TraceDebug(null, "Password credential {Id} was locked", Id); return Result.Ok; } - case Events.PasswordCredentials.AccountUnlocked _: + case AccountUnlocked _: { Recorder.TraceDebug(null, "Password credential {Id} was unlocked", Id); return Result.Ok; } - case Events.PasswordCredentials.RegistrationVerificationCreated created: + case RegistrationVerificationCreated created: { Verification = Verification.Renew(created.Token); Recorder.TraceDebug(null, "Password credential {Id} verification has been renewed", Id); return Result.Ok; } - case Events.PasswordCredentials.RegistrationVerificationVerified _: + case RegistrationVerificationVerified _: { Verification = Verification.Verify(); Recorder.TraceDebug(null, "Password credential {Id} has been verified", Id); return Result.Ok; } - case Events.PasswordCredentials.PasswordResetInitiated changed: + case PasswordResetInitiated changed: { var reset = Password.InitiatePasswordReset(changed.Token); if (!reset.IsSuccessful) @@ -202,7 +203,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PasswordCredentials.PasswordResetCompleted changed: + case PasswordResetCompleted changed: { var reset = Password.ResetPassword(_passwordHasherService, changed.Token, changed.PasswordHash); if (!reset.IsSuccessful) @@ -247,7 +248,7 @@ public Result InitiatePasswordReset() } var token = _tokensService.CreatePasswordResetToken(); - return RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.PasswordResetInitiated.Create(Id, token)); + return RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.PasswordResetInitiated(Id, token)); } public Result InitiateRegistrationVerification() @@ -259,7 +260,7 @@ public Result InitiateRegistrationVerification() var token = _tokensService.CreateRegistrationVerificationToken(); return RaiseChangeEvent( - IdentityDomain.Events.PasswordCredentials.RegistrationVerificationCreated.Create(Id, token)); + IdentityDomain.Events.PasswordCredentials.RegistrationVerificationCreated(Id, token)); } public Result ResetPassword(string token, string password) @@ -298,11 +299,11 @@ public Result ResetPassword(string token, string password) var passwordHash = _passwordHasherService.HashPassword(password); RaiseChangeEvent( - IdentityDomain.Events.PasswordCredentials.PasswordResetCompleted.Create(Id, token, passwordHash)); + IdentityDomain.Events.PasswordCredentials.PasswordResetCompleted(Id, token, passwordHash)); if (Login.HasJustUnlocked) { - RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountUnlocked.Create(Id)); + RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountUnlocked(Id)); } return Result.Ok; @@ -317,14 +318,14 @@ public Result SetCredential(string password) } return RaiseChangeEvent( - IdentityDomain.Events.PasswordCredentials.CredentialsChanged.Create(Id, + IdentityDomain.Events.PasswordCredentials.CredentialsChanged(Id, _passwordHasherService.HashPassword(password))); } public Result SetRegistrationDetails(EmailAddress emailAddress, PersonDisplayName displayName) { return RaiseChangeEvent( - IdentityDomain.Events.PasswordCredentials.RegistrationChanged.Create(Id, emailAddress, displayName)); + IdentityDomain.Events.PasswordCredentials.RegistrationChanged(Id, emailAddress, displayName)); } #if TESTINGONLY @@ -387,7 +388,7 @@ public Result VerifyPassword(string password, bool auditAttempt = t var isVerified = verify.Value; var raised = RaiseChangeEvent( - IdentityDomain.Events.PasswordCredentials.PasswordVerified.Create(Id, isVerified, auditAttempt)); + IdentityDomain.Events.PasswordCredentials.PasswordVerified(Id, isVerified, auditAttempt)); if (!raised.IsSuccessful) { return raised.Error; @@ -395,7 +396,7 @@ public Result VerifyPassword(string password, bool auditAttempt = t if (Login.HasJustLocked) { - var locked = RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountLocked.Create(Id)); + var locked = RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountLocked(Id)); if (!locked.IsSuccessful) { return locked.Error; @@ -404,7 +405,7 @@ public Result VerifyPassword(string password, bool auditAttempt = t if (Login.HasJustUnlocked) { - var unlocked = RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountUnlocked.Create(Id)); + var unlocked = RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.AccountUnlocked(Id)); if (!unlocked.IsSuccessful) { return unlocked.Error; @@ -423,7 +424,7 @@ public Result VerifyRegistration() : Resources.PasswordCredentialsRoot_RegistrationVerifyingExpired); } - return RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.RegistrationVerificationVerified.Create(Id)); + return RaiseChangeEvent(IdentityDomain.Events.PasswordCredentials.RegistrationVerificationVerified(Id)); } private static LoginMonitor CreateLoginMonitor(IConfigurationSettings settings) diff --git a/src/IdentityDomain/SSOUserRoot.cs b/src/IdentityDomain/SSOUserRoot.cs index 2645eeda..a6ca0913 100644 --- a/src/IdentityDomain/SSOUserRoot.cs +++ b/src/IdentityDomain/SSOUserRoot.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.SSOUsers; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -20,7 +21,7 @@ public static Result Create(IRecorder recorder, IIdentifierF string providerName, Identifier userId) { var root = new SSOUserRoot(recorder, idFactory, encryptionService); - root.RaiseCreateEvent(IdentityDomain.Events.SSOUsers.Created.Create(root.Id, providerName, userId)); + root.RaiseCreateEvent(IdentityDomain.Events.SSOUsers.Created(root.Id, providerName, userId)); return root; } @@ -73,14 +74,14 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.SSOUsers.Created created: + case Created created: { ProviderName = created.ProviderName; UserId = created.UserId.ToId(); return Result.Ok; } - case Events.SSOUsers.TokensUpdated changed: + case TokensUpdated changed: { var emailAddress = Domain.Shared.EmailAddress.Create(changed.EmailAddress); if (!emailAddress.IsSuccessful) @@ -126,7 +127,7 @@ public Result UpdateDetails(SSOAuthTokens tokens, EmailAddress emailAddre { var secureTokens = _encryptionService.Encrypt(tokens.ToJson(false)!); return RaiseChangeEvent( - IdentityDomain.Events.SSOUsers.TokensUpdated.Create(Id, secureTokens, emailAddress, name, timezone, + IdentityDomain.Events.SSOUsers.TokensUpdated(Id, secureTokens, emailAddress, name, timezone, address)); } } \ No newline at end of file diff --git a/src/IdentityInfrastructure/Persistence/ReadModels/APIKeyProjection.cs b/src/IdentityInfrastructure/Persistence/ReadModels/APIKeyProjection.cs index 274d89ca..c8b38a46 100644 --- a/src/IdentityInfrastructure/Persistence/ReadModels/APIKeyProjection.cs +++ b/src/IdentityInfrastructure/Persistence/ReadModels/APIKeyProjection.cs @@ -3,6 +3,7 @@ using Common; using Domain.Common.Events; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.APIKeys; using Domain.Interfaces; using Domain.Interfaces.Entities; using IdentityApplication.Persistence.ReadModels; @@ -28,7 +29,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.APIKeys.Created e: + case Created e: return await _authTokens.HandleCreateAsync(e.RootId.ToId(), dto => { dto.UserId = e.UserId; @@ -36,14 +37,14 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven }, cancellationToken); - case Events.APIKeys.ParametersChanged e: + case ParametersChanged e: return await _authTokens.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Description = e.Description; dto.ExpiresOn = e.ExpiresOn.ToOptional(); }, cancellationToken); - case Events.APIKeys.KeyVerified _: + case KeyVerified _: return true; case Global.StreamDeleted e: diff --git a/src/IdentityInfrastructure/Persistence/ReadModels/AuthTokensProjection.cs b/src/IdentityInfrastructure/Persistence/ReadModels/AuthTokensProjection.cs index e5f326e4..f3ba9b59 100644 --- a/src/IdentityInfrastructure/Persistence/ReadModels/AuthTokensProjection.cs +++ b/src/IdentityInfrastructure/Persistence/ReadModels/AuthTokensProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.AuthTokens; using Domain.Interfaces; using Domain.Interfaces.Entities; using IdentityApplication.Persistence.ReadModels; @@ -27,11 +28,11 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.AuthTokens.Created e: + case Created e: return await _authTokens.HandleCreateAsync(e.RootId.ToId(), dto => { dto.UserId = e.UserId; }, cancellationToken); - case Events.AuthTokens.TokensChanged e: + case TokensChanged e: return await _authTokens.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.AccessToken = e.AccessToken; @@ -40,7 +41,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.RefreshTokenExpiresOn = e.RefreshTokenExpiresOn; }, cancellationToken); - case Events.AuthTokens.TokensRefreshed e: + case TokensRefreshed e: return await _authTokens.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.AccessToken = e.AccessToken; @@ -49,7 +50,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.RefreshTokenExpiresOn = e.RefreshTokenExpiresOn; }, cancellationToken); - case Events.AuthTokens.TokensRevoked e: + case TokensRevoked e: return await _authTokens.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.AccessToken = Optional.None; diff --git a/src/IdentityInfrastructure/Persistence/ReadModels/PasswordCredentialProjection.cs b/src/IdentityInfrastructure/Persistence/ReadModels/PasswordCredentialProjection.cs index fe53889a..4f5bad49 100644 --- a/src/IdentityInfrastructure/Persistence/ReadModels/PasswordCredentialProjection.cs +++ b/src/IdentityInfrastructure/Persistence/ReadModels/PasswordCredentialProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.PasswordCredentials; using Domain.Interfaces; using Domain.Interfaces.Entities; using IdentityApplication.Persistence.ReadModels; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.PasswordCredentials.Created e: + case Created e: return await _credentials.HandleCreateAsync(e.RootId.ToId(), dto => { dto.UserId = e.UserId; @@ -36,46 +37,46 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven }, cancellationToken); - case Events.PasswordCredentials.CredentialsChanged e: + case CredentialsChanged e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.PasswordResetToken = Optional.None; }, cancellationToken); - case Events.PasswordCredentials.RegistrationChanged e: + case RegistrationChanged e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.UserName = e.Name; dto.UserEmailAddress = e.EmailAddress; }, cancellationToken); - case Events.PasswordCredentials.PasswordVerified _: + case PasswordVerified _: return true; - case Events.PasswordCredentials.AccountLocked e: + case AccountLocked e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.AccountLocked = true; }, cancellationToken); - case Events.PasswordCredentials.AccountUnlocked e: + case AccountUnlocked e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.AccountLocked = false; }, cancellationToken); - case Events.PasswordCredentials.RegistrationVerificationCreated e: + case RegistrationVerificationCreated e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.RegistrationVerificationToken = e.Token; }, cancellationToken); - case Events.PasswordCredentials.RegistrationVerificationVerified e: + case RegistrationVerificationVerified e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.RegistrationVerificationToken = Optional.None; dto.RegistrationVerified = true; }, cancellationToken); - case Events.PasswordCredentials.PasswordResetInitiated e: + case PasswordResetInitiated e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.PasswordResetToken = e.Token; }, cancellationToken); - case Events.PasswordCredentials.PasswordResetCompleted e: + case PasswordResetCompleted e: return await _credentials.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.PasswordResetToken = Optional.None; }, cancellationToken); diff --git a/src/IdentityInfrastructure/Persistence/ReadModels/SSOUserProjection.cs b/src/IdentityInfrastructure/Persistence/ReadModels/SSOUserProjection.cs index 7d0fd844..24070cdb 100644 --- a/src/IdentityInfrastructure/Persistence/ReadModels/SSOUserProjection.cs +++ b/src/IdentityInfrastructure/Persistence/ReadModels/SSOUserProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Identities.SSOUsers; using Domain.Interfaces; using Domain.Interfaces.Entities; using IdentityApplication.Persistence.ReadModels; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.SSOUsers.Created e: + case Created e: return await _users.HandleCreateAsync(e.RootId.ToId(), dto => { dto.UserId = e.UserId; @@ -35,7 +36,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven }, cancellationToken); - case Events.SSOUsers.TokensUpdated e: + case TokensUpdated e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Tokens = e.Tokens; diff --git a/src/Infrastructure.Shared/DomainServices/TokensService.cs b/src/Infrastructure.Shared/DomainServices/TokensService.cs index e1cfffd9..efc4e0cf 100644 --- a/src/Infrastructure.Shared/DomainServices/TokensService.cs +++ b/src/Infrastructure.Shared/DomainServices/TokensService.cs @@ -2,7 +2,7 @@ using Common; using Domain.Interfaces.Validations; using Domain.Services.Shared.DomainServices; -using Domain.Shared; +using Domain.Shared.Identities; namespace Infrastructure.Shared.DomainServices; diff --git a/src/OrganizationsApplication.UnitTests/OrganizationsApplicationSpec.cs b/src/OrganizationsApplication.UnitTests/OrganizationsApplicationSpec.cs index e1ebb26c..d9ecb616 100644 --- a/src/OrganizationsApplication.UnitTests/OrganizationsApplicationSpec.cs +++ b/src/OrganizationsApplication.UnitTests/OrganizationsApplicationSpec.cs @@ -14,6 +14,7 @@ using OrganizationsDomain; using UnitTesting.Common; using Xunit; +using OrganizationOwnership = Domain.Shared.Organizations.OrganizationOwnership; namespace OrganizationsApplication.UnitTests; @@ -63,14 +64,14 @@ public async Task WhenCreateOrganizationAsync_ThenReturnsOrganization() { var result = await _application.CreateOrganizationAsync(_caller.Object, "auserid", "aname", - OrganizationOwnership.Personal, CancellationToken.None); + Application.Resources.Shared.OrganizationOwnership.Personal, CancellationToken.None); result.Value.Name.Should().Be("aname"); - result.Value.Ownership.Should().Be(OrganizationOwnership.Personal); + result.Value.Ownership.Should().Be(Application.Resources.Shared.OrganizationOwnership.Personal); result.Value.CreatedById.Should().Be("auserid"); _repository.Verify(rep => rep.SaveAsync(It.Is(org => org.Name == "aname" - && org.Ownership == Ownership.Personal + && org.Ownership == OrganizationOwnership.Personal && org.CreatedById == "auserid" && org.Settings.Properties.Count == 1 && org.Settings.Properties["aname"].Value.As() == "avalue" @@ -101,11 +102,11 @@ await _application.CreateSharedOrganizationAsync(_caller.Object, "aname", CancellationToken.None); result.Value.Name.Should().Be("aname"); - result.Value.Ownership.Should().Be(OrganizationOwnership.Shared); + result.Value.Ownership.Should().Be(Application.Resources.Shared.OrganizationOwnership.Shared); result.Value.CreatedById.Should().Be("acallerid"); _repository.Verify(rep => rep.SaveAsync(It.Is(org => org.Name == "aname" - && org.Ownership == Ownership.Shared + && org.Ownership == OrganizationOwnership.Shared && org.CreatedById == "acallerid" && org.Settings.Properties.Count == 1 && org.Settings.Properties["aname"].Value.As() == "avalue" @@ -134,7 +135,7 @@ public async Task WhenGetAndNotExists_ThenReturnsError() public async Task WhenGet_ThenReturnsOrganization() { var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Personal, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Personal, "auserid".ToId(), DisplayName.Create("aname").Value).Value; org.CreateSettings(Settings.Create(new Dictionary { { "aname", Setting.Create("avalue", true).Value } @@ -147,7 +148,7 @@ public async Task WhenGet_ThenReturnsOrganization() result.Value.Name.Should().Be("aname"); result.Value.CreatedById.Should().Be("auserid"); - result.Value.Ownership.Should().Be(OrganizationOwnership.Personal); + result.Value.Ownership.Should().Be(Application.Resources.Shared.OrganizationOwnership.Personal); } [Fact] @@ -166,7 +167,7 @@ public async Task WhenGetSettingsAndNotExists_ThenReturnsError() public async Task WhenGetSettings_ThenReturnsSettings() { var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Personal, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Personal, "auserid".ToId(), DisplayName.Create("aname").Value).Value; org.CreateSettings(Settings.Create(new Dictionary { { "aname", Setting.Create("avalue", true).Value } @@ -198,7 +199,7 @@ public async Task WhenChangeSettingsAndNotExists_ThenReturnsError() public async Task WhenChangeSettings_ThenReturnsSettings() { var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; org.CreateSettings(Settings.Create(new Dictionary { { "aname1", Setting.Create("anoldvalue", true).Value }, @@ -218,7 +219,7 @@ public async Task WhenChangeSettings_ThenReturnsSettings() result.Should().BeSuccess(); _repository.Verify(rep => rep.SaveAsync(It.Is(o => o.Name == "aname" - && o.Ownership == Ownership.Shared + && o.Ownership == OrganizationOwnership.Shared && o.CreatedById == "auserid" && o.Settings.Properties.Count == 4 && o.Settings.Properties["aname1"].Value.As() == "anewvalue" @@ -250,7 +251,7 @@ public async Task WhenInviteMemberToOrganizationAsync_ThenInvites() _caller.Setup(cc => cc.Roles) .Returns(new ICallerContext.CallerRoles(Array.Empty(), new[] { TenantRoles.Owner })); var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; _repository.Setup(s => s.LoadAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(org); @@ -273,7 +274,7 @@ public async Task WhenInviteMemberToOrganizationAsync_ThenInvites() result.Should().BeSuccess(); result.Value.Name.Should().Be("aname"); result.Value.CreatedById.Should().Be("auserid"); - result.Value.Ownership.Should().Be(OrganizationOwnership.Shared); + result.Value.Ownership.Should().Be(Application.Resources.Shared.OrganizationOwnership.Shared); _endUsersService.Verify(eus => eus.InviteMemberToOrganizationPrivateAsync(_caller.Object, "anorganizationid", "auserid", null, CancellationToken.None)); @@ -296,7 +297,7 @@ public async Task WhenListMembersForOrganizationAsyncAndNotExist_ThenReturnsErro public async Task WhenListMembersForOrganizationAsyncWithUnregisteredUser_ThenReturnsMemberships() { var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; _repository.Setup(s => s.LoadAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(org); @@ -351,7 +352,7 @@ public async Task WhenListMembersForOrganizationAsyncWithUnregisteredUser_ThenRe public async Task WhenListMembersForOrganizationAsyncWithRegisteredUsers_ThenReturnsMemberships() { var org = OrganizationRoot.Create(_recorder.Object, _idFactory.Object, _tenantSettingService.Object, - Ownership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Shared, "auserid".ToId(), DisplayName.Create("aname").Value).Value; _repository.Setup(s => s.LoadAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(org); diff --git a/src/OrganizationsApplication/OrganizationsApplication.cs b/src/OrganizationsApplication/OrganizationsApplication.cs index a94ceb16..a2f66c33 100644 --- a/src/OrganizationsApplication/OrganizationsApplication.cs +++ b/src/OrganizationsApplication/OrganizationsApplication.cs @@ -12,6 +12,7 @@ using Domain.Shared; using OrganizationsApplication.Persistence; using OrganizationsDomain; +using OrganizationOwnership = Domain.Shared.Organizations.OrganizationOwnership; namespace OrganizationsApplication; @@ -71,7 +72,7 @@ public async Task> ChangeSettingsAsync(ICallerContext caller, stri } public async Task> CreateOrganizationAsync(ICallerContext caller, string creatorId, - string name, OrganizationOwnership ownership, CancellationToken cancellationToken) + string name, Application.Resources.Shared.OrganizationOwnership ownership, CancellationToken cancellationToken) { var displayName = DisplayName.Create(name); if (!displayName.IsSuccessful) @@ -80,7 +81,7 @@ public async Task> CreateOrganizationAsync(ICallerCo } var created = OrganizationRoot.Create(_recorder, _identifierFactory, _tenantSettingService, - ownership.ToEnumOrDefault(Ownership.Shared), creatorId.ToId(), displayName.Value); + ownership.ToEnumOrDefault(OrganizationOwnership.Shared), creatorId.ToId(), displayName.Value); if (!created.IsSuccessful) { return created.Error; @@ -123,13 +124,14 @@ public async Task> CreateSharedOrganizationAsync(ICa CancellationToken cancellationToken) { var creatorId = caller.CallerId; - var created = await CreateOrganizationAsync(caller, creatorId, name, OrganizationOwnership.Shared, - cancellationToken); + var created = await CreateOrganizationAsync(caller, creatorId, name, + Application.Resources.Shared.OrganizationOwnership.Shared, cancellationToken); if (!created.IsSuccessful) { return created.Error; } + //TODO: replaced by a notification! var organization = created.Value; var membership = await _endUsersService.CreateMembershipForCallerPrivateAsync(caller, organization.Id, cancellationToken); @@ -284,7 +286,8 @@ public static Organization ToOrganization(this OrganizationRoot organization) Id = organization.Id, Name = organization.Name, CreatedById = organization.CreatedById, - Ownership = organization.Ownership.ToEnumOrDefault(OrganizationOwnership.Shared) + Ownership = organization.Ownership.ToEnumOrDefault( + Application.Resources.Shared.OrganizationOwnership.Shared) }; } diff --git a/src/OrganizationsApplication/Persistence/ReadModels/Organization.cs b/src/OrganizationsApplication/Persistence/ReadModels/Organization.cs index 060a306e..7c9fd5cd 100644 --- a/src/OrganizationsApplication/Persistence/ReadModels/Organization.cs +++ b/src/OrganizationsApplication/Persistence/ReadModels/Organization.cs @@ -1,6 +1,6 @@ using Application.Persistence.Common; using Common; -using OrganizationsDomain; +using Domain.Shared.Organizations; using QueryAny; namespace OrganizationsApplication.Persistence.ReadModels; @@ -12,5 +12,5 @@ public class Organization : ReadModelEntity public Optional Name { get; set; } - public Optional Ownership { get; set; } + public Optional Ownership { get; set; } } \ No newline at end of file diff --git a/src/OrganizationsDomain.UnitTests/OrganizationRootSpec.cs b/src/OrganizationsDomain.UnitTests/OrganizationRootSpec.cs index f53e3296..65279070 100644 --- a/src/OrganizationsDomain.UnitTests/OrganizationRootSpec.cs +++ b/src/OrganizationsDomain.UnitTests/OrganizationRootSpec.cs @@ -2,8 +2,10 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Organizations; using Domain.Interfaces.Entities; using Domain.Interfaces.Services; +using Domain.Shared.Organizations; using FluentAssertions; using Moq; using Xunit; @@ -28,7 +30,7 @@ public OrganizationRootSpec() .Returns((string value) => value); _org = OrganizationRoot.Create(recorder.Object, identifierFactory.Object, tenantSettingService.Object, - Ownership.Personal, "acreatorid".ToId(), DisplayName.Create("aname").Value).Value; + OrganizationOwnership.Personal, "acreatorid".ToId(), DisplayName.Create("aname").Value).Value; } [Fact] @@ -36,7 +38,7 @@ public void WhenCreate_ThenAssigns() { _org.Name.Name.Should().Be("aname"); _org.CreatedById.Should().Be("acreatorid".ToId()); - _org.Ownership.Should().Be(Ownership.Personal); + _org.Ownership.Should().Be(OrganizationOwnership.Personal); _org.Settings.Should().Be(Settings.Empty); } @@ -52,7 +54,7 @@ public void WhenCreateSettings_ThenAddsSettings() _org.Settings.Properties.Count.Should().Be(2); _org.Settings.Properties["aname1"].Should().Be(Setting.Create("avalue1", true).Value); _org.Settings.Properties["aname2"].Should().Be(Setting.Create("avalue2", true).Value); - _org.Events.Last().Should().BeOfType(); + _org.Events.Last().Should().BeOfType(); } [Fact] @@ -73,7 +75,7 @@ public void WhenUpdateSettings_ThenAddsAndUpdatesSettings() _org.Settings.Properties["aname1"].Should().Be(Setting.Create("anewvalue1", true).Value); _org.Settings.Properties["aname2"].Should().Be(Setting.Create("anoldvalue2", false).Value); _org.Settings.Properties["aname3"].Should().Be(Setting.Create("anewvalue3", true).Value); - _org.Events[3].Should().BeOfType(); - _org.Events.Last().Should().BeOfType(); + _org.Events[3].Should().BeOfType(); + _org.Events.Last().Should().BeOfType(); } } \ No newline at end of file diff --git a/src/OrganizationsDomain.UnitTests/SettingSpec.cs b/src/OrganizationsDomain.UnitTests/SettingSpec.cs index 9e670a96..47974671 100644 --- a/src/OrganizationsDomain.UnitTests/SettingSpec.cs +++ b/src/OrganizationsDomain.UnitTests/SettingSpec.cs @@ -1,4 +1,5 @@ using Domain.Interfaces.Services; +using Domain.Shared.Organizations; using FluentAssertions; using Moq; using UnitTesting.Common; diff --git a/src/OrganizationsDomain/Events.cs b/src/OrganizationsDomain/Events.cs index 66a36c54..a7c7a776 100644 --- a/src/OrganizationsDomain/Events.cs +++ b/src/OrganizationsDomain/Events.cs @@ -1,96 +1,51 @@ using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.Organizations; +using Domain.Shared.Organizations; namespace OrganizationsDomain; public static class Events { - public sealed class Created : IDomainEvent + public static Created Created(Identifier id, OrganizationOwnership ownership, Identifier createdBy, + DisplayName name) { - public static Created Create(Identifier id, Ownership ownership, Identifier createdBy, DisplayName name) + return new Created { - return new Created - { - Name = name, - Ownership = ownership, - CreatedById = createdBy, - RootId = id, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string CreatedById { get; set; } - - public required string Name { get; set; } - - public required Ownership Ownership { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + Name = name, + Ownership = ownership, + CreatedById = createdBy, + RootId = id, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class SettingCreated : IDomainEvent + public static SettingCreated SettingCreated(Identifier id, string name, string value, SettingValueType valueType, + bool isEncrypted) { - public static SettingCreated Create(Identifier id, string name, string value, SettingValueType valueType, - bool isEncrypted) + return new SettingCreated { - return new SettingCreated - { - RootId = id, - Name = name, - StringValue = value, - ValueType = valueType, - IsEncrypted = isEncrypted, - OccurredUtc = DateTime.UtcNow - }; - } - - public required bool IsEncrypted { get; set; } - - public required string Name { get; set; } - - public required string StringValue { get; set; } - - public required SettingValueType ValueType { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Name = name, + StringValue = value, + ValueType = valueType, + IsEncrypted = isEncrypted, + OccurredUtc = DateTime.UtcNow + }; } - public sealed class SettingUpdated : IDomainEvent + public static SettingUpdated SettingUpdated(Identifier id, string name, string from, SettingValueType fromType, + string to, SettingValueType toType, bool isEncrypted) { - public static SettingUpdated Create(Identifier id, string name, string from, SettingValueType fromType, - string to, SettingValueType toType, bool isEncrypted) + return new SettingUpdated { - return new SettingUpdated - { - RootId = id, - Name = name, - From = from, - FromType = fromType, - To = to, - ToType = toType, - IsEncrypted = isEncrypted, - OccurredUtc = DateTime.UtcNow - }; - } - - public required string From { get; set; } - - public required SettingValueType FromType { get; set; } - - public required bool IsEncrypted { get; set; } - - public required string Name { get; set; } - - public required string To { get; set; } - - public required SettingValueType ToType { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + Name = name, + From = from, + FromType = fromType, + To = to, + ToType = toType, + IsEncrypted = isEncrypted, + OccurredUtc = DateTime.UtcNow + }; } } \ No newline at end of file diff --git a/src/OrganizationsDomain/OrganizationRoot.cs b/src/OrganizationsDomain/OrganizationRoot.cs index 20661f94..7c741d05 100644 --- a/src/OrganizationsDomain/OrganizationRoot.cs +++ b/src/OrganizationsDomain/OrganizationRoot.cs @@ -2,12 +2,14 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Organizations; using Domain.Interfaces; using Domain.Interfaces.Authorization; using Domain.Interfaces.Entities; using Domain.Interfaces.Services; using Domain.Interfaces.ValueObjects; using Domain.Shared; +using Domain.Shared.Organizations; namespace OrganizationsDomain; @@ -18,10 +20,11 @@ public sealed class OrganizationRoot : AggregateRootBase private readonly ITenantSettingService _tenantSettingService; public static Result Create(IRecorder recorder, IIdentifierFactory idFactory, - ITenantSettingService tenantSettingService, Ownership ownership, Identifier createdBy, DisplayName name) + ITenantSettingService tenantSettingService, OrganizationOwnership ownership, Identifier createdBy, + DisplayName name) { var root = new OrganizationRoot(recorder, idFactory, tenantSettingService); - root.RaiseCreateEvent(OrganizationsDomain.Events.Created.Create(root.Id, ownership, createdBy, name)); + root.RaiseCreateEvent(OrganizationsDomain.Events.Created(root.Id, ownership, createdBy, name)); return root; } @@ -44,7 +47,7 @@ private OrganizationRoot(IRecorder recorder, IIdentifierFactory idFactory, public DisplayName Name { get; private set; } = DisplayName.Empty; - public Ownership Ownership { get; private set; } + public OrganizationOwnership Ownership { get; private set; } public Settings Settings { get; private set; } = Settings.Empty; @@ -72,7 +75,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Created created: + case Created created: { var name = DisplayName.Create(created.Name); if (!name.IsSuccessful) @@ -86,7 +89,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.SettingCreated created: + case SettingCreated created: { var value = Setting.From(created.StringValue, created.ValueType, created.IsEncrypted, _tenantSettingService); @@ -106,7 +109,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.SettingUpdated updated: + case SettingUpdated updated: { var to = Setting.From(updated.To, updated.ToType, updated.IsEncrypted, _tenantSettingService); if (!to.IsSuccessful) @@ -147,7 +150,7 @@ public Result CreateSettings(Settings settings) var valueValue = value.IsEncrypted ? _tenantSettingService.Encrypt(value.Value.ToString() ?? string.Empty) : value.Value.ToString() ?? string.Empty; - RaiseChangeEvent(OrganizationsDomain.Events.SettingCreated.Create(Id, key, valueValue, value.ValueType, + RaiseChangeEvent(OrganizationsDomain.Events.SettingCreated(Id, key, valueValue, value.ValueType, value.IsEncrypted)); } @@ -164,7 +167,7 @@ public Result UpdateSettings(Settings settings) ? _tenantSettingService.Encrypt(value.Value.ToString() ?? string.Empty) : value.Value.ToString() ?? string.Empty; var oldValue = oldSetting!.Value.ToString() ?? string.Empty; - RaiseChangeEvent(OrganizationsDomain.Events.SettingUpdated.Create(Id, key, oldValue, + RaiseChangeEvent(OrganizationsDomain.Events.SettingUpdated(Id, key, oldValue, oldSetting.ValueType, valueValue, value.ValueType, value.IsEncrypted)); } @@ -174,7 +177,7 @@ public Result UpdateSettings(Settings settings) ? _tenantSettingService.Encrypt(value.Value.ToString() ?? string.Empty) : value.Value.ToString() ?? string.Empty; RaiseChangeEvent( - OrganizationsDomain.Events.SettingCreated.Create(Id, key, valueValue, value.ValueType, + OrganizationsDomain.Events.SettingCreated(Id, key, valueValue, value.ValueType, value.IsEncrypted)); } } diff --git a/src/OrganizationsDomain/OrganizationsDomain.csproj b/src/OrganizationsDomain/OrganizationsDomain.csproj index bf791e77..603c53c7 100644 --- a/src/OrganizationsDomain/OrganizationsDomain.csproj +++ b/src/OrganizationsDomain/OrganizationsDomain.csproj @@ -5,8 +5,7 @@ - - + diff --git a/src/OrganizationsDomain/Ownership.cs b/src/OrganizationsDomain/Ownership.cs deleted file mode 100644 index de152a1d..00000000 --- a/src/OrganizationsDomain/Ownership.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace OrganizationsDomain; - -public enum Ownership -{ - Shared = 0, - Personal = 1 -} \ No newline at end of file diff --git a/src/OrganizationsDomain/Setting.cs b/src/OrganizationsDomain/Setting.cs index be7e26bf..efe3c8d2 100644 --- a/src/OrganizationsDomain/Setting.cs +++ b/src/OrganizationsDomain/Setting.cs @@ -3,6 +3,7 @@ using Domain.Common.ValueObjects; using Domain.Interfaces; using Domain.Interfaces.Services; +using Domain.Shared.Organizations; namespace OrganizationsDomain; @@ -93,11 +94,4 @@ public static Result From(string stringValue, SettingValueType v return new Setting(value, valueType, isEncrypted); } -} - -public enum SettingValueType -{ - String = 0, - Number = 1, - Boolean = 2 } \ No newline at end of file diff --git a/src/OrganizationsInfrastructure/Persistence/ReadModels/OrganizationProjection.cs b/src/OrganizationsInfrastructure/Persistence/ReadModels/OrganizationProjection.cs index 6b0cbb83..6434c565 100644 --- a/src/OrganizationsInfrastructure/Persistence/ReadModels/OrganizationProjection.cs +++ b/src/OrganizationsInfrastructure/Persistence/ReadModels/OrganizationProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.Organizations; using Domain.Interfaces; using Domain.Interfaces.Entities; using Infrastructure.Persistence.Common; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.Created e: + case Created e: return await _organizations.HandleCreateAsync(e.RootId.ToId(), dto => { dto.Name = e.Name; @@ -36,7 +37,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven }, cancellationToken); - case Events.SettingCreated _: + case SettingCreated _: return true; default: diff --git a/src/SaaStack.sln b/src/SaaStack.sln index ef10e8fd..ad7b9af7 100644 --- a/src/SaaStack.sln +++ b/src/SaaStack.sln @@ -342,6 +342,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserProfilesInfrastructure. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserProfilesInfrastructure.UnitTests", "UserProfilesInfrastructure.UnitTests\UserProfilesInfrastructure.UnitTests.csproj", "{A9D1A686-DEBA-4EC6-93E2-290392F41B13}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Domain.Events.Shared", "Domain.Events.Shared\Domain.Events.Shared.csproj", "{3AC2CCAF-A248-4FCA-9C42-BD207E528D27}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1093,6 +1095,12 @@ Global {A9D1A686-DEBA-4EC6-93E2-290392F41B13}.Release|Any CPU.Build.0 = Release|Any CPU {A9D1A686-DEBA-4EC6-93E2-290392F41B13}.ReleaseForDeploy|Any CPU.ActiveCfg = ReleaseForDeploy|Any CPU {A9D1A686-DEBA-4EC6-93E2-290392F41B13}.ReleaseForDeploy|Any CPU.Build.0 = ReleaseForDeploy|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.Release|Any CPU.Build.0 = Release|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.ReleaseForDeploy|Any CPU.ActiveCfg = ReleaseForDeploy|Any CPU + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27}.ReleaseForDeploy|Any CPU.Build.0 = ReleaseForDeploy|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {F5C77A86-38AF-40E4-82FC-617E624B2754} = {508E7DA4-4DF2-4201-955D-CCF70C41AD05} @@ -1258,5 +1266,6 @@ Global {2F4A4802-AD6F-472A-BD65-58896285E00C} = {153F22CE-3C45-4CF5-991A-01C866EC429F} {8CB11E5D-01DE-4FCF-98B1-4998E80D561D} = {153F22CE-3C45-4CF5-991A-01C866EC429F} {A9D1A686-DEBA-4EC6-93E2-290392F41B13} = {153F22CE-3C45-4CF5-991A-01C866EC429F} + {3AC2CCAF-A248-4FCA-9C42-BD207E528D27} = {3782A767-2274-4F44-80C6-D6C6EEB9C9A5} EndGlobalSection EndGlobal diff --git a/src/SaaStack.sln.DotSettings b/src/SaaStack.sln.DotSettings index 18ec4ccc..91cc9b75 100644 --- a/src/SaaStack.sln.DotSettings +++ b/src/SaaStack.sln.DotSettings @@ -902,6 +902,7 @@ public void When$condition$_Then$outcome$() True True True + True True True True diff --git a/src/Tools.Analyzers.NonPlatform.UnitTests/DomainDrivenDesignAnalyzerSpec.cs b/src/Tools.Analyzers.NonPlatform.UnitTests/DomainDrivenDesignAnalyzerSpec.cs index d0b61b00..7e0a8018 100644 --- a/src/Tools.Analyzers.NonPlatform.UnitTests/DomainDrivenDesignAnalyzerSpec.cs +++ b/src/Tools.Analyzers.NonPlatform.UnitTests/DomainDrivenDesignAnalyzerSpec.cs @@ -3658,28 +3658,6 @@ public static AClassed Create() } } - [Trait("Category", "Unit")] - public class GivenRule044 - { - [Fact] - public async Task WhenMissingCreateFactory_ThenAlerts() - { - const string input = @" -using System; -using Domain.Interfaces.Entities; -namespace ANamespace; -public sealed class AClassed : IDomainEvent -{ - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } -}"; - - await Verify.DiagnosticExists( - DomainDrivenDesignAnalyzer.Rule044, input, 5, 21, "AClassed"); - } - } - [Trait("Category", "Unit")] public class GivenRule045 { diff --git a/src/Tools.Analyzers.NonPlatform/AnalyzerReleases.Shipped.md b/src/Tools.Analyzers.NonPlatform/AnalyzerReleases.Shipped.md index 20b189ae..d015254a 100644 --- a/src/Tools.Analyzers.NonPlatform/AnalyzerReleases.Shipped.md +++ b/src/Tools.Analyzers.NonPlatform/AnalyzerReleases.Shipped.md @@ -42,7 +42,6 @@ SAASDDD041 | SaaStackDDD | Warning | DomainEvents must be sealed SAASDDD042 | SaaStackDDD | Error | DomainEvents must have a parameterless constructor SAASDDD043 | SaaStackDDD | Error | DomainEvents must be named in the past tense - SAASDDD044 | SaaStackDDD | Error | DomainEvents must have at least one Create() class factory method SAASDDD045 | SaaStackDDD | Error | Create() class factory methods must return correct types SAASDDD046 | SaaStackDDD | Error | Properties must have public getters and setters SAASDDD047 | SaaStackDDD | Error | Properties must be marked required or nullable or initialized diff --git a/src/Tools.Analyzers.NonPlatform/DomainDrivenDesignAnalyzer.cs b/src/Tools.Analyzers.NonPlatform/DomainDrivenDesignAnalyzer.cs index 1bf2795d..1138c884 100644 --- a/src/Tools.Analyzers.NonPlatform/DomainDrivenDesignAnalyzer.cs +++ b/src/Tools.Analyzers.NonPlatform/DomainDrivenDesignAnalyzer.cs @@ -182,9 +182,6 @@ public class DomainDrivenDesignAnalyzer : DiagnosticAnalyzer internal static readonly DiagnosticDescriptor Rule043 = "SAASDDD043".GetDescriptor(DiagnosticSeverity.Info, AnalyzerConstants.Categories.Ddd, nameof(Resources.SAASDDD043Title), nameof(Resources.SAASDDD043Description), nameof(Resources.SAASDDD043MessageFormat)); - internal static readonly DiagnosticDescriptor Rule044 = "SAASDDD044".GetDescriptor(DiagnosticSeverity.Error, - AnalyzerConstants.Categories.Ddd, nameof(Resources.SAASDDD044Title), nameof(Resources.SAASDDD044Description), - nameof(Resources.SAASDDD044MessageFormat)); internal static readonly DiagnosticDescriptor Rule045 = "SAASDDD045".GetDescriptor(DiagnosticSeverity.Error, AnalyzerConstants.Categories.Ddd, nameof(Resources.SAASDDD045Title), nameof(Resources.SAASDDD045Description), nameof(Resources.SAASDDD045MessageFormat)); @@ -209,7 +206,7 @@ public class DomainDrivenDesignAnalyzer : DiagnosticAnalyzer Rule010, Rule011, Rule012, Rule013, Rule014, Rule015, Rule016, Rule017, Rule018, Rule020, Rule021, Rule022, Rule023, Rule024, Rule025, Rule026, Rule027, Rule030, Rule031, Rule032, Rule033, Rule034, Rule035, Rule036, - Rule040, Rule041, Rule042, Rule043, Rule044, Rule045, Rule046, Rule047, Rule048, Rule049); + Rule040, Rule041, Rule042, Rule043, Rule045, Rule046, Rule047, Rule048, Rule049); public override void Initialize(AnalysisContext context) { @@ -525,11 +522,7 @@ private static void AnalyzeDomainEvent(SyntaxNodeAnalysisContext context) var classFactoryMethods = allMethods .Where(method => method.IsPublicStaticMethod() && method.IsNamed(ClassFactoryMethodName)) .ToList(); - if (classFactoryMethods.HasNone()) - { - context.ReportDiagnostic(Rule044, classDeclarationSyntax); - } - else + if (classFactoryMethods.HasAny()) { foreach (var method in classFactoryMethods) { diff --git a/src/UserProfilesDomain.UnitTests/UserProfileRootSpec.cs b/src/UserProfilesDomain.UnitTests/UserProfileRootSpec.cs index 3b9cee6a..09d4fd0d 100644 --- a/src/UserProfilesDomain.UnitTests/UserProfileRootSpec.cs +++ b/src/UserProfilesDomain.UnitTests/UserProfileRootSpec.cs @@ -2,6 +2,7 @@ using Common.Extensions; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.UserProfiles; using Domain.Interfaces.Entities; using Domain.Shared; using FluentAssertions; @@ -37,7 +38,7 @@ public void WhenConstructed_ThenAssigned() _profile.EmailAddress.HasValue.Should().BeFalse(); _profile.Address.Should().Be(Address.Default); _profile.Timezone.Should().Be(Timezone.Default); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -72,7 +73,7 @@ public void WhenSetEmailAddress_ThenSets() result.Should().BeSuccess(); _profile.EmailAddress.Value.Should().Be(emailAddress); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -101,7 +102,7 @@ public void WhenSetContactAddress_ThenSets() _profile.Address.State.Should().Be("astate"); _profile.Address.CountryCode.Should().Be(CountryCodes.Default); _profile.Address.Zip.Should().Be("azip"); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -123,7 +124,7 @@ public void WhenSetTimezone_ThenSets() result.Should().BeSuccess(); _profile.Address.CountryCode.Should().Be(CountryCodes.Default); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -146,7 +147,7 @@ public void WhenChangeName_ThenChanges() result.Should().BeSuccess(); _profile.Name.Value.FirstName.Text.Should().Be("anewfirstname"); _profile.Name.Value.LastName.Value.Text.Should().Be("anewlastname"); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -168,7 +169,7 @@ public void WhenChangeDisplayName_ThenChanges() result.Should().BeSuccess(); _profile.DisplayName.Value.Text.Should().Be("anewdisplayname"); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } [Fact] @@ -190,6 +191,6 @@ public void WhenChangePhoneNumber_ThenChanges() result.Should().BeSuccess(); _profile.PhoneNumber.Value.Number.Should().Be("+6498876986"); - _profile.Events.Last().Should().BeOfType(); + _profile.Events.Last().Should().BeOfType(); } } \ No newline at end of file diff --git a/src/UserProfilesDomain/Events.cs b/src/UserProfilesDomain/Events.cs index a4ac5e56..d3a4de2c 100644 --- a/src/UserProfilesDomain/Events.cs +++ b/src/UserProfilesDomain/Events.cs @@ -1,193 +1,95 @@ using Domain.Common.ValueObjects; -using Domain.Interfaces.Entities; +using Domain.Events.Shared.UserProfiles; using Domain.Shared; -using PhoneNumber = Domain.Shared.PhoneNumber; namespace UserProfilesDomain; public static class Events { - public sealed class Created : IDomainEvent + public static ContactAddressChanged ContactAddressChanged(Identifier id, Identifier userId, Address address) { - public static Created Create(Identifier id, ProfileType type, Identifier userId, PersonName name) + return new ContactAddressChanged { - return new Created - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - FirstName = name.FirstName, - LastName = name.LastName.ValueOrDefault!, - DisplayName = name.FirstName, - Type = type.ToString() - }; - } - - public required string DisplayName { get; set; } - - public required string FirstName { get; set; } - - public string? LastName { get; set; } - - public required string Type { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + Line1 = address.Line1, + Line2 = address.Line2, + Line3 = address.Line3, + City = address.City, + State = address.State, + CountryCode = address.CountryCode.Alpha3, + Zip = address.Zip + }; } - public sealed class EmailAddressChanged : IDomainEvent + public static Created Created(Identifier id, ProfileType type, Identifier userId, PersonName name) { - public static EmailAddressChanged Create(Identifier id, Identifier userId, EmailAddress emailAddress) + return new Created { - return new EmailAddressChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - EmailAddress = emailAddress - }; - } - - public required string EmailAddress { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + FirstName = name.FirstName, + LastName = name.LastName.ValueOrDefault!, + DisplayName = name.FirstName, + Type = type.ToString() + }; } - public sealed class ContactAddressChanged : IDomainEvent + public static DisplayNameChanged DisplayNameChanged(Identifier id, Identifier userId, PersonDisplayName name) { - public static ContactAddressChanged Create(Identifier id, Identifier userId, Address address) + return new DisplayNameChanged { - return new ContactAddressChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - Line1 = address.Line1, - Line2 = address.Line2, - Line3 = address.Line3, - City = address.City, - State = address.State, - CountryCode = address.CountryCode.Alpha3, - Zip = address.Zip - }; - } - - public string? City { get; set; } - - public required string CountryCode { get; set; } - - public string? Line1 { get; set; } - - public string? Line2 { get; set; } - - public string? Line3 { get; set; } - - public string? State { get; set; } - - public required string UserId { get; set; } - - public string? Zip { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + DisplayName = name + }; } - public sealed class TimezoneChanged : IDomainEvent + public static EmailAddressChanged EmailAddressChanged(Identifier id, Identifier userId, EmailAddress emailAddress) { - public static TimezoneChanged Create(Identifier id, Identifier userId, Timezone timezone) + return new EmailAddressChanged { - return new TimezoneChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - Timezone = timezone.Code.ToString() - }; - } - - public required string Timezone { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + EmailAddress = emailAddress + }; } - public sealed class NameChanged : IDomainEvent + public static NameChanged NameChanged(Identifier id, Identifier userId, PersonName name) { - public static NameChanged Create(Identifier id, Identifier userId, PersonName name) + return new NameChanged { - return new NameChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - FirstName = name.FirstName, - LastName = name.LastName.ValueOrDefault! - }; - } - - public required string FirstName { get; set; } - - public string? LastName { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + FirstName = name.FirstName, + LastName = name.LastName.ValueOrDefault! + }; } - public sealed class DisplayNameChanged : IDomainEvent + public static PhoneNumberChanged PhoneNumberChanged(Identifier id, Identifier userId, PhoneNumber number) { - public static DisplayNameChanged Create(Identifier id, Identifier userId, PersonDisplayName name) + return new PhoneNumberChanged { - return new DisplayNameChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - DisplayName = name - }; - } - - public required string DisplayName { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + Number = number + }; } - public sealed class PhoneNumberChanged : IDomainEvent + public static TimezoneChanged TimezoneChanged(Identifier id, Identifier userId, Timezone timezone) { - public static PhoneNumberChanged Create(Identifier id, Identifier userId, PhoneNumber number) + return new TimezoneChanged { - return new PhoneNumberChanged - { - RootId = id, - OccurredUtc = DateTime.UtcNow, - UserId = userId, - Number = number - }; - } - - public required string Number { get; set; } - - public required string UserId { get; set; } - - public required string RootId { get; set; } - - public required DateTime OccurredUtc { get; set; } + RootId = id, + OccurredUtc = DateTime.UtcNow, + UserId = userId, + Timezone = timezone.Code.ToString() + }; } } \ No newline at end of file diff --git a/src/UserProfilesDomain/UserProfileRoot.cs b/src/UserProfilesDomain/UserProfileRoot.cs index c868b62c..43a6c2a3 100644 --- a/src/UserProfilesDomain/UserProfileRoot.cs +++ b/src/UserProfilesDomain/UserProfileRoot.cs @@ -3,6 +3,7 @@ using Domain.Common.Entities; using Domain.Common.Identity; using Domain.Common.ValueObjects; +using Domain.Events.Shared.UserProfiles; using Domain.Interfaces; using Domain.Interfaces.Entities; using Domain.Interfaces.ValueObjects; @@ -16,7 +17,7 @@ public static Result Create(IRecorder recorder, IIdentif ProfileType type, Identifier userId, PersonName name) { var root = new UserProfileRoot(recorder, idFactory); - root.RaiseCreateEvent(UserProfilesDomain.Events.Created.Create(root.Id, type, userId, name)); + root.RaiseCreateEvent(UserProfilesDomain.Events.Created(root.Id, type, userId, name)); return root; } @@ -84,7 +85,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco { switch (@event) { - case Events.Created created: + case Created created: { UserId = created.UserId.ToId(); Type = created.Type.ToEnumOrDefault(ProfileType.Person); @@ -111,7 +112,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.EmailAddressChanged changed: + case EmailAddressChanged changed: { var email = Domain.Shared.EmailAddress.Create(changed.EmailAddress); if (!email.IsSuccessful) @@ -125,7 +126,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.ContactAddressChanged changed: + case ContactAddressChanged changed: { var address = Address.Create(changed.Line1, changed.Line2, changed.Line3, changed.City, changed.State, CountryCodes.FindOrDefault(changed.CountryCode), changed.Zip); @@ -139,7 +140,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.TimezoneChanged changed: + case TimezoneChanged changed: { var timezone = Timezone.Create(changed.Timezone); if (!timezone.IsSuccessful) @@ -152,7 +153,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.NameChanged changed: + case NameChanged changed: { var name = PersonName.Create(changed.FirstName, changed.LastName); if (!name.IsSuccessful) @@ -165,7 +166,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.DisplayNameChanged changed: + case DisplayNameChanged changed: { var name = PersonDisplayName.Create(changed.DisplayName); if (!name.IsSuccessful) @@ -178,7 +179,7 @@ protected override Result OnStateChanged(IDomainEvent @event, bool isReco return Result.Ok; } - case Events.PhoneNumberChanged changed: + case PhoneNumberChanged changed: { var number = Domain.Shared.PhoneNumber.Create(changed.Number); if (!number.IsSuccessful) @@ -203,7 +204,7 @@ public Result ChangeDisplayName(Identifier modifierId, PersonDisplayName return Error.RoleViolation(Resources.UserProfilesDomain_NotOwner); } - return RaiseChangeEvent(UserProfilesDomain.Events.DisplayNameChanged.Create(Id, UserId, displayName)); + return RaiseChangeEvent(UserProfilesDomain.Events.DisplayNameChanged(Id, UserId, displayName)); } public Result ChangeName(Identifier modifierId, PersonName name) @@ -213,7 +214,7 @@ public Result ChangeName(Identifier modifierId, PersonName name) return Error.RoleViolation(Resources.UserProfilesDomain_NotOwner); } - return RaiseChangeEvent(UserProfilesDomain.Events.NameChanged.Create(Id, UserId, name)); + return RaiseChangeEvent(UserProfilesDomain.Events.NameChanged(Id, UserId, name)); } public Result ChangePhoneNumber(Identifier modifierId, PhoneNumber number) @@ -228,7 +229,7 @@ public Result ChangePhoneNumber(Identifier modifierId, PhoneNumber number return Error.RuleViolation(Resources.UserProfilesDomain_NotAPerson); } - return RaiseChangeEvent(UserProfilesDomain.Events.PhoneNumberChanged.Create(Id, UserId, number)); + return RaiseChangeEvent(UserProfilesDomain.Events.PhoneNumberChanged(Id, UserId, number)); } public Result SetContactAddress(Identifier modifierId, Address address) @@ -238,7 +239,7 @@ public Result SetContactAddress(Identifier modifierId, Address address) return Error.RoleViolation(Resources.UserProfilesDomain_NotOwner); } - return RaiseChangeEvent(UserProfilesDomain.Events.ContactAddressChanged.Create(Id, UserId, address)); + return RaiseChangeEvent(UserProfilesDomain.Events.ContactAddressChanged(Id, UserId, address)); } public Result SetEmailAddress(Identifier modifierId, EmailAddress emailAddress) @@ -253,7 +254,7 @@ public Result SetEmailAddress(Identifier modifierId, EmailAddress emailAd return Error.RuleViolation(Resources.UserProfilesDomain_NotAPerson); } - return RaiseChangeEvent(UserProfilesDomain.Events.EmailAddressChanged.Create(Id, UserId, emailAddress)); + return RaiseChangeEvent(UserProfilesDomain.Events.EmailAddressChanged(Id, UserId, emailAddress)); } public Result SetTimezone(Identifier modifierId, Timezone timezone) @@ -263,7 +264,7 @@ public Result SetTimezone(Identifier modifierId, Timezone timezone) return Error.RoleViolation(Resources.UserProfilesDomain_NotOwner); } - return RaiseChangeEvent(UserProfilesDomain.Events.TimezoneChanged.Create(Id, UserId, timezone)); + return RaiseChangeEvent(UserProfilesDomain.Events.TimezoneChanged(Id, UserId, timezone)); } #if TESTINGONLY diff --git a/src/UserProfilesDomain/UserProfilesDomain.csproj b/src/UserProfilesDomain/UserProfilesDomain.csproj index bf791e77..603c53c7 100644 --- a/src/UserProfilesDomain/UserProfilesDomain.csproj +++ b/src/UserProfilesDomain/UserProfilesDomain.csproj @@ -5,8 +5,7 @@ - - + diff --git a/src/UserProfilesInfrastructure/Persistence/ReadModels/EndUserProjection.cs b/src/UserProfilesInfrastructure/Persistence/ReadModels/EndUserProjection.cs index 86282c0a..6d30ceb2 100644 --- a/src/UserProfilesInfrastructure/Persistence/ReadModels/EndUserProjection.cs +++ b/src/UserProfilesInfrastructure/Persistence/ReadModels/EndUserProjection.cs @@ -2,6 +2,7 @@ using Application.Persistence.Interfaces; using Common; using Domain.Common.ValueObjects; +using Domain.Events.Shared.UserProfiles; using Domain.Interfaces; using Domain.Interfaces.Entities; using Infrastructure.Persistence.Common; @@ -27,7 +28,7 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven { switch (changeEvent) { - case Events.Created e: + case Created e: return await _users.HandleCreateAsync(e.RootId.ToId(), dto => { dto.Type = e.Type; @@ -37,30 +38,30 @@ public async Task> ProjectEventAsync(IDomainEvent changeEven dto.LastName = e.LastName; }, cancellationToken); - case Events.NameChanged e: + case NameChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.FirstName = e.FirstName; dto.LastName = e.LastName; }, cancellationToken); - case Events.DisplayNameChanged e: + case DisplayNameChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.DisplayName = e.DisplayName; }, cancellationToken); - case Events.EmailAddressChanged e: + case EmailAddressChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.EmailAddress = e.EmailAddress; }, cancellationToken); - case Events.PhoneNumberChanged e: + case PhoneNumberChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.PhoneNumber = e.Number; }, cancellationToken); - case Events.TimezoneChanged e: + case TimezoneChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.Timezone = e.Timezone; }, cancellationToken); - case Events.ContactAddressChanged e: + case ContactAddressChanged e: return await _users.HandleUpdateAsync(e.RootId.ToId(), dto => { dto.CountryCode = e.CountryCode; }, cancellationToken);