diff --git a/backend/Dockerfile b/backend/Dockerfile
index 5990f8d..25dc31c 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,11 +1,12 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
-FROM mcr.microsoft.com/dotnet/aspnet:7.0.10-alpine3.18 AS base
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
-FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
+#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/
RUN dotnet restore "src/api/api.csproj"
diff --git a/backend/UnitTests/UnitTests.csproj b/backend/UnitTests/UnitTests.csproj
deleted file mode 100644
index 4ba4b01..0000000
--- a/backend/UnitTests/UnitTests.csproj
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- net7.0
- enable
- enable
-
- false
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
diff --git a/backend/UnitTests/Usings.cs b/backend/UnitTests/Usings.cs
deleted file mode 100644
index 8c927eb..0000000
--- a/backend/UnitTests/Usings.cs
+++ /dev/null
@@ -1 +0,0 @@
-global using Xunit;
\ No newline at end of file
diff --git a/backend/bruno/KSummarized/ToDo/List/Create.bru b/backend/bruno/KSummarized/ToDo/List/Create.bru
new file mode 100644
index 0000000..b3e2ba6
--- /dev/null
+++ b/backend/bruno/KSummarized/ToDo/List/Create.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Create
+ type: http
+ seq: 2
+}
+
+post {
+ url: https://{{api_base_url}}/api/todo/lists
+ body: json
+ auth: bearer
+}
+
+auth:bearer {
+ token: {{token}}
+}
+
+body:json {
+ {
+ "name": "Demo"
+ }
+}
+
+vars:post-response {
+ listId: res.body.id
+}
diff --git a/backend/bruno/KSummarized/ToDo/List/Delete.bru b/backend/bruno/KSummarized/ToDo/List/Delete.bru
new file mode 100644
index 0000000..996430a
--- /dev/null
+++ b/backend/bruno/KSummarized/ToDo/List/Delete.bru
@@ -0,0 +1,19 @@
+meta {
+ name: Delete
+ type: http
+ seq: 4
+}
+
+delete {
+ url: https://{{api_base_url}}/api/todo/lists/{{listId}}
+ body: json
+ auth: bearer
+}
+
+auth:bearer {
+ token: {{token}}
+}
+
+body:json {
+ "ToDo"
+}
diff --git a/backend/bruno/KSummarized/ToDo/List/Get.bru b/backend/bruno/KSummarized/ToDo/List/Get.bru
new file mode 100644
index 0000000..df97d89
--- /dev/null
+++ b/backend/bruno/KSummarized/ToDo/List/Get.bru
@@ -0,0 +1,15 @@
+meta {
+ name: Get
+ type: http
+ seq: 5
+}
+
+get {
+ url: https://{{api_base_url}}/api/todo/lists/{{listId}}
+ body: none
+ auth: bearer
+}
+
+auth:bearer {
+ token: {{token}}
+}
diff --git a/backend/bruno/KSummarized/ToDo/List/List.bru b/backend/bruno/KSummarized/ToDo/List/List.bru
new file mode 100644
index 0000000..7b6343c
--- /dev/null
+++ b/backend/bruno/KSummarized/ToDo/List/List.bru
@@ -0,0 +1,15 @@
+meta {
+ name: List
+ type: http
+ seq: 1
+}
+
+get {
+ url: https://{{api_base_url}}/api/todo/lists
+ body: none
+ auth: bearer
+}
+
+auth:bearer {
+ token: {{token}}
+}
diff --git a/backend/bruno/KSummarized/ToDo/List/Rename.bru b/backend/bruno/KSummarized/ToDo/List/Rename.bru
new file mode 100644
index 0000000..cf40331
--- /dev/null
+++ b/backend/bruno/KSummarized/ToDo/List/Rename.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Rename
+ type: http
+ seq: 3
+}
+
+put {
+ url: https://{{api_base_url}}/api/todo/lists/{{listId}}
+ body: json
+ auth: bearer
+}
+
+auth:bearer {
+ token: {{token}}
+}
+
+body:json {
+ {
+ "name": "Renamed"
+ }
+}
diff --git a/backend/bruno/KSummarized/bruno.json b/backend/bruno/KSummarized/bruno.json
new file mode 100644
index 0000000..a2739bb
--- /dev/null
+++ b/backend/bruno/KSummarized/bruno.json
@@ -0,0 +1,5 @@
+{
+ "version": "1",
+ "name": "KSummarized",
+ "type": "collection"
+}
\ No newline at end of file
diff --git a/backend/bruno/KSummarized/environments/Local.bru b/backend/bruno/KSummarized/environments/Local.bru
new file mode 100644
index 0000000..4dc37f4
--- /dev/null
+++ b/backend/bruno/KSummarized/environments/Local.bru
@@ -0,0 +1,12 @@
+vars {
+ keycloak_realm: KnowledgeSummarized
+ keycloak_url: http://localhost:8080
+ api_base_url: localhost:5000
+}
+vars:secret [
+ token,
+ keycloak_client_id,
+ keycloak_client_secret,
+ keycloak_username,
+ keycloak_password
+]
diff --git a/backend/bruno/KSummarized/token.bru b/backend/bruno/KSummarized/token.bru
new file mode 100644
index 0000000..064ea26
--- /dev/null
+++ b/backend/bruno/KSummarized/token.bru
@@ -0,0 +1,23 @@
+meta {
+ name: Get access token
+ type: http
+ seq: 1
+}
+
+post {
+ url: {{keycloak_url}}/realms/{{keycloak_realm}}/protocol/openid-connect/token
+ body: formUrlEncoded
+ auth: none
+}
+
+body:form-urlencoded {
+ client_id: {{keycloak_client_id}}
+ grant_type: password
+ client_secret: {{keycloak_client_secret}}
+ username: {{keycloak_username}}
+ password: {{keycloak_password}}
+}
+
+vars:post-response {
+ token: res.body.access_token
+}
diff --git a/backend/ksummarized.sln b/backend/ksummarized.sln
index 58eff14..20d82c5 100644
--- a/backend/ksummarized.sln
+++ b/backend/ksummarized.sln
@@ -1,64 +1,43 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.4.33213.308
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D7A1B70F-EE88-4B3C-A209-FE2517ADD026}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "api", "src\api\api.csproj", "{917A96E2-DAE3-432B-8C65-362D34194104}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A2E313A3-EE03-4A78-ABCE-42E7A4B7029A}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D12C229D-2E15-43BD-951F-EF05AE7633D9}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{D21A0FAE-B25F-4975-9EBC-76E24CDA1969}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|x64.ActiveCfg = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|x64.Build.0 = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|x86.ActiveCfg = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Debug|x86.Build.0 = Debug|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|Any CPU.Build.0 = Release|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|x64.ActiveCfg = Release|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|x64.Build.0 = Release|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|x86.ActiveCfg = Release|Any CPU
- {917A96E2-DAE3-432B-8C65-362D34194104}.Release|x86.Build.0 = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|x64.ActiveCfg = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|x64.Build.0 = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|x86.ActiveCfg = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Debug|x86.Build.0 = Debug|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|Any CPU.Build.0 = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|x64.ActiveCfg = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|x64.Build.0 = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|x86.ActiveCfg = Release|Any CPU
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969}.Release|x86.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {917A96E2-DAE3-432B-8C65-362D34194104} = {D7A1B70F-EE88-4B3C-A209-FE2517ADD026}
- {D21A0FAE-B25F-4975-9EBC-76E24CDA1969} = {A2E313A3-EE03-4A78-ABCE-42E7A4B7029A}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {EB55458A-327D-41D5-8211-352C32273E00}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DE2804D2-3D3D-4A41-91C7-4FEEF71A4434}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "api", "src\api\api.csproj", "{949171D5-4018-4C40-AB2B-687B39F20974}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{4CA15B69-5E75-48E2-BE26-EA818B675CFC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "unit", "test\unit\unit.csproj", "{B930D2FA-7FC6-4772-89EA-6B925EDD2EBC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "infrastructure", "src\infrastructure\infrastructure.csproj", "{9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {949171D5-4018-4C40-AB2B-687B39F20974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {949171D5-4018-4C40-AB2B-687B39F20974}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {949171D5-4018-4C40-AB2B-687B39F20974}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {949171D5-4018-4C40-AB2B-687B39F20974}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B930D2FA-7FC6-4772-89EA-6B925EDD2EBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B930D2FA-7FC6-4772-89EA-6B925EDD2EBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B930D2FA-7FC6-4772-89EA-6B925EDD2EBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B930D2FA-7FC6-4772-89EA-6B925EDD2EBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {949171D5-4018-4C40-AB2B-687B39F20974} = {DE2804D2-3D3D-4A41-91C7-4FEEF71A4434}
+ {B930D2FA-7FC6-4772-89EA-6B925EDD2EBC} = {4CA15B69-5E75-48E2-BE26-EA818B675CFC}
+ {9D4BB729-24FB-4B6E-9EFD-B8C2E0A2B1EB} = {DE2804D2-3D3D-4A41-91C7-4FEEF71A4434}
+ EndGlobalSection
+EndGlobal
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/AuthenticationController.cs b/backend/src/api/Controllers/AuthenticationController.cs
deleted file mode 100644
index de8b353..0000000
--- a/backend/src/api/Controllers/AuthenticationController.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using api.Constants;
-using api.Data.DTO;
-using api.Services.Users;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using System.IdentityModel.Tokens.Jwt;
-
-namespace api.Controllers;
-
-[ApiController]
-[Route("/api/auth")]
-public class AuthenticationController : ControllerBase
-{
- private readonly IUserService _userService;
- private readonly ILogger _logger;
-
- public AuthenticationController(IUserService userService, ILogger logger)
- {
- _userService = userService;
- _logger = logger;
- }
-
- [HttpGet("create-user")]
- [Authorize]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- public async Task CreateUser()
- {
- var accessToken = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
- var jsonTokenData = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
- var keycloakUuid = jsonTokenData.Subject;
- var userEmail = jsonTokenData.Claims.FirstOrDefault(claim => claim.Type == "email")?.Value;
-
- if (userEmail == null)
- {
- _logger.LogInformation("User with keycloakUuid={keycloakUuid} tried to log in without email.", keycloakUuid);
- return BadRequest("Required data missing");
- }
-
- var (isSuccess, error) = await _userService.CreateKeycloakUser(
- new UserDTO
- {
- KeycloakUuid = keycloakUuid,
- Email = userEmail
- }
- );
-
- if (isSuccess)
- {
- _logger.LogInformation("The user {email} has been created successfully.", userEmail);
- return Ok("User created");
- }
- else
- {
- if (error == ErrorMessages.UserAlreadyExists)
- {
- _logger.LogInformation("The user {email} has already been created.", userEmail);
- return Ok("User is already created");
- }
- _logger.LogInformation("Failure during creation of {email} user.", userEmail);
- return BadRequest(error);
- }
- }
-}
diff --git a/backend/src/api/Controllers/GreetingsController.cs b/backend/src/api/Controllers/GreetingsController.cs
deleted file mode 100644
index 665bed0..0000000
--- a/backend/src/api/Controllers/GreetingsController.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-
-namespace api.Controllers;
-
-[ApiController]
-[Route("/api/greetings")]
-public class GreetingsController : ControllerBase
-{
- [HttpGet]
- [Authorize]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [Route("user")]
- public IActionResult Greet()
- {
- return Ok($"Hello {HttpContext?.User?.Identity?.Name ?? "World" }");
- }
-
- [HttpGet]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [Route("HelloWorld")]
- public IActionResult HelloWorld()
- {
- return Ok("Hello World!");
- }
-}
diff --git a/backend/src/api/Controllers/TodoController.cs b/backend/src/api/Controllers/TodoController.cs
new file mode 100644
index 0000000..0a37197
--- /dev/null
+++ b/backend/src/api/Controllers/TodoController.cs
@@ -0,0 +1,107 @@
+using core.Ports;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace api.Controllers;
+
+[Authorize]
+[Route("/api/todo")]
+[ApiController]
+public class TodoController : ControllerBase
+{
+ private readonly ITodoService _service;
+ private readonly ILogger _logger;
+
+ public TodoController(ITodoService service, ILogger logger)
+ {
+ _service = service;
+ _logger = logger;
+ }
+
+ [HttpGet("lists")]
+ public IActionResult GetLists()
+ {
+ var userId = Request.UserId();
+ _logger.LogDebug("User: {user} requested his lists", userId);
+ return userId switch
+ {
+ null => Unauthorized(),
+ var user => Ok(_service.GetLists(user)),
+ };
+ }
+
+ [HttpGet("lists/{id}")]
+ public IActionResult GetList([FromRoute] int id)
+ {
+ var userId = Request.UserId();
+ _logger.LogDebug("User: {user} requested his list: {id}", userId, id);
+ if (userId is null) { return Unauthorized(); }
+ var list = _service.GetList(userId, id);
+ return list switch
+ {
+ null => NotFound(),
+ var user => Ok(list),
+ };
+ }
+
+ [HttpDelete("lists/{id}")]
+ public IActionResult DeleteList([FromRoute] int id)
+ {
+ var userId = Request.UserId();
+ _logger.LogDebug("User: {user} deleted his list: {id}", userId, id);
+ if (userId is null) { return Unauthorized(); }
+ var success = _service.DeleteList(userId, id);
+ if (success)
+ {
+ return Ok();
+ }
+ return BadRequest();
+ }
+
+ [HttpPost("lists")]
+ public async Task CreateLists([FromBody] Request request)
+ {
+ var userId = Request.UserId();
+ _logger.LogDebug("User: {user} created: {list}", userId, request.Name);
+ return userId switch
+ {
+ null => Unauthorized(),
+ var user => await Create(user, request.Name),
+ };
+
+ async Task Create(string user, string name)
+ {
+ //TODO: return DTO instead of DAO
+ var list = await _service.CreateList(user, name);
+ return Created(HttpContext.Request.Path.Add(new PathString($"/{list.Id}")), list);
+ }
+ }
+
+ [HttpPut("lists/{id}")]
+ public async Task RenameList([FromRoute] int id, [FromBody] Request request)
+ {
+ var userId = Request.UserId();
+ _logger.LogDebug("User: {user} renamed: {id} to: {list}", userId, id, request.Name);
+ return userId switch
+ {
+ null => Unauthorized(),
+ var user => await Rename(user, id, request.Name),
+ };
+
+ async Task Rename(string user, int id, string name)
+ {
+ //TODO: return DTO instead of DAO
+ var list = await _service.RenameList(user, id, name);
+ if (list)
+ {
+ return Ok();
+ }
+ return BadRequest();
+ }
+ }
+}
+
+public class Request
+{
+ public required string Name { get; set; }
+}
diff --git a/backend/src/api/Data/DAO/UserModel.cs b/backend/src/api/Data/DAO/UserModel.cs
deleted file mode 100644
index 12253d3..0000000
--- a/backend/src/api/Data/DAO/UserModel.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace api.Data.DAO;
-
-public class UserModel
-{
- [Key]
- public int Id { get; set; }
- public required string KeycloakUuid { get; set; }
- [EmailAddress]
- public required string Email { get; set; }
-}
diff --git a/backend/src/api/Data/DTO/TodoListDTO.cs b/backend/src/api/Data/DTO/TodoListDTO.cs
new file mode 100644
index 0000000..275e8d4
--- /dev/null
+++ b/backend/src/api/Data/DTO/TodoListDTO.cs
@@ -0,0 +1,3 @@
+namespace api.Data.DTO;
+
+public record TodoListDTO(int Id, string Name);
diff --git a/backend/src/api/Data/DTO/UserDTO.cs b/backend/src/api/Data/DTO/UserDTO.cs
deleted file mode 100644
index 7079db2..0000000
--- a/backend/src/api/Data/DTO/UserDTO.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-
-namespace api.Data.DTO;
-
-public class UserDTO
-{
- [Required]
- public required string KeycloakUuid { get; set; }
- [Required]
- [EmailAddress]
- public required string Email { get; set; }
-}
diff --git a/backend/src/api/Data/KeycloakJwtOptions.cs b/backend/src/api/Data/KeycloakJwtOptions.cs
deleted file mode 100644
index a72287e..0000000
--- a/backend/src/api/Data/KeycloakJwtOptions.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace api.Data;
-public class KeycloakJwtOptions
-{
- public required string Issuer { get; set; }
- public required string Audience { get; set; }
- public required string Secret { get; set; }
-
- [SetsRequiredMembers]
- public KeycloakJwtOptions(string issuer, string audience, string secret)
- {
- Issuer = issuer;
- Audience = audience;
- Secret = secret;
- }
-}
diff --git a/backend/src/api/Program.cs b/backend/src/api/Program.cs
index 681bf74..4e0557e 100644
--- a/backend/src/api/Program.cs
+++ b/backend/src/api/Program.cs
@@ -1,111 +1,105 @@
-using api.Data;
-using api.Services.Users;
-using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.IdentityModel.Tokens;
-using Microsoft.OpenApi.Models;
-using Microsoft.EntityFrameworkCore;
-using Serilog;
-using api;
-using System.Security.Cryptography;
-
-const string logFormat = "[{Timestamp:HH:mm:ss} {Level:u3}] {CorelationId} | {Message:lj}{NewLine}{Exception}";
-Log.Logger = new LoggerConfiguration().Enrich.WithCorrelationId()
- .WriteTo
- .Console(outputTemplate: logFormat)
- .CreateLogger();
-
-try
-{
- var builder = WebApplication.CreateBuilder(args);
- builder.Services.AddHttpContextAccessor();
- builder.Host.UseSerilog();
- builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("KSummarized")));
- var keycloakJwtOptions = new KeycloakJwtOptions(
- builder.Configuration.GetValue("KeycloakJwt:Issuer")!,
- builder.Configuration.GetValue("KeycloakJwt:Audience")!,
- builder.Configuration.GetValue("KeycloakJwt:Secret")!
- );
- if(keycloakJwtOptions.Secret is null || keycloakJwtOptions.Issuer is null || keycloakJwtOptions.Audience is null)
- {
- throw new Exception("Can't start application without JWT options");
- }
-
- // Create RSA key for offline validation of Keycloak token
- RSA rsa = RSA.Create();
- rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(keycloakJwtOptions.Secret), out _);
- var rsaKeycloakSecurityKey = new RsaSecurityKey(rsa)
- {
- KeyId = Guid.NewGuid().ToString()
- };
-
- var tokenValidationParameters = new TokenValidationParameters()
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = rsaKeycloakSecurityKey,
- ValidAudience = keycloakJwtOptions.Audience,
- ValidateAudience = true,
- ValidIssuer = keycloakJwtOptions.Issuer,
- ValidateIssuer = true,
- ValidateLifetime = true
- };
- builder.Services.AddSingleton(tokenValidationParameters);
- builder.Services.AddSingleton(keycloakJwtOptions);
-
- builder.Services.AddAuthentication(options =>
- {
- options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
- })
- .AddJwtBearer(options =>
- {
- options.SaveToken = true;
- options.RequireHttpsMetadata = true;
- options.TokenValidationParameters = tokenValidationParameters;
- });
-
- builder.Services.AddControllers();
- builder.Services.AddSwaggerGen(c =>
- {
- c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1" });
- });
- builder.Services.AddScoped();
-
- builder.Services.AddCors(options =>
- {
- options.AddPolicy(name: "AllowAll", builder =>
- {
- builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
- });
- });
-
- var app = builder.Build();
-
- if (app.Environment.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseSwagger();
- app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "api v1"));
- }
-
- app.UseCors("AllowAll");
- app.UseAuthentication();
-
- app.UseHttpsRedirection();
- app.UseHsts();
-
- app.UseSerilogRequestLogging();
- app.UseRouting();
- app.UseAuthorization();
-
- app.MapControllers();
-
- app.Run();
-}
-catch (Exception ex)
-{
- Log.Fatal("Error starting the application: {Exception}", ex);
-}
-finally
-{
- Log.CloseAndFlush();
-}
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.OpenApi.Models;
+using Serilog;
+using System.Security.Cryptography;
+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()
+ .WriteTo
+ .Console(outputTemplate: logFormat)
+ .CreateLogger();
+
+try
+{
+ var builder = WebApplication.CreateBuilder(args);
+ builder.Services.AddHttpContextAccessor();
+ builder.Host.UseSerilog();
+ 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
+ RSA rsa = RSA.Create();
+ rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(keycloakJwtOptions.Secret), out _);
+ var rsaKeycloakSecurityKey = new RsaSecurityKey(rsa)
+ {
+ KeyId = Guid.NewGuid().ToString()
+ };
+
+ var tokenValidationParameters = new TokenValidationParameters()
+ {
+ ValidateIssuerSigningKey = true,
+ IssuerSigningKey = rsaKeycloakSecurityKey,
+ ValidAudience = keycloakJwtOptions.Audience,
+ ValidateAudience = true,
+ ValidIssuer = keycloakJwtOptions.Issuer,
+ ValidateIssuer = true,
+ ValidateLifetime = true
+ };
+
+ builder.Services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ })
+ .AddJwtBearer(options =>
+ {
+ options.SaveToken = true;
+ options.RequireHttpsMetadata = true;
+ options.TokenValidationParameters = tokenValidationParameters;
+ });
+
+ builder.Services.AddControllers();
+ builder.Services.AddSwaggerGen(c =>
+ {
+ c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1" });
+ });
+ builder.Services.AddScoped();
+
+ builder.Services.AddCors(options =>
+ {
+ options.AddPolicy(name: "AllowAll", builder =>
+ {
+ builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
+ });
+ });
+
+ var app = builder.Build();
+
+ if (app.Environment.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ app.UseSwagger();
+ app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "api v1"));
+ }
+
+ app.UseCors("AllowAll");
+ app.UseAuthentication();
+
+ app.UseHttpsRedirection();
+ app.UseHsts();
+
+ app.UseSerilogRequestLogging();
+ app.UseRouting();
+ app.UseAuthorization();
+
+ app.MapControllers();
+
+ app.Run();
+}
+catch (Exception ex)
+{
+ Log.Fatal("Error starting the application: {Exception}", ex);
+}
+finally
+{
+ Log.CloseAndFlush();
+}
diff --git a/backend/src/api/RequestExtensions.cs b/backend/src/api/RequestExtensions.cs
new file mode 100644
index 0000000..2d45f01
--- /dev/null
+++ b/backend/src/api/RequestExtensions.cs
@@ -0,0 +1,20 @@
+using Microsoft.IdentityModel.JsonWebTokens;
+
+namespace api;
+
+public static class RequestExtensions
+{
+ public static string? UserId(this HttpRequest request)
+ {
+ try
+ {
+ var accessToken = request.Headers.Authorization.ToString().Split(' ')[1];
+ var jsonTokenData = new JsonWebTokenHandler().ReadJsonWebToken(accessToken);
+ return jsonTokenData.Subject;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+}
diff --git a/backend/src/api/Services/Users/IUserService.cs b/backend/src/api/Services/Users/IUserService.cs
deleted file mode 100644
index 5b09ba7..0000000
--- a/backend/src/api/Services/Users/IUserService.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using api.Data.DTO;
-
-namespace api.Services.Users;
-
-public interface IUserService
-{
- Task<(bool isSuccess, string? error)> CreateKeycloakUser(UserDTO user);
-}
diff --git a/backend/src/api/Services/Users/UserService.cs b/backend/src/api/Services/Users/UserService.cs
deleted file mode 100644
index 08d440f..0000000
--- a/backend/src/api/Services/Users/UserService.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using api.Data;
-using api.Data.DTO;
-using api.Data.DAO;
-using api.Constants;
-
-namespace api.Services.Users;
-
-public class UserService : IUserService
-{
- private readonly ApplicationDbContext _applicationDbContext;
-
- public UserService(ApplicationDbContext applicationDbContext)
- {
- _applicationDbContext = applicationDbContext;
- }
-
- public async Task<(bool isSuccess, string? error)> CreateKeycloakUser(UserDTO user)
- {
- var userInstance = _applicationDbContext.Users.FirstOrDefault(userInstance => userInstance.KeycloakUuid.Equals(user.KeycloakUuid));
- if (userInstance != null)
- {
- return (false, ErrorMessages.UserAlreadyExists);
- }
- var newUser = new UserModel()
- {
- KeycloakUuid = user.KeycloakUuid,
- Email = user.Email
- };
- await _applicationDbContext.Users.AddAsync(newUser);
- await _applicationDbContext.SaveChangesAsync();
- return (true, null);
- }
-}
diff --git a/backend/src/api/api.csproj b/backend/src/api/api.csproj
index 217deeb..47086bf 100644
--- a/backend/src/api/api.csproj
+++ b/backend/src/api/api.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
f7cb2e8e-61a4-4a0a-9259-839230fcfe2d
Linux
enable
@@ -9,18 +9,26 @@
-
-
-
-
- all
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
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/api/Data/ApplicationDbContext.cs b/backend/src/infrastructure/Data/ApplicationDbContext.cs
similarity index 57%
rename from backend/src/api/Data/ApplicationDbContext.cs
rename to backend/src/infrastructure/Data/ApplicationDbContext.cs
index 0ec7301..df8dfd3 100644
--- a/backend/src/api/Data/ApplicationDbContext.cs
+++ b/backend/src/infrastructure/Data/ApplicationDbContext.cs
@@ -1,13 +1,11 @@
-using api.Data.DAO;
-using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
-namespace api.Data;
+namespace infrastructure.Data;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
- public DbSet Users { get; set; }
+ public DbSet TodoLists { get; set; }
}
diff --git a/backend/src/infrastructure/Data/TodoListModel.cs b/backend/src/infrastructure/Data/TodoListModel.cs
new file mode 100644
index 0000000..d838b5b
--- /dev/null
+++ b/backend/src/infrastructure/Data/TodoListModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace infrastructure.Data;
+
+[Table("todo_lists")]
+public class TodoListModel
+{
+ [Key]
+ public int Id { get; set; }
+ [MaxLength(512)]
+ public required string Name { get; set; }
+ public required Guid Owner { get; set; }
+}
diff --git a/backend/src/infrastructure/Data/TodoService.cs b/backend/src/infrastructure/Data/TodoService.cs
new file mode 100644
index 0000000..3d2dcc0
--- /dev/null
+++ b/backend/src/infrastructure/Data/TodoService.cs
@@ -0,0 +1,62 @@
+using Microsoft.EntityFrameworkCore;
+using core.Ports;
+using core;
+
+namespace infrastructure.Data;
+
+public class TodoService : ITodoService
+{
+
+ private readonly ApplicationDbContext _context;
+
+ public TodoService(ApplicationDbContext context)
+ {
+ _context = context;
+ }
+
+ public IEnumerable GetLists(string userId)
+ {
+ return _context.TodoLists.AsNoTracking()
+ .Where(list => list.Owner.Equals(Guid.Parse(userId)))
+ .Select(list => new TodoList { Id = list.Id, Name = list.Name, Owner = list.Owner })
+ .AsEnumerable();
+ }
+
+ 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() { Id = list.Id, Name = list.Name, Owner = list.Owner }; }
+ return null;
+ }
+
+ 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 new TodoList() { Id = newList.Id, Name = newList.Name, Owner = newList.Owner };
+ }
+
+ public bool DeleteList(string userId, int id)
+ {
+ var list = _context.TodoLists
+ .SingleOrDefault(l => l.Owner.Equals(Guid.Parse(userId)) && l.Id == id);
+ if (list is null) { return false; }
+ _context.TodoLists.Remove(list);
+ _context.SaveChanges();
+ return true;
+ }
+
+ public async Task RenameList(string userId, int id, string name)
+ {
+ var list = _context.TodoLists
+ .SingleOrDefault(l => l.Owner.Equals(Guid.Parse(userId)) && l.Id == id);
+
+ if (list is null) { return false; }
+ list.Name = name;
+ await _context.SaveChangesAsync();
+ return true;
+ }
+}
diff --git a/backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs b/backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs
new file mode 100644
index 0000000..83a139c
--- /dev/null
+++ b/backend/src/infrastructure/Keycloack/KeycloakJwtOptions.cs
@@ -0,0 +1,7 @@
+namespace infrastructure.Keycloak;
+public class KeycloakJwtOptions
+{
+ public required string Issuer { get; init; }
+ public required string Audience { get; init; }
+ public required string Secret { get; init; }
+}
diff --git a/backend/src/api/Migrations/20240223084836_Init.Designer.cs b/backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs
similarity index 64%
rename from backend/src/api/Migrations/20240223084836_Init.Designer.cs
rename to backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs
index a363f14..ba9fe02 100644
--- a/backend/src/api/Migrations/20240223084836_Init.Designer.cs
+++ b/backend/src/infrastructure/Migrations/20240330212015_TodoList.Designer.cs
@@ -1,30 +1,31 @@
-//
+//
+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("20240223084836_Init")]
- partial class Init
+ [Migration("20240330212015_TodoList")]
+ partial class TodoList
{
///
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "7.0.2")
+ .HasAnnotation("ProductVersion", "8.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
- modelBuilder.Entity("api.Data.DAO.UserModel", b =>
+ modelBuilder.Entity("api.Data.DAO.TodoListModel", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -32,17 +33,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder)
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
- b.Property("Email")
+ b.Property("Name")
.IsRequired()
- .HasColumnType("text");
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
- b.Property("KeycloakUuid")
- .IsRequired()
- .HasColumnType("text");
+ b.Property("Owner")
+ .HasColumnType("uuid");
b.HasKey("Id");
- b.ToTable("Users");
+ b.ToTable("todo_lists");
});
#pragma warning restore 612, 618
}
diff --git a/backend/src/api/Migrations/20240223084836_Init.cs b/backend/src/infrastructure/Migrations/20240330212015_TodoList.cs
similarity index 62%
rename from backend/src/api/Migrations/20240223084836_Init.cs
rename to backend/src/infrastructure/Migrations/20240330212015_TodoList.cs
index 9f4ae7a..13b4cef 100644
--- a/backend/src/api/Migrations/20240223084836_Init.cs
+++ b/backend/src/infrastructure/Migrations/20240330212015_TodoList.cs
@@ -1,28 +1,29 @@
-using Microsoft.EntityFrameworkCore.Migrations;
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
-namespace api.Migrations
+namespace infrastructure.Migrations
{
///
- public partial class Init : Migration
+ public partial class TodoList : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
- name: "Users",
+ name: "todo_lists",
columns: table => new
{
Id = table.Column(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
- KeycloakUuid = table.Column(type: "text", nullable: false),
- Email = table.Column(type: "text", nullable: false)
+ Name = table.Column(type: "character varying(512)", maxLength: 512, nullable: false),
+ Owner = table.Column(type: "uuid", nullable: false)
},
constraints: table =>
{
- table.PrimaryKey("PK_Users", x => x.Id);
+ table.PrimaryKey("PK_todo_lists", x => x.Id);
});
}
@@ -30,7 +31,7 @@ protected override void Up(MigrationBuilder migrationBuilder)
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
- name: "Users");
+ name: "todo_lists");
}
}
}
diff --git a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs b/backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
similarity index 66%
rename from backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs
rename to backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
index c339c3c..42e6371 100644
--- a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/backend/src/infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -1,13 +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
@@ -16,12 +17,12 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "7.0.2")
+ .HasAnnotation("ProductVersion", "8.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
- modelBuilder.Entity("api.Data.DAO.UserModel", b =>
+ modelBuilder.Entity("api.Data.DAO.TodoListModel", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
@@ -29,17 +30,17 @@ protected override void BuildModel(ModelBuilder modelBuilder)
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
- b.Property("Email")
+ b.Property("Name")
.IsRequired()
- .HasColumnType("text");
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
- b.Property("KeycloakUuid")
- .IsRequired()
- .HasColumnType("text");
+ b.Property("Owner")
+ .HasColumnType("uuid");
b.HasKey("Id");
- b.ToTable("Users");
+ b.ToTable("todo_lists");
});
#pragma warning restore 612, 618
}
diff --git a/backend/src/infrastructure/infrastructure.csproj b/backend/src/infrastructure/infrastructure.csproj
new file mode 100644
index 0000000..7d93446
--- /dev/null
+++ b/backend/src/infrastructure/infrastructure.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/backend/test/ksummarized.UnitTests/UnitTest1.cs b/backend/test/ksummarized.UnitTests/UnitTest1.cs
deleted file mode 100644
index 33840dd..0000000
--- a/backend/test/ksummarized.UnitTests/UnitTest1.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace ksummarized.UnitTests
-{
- [TestClass]
- public class UnitTest1
- {
- [TestMethod]
- public void TestMethod1()
- {
- }
- }
-}
diff --git a/backend/test/ksummarized.UnitTests/ksummarized.UnitTests.csproj b/backend/test/ksummarized.UnitTests/ksummarized.UnitTests.csproj
deleted file mode 100644
index d6f1239..0000000
--- a/backend/test/ksummarized.UnitTests/ksummarized.UnitTests.csproj
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- net7.0
-
- false
-
-
-
-
-
-
-
-
-
-
diff --git a/backend/UnitTests/UnitTest1.cs b/backend/test/unit/UnitTest1.cs
similarity index 75%
rename from backend/UnitTests/UnitTest1.cs
rename to backend/test/unit/UnitTest1.cs
index d88634b..d334e44 100644
--- a/backend/UnitTests/UnitTest1.cs
+++ b/backend/test/unit/UnitTest1.cs
@@ -1,10 +1,10 @@
-namespace UnitTests;
-
-public class UnitTest1
-{
- [Fact]
- public void Test1()
- {
-
- }
+namespace unit;
+
+public class UnitTest1
+{
+ [Fact]
+ public void Test1()
+ {
+
+ }
}
\ No newline at end of file
diff --git a/backend/test/unit/unit.csproj b/backend/test/unit/unit.csproj
new file mode 100644
index 0000000..3aa9860
--- /dev/null
+++ b/backend/test/unit/unit.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/helpers/RequireAuth.tsx b/frontend/src/helpers/RequireAuth.tsx
index 3014338..8bfa471 100644
--- a/frontend/src/helpers/RequireAuth.tsx
+++ b/frontend/src/helpers/RequireAuth.tsx
@@ -7,21 +7,6 @@ import Constants from "./Constants";
export default function RequireAuth() {
const { isLogin, keycloak } = useAuth();
-
- const createUserInBackend = async () => {
- const response = await fetch(`${Constants.BASE_URL}/auth/create-user`, {
- headers: { Authorization: `Bearer ${keycloak!.token}` },
- });
- if (response.status !== 200) {
- const errorMessage = await response.text();
- throw new Error(errorMessage);
- }
- };
-
- if (isLogin) {
- createUserInBackend();
- }
-
return isLogin ? : Authenticating...
;
}
diff --git a/global.json b/global.json
deleted file mode 100644
index 8058dfb..0000000
--- a/global.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "sdk": {
- "version": "7.0.405",
- "rollForward": "latestFeature"
- }
-}
diff --git a/scripts/apply_migrations.ps1 b/scripts/apply_migrations.ps1
index 201925c..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 2>&1 > $null
+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