diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticatePasswordRequest.cs b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticatePasswordRequest.cs similarity index 96% rename from TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticatePasswordRequest.cs rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticatePasswordRequest.cs index 7b66b8f..d16b8eb 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticatePasswordRequest.cs +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticatePasswordRequest.cs @@ -1,4 +1,4 @@ -namespace TimetableDesigner.Backend.Services.Authentication.DTO; +namespace TimetableDesigner.Backend.Services.Authentication.DTO.API; public class AuthenticatePasswordRequest { diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateResponse.cs b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateResponse.cs similarity index 96% rename from TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateResponse.cs rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateResponse.cs index 219f03f..76ed6e6 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateResponse.cs +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateResponse.cs @@ -1,4 +1,4 @@ -namespace TimetableDesigner.Backend.Services.Authentication.DTO; +namespace TimetableDesigner.Backend.Services.Authentication.DTO.API; public class AuthenticateResponse { diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateTokenRequest.cs b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateTokenRequest.cs similarity index 96% rename from TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateTokenRequest.cs rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateTokenRequest.cs index 08496d9..a964371 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/AuthenticateTokenRequest.cs +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/AuthenticateTokenRequest.cs @@ -1,4 +1,4 @@ -namespace TimetableDesigner.Backend.Services.Authentication.DTO; +namespace TimetableDesigner.Backend.Services.Authentication.DTO.API; public class AuthenticateTokenRequest { diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/RegisterRequest.cs b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterRequest.cs similarity index 96% rename from TimetableDesigner.Backend.Services.Authentication.DTO/RegisterRequest.cs rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterRequest.cs index 42f621f..2047f1f 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/RegisterRequest.cs +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterRequest.cs @@ -1,4 +1,4 @@ -namespace TimetableDesigner.Backend.Services.Authentication.DTO; +namespace TimetableDesigner.Backend.Services.Authentication.DTO.API; public class RegisterRequest { diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/RegisterResponse.cs b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterResponse.cs similarity index 92% rename from TimetableDesigner.Backend.Services.Authentication.DTO/RegisterResponse.cs rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterResponse.cs index bb53912..09726b9 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/RegisterResponse.cs +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/RegisterResponse.cs @@ -1,4 +1,4 @@ -namespace TimetableDesigner.Backend.Services.Authentication.DTO; +namespace TimetableDesigner.Backend.Services.Authentication.DTO.API; public class RegisterResponse { diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.csproj b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj similarity index 77% rename from TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.csproj rename to TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj index 17b910f..237d661 100644 --- a/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.csproj +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.API/TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.Events/TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.Events/TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/TimetableDesigner.Backend.Services.Authentication.DTO/TimetableDesigner.Backend.Services.Authentication.DTO.Events/TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/TimetableDesigner.Backend.Services.Authentication.sln b/TimetableDesigner.Backend.Services.Authentication.sln index 025f8ef..1a43359 100644 --- a/TimetableDesigner.Backend.Services.Authentication.sln +++ b/TimetableDesigner.Backend.Services.Authentication.sln @@ -2,7 +2,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Backend.Services.Authentication", "TimetableDesigner.Backend.Services.Authentication\TimetableDesigner.Backend.Services.Authentication.csproj", "{F8C0AEF3-B53F-4904-90F7-EE4A8587F023}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Backend.Services.Authentication.DTO", "TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.csproj", "{384C8036-ACA7-40EB-924D-5E0271BEDB09}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TimetableDesigner.Backend.Services.Authentication.DTO", "TimetableDesigner.Backend.Services.Authentication.DTO", "{B610971F-EF8F-45D2-B869-41617ED447C8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Backend.Services.Authentication.DTO.API", "TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.API\TimetableDesigner.Backend.Services.Authentication.DTO.API.csproj", "{0639DAB9-E1B4-454E-A3E9-F7B712A697E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimetableDesigner.Backend.Services.Authentication.DTO.Events", "TimetableDesigner.Backend.Services.Authentication.DTO\TimetableDesigner.Backend.Services.Authentication.DTO.Events\TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj", "{3E39EDEE-621F-49BC-B777-174BB047BCA7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -14,9 +18,17 @@ Global {F8C0AEF3-B53F-4904-90F7-EE4A8587F023}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8C0AEF3-B53F-4904-90F7-EE4A8587F023}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8C0AEF3-B53F-4904-90F7-EE4A8587F023}.Release|Any CPU.Build.0 = Release|Any CPU - {384C8036-ACA7-40EB-924D-5E0271BEDB09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {384C8036-ACA7-40EB-924D-5E0271BEDB09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {384C8036-ACA7-40EB-924D-5E0271BEDB09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {384C8036-ACA7-40EB-924D-5E0271BEDB09}.Release|Any CPU.Build.0 = Release|Any CPU + {0639DAB9-E1B4-454E-A3E9-F7B712A697E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0639DAB9-E1B4-454E-A3E9-F7B712A697E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0639DAB9-E1B4-454E-A3E9-F7B712A697E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0639DAB9-E1B4-454E-A3E9-F7B712A697E8}.Release|Any CPU.Build.0 = Release|Any CPU + {3E39EDEE-621F-49BC-B777-174BB047BCA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E39EDEE-621F-49BC-B777-174BB047BCA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E39EDEE-621F-49BC-B777-174BB047BCA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E39EDEE-621F-49BC-B777-174BB047BCA7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {0639DAB9-E1B4-454E-A3E9-F7B712A697E8} = {B610971F-EF8F-45D2-B869-41617ED447C8} + {3E39EDEE-621F-49BC-B777-174BB047BCA7} = {B610971F-EF8F-45D2-B869-41617ED447C8} EndGlobalSection EndGlobal diff --git a/TimetableDesigner.Backend.Services.Authentication/API/Endpoints.cs b/TimetableDesigner.Backend.Services.Authentication/API/Endpoints.cs index 1e9109e..1bce858 100644 --- a/TimetableDesigner.Backend.Services.Authentication/API/Endpoints.cs +++ b/TimetableDesigner.Backend.Services.Authentication/API/Endpoints.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http.HttpResults; -using TimetableDesigner.Backend.Services.Authentication.Application.Register; -using TimetableDesigner.Backend.Services.Authentication.DTO; +using TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register; +using TimetableDesigner.Backend.Services.Authentication.DTO.API; namespace TimetableDesigner.Backend.Services.Authentication.API; @@ -18,11 +18,10 @@ public static class Endpoints return app; } - public static async Task, ProblemHttpResult>> Register(RegisterRequest request, RegisterHandler handler) + public static async Task, ProblemHttpResult>> Register(RegisterCommand command, RegisterHandler handler) { - RegisterCommand command = request.ToCommand(); - RegisterResponse account = await handler.HandleAsync(command); - return Results.Created($"accounts/{account.Id}", account); + RegisterDto data = await handler.HandleAsync(command); + return Results.Created($"accounts/{data.Id}", data); } public static async Task, ProblemHttpResult>> AuthenticatePassword(AuthenticatePasswordRequest request) diff --git a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterCommand.cs b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterCommand.cs similarity index 80% rename from TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterCommand.cs rename to TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterCommand.cs index 8e53983..33f6676 100644 --- a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterCommand.cs +++ b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterCommand.cs @@ -1,3 +1,3 @@ -namespace TimetableDesigner.Backend.Services.Authentication.Application.Register; +namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register; public record RegisterCommand(string Email, string Password); \ No newline at end of file diff --git a/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterDto.cs b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterDto.cs new file mode 100644 index 0000000..5762b64 --- /dev/null +++ b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterDto.cs @@ -0,0 +1,6 @@ +namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register; + +public class RegisterDto +{ + +} \ No newline at end of file diff --git a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterHandler.cs b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterHandler.cs similarity index 70% rename from TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterHandler.cs rename to TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterHandler.cs index e8eec35..f2b2a97 100644 --- a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterHandler.cs +++ b/TimetableDesigner.Backend.Services.Authentication/Application/Commands/Register/RegisterHandler.cs @@ -1,7 +1,6 @@ using TimetableDesigner.Backend.Services.Authentication.Database; -using TimetableDesigner.Backend.Services.Authentication.DTO; -namespace TimetableDesigner.Backend.Services.Authentication.Application.Register; +namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register; public class RegisterHandler { @@ -12,7 +11,7 @@ public class RegisterHandler _databaseContext = databaseContext; } - public async Task HandleAsync(RegisterCommand command) + public async Task HandleAsync(RegisterCommand command) { return null; } diff --git a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterRequestMapper.cs b/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterRequestMapper.cs deleted file mode 100644 index cde2fcc..0000000 --- a/TimetableDesigner.Backend.Services.Authentication/Application/Register/RegisterRequestMapper.cs +++ /dev/null @@ -1,8 +0,0 @@ -using TimetableDesigner.Backend.Services.Authentication.DTO; - -namespace TimetableDesigner.Backend.Services.Authentication.Application.Register; - -public static class RegisterRequestMapper -{ - public static RegisterCommand ToCommand(this RegisterRequest request) => new RegisterCommand(request.Email, request.Password); -} \ No newline at end of file diff --git a/TimetableDesigner.Backend.Services.Authentication/DTO/Validators/RegisterRequestValidator.cs b/TimetableDesigner.Backend.Services.Authentication/DTO/Validators/RegisterRequestValidator.cs new file mode 100644 index 0000000..3091c72 --- /dev/null +++ b/TimetableDesigner.Backend.Services.Authentication/DTO/Validators/RegisterRequestValidator.cs @@ -0,0 +1,33 @@ +using FluentValidation; +using Microsoft.EntityFrameworkCore; +using TimetableDesigner.Backend.Services.Authentication.Database; +using TimetableDesigner.Backend.Services.Authentication.DTO.API; + +namespace TimetableDesigner.Backend.Services.Authentication.DTO.Validators; + +public class RegisterRequestValidator : AbstractValidator +{ + private readonly DatabaseContext _databaseContext; + + public RegisterRequestValidator(DatabaseContext databaseContext) + { + _databaseContext = databaseContext; + + RuleFor(x => x.Email) + .NotEmpty() + .EmailAddress() + .MustAsync(EmailNotUsed).WithMessage("Email already used"); + RuleFor(x => x.Password) + .NotEmpty() + .MinimumLength(8) + .Must(x => x.Any(char.IsUpper)).WithMessage("Password must contain at least one uppercase letter") + .Must(x => x.Any(char.IsLower)).WithMessage("Password must contain at least one lowercase letter") + .Must(x => x.Any(char.IsDigit)).WithMessage("Password must contain at least one digit"); + RuleFor(x => x.PasswordConfirmation) + .NotEmpty() + .Equal(x => x.Password); + } + + private Task EmailNotUsed(string value, CancellationToken cancellationToken) => + _databaseContext.Accounts.AnyAsync(x => x.Email == value, cancellationToken); +} \ No newline at end of file diff --git a/TimetableDesigner.Backend.Services.Authentication/Program.cs b/TimetableDesigner.Backend.Services.Authentication/Program.cs index be6e8ca..8944403 100644 --- a/TimetableDesigner.Backend.Services.Authentication/Program.cs +++ b/TimetableDesigner.Backend.Services.Authentication/Program.cs @@ -1,6 +1,10 @@ +using System.Reflection; +using FluentValidation; +using Microsoft.AspNetCore.Identity.Data; using Microsoft.EntityFrameworkCore; using TimetableDesigner.Backend.Services.Authentication.API; using TimetableDesigner.Backend.Services.Authentication.Database; +using TimetableDesigner.Backend.Services.Authentication.DTO.Validators; namespace TimetableDesigner.Backend.Services.Authentication; @@ -12,6 +16,7 @@ public static class Program .SetupOpenApi() .SetupSecurity() .SetupDatabase() + .SetupValidation() .Build(); if (app.Environment.IsDevelopment()) @@ -40,6 +45,12 @@ public static class Program builder.Services.AddDbContext(x => x.UseNpgsql(builder.Configuration.GetConnectionString("Database")), ServiceLifetime.Transient); return builder; } + + private static WebApplicationBuilder SetupValidation(this WebApplicationBuilder builder) + { + builder.Services.AddScoped, RegisterRequestValidator>(); + return builder; + } private static WebApplication InitializeDatabase(this WebApplication app) { diff --git a/TimetableDesigner.Backend.Services.Authentication/TimetableDesigner.Backend.Services.Authentication.csproj b/TimetableDesigner.Backend.Services.Authentication/TimetableDesigner.Backend.Services.Authentication.csproj index dc3bf08..6d817d5 100644 --- a/TimetableDesigner.Backend.Services.Authentication/TimetableDesigner.Backend.Services.Authentication.csproj +++ b/TimetableDesigner.Backend.Services.Authentication/TimetableDesigner.Backend.Services.Authentication.csproj @@ -1,13 +1,15 @@ - net9.0 + net10.0 enable enable Linux + 14 + all @@ -17,11 +19,11 @@ - + - +