From 08ff0b79482a02b07dba3e3200d1456bc06e140b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Tracewicz?= Date: Tue, 10 Sep 2024 21:30:18 +0200 Subject: [PATCH] Closes #60 Modularize backend --- backend/Dockerfile | 1 + backend/src/api/Constants/ErrorMessages.cs | 6 ------ backend/src/api/Controllers/TodoController.cs | 2 +- backend/src/api/Program.cs | 14 +++++++++----- backend/src/api/Services/Todo/ITodoService.cs | 13 ------------- backend/src/api/api.csproj | 10 +++++++--- backend/src/core/Ports/ITodoService.cs | 10 ++++++++++ backend/src/core/TodoList.cs | 10 ++++++++++ backend/src/core/core.csproj | 9 +++++++++ backend/src/infrastructure/Class1.cs | 6 ------ .../Data/ApplicationDbContext.cs | 3 +-- .../Data}/TodoListModel.cs | 4 ++-- .../Data}/TodoService.cs | 19 +++++++++---------- .../Keycloack}/KeycloakJwtOptions.cs | 4 +--- .../20240330212015_TodoList.Designer.cs | 6 +++--- .../Migrations/20240330212015_TodoList.cs | 4 ++-- .../ApplicationDbContextModelSnapshot.cs | 6 +++--- .../src/infrastructure/infrastructure.csproj | 13 +++++++++++++ scripts/apply_migrations.ps1 | 6 +++--- 19 files changed, 84 insertions(+), 62 deletions(-) delete mode 100644 backend/src/api/Constants/ErrorMessages.cs delete mode 100644 backend/src/api/Services/Todo/ITodoService.cs create mode 100644 backend/src/core/Ports/ITodoService.cs create mode 100644 backend/src/core/TodoList.cs create mode 100644 backend/src/core/core.csproj delete mode 100644 backend/src/infrastructure/Class1.cs rename backend/src/{api => infrastructure}/Data/ApplicationDbContext.cs (85%) rename backend/src/{api/Data/DAO => infrastructure/Data}/TodoListModel.cs (77%) rename backend/src/{api/Services/Todo => infrastructure/Data}/TodoService.cs (71%) rename backend/src/{api/Data => infrastructure/Keycloack}/KeycloakJwtOptions.cs (74%) rename backend/src/{api => infrastructure}/Migrations/20240330212015_TodoList.Designer.cs (94%) rename backend/src/{api => infrastructure}/Migrations/20240330212015_TodoList.cs (96%) rename backend/src/{api => infrastructure}/Migrations/ApplicationDbContextModelSnapshot.cs (94%) diff --git a/backend/Dockerfile b/backend/Dockerfile index 7a65178..25dc31c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -5,6 +5,7 @@ WORKDIR /app EXPOSE 80 EXPOSE 443 +#Todo: clean it up for multiproject build FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY src/api/api.csproj src/api/ diff --git a/backend/src/api/Constants/ErrorMessages.cs b/backend/src/api/Constants/ErrorMessages.cs deleted file mode 100644 index 12f82b7..0000000 --- a/backend/src/api/Constants/ErrorMessages.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace api.Constants; - -public static class ErrorMessages -{ - public const string UserAlreadyExists = "User already exists"; -} diff --git a/backend/src/api/Controllers/TodoController.cs b/backend/src/api/Controllers/TodoController.cs index 5436e8c..4506d68 100644 --- a/backend/src/api/Controllers/TodoController.cs +++ b/backend/src/api/Controllers/TodoController.cs @@ -1,4 +1,4 @@ -using api.Services; +using core.Ports; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/backend/src/api/Program.cs b/backend/src/api/Program.cs index f6d88a0..4e0557e 100644 --- a/backend/src/api/Program.cs +++ b/backend/src/api/Program.cs @@ -1,12 +1,13 @@ -using api.Data; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; -using Microsoft.EntityFrameworkCore; using Serilog; -using api; using System.Security.Cryptography; -using api.Services; +using api; +using infrastructure.Data; +using infrastructure.Keycloak; +using core.Ports; const string logFormat = "[{Timestamp:HH:mm:ss} {Level:u3}] {CorelationId} | {Message:lj}{NewLine}{Exception}"; Log.Logger = new LoggerConfiguration().Enrich.WithCorrelationId() @@ -19,7 +20,10 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpContextAccessor(); builder.Host.UseSerilog(); - builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("KSummarized"))); + builder.Services.AddDbContext( + options => options.UseNpgsql(builder.Configuration.GetConnectionString("KSummarized"), + x => x.MigrationsAssembly("infrastructure") + )); var keycloakJwtOptions = builder.Configuration.GetRequiredSection("KeycloakJwt").Get()!; // Create RSA key for offline validation of Keycloak token diff --git a/backend/src/api/Services/Todo/ITodoService.cs b/backend/src/api/Services/Todo/ITodoService.cs deleted file mode 100644 index fe5788e..0000000 --- a/backend/src/api/Services/Todo/ITodoService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using api.Data.DAO; -using api.Data.DTO; - -namespace api.Services; - -public interface ITodoService -{ - Task CreateList(string user, string name); - IEnumerable GetLists(string userId); - TodoListDTO? GetList(string userId, int id); - bool DeleteList(string userId, int id); - Task RenameList(string user, int id, string name); -} diff --git a/backend/src/api/api.csproj b/backend/src/api/api.csproj index 1ed02ca..47086bf 100644 --- a/backend/src/api/api.csproj +++ b/backend/src/api/api.csproj @@ -11,10 +11,9 @@ - - - all + runtime; build; native; contentfiles; analyzers; buildtransitive + all @@ -27,4 +26,9 @@ + + + + + diff --git a/backend/src/core/Ports/ITodoService.cs b/backend/src/core/Ports/ITodoService.cs new file mode 100644 index 0000000..21ef07a --- /dev/null +++ b/backend/src/core/Ports/ITodoService.cs @@ -0,0 +1,10 @@ +namespace core.Ports; + +public interface ITodoService +{ + Task CreateList(string user, string name); + IEnumerable GetLists(string userId); + TodoList? GetList(string userId, int id); + bool DeleteList(string userId, int id); + Task RenameList(string user, int id, string name); +} diff --git a/backend/src/core/TodoList.cs b/backend/src/core/TodoList.cs new file mode 100644 index 0000000..8392f04 --- /dev/null +++ b/backend/src/core/TodoList.cs @@ -0,0 +1,10 @@ +namespace core; + +public class TodoList +{ + public int Id { get; set; } + public required string Name { get; set; } + public required Guid Owner { get; set; } + + public bool IsAuthorized(Guid person) => Owner.Equals(person); +} diff --git a/backend/src/core/core.csproj b/backend/src/core/core.csproj new file mode 100644 index 0000000..bb23fb7 --- /dev/null +++ b/backend/src/core/core.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/backend/src/infrastructure/Class1.cs b/backend/src/infrastructure/Class1.cs deleted file mode 100644 index 47bb804..0000000 --- a/backend/src/infrastructure/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace infrastructure; - -public class Class1 -{ - -} diff --git a/backend/src/api/Data/ApplicationDbContext.cs b/backend/src/infrastructure/Data/ApplicationDbContext.cs similarity index 85% rename from backend/src/api/Data/ApplicationDbContext.cs rename to backend/src/infrastructure/Data/ApplicationDbContext.cs index 8bbcdb8..df8dfd3 100644 --- a/backend/src/api/Data/ApplicationDbContext.cs +++ b/backend/src/infrastructure/Data/ApplicationDbContext.cs @@ -1,7 +1,6 @@ -using api.Data.DAO; using Microsoft.EntityFrameworkCore; -namespace api.Data; +namespace infrastructure.Data; public class ApplicationDbContext : DbContext { diff --git a/backend/src/api/Data/DAO/TodoListModel.cs b/backend/src/infrastructure/Data/TodoListModel.cs similarity index 77% rename from backend/src/api/Data/DAO/TodoListModel.cs rename to backend/src/infrastructure/Data/TodoListModel.cs index f2f8a57..d838b5b 100644 --- a/backend/src/api/Data/DAO/TodoListModel.cs +++ b/backend/src/infrastructure/Data/TodoListModel.cs @@ -1,7 +1,7 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace api.Data.DAO; +namespace infrastructure.Data; [Table("todo_lists")] public class TodoListModel diff --git a/backend/src/api/Services/Todo/TodoService.cs b/backend/src/infrastructure/Data/TodoService.cs similarity index 71% rename from backend/src/api/Services/Todo/TodoService.cs rename to backend/src/infrastructure/Data/TodoService.cs index 8b24c70..3d2dcc0 100644 --- a/backend/src/api/Services/Todo/TodoService.cs +++ b/backend/src/infrastructure/Data/TodoService.cs @@ -1,9 +1,8 @@ -using api.Data; -using api.Data.DAO; -using api.Data.DTO; using Microsoft.EntityFrameworkCore; +using core.Ports; +using core; -namespace api.Services; +namespace infrastructure.Data; public class TodoService : ITodoService { @@ -15,29 +14,29 @@ public TodoService(ApplicationDbContext context) _context = context; } - public IEnumerable GetLists(string userId) + public IEnumerable GetLists(string userId) { return _context.TodoLists.AsNoTracking() .Where(list => list.Owner.Equals(Guid.Parse(userId))) - .Select(list => new TodoListDTO(list.Id, list.Name)) + .Select(list => new TodoList { Id = list.Id, Name = list.Name, Owner = list.Owner }) .AsEnumerable(); } - public TodoListDTO? GetList(string userId, int id) + public TodoList? GetList(string userId, int id) { var list = _context.TodoLists.AsNoTracking() .SingleOrDefault(l => l.Owner.Equals(Guid.Parse(userId)) && l.Id == id); //TODO: Consider creating a mapper instead of this manual new - if (list is not null) { return new(list.Id, list.Name); } + if (list is not null) { return new() { Id = list.Id, Name = list.Name, Owner = list.Owner }; } return null; } - public async Task CreateList(string user, string name) + public async Task CreateList(string user, string name) { var newList = new TodoListModel() { Name = name, Owner = Guid.Parse(user) }; _context.TodoLists.Add(newList); await _context.SaveChangesAsync(); - return newList; + return new TodoList() { Id = newList.Id, Name = newList.Name, Owner = newList.Owner }; } public bool DeleteList(string userId, int id) diff --git a/backend/src/api/Data/KeycloakJwtOptions.cs b/backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs similarity index 74% rename from backend/src/api/Data/KeycloakJwtOptions.cs rename to backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs index 42f458c..83a139c 100644 --- a/backend/src/api/Data/KeycloakJwtOptions.cs +++ b/backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs @@ -1,6 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -namespace api.Data; +namespace infrastructure.Keycloak; public class KeycloakJwtOptions { public required string Issuer { get; init; } diff --git a/backend/src/api/Migrations/20240330212015_TodoList.Designer.cs b/backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs similarity index 94% rename from backend/src/api/Migrations/20240330212015_TodoList.Designer.cs rename to backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs index 121acfa..ba9fe02 100644 --- a/backend/src/api/Migrations/20240330212015_TodoList.Designer.cs +++ b/backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs @@ -1,15 +1,15 @@ -// +// using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using api.Data; +using infrastructure.Data; #nullable disable -namespace api.Migrations +namespace infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] [Migration("20240330212015_TodoList")] diff --git a/backend/src/api/Migrations/20240330212015_TodoList.cs b/backend/src/infrastructure/Migrations/20240330212015_TodoList.cs similarity index 96% rename from backend/src/api/Migrations/20240330212015_TodoList.cs rename to backend/src/infrastructure/Migrations/20240330212015_TodoList.cs index e0bf4b0..13b4cef 100644 --- a/backend/src/api/Migrations/20240330212015_TodoList.cs +++ b/backend/src/infrastructure/Migrations/20240330212015_TodoList.cs @@ -1,10 +1,10 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace api.Migrations +namespace infrastructure.Migrations { /// public partial class TodoList : Migration diff --git a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs b/backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs similarity index 94% rename from backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs rename to backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index 1b642d3..42e6371 100644 --- a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -1,14 +1,14 @@ -// +// using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using api.Data; +using infrastructure.Data; #nullable disable -namespace api.Migrations +namespace infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] partial class ApplicationDbContextModelSnapshot : ModelSnapshot diff --git a/backend/src/infrastructure/infrastructure.csproj b/backend/src/infrastructure/infrastructure.csproj index bb23fb7..7d93446 100644 --- a/backend/src/infrastructure/infrastructure.csproj +++ b/backend/src/infrastructure/infrastructure.csproj @@ -6,4 +6,17 @@ enable + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/scripts/apply_migrations.ps1 b/scripts/apply_migrations.ps1 index 05aa6c2..773a305 100755 --- a/scripts/apply_migrations.ps1 +++ b/scripts/apply_migrations.ps1 @@ -11,9 +11,9 @@ get-content ../.env | foreach { Write-Host "Starting DB" docker compose up db -d 2>&1 > $null Write-Output "Generateing migration script" -Set-Location ../backend/src/api +Set-Location ../backend mkdir migration_scripts 2>&1 > $null -dotnet ef migrations script --idempotent -o ./migration_scripts/migration.sql +dotnet ef migrations script --idempotent -o ./migration_scripts/migration.sql -p ./src/infrastructure -s ./src/api Write-Output "Applying.." $passwd = "PGPASSWORD=" + $Env:POSTGRES_PASSWORD @@ -24,7 +24,7 @@ docker run --network host -e $passwd -v ${src}:/migrations/ --rm postgres ` Write-Output "Cleanup" Remove-Item -Recurse -Force migration_scripts -Set-Location ../../../scripts +Set-Location ../scripts Write-Output "Migrations had been applyed!" Write-Host "Stoping DB" docker stop ks-database 2>&1 > $null