diff --git a/Directory.Packages.props b/Directory.Packages.props index ada3c11..9717e70 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,7 +4,6 @@ true - @@ -16,7 +15,6 @@ - diff --git a/Hutopy.sln b/Hutopy.sln index 451a7bc..5521526 100644 --- a/Hutopy.sln +++ b/Hutopy.sln @@ -3,18 +3,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "src\Domain\Domain.csproj", "{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "src\Application\Application.csproj", "{34C0FACD-F3D9-400C-8945-554DD6B0819A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{664D406C-2F83-48F0-BFC3-408D5CB53C65}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain.UnitTests", "tests\Domain.UnitTests\Domain.UnitTests.csproj", "{DC37FD87-552C-4613-9F16-1537CA522898}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig @@ -30,56 +22,27 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.FunctionalTests", "tests\Application.FunctionalTests\Application.FunctionalTests.csproj", "{EA6127A5-94C9-4C31-AD11-E6811B92B520}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure.IntegrationTests", "tests\Infrastructure.IntegrationTests\Infrastructure.IntegrationTests.csproj", "{01FA6786-921D-4CE8-8C50-4FDA66C9477D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.Build.0 = Release|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.Build.0 = Release|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU {117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU - {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.Build.0 = Release|Any CPU {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.Build.0 = Release|Any CPU - {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.Build.0 = Release|Any CPU - {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} {117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {DC37FD87-552C-4613-9F16-1537CA522898} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} {4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} - {EA6127A5-94C9-4C31-AD11-E6811B92B520} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} - {01FA6786-921D-4CE8-8C50-4FDA66C9477D} = {664D406C-2F83-48F0-BFC3-408D5CB53C65} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430} diff --git a/README.md b/README.md index 170ea30..fcf7464 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ ## Patterns / strategy used - Clean Architecture ( with Infrastructure, Domain, Application and Web layers ) - Minimal API endpoints. -- Guards ( Fail fast ) : https://github.com/ardalis/GuardClauses ## Tools - Install Docker : https://www.docker.com/get-started/ diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj deleted file mode 100644 index 996edb9..0000000 --- a/src/Application/Application.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Hutopy.Application - Hutopy.Application - - - - - - - - - - - - - - - - diff --git a/src/Domain/Common/BaseAuditableEntity.cs b/src/Domain/Common/BaseAuditableEntity.cs deleted file mode 100644 index 617d876..0000000 --- a/src/Domain/Common/BaseAuditableEntity.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Hutopy.Domain.Common; - -public abstract class BaseAuditableEntity : BaseEntity -{ - public DateTimeOffset CreatedAt { get; set; } - - public Guid? CreatedBy { get; set; } - - public DateTimeOffset LastModifiedAt { get; set; } - - public Guid? LastModifiedBy { get; set; } -} diff --git a/src/Domain/Common/BaseEntity.cs b/src/Domain/Common/BaseEntity.cs deleted file mode 100644 index 080e1d4..0000000 --- a/src/Domain/Common/BaseEntity.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Hutopy.Domain.Common; - -public abstract class BaseEntity -{ - // This can easily be modified to be BaseEntity and public T Id to support different key types. - // Using non-generic integer types for simplicity - public Guid Id { get; set; } - - private readonly List _domainEvents = []; - - [NotMapped] - public IEnumerable DomainEvents => _domainEvents.AsReadOnly(); - - public void AddDomainEvent(BaseEvent domainEvent) - { - _domainEvents.Add(domainEvent); - } - - public void RemoveDomainEvent(BaseEvent domainEvent) - { - _domainEvents.Remove(domainEvent); - } - - public void ClearDomainEvents() - { - _domainEvents.Clear(); - } -} diff --git a/src/Domain/Common/BaseEvent.cs b/src/Domain/Common/BaseEvent.cs deleted file mode 100644 index 5df80ee..0000000 --- a/src/Domain/Common/BaseEvent.cs +++ /dev/null @@ -1,7 +0,0 @@ -using MediatR; - -namespace Hutopy.Domain.Common; - -public abstract class BaseEvent : INotification -{ -} diff --git a/src/Domain/Common/ValueObject.cs b/src/Domain/Common/ValueObject.cs deleted file mode 100644 index 6604643..0000000 --- a/src/Domain/Common/ValueObject.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace Hutopy.Domain.Common; - -// Learn more: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects -public abstract class ValueObject -{ - private static bool EqualOperator(ValueObject left, ValueObject right) - { - if (left is null ^ right is null) - { - return false; - } - - return left?.Equals(right!) != false; - } - - protected static bool NotEqualOperator(ValueObject left, ValueObject right) - { - return !(EqualOperator(left, right)); - } - - protected abstract IEnumerable GetEqualityComponents(); - - public override bool Equals(object? obj) - { - if (obj == null || obj.GetType() != GetType()) - { - return false; - } - - var other = (ValueObject)obj; - return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); - } - - public override int GetHashCode() - { - var hash = new HashCode(); - - foreach (var component in GetEqualityComponents()) - { - hash.Add(component); - } - - return hash.ToHashCode(); - } -} diff --git a/src/Domain/Constants/Policies.cs b/src/Domain/Constants/Policies.cs deleted file mode 100644 index 401d6dd..0000000 --- a/src/Domain/Constants/Policies.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Hutopy.Domain.Constants; - -public abstract class Policies -{ - public const string CanPurge = nameof(CanPurge); - public const string CanDelete = nameof(CanDelete); -} \ No newline at end of file diff --git a/src/Domain/Domain.csproj b/src/Domain/Domain.csproj deleted file mode 100644 index 56e216d..0000000 --- a/src/Domain/Domain.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - Hutopy.Domain - Hutopy.Domain - - - - - - - - diff --git a/src/Domain/Enums/PriorityLevel.cs b/src/Domain/Enums/PriorityLevel.cs deleted file mode 100644 index 0a7ca16..0000000 --- a/src/Domain/Enums/PriorityLevel.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Hutopy.Domain.Enums; - -public enum PriorityLevel -{ - None = 0, - Low = 1, - Medium = 2, - High = 3 -} diff --git a/src/Domain/Exceptions/UnsupportedColourException.cs b/src/Domain/Exceptions/UnsupportedColourException.cs deleted file mode 100644 index 676bbc7..0000000 --- a/src/Domain/Exceptions/UnsupportedColourException.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Hutopy.Domain.Exceptions; - -public class UnsupportedColourException( - string code) : Exception($"Colour \"{code}\" is unsupported."); diff --git a/src/Domain/GlobalUsings.cs b/src/Domain/GlobalUsings.cs deleted file mode 100644 index d6161ca..0000000 --- a/src/Domain/GlobalUsings.cs +++ /dev/null @@ -1,2 +0,0 @@ -global using Hutopy.Domain.Common; -global using Hutopy.Domain.Exceptions; diff --git a/src/Domain/ValueObjects/Colour.cs b/src/Domain/ValueObjects/Colour.cs deleted file mode 100644 index 7bd2590..0000000 --- a/src/Domain/ValueObjects/Colour.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace Hutopy.Domain.ValueObjects; - -public class Colour(string code) : ValueObject -{ - public static Colour From(string code) - { - var colour = new Colour(code); - - if (!SupportedColours.Contains(colour)) - { - throw new UnsupportedColourException(code); - } - - return colour; - } - - public static Colour White => new("#FFFFFF"); - - public static Colour Red => new("#FF5733"); - - public static Colour Orange => new("#FFC300"); - - public static Colour Yellow => new("#FFFF66"); - - public static Colour Green => new("#CCFF99"); - - public static Colour Blue => new("#6666FF"); - - public static Colour Purple => new("#9966CC"); - - public static Colour Grey => new("#999999"); - - public string Code { get; private set; } = string.IsNullOrWhiteSpace(code)?"#000000":code; - - public static implicit operator string(Colour colour) - { - return colour.ToString(); - } - - public static explicit operator Colour(string code) - { - return From(code); - } - - public override string ToString() - { - return Code; - } - - private static IEnumerable SupportedColours - { - get - { - yield return White; - yield return Red; - yield return Orange; - yield return Yellow; - yield return Green; - yield return Blue; - yield return Purple; - yield return Grey; - } - } - - protected override IEnumerable GetEqualityComponents() - { - yield return Code; - } -} diff --git a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs b/src/Infrastructure/BlobStorage/AzureBlobStorage.cs similarity index 99% rename from src/Infrastructure/AzureBlob/AzureBlobStorage.cs rename to src/Infrastructure/BlobStorage/AzureBlobStorage.cs index c2f3c72..fdf6fe9 100644 --- a/src/Infrastructure/AzureBlob/AzureBlobStorage.cs +++ b/src/Infrastructure/BlobStorage/AzureBlobStorage.cs @@ -4,7 +4,7 @@ using Azure.Storage.Blobs.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -namespace Hutopy.Infrastructure.AzureBlob; +namespace Hutopy.Infrastructure.BlobStorage; public class AzureBlobStorage { diff --git a/src/Infrastructure/AzureBlob/BlobStructure.txt b/src/Infrastructure/BlobStorage/BlobStructure.txt similarity index 100% rename from src/Infrastructure/AzureBlob/BlobStructure.txt rename to src/Infrastructure/BlobStorage/BlobStructure.txt diff --git a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs b/src/Infrastructure/BlobStorage/CommonFileNames.cs similarity index 72% rename from src/Application/AzureBlobStorage/Constants/CommonFileNames.cs rename to src/Infrastructure/BlobStorage/CommonFileNames.cs index 6a37a08..7b40a7d 100644 --- a/src/Application/AzureBlobStorage/Constants/CommonFileNames.cs +++ b/src/Infrastructure/BlobStorage/CommonFileNames.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.AzureBlobStorage.Constants; +namespace Hutopy.Infrastructure.BlobStorage; public static class CommonFileNames { diff --git a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs b/src/Infrastructure/BlobStorage/ContainerNames.cs similarity index 68% rename from src/Application/AzureBlobStorage/Constants/ContainerNames.cs rename to src/Infrastructure/BlobStorage/ContainerNames.cs index 039a27d..7319810 100644 --- a/src/Application/AzureBlobStorage/Constants/ContainerNames.cs +++ b/src/Infrastructure/BlobStorage/ContainerNames.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.AzureBlobStorage.Constants; +namespace Hutopy.Infrastructure.BlobStorage; public static class ContainerNames { diff --git a/src/Infrastructure/AzureBlob/ContentTypes.cs b/src/Infrastructure/BlobStorage/ContentTypes.cs similarity index 95% rename from src/Infrastructure/AzureBlob/ContentTypes.cs rename to src/Infrastructure/BlobStorage/ContentTypes.cs index 8af77a1..7ce942e 100644 --- a/src/Infrastructure/AzureBlob/ContentTypes.cs +++ b/src/Infrastructure/BlobStorage/ContentTypes.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Infrastructure.AzureBlob; +namespace Hutopy.Infrastructure.BlobStorage; public static class ContentTypes { diff --git a/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs b/src/Infrastructure/BlobStorage/SubDirectoryNames.cs similarity index 69% rename from src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs rename to src/Infrastructure/BlobStorage/SubDirectoryNames.cs index 7590b74..1bb509d 100644 --- a/src/Application/AzureBlobStorage/Constants/SubDirectoryNames.cs +++ b/src/Infrastructure/BlobStorage/SubDirectoryNames.cs @@ -1,4 +1,4 @@ -namespace Hutopy.Application.AzureBlobStorage.Constants; +namespace Hutopy.Infrastructure.BlobStorage; public static class SubDirectoryNames { diff --git a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs index ff313b4..5b89257 100644 --- a/src/Infrastructure/Data/ApplicationDbContextInitializer.cs +++ b/src/Infrastructure/Data/ApplicationDbContextInitializer.cs @@ -1,5 +1,4 @@ -using Hutopy.Domain.Constants; -using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; @@ -55,13 +54,13 @@ public class ApplicationDbContextInitializer( private async Task TrySeedAsync() { - var administratorRole = new ApplicationRole(Roles.Administrator); + var administratorRole = new ApplicationRole(KnownRoles.Administrator); if (roleManager.Roles.All(r => r.Name != administratorRole.Name)) { await roleManager.CreateAsync(administratorRole); } - var roleCreator = new ApplicationRole(Roles.Creator); + var roleCreator = new ApplicationRole(KnownRoles.Creator); if (roleManager.Roles.All(r => r.Name != roleCreator.Name)) { await roleManager.CreateAsync(roleCreator); diff --git a/src/Infrastructure/DependencyInjection.cs b/src/Infrastructure/DependencyInjection.cs index 0a328f5..bffd9d3 100644 --- a/src/Infrastructure/DependencyInjection.cs +++ b/src/Infrastructure/DependencyInjection.cs @@ -1,5 +1,4 @@ -using Hutopy.Domain.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; using Microsoft.AspNetCore.Identity; @@ -49,9 +48,6 @@ public static class DependencyInjection // Scoped services services.AddScoped(); - services.AddAuthorization(options => - options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator))); - return services; } } diff --git a/src/Domain/Constants/Roles.cs b/src/Infrastructure/Identity/KnownRoles.cs similarity index 61% rename from src/Domain/Constants/Roles.cs rename to src/Infrastructure/Identity/KnownRoles.cs index b285a6e..109c3fa 100644 --- a/src/Domain/Constants/Roles.cs +++ b/src/Infrastructure/Identity/KnownRoles.cs @@ -1,6 +1,6 @@ -namespace Hutopy.Domain.Constants; +namespace Hutopy.Infrastructure.Identity; -public abstract class Roles +public static class KnownRoles { public const string Administrator = nameof(Administrator); public const string Creator = nameof(Creator); diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 93b2a22..0967acf 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -18,9 +18,6 @@ - - - diff --git a/src/Web/Features/Contents/Handlers/ChangeBanner.cs b/src/Web/Features/Contents/Handlers/ChangeBanner.cs index 950d1b6..8c51ddd 100644 --- a/src/Web/Features/Contents/Handlers/ChangeBanner.cs +++ b/src/Web/Features/Contents/Handlers/ChangeBanner.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; diff --git a/src/Web/Features/Contents/Handlers/ChangeLogo.cs b/src/Web/Features/Contents/Handlers/ChangeLogo.cs index 5bbc6b9..5d987c9 100644 --- a/src/Web/Features/Contents/Handlers/ChangeLogo.cs +++ b/src/Web/Features/Contents/Handlers/ChangeLogo.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Web.Features.Contents.Data; namespace Hutopy.Web.Features.Contents.Handlers; diff --git a/src/Web/Features/Contents/Handlers/CreateContent.cs b/src/Web/Features/Contents/Handlers/CreateContent.cs index 46e9bb9..e139c44 100644 --- a/src/Web/Features/Contents/Handlers/CreateContent.cs +++ b/src/Web/Features/Contents/Handlers/CreateContent.cs @@ -1,6 +1,5 @@ using System.Collections.Concurrent; -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Contents.Handlers.Models; diff --git a/src/Web/Features/Users/Handlers/ChangePortrait.cs b/src/Web/Features/Users/Handlers/ChangePortrait.cs index ec624bb..4ab1c4c 100644 --- a/src/Web/Features/Users/Handlers/ChangePortrait.cs +++ b/src/Web/Features/Users/Handlers/ChangePortrait.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Infrastructure.Identity; using Hutopy.Web.Common; diff --git a/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs index 552a881..c5ec37c 100644 --- a/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs +++ b/src/Web/Features/Users/Handlers/GetCurrentUserProfilePicture.cs @@ -1,5 +1,4 @@ -using Hutopy.Application.AzureBlobStorage.Constants; -using Hutopy.Infrastructure.AzureBlob; +using Hutopy.Infrastructure.BlobStorage; using Hutopy.Infrastructure.Identity; namespace Hutopy.Web.Features.Users.Handlers; diff --git a/src/Web/Features/Users/Handlers/LoginWithGoogle.cs b/src/Web/Features/Users/Handlers/LoginWithGoogle.cs index bdb814d..49d0e8f 100644 --- a/src/Web/Features/Users/Handlers/LoginWithGoogle.cs +++ b/src/Web/Features/Users/Handlers/LoginWithGoogle.cs @@ -30,8 +30,7 @@ public class GoogleUserInfo [PublicAPI] public record LoginWithGoogleRequest( - string Token) - : IRequest; + string Token); public record LoginWithGoogleResponse( string AccessToken, diff --git a/src/Web/GlobalUsings.cs b/src/Web/GlobalUsings.cs index 4f99808..4b94f25 100644 --- a/src/Web/GlobalUsings.cs +++ b/src/Web/GlobalUsings.cs @@ -1,6 +1,4 @@ -global using Ardalis.GuardClauses; global using FastEndpoints; global using FluentValidation; global using JetBrains.Annotations; -global using MediatR; global using Microsoft.EntityFrameworkCore; diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 741415a..6858ab6 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -1,5 +1,4 @@ using Azure.Identity; -using Hutopy.Application; using Hutopy.Infrastructure; using Hutopy.Infrastructure.Data; using Hutopy.Infrastructure.Identity; diff --git a/src/Web/TestDataSeeder.cs b/src/Web/TestDataSeeder.cs index b6b599b..530ca5f 100644 --- a/src/Web/TestDataSeeder.cs +++ b/src/Web/TestDataSeeder.cs @@ -1,5 +1,4 @@ -using Hutopy.Domain.Constants; -using Hutopy.Infrastructure.Identity; +using Hutopy.Infrastructure.Identity; using Hutopy.Web.Common; using Hutopy.Web.Features.Contents.Data; using Hutopy.Web.Features.Messages.Data; @@ -34,7 +33,7 @@ internal class TestDataSeeder( { if (contentContext.Contents.Any()) return; - _users.Add(await CreateUserAsync("admin", null, Roles.Administrator)); + _users.Add(await CreateUserAsync("admin", null, KnownRoles.Administrator)); var userA = await CreateUserAsync("userA", null); _users.Add(userA); _users.Add(await CreateUserAsync("userB", null)); @@ -44,7 +43,7 @@ internal class TestDataSeeder( var creatorUser = await CreateUserAsync( creator.Name, creator.Images.Logo, - Roles.Creator); + KnownRoles.Creator); creator.Id = creatorUser.Id; creator.CreatedBy = creator.Id; diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 97eb60a..68ad88e 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -7,7 +7,6 @@ - diff --git a/tests/Application.FunctionalTests/Application.FunctionalTests.csproj b/tests/Application.FunctionalTests/Application.FunctionalTests.csproj deleted file mode 100644 index c3a8232..0000000 --- a/tests/Application.FunctionalTests/Application.FunctionalTests.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - Hutopy.Application.FunctionalTests - Hutopy.Application.FunctionalTests - - - - - - - - - PreserveNewest - true - PreserveNewest - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - diff --git a/tests/Application.FunctionalTests/BaseTestFixture.cs b/tests/Application.FunctionalTests/BaseTestFixture.cs deleted file mode 100644 index 27606ee..0000000 --- a/tests/Application.FunctionalTests/BaseTestFixture.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Hutopy.Application.FunctionalTests; - -using static Testing; - -[TestFixture] -public abstract class BaseTestFixture -{ - [SetUp] - public async Task TestSetUp() - { - await ResetState(); - } -} diff --git a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs b/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs deleted file mode 100644 index b8abf73..0000000 --- a/tests/Application.FunctionalTests/CustomWebApplicationFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Data.Common; -using Hutopy.Infrastructure.Data; -using Hutopy.Web; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.AspNetCore.TestHost; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; - -namespace Hutopy.Application.FunctionalTests; - -using static Testing; - -public class CustomWebApplicationFactory( - DbConnection connection) - : WebApplicationFactory -{ - protected override void ConfigureWebHost(IWebHostBuilder builder) - { - builder.ConfigureTestServices(services => - { - services - .RemoveAll>() - .AddDbContext((sp, options) => - { - options.AddInterceptors(sp.GetServices()); - options.UseSqlServer(connection); - }); - }); - } -} diff --git a/tests/Application.FunctionalTests/GlobalUsings.cs b/tests/Application.FunctionalTests/GlobalUsings.cs deleted file mode 100644 index dd2bce7..0000000 --- a/tests/Application.FunctionalTests/GlobalUsings.cs +++ /dev/null @@ -1,4 +0,0 @@ -global using Ardalis.GuardClauses; -global using FluentAssertions; -global using Moq; -global using NUnit.Framework; \ No newline at end of file diff --git a/tests/Application.FunctionalTests/ITestDatabase.cs b/tests/Application.FunctionalTests/ITestDatabase.cs deleted file mode 100644 index b3ffc55..0000000 --- a/tests/Application.FunctionalTests/ITestDatabase.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Data.Common; - -namespace Hutopy.Application.FunctionalTests; - -public interface ITestDatabase -{ - Task InitialiseAsync(); - - DbConnection GetConnection(); - - Task ResetAsync(); - - Task DisposeAsync(); -} diff --git a/tests/Application.FunctionalTests/SqlServerTestDatabase.cs b/tests/Application.FunctionalTests/SqlServerTestDatabase.cs deleted file mode 100644 index bd88b6d..0000000 --- a/tests/Application.FunctionalTests/SqlServerTestDatabase.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Data.Common; -using Hutopy.Infrastructure.Data; -using Microsoft.Data.SqlClient; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Respawn; - -namespace Hutopy.Application.FunctionalTests; - -public class SqlServerTestDatabase : ITestDatabase -{ - private readonly string _connectionString = null!; - private SqlConnection _connection = null!; - private Respawner _respawner = null!; - - public SqlServerTestDatabase() - { - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .AddEnvironmentVariables() - .Build(); - - var connectionString = configuration.GetConnectionString("MssqlConnection"); - - Guard.Against.Null(connectionString); - - _connectionString = connectionString; - } - - public async Task InitialiseAsync() - { - _connection = new SqlConnection(_connectionString); - - var options = new DbContextOptionsBuilder() - .UseSqlServer(_connectionString) - .Options; - - var context = new ApplicationDbContext(options); - - context.Database.Migrate(); - - _respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions - { - TablesToIgnore = new Respawn.Graph.Table[] { "__EFMigrationsHistory" } - }); - } - - public DbConnection GetConnection() - { - return _connection; - } - - public async Task ResetAsync() - { - await _respawner.ResetAsync(_connectionString); - } - - public async Task DisposeAsync() - { - await _connection.DisposeAsync(); - } -} diff --git a/tests/Application.FunctionalTests/TestDatabaseFactory.cs b/tests/Application.FunctionalTests/TestDatabaseFactory.cs deleted file mode 100644 index 0164872..0000000 --- a/tests/Application.FunctionalTests/TestDatabaseFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Hutopy.Application.FunctionalTests; - -public static class TestDatabaseFactory -{ - public static async Task CreateAsync() - { - var database = new TestcontainersTestDatabase(); - - await database.InitialiseAsync(); - - return database; - } -} diff --git a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs b/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs deleted file mode 100644 index 342336f..0000000 --- a/tests/Application.FunctionalTests/TestcontainersTestDatabase.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Data.Common; -using Hutopy.Infrastructure.Data; -using Microsoft.Data.SqlClient; -using Microsoft.EntityFrameworkCore; -using Respawn; -using Testcontainers.MsSql; - -namespace Hutopy.Application.FunctionalTests; - -public class TestcontainersTestDatabase : ITestDatabase -{ - private readonly MsSqlContainer _container; - private DbConnection _connection = null!; - private string _connectionString = null!; - private Respawner _respawner = null!; - - public TestcontainersTestDatabase() - { - _container = new MsSqlBuilder() - .WithAutoRemove(true) - .Build(); - } - - public async Task InitialiseAsync() - { - await _container.StartAsync(); - - _connectionString = _container.GetConnectionString(); - - _connection = new SqlConnection(_connectionString); - - var options = new DbContextOptionsBuilder() - .UseSqlServer(_connectionString) - .Options; - - var context = new ApplicationDbContext(options); - - await context.Database.MigrateAsync(); - - _respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions - { - TablesToIgnore = ["__EFMigrationsHistory"] - }); - } - - public DbConnection GetConnection() - { - return _connection; - } - - public async Task ResetAsync() - { - await _respawner.ResetAsync(_connectionString); - } - - public async Task DisposeAsync() - { - await _connection.DisposeAsync(); - await _container.DisposeAsync(); - } -} diff --git a/tests/Application.FunctionalTests/Testing.cs b/tests/Application.FunctionalTests/Testing.cs deleted file mode 100644 index dc44dc4..0000000 --- a/tests/Application.FunctionalTests/Testing.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Hutopy.Domain.Constants; -using Hutopy.Infrastructure.Data; -using Hutopy.Infrastructure.Identity; -using MediatR; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; - -namespace Hutopy.Application.FunctionalTests; - -[SetUpFixture] -public partial class Testing -{ - private static ITestDatabase _database; - private static CustomWebApplicationFactory _factory = null!; - private static IServiceScopeFactory _scopeFactory = null!; - private static Guid _userId; - - [OneTimeSetUp] - public async Task RunBeforeAnyTests() - { - _database = await TestDatabaseFactory.CreateAsync(); - - _factory = new CustomWebApplicationFactory(_database.GetConnection()); - - _scopeFactory = _factory.Services.GetRequiredService(); - } - - public static async Task SendAsync(IRequest request) - { - using var scope = _scopeFactory.CreateScope(); - - var mediator = scope.ServiceProvider.GetRequiredService(); - - return await mediator.Send(request); - } - - public static async Task SendAsync(IBaseRequest request) - { - using var scope = _scopeFactory.CreateScope(); - - var mediator = scope.ServiceProvider.GetRequiredService(); - - await mediator.Send(request); - } - - public static Guid GetUserId() - { - return _userId; - } - - public static async Task RunAsDefaultUserAsync() - { - return await RunAsUserAsync( - "test@local", - "Testing1234!", - []); - } - - public static async Task RunAsAdministratorAsync() - { - return await RunAsUserAsync( - "administrator@local", - "Administrator1234!", - [Roles.Administrator]); - } - - public static async Task RunAsUserAsync(string userName, string password, string[] roles) - { - using var scope = _scopeFactory.CreateScope(); - - var userManager = scope.ServiceProvider.GetRequiredService(); - - var user = new ApplicationUser - { - UserName = userName, Email = userName, Firstname = "FirstName", Lastname = "LastName" - }; - - var result = await userManager.CreateAsync(user, password); - - if (roles.Any()) - { - var roleManager = scope.ServiceProvider.GetRequiredService>(); - - foreach (var role in roles) - { - await roleManager.CreateAsync(new IdentityRole(role)); - } - - await userManager.AddToRolesAsync(user, roles); - } - - if (result.Succeeded) - { - _userId = user.Id; - - return _userId; - } - - var errors = string.Join(Environment.NewLine, result.ToApplicationResult().Errors); - - throw new Exception($"Unable to create {userName}.{Environment.NewLine}{errors}"); - } - - public static async Task ResetState() - { - try - { - await _database.ResetAsync(); - } - catch (Exception) - { - } - - _userId = Guid.Empty; - } - - public static async Task FindAsync(params object[] keyValues) - where TEntity : class - { - using var scope = _scopeFactory.CreateScope(); - - var context = scope.ServiceProvider.GetRequiredService(); - - return await context.FindAsync(keyValues); - } - - public static async Task AddAsync(TEntity entity) - where TEntity : class - { - using var scope = _scopeFactory.CreateScope(); - - var context = scope.ServiceProvider.GetRequiredService(); - - context.Add(entity); - - await context.SaveChangesAsync(); - } - - public static async Task CountAsync() where TEntity : class - { - using var scope = _scopeFactory.CreateScope(); - - var context = scope.ServiceProvider.GetRequiredService(); - - return await context.Set().CountAsync(); - } - - [OneTimeTearDown] - public async Task RunAfterAnyTests() - { - await _database.DisposeAsync(); - await _factory.DisposeAsync(); - } -} diff --git a/tests/Application.FunctionalTests/appsettings.json b/tests/Application.FunctionalTests/appsettings.json deleted file mode 100644 index 31e3e45..0000000 --- a/tests/Application.FunctionalTests/appsettings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ConnectionStrings": { - "MssqlConnection": "Server=(localdb)\\mssqllocaldb;Database=HutopyTestDb;Trusted_Connection=True;MultipleActiveResultSets=true" - } -} diff --git a/tests/Domain.UnitTests/Domain.UnitTests.csproj b/tests/Domain.UnitTests/Domain.UnitTests.csproj deleted file mode 100644 index e400eb6..0000000 --- a/tests/Domain.UnitTests/Domain.UnitTests.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - Hutopy.Domain.UnitTests - Hutopy.Domain.UnitTests - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - diff --git a/tests/Domain.UnitTests/ValueObjects/ColourTests.cs b/tests/Domain.UnitTests/ValueObjects/ColourTests.cs deleted file mode 100644 index 50e7785..0000000 --- a/tests/Domain.UnitTests/ValueObjects/ColourTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Hutopy.Domain.Exceptions; -using Hutopy.Domain.ValueObjects; -using FluentAssertions; -using NUnit.Framework; - -namespace Hutopy.Domain.UnitTests.ValueObjects; - -public class ColourTests -{ - [Test] - public void ShouldReturnCorrectColourCode() - { - var code = "#FFFFFF"; - - var colour = Colour.From(code); - - colour.Code.Should().Be(code); - } - - [Test] - public void ToStringReturnsCode() - { - var colour = Colour.White; - - colour.ToString().Should().Be(colour.Code); - } - - [Test] - public void ShouldPerformImplicitConversionToColourCodeString() - { - string code = Colour.White; - - code.Should().Be("#FFFFFF"); - } - - [Test] - public void ShouldPerformExplicitConversionGivenSupportedColourCode() - { - var colour = (Colour)"#FFFFFF"; - - colour.Should().Be(Colour.White); - } - - [Test] - public void ShouldThrowUnsupportedColourExceptionGivenNotSupportedColourCode() - { - FluentActions.Invoking(() => Colour.From("##FF33CC")) - .Should().Throw(); - } -} diff --git a/tests/Infrastructure.IntegrationTests/GlobalUsings.cs b/tests/Infrastructure.IntegrationTests/GlobalUsings.cs deleted file mode 100644 index cefced4..0000000 --- a/tests/Infrastructure.IntegrationTests/GlobalUsings.cs +++ /dev/null @@ -1 +0,0 @@ -global using NUnit.Framework; \ No newline at end of file diff --git a/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj b/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj deleted file mode 100644 index 52d7836..0000000 --- a/tests/Infrastructure.IntegrationTests/Infrastructure.IntegrationTests.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Hutopy.Infrastructure.IntegrationTests - Hutopy.Infrastructure.IntegrationTests - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - -