From 936dc104310e49ab320ce196655017c397982d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Tracewicz?= Date: Sat, 30 Mar 2024 22:34:33 +0100 Subject: [PATCH] Closes #60 Initial implementation of getting all of users Todo Lists. --- backend/src/api/Controllers/TodoController.cs | 27 ++++++++++ backend/src/api/Data/ApplicationDbContext.cs | 3 +- backend/src/api/Data/DAO/TodoListModel.cs | 14 +++++ backend/src/api/Data/DTO/TodoListDTO.cs | 3 ++ .../20240330212015_TodoList.Designer.cs | 51 +++++++++++++++++++ .../api/Migrations/20240330212015_TodoList.cs | 37 ++++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 17 ++++--- backend/src/api/Program.cs | 2 + backend/src/api/Services/Todo/ITodoService.cs | 8 +++ backend/src/api/Services/Todo/TodoService.cs | 24 +++++++++ 10 files changed, 176 insertions(+), 10 deletions(-) create mode 100644 backend/src/api/Controllers/TodoController.cs create mode 100644 backend/src/api/Data/DAO/TodoListModel.cs create mode 100644 backend/src/api/Data/DTO/TodoListDTO.cs create mode 100644 backend/src/api/Migrations/20240330212015_TodoList.Designer.cs create mode 100644 backend/src/api/Migrations/20240330212015_TodoList.cs create mode 100644 backend/src/api/Services/Todo/ITodoService.cs create mode 100644 backend/src/api/Services/Todo/TodoService.cs diff --git a/backend/src/api/Controllers/TodoController.cs b/backend/src/api/Controllers/TodoController.cs new file mode 100644 index 0000000..ee522a4 --- /dev/null +++ b/backend/src/api/Controllers/TodoController.cs @@ -0,0 +1,27 @@ +using api.Data.DTO; +using api.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace api.Controllers; + +[Authorize] +[Route("/api/todo")] +[ApiController] +public class TodoController : ControllerBase +{ + private readonly ITodoService _service; + + public TodoController(ITodoService service) => _service = service; + + [HttpGet("lists")] + public IActionResult List() + { + return Request.UserId() switch + { + null => Unauthorized(), + var user => Ok(_service.GetLists(user)), + }; + } + +} diff --git a/backend/src/api/Data/ApplicationDbContext.cs b/backend/src/api/Data/ApplicationDbContext.cs index 0ec7301..8bbcdb8 100644 --- a/backend/src/api/Data/ApplicationDbContext.cs +++ b/backend/src/api/Data/ApplicationDbContext.cs @@ -1,5 +1,4 @@ using api.Data.DAO; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace api.Data; @@ -9,5 +8,5 @@ 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/api/Data/DAO/TodoListModel.cs b/backend/src/api/Data/DAO/TodoListModel.cs new file mode 100644 index 0000000..f2f8a57 --- /dev/null +++ b/backend/src/api/Data/DAO/TodoListModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace api.Data.DAO; + +[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/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/Migrations/20240330212015_TodoList.Designer.cs b/backend/src/api/Migrations/20240330212015_TodoList.Designer.cs new file mode 100644 index 0000000..121acfa --- /dev/null +++ b/backend/src/api/Migrations/20240330212015_TodoList.Designer.cs @@ -0,0 +1,51 @@ +// +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; + +#nullable disable + +namespace api.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240330212015_TodoList")] + partial class TodoList + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("api.Data.DAO.TodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("Owner") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("todo_lists"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/src/api/Migrations/20240330212015_TodoList.cs b/backend/src/api/Migrations/20240330212015_TodoList.cs new file mode 100644 index 0000000..e0bf4b0 --- /dev/null +++ b/backend/src/api/Migrations/20240330212015_TodoList.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace api.Migrations +{ + /// + public partial class TodoList : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "todo_lists", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + Owner = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_todo_lists", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "todo_lists"); + } + } +} diff --git a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs b/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs index c339c3c..1b642d3 100644 --- a/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/backend/src/api/Migrations/ApplicationDbContextModelSnapshot.cs @@ -1,4 +1,5 @@ // +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -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/api/Program.cs b/backend/src/api/Program.cs index 9f9c12a..dcec027 100644 --- a/backend/src/api/Program.cs +++ b/backend/src/api/Program.cs @@ -6,6 +6,7 @@ using Serilog; using api; using System.Security.Cryptography; +using api.Services; const string logFormat = "[{Timestamp:HH:mm:ss} {Level:u3}] {CorelationId} | {Message:lj}{NewLine}{Exception}"; Log.Logger = new LoggerConfiguration().Enrich.WithCorrelationId() @@ -57,6 +58,7 @@ { c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1" }); }); + builder.Services.AddScoped(); builder.Services.AddCors(options => { diff --git a/backend/src/api/Services/Todo/ITodoService.cs b/backend/src/api/Services/Todo/ITodoService.cs new file mode 100644 index 0000000..ff5f22a --- /dev/null +++ b/backend/src/api/Services/Todo/ITodoService.cs @@ -0,0 +1,8 @@ +using api.Data.DTO; + +namespace api.Services; + +public interface ITodoService +{ + public IEnumerable GetLists(string userId); +} \ No newline at end of file diff --git a/backend/src/api/Services/Todo/TodoService.cs b/backend/src/api/Services/Todo/TodoService.cs new file mode 100644 index 0000000..f616843 --- /dev/null +++ b/backend/src/api/Services/Todo/TodoService.cs @@ -0,0 +1,24 @@ +using api.Data; +using api.Data.DTO; +using Microsoft.EntityFrameworkCore; + +namespace api.Services; + +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 TodoListDTO(list.Id, list.Name)) + .AsEnumerable(); + } +}