From 74878c1536d8f8909bcd3a820c025c0522834110 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Mon, 13 Oct 2025 12:54:37 +0200 Subject: [PATCH] Creating of git for project ApiEfCoreLibrary --- .gitignore | 5 + ApiEfCoreLibrary.sln | 16 ++ ApiEfCoreLibrary/ApiEfCoreLibrary.csproj | 23 ++ ApiEfCoreLibrary/ApiEfCoreLibrary.http | 6 + .../DTO/Author/Request/CreateAuthorDto.cs | 7 + .../DTO/Author/Request/UpdateAuthorDto.cs | 8 + .../DTO/Author/Response/GetAuthorDto.cs | 11 + .../DTO/Book/Request/CreateBookDto.cs | 9 + .../DTO/Book/Request/UpdateBookDto.cs | 10 + .../DTO/Book/Response/GetBookDto.cs | 12 + .../DTO/Loan/Request/CreateLoanDto.cs | 8 + .../DTO/Loan/Request/PatchLoanDto.cs | 7 + .../DTO/Loan/Request/UpdateLoanDto.cs | 11 + .../DTO/Loan/Response/GetLoanDto.cs | 23 ++ .../DTO/User/Request/CreateUserDto.cs | 9 + .../DTO/User/Request/UpdateUserDto.cs | 10 + .../DTO/User/Response/GetUserDto.cs | 13 ++ .../Endpoints/Author/CreateAuthorEndpoint.cs | 37 +++ .../Endpoints/Author/DeleteAuthorEndpoint.cs | 36 +++ .../Endpoints/Author/GetAllAuthorsEndpoint.cs | 40 ++++ .../Endpoints/Author/GetAuthorEndpoint.cs | 53 +++++ .../Endpoints/Author/UpdateAuthorEndpoint.cs | 40 ++++ .../Endpoints/Book/CreateBookEndpoint.cs | 52 +++++ .../Endpoints/Book/DeleteBookEndpoint.cs | 37 +++ .../Endpoints/Book/GetAllBooksEndpoint.cs | 33 +++ .../Endpoints/Book/GetBookEndpoint.cs | 43 ++++ .../Endpoints/Book/UpdateBookEndpoint.cs | 53 +++++ .../Endpoints/Loan/CreateLoanEndpoint.cs | 58 +++++ .../Endpoints/Loan/DeleteLoanEndpoint.cs | 37 +++ .../Endpoints/Loan/GetAllLoansEndpoint.cs | 44 ++++ .../Endpoints/Loan/GetLoanEndpoint.cs | 55 +++++ .../Endpoints/Loan/PatchLoanEndpoint.cs | 53 +++++ .../Endpoints/Loan/UpdateLoanEndpoint.cs | 61 +++++ .../Endpoints/User/CreateUserEndpoint.cs | 40 ++++ .../Endpoints/User/DeleteUserEndpoint.cs | 36 +++ .../Endpoints/User/GetAllUsersEndpoint.cs | 52 +++++ .../Endpoints/User/GetUserEndpoint.cs | 64 ++++++ .../Endpoints/User/UpdateUserEndpoint.cs | 43 ++++ ApiEfCoreLibrary/LibraryDbContext.cs | 32 +++ ...20250923063940_InitialDatabase.Designer.cs | 187 +++++++++++++++ .../20250923063940_InitialDatabase.cs | 127 ++++++++++ .../LibraryDbContextModelSnapshot.cs | 217 ++++++++++++++++++ ApiEfCoreLibrary/Models/Author.cs | 11 + ApiEfCoreLibrary/Models/Book.cs | 13 ++ ApiEfCoreLibrary/Models/Loan.cs | 15 ++ ApiEfCoreLibrary/Models/Login.cs | 11 + ApiEfCoreLibrary/Models/User.cs | 13 ++ ApiEfCoreLibrary/Program.cs | 27 +++ .../Properties/launchSettings.json | 41 ++++ ApiEfCoreLibrary/appsettings.Development.json | 8 + ApiEfCoreLibrary/appsettings.json | 9 + 51 files changed, 1866 insertions(+) create mode 100644 .gitignore create mode 100644 ApiEfCoreLibrary.sln create mode 100644 ApiEfCoreLibrary/ApiEfCoreLibrary.csproj create mode 100644 ApiEfCoreLibrary/ApiEfCoreLibrary.http create mode 100644 ApiEfCoreLibrary/DTO/Author/Request/CreateAuthorDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Author/Request/UpdateAuthorDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Author/Response/GetAuthorDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Book/Request/CreateBookDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Book/Request/UpdateBookDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Book/Response/GetBookDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Loan/Request/CreateLoanDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Loan/Request/PatchLoanDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Loan/Request/UpdateLoanDto.cs create mode 100644 ApiEfCoreLibrary/DTO/Loan/Response/GetLoanDto.cs create mode 100644 ApiEfCoreLibrary/DTO/User/Request/CreateUserDto.cs create mode 100644 ApiEfCoreLibrary/DTO/User/Request/UpdateUserDto.cs create mode 100644 ApiEfCoreLibrary/DTO/User/Response/GetUserDto.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Author/CreateAuthorEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Author/DeleteAuthorEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Author/GetAllAuthorsEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Author/GetAuthorEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Author/UpdateAuthorEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Book/CreateBookEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Book/DeleteBookEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Book/GetAllBooksEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Book/GetBookEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Book/UpdateBookEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/CreateLoanEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/DeleteLoanEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/GetAllLoansEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/GetLoanEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/PatchLoanEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/Loan/UpdateLoanEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/User/CreateUserEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/User/DeleteUserEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/User/GetAllUsersEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/User/GetUserEndpoint.cs create mode 100644 ApiEfCoreLibrary/Endpoints/User/UpdateUserEndpoint.cs create mode 100644 ApiEfCoreLibrary/LibraryDbContext.cs create mode 100644 ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.Designer.cs create mode 100644 ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.cs create mode 100644 ApiEfCoreLibrary/Migrations/LibraryDbContextModelSnapshot.cs create mode 100644 ApiEfCoreLibrary/Models/Author.cs create mode 100644 ApiEfCoreLibrary/Models/Book.cs create mode 100644 ApiEfCoreLibrary/Models/Loan.cs create mode 100644 ApiEfCoreLibrary/Models/Login.cs create mode 100644 ApiEfCoreLibrary/Models/User.cs create mode 100644 ApiEfCoreLibrary/Program.cs create mode 100644 ApiEfCoreLibrary/Properties/launchSettings.json create mode 100644 ApiEfCoreLibrary/appsettings.Development.json create mode 100644 ApiEfCoreLibrary/appsettings.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/ApiEfCoreLibrary.sln b/ApiEfCoreLibrary.sln new file mode 100644 index 0000000..4d337f6 --- /dev/null +++ b/ApiEfCoreLibrary.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiEfCoreLibrary", "ApiEfCoreLibrary\ApiEfCoreLibrary.csproj", "{E7D4AEB5-54C1-429D-8B2F-CAE960763823}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E7D4AEB5-54C1-429D-8B2F-CAE960763823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7D4AEB5-54C1-429D-8B2F-CAE960763823}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7D4AEB5-54C1-429D-8B2F-CAE960763823}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7D4AEB5-54C1-429D-8B2F-CAE960763823}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/ApiEfCoreLibrary/ApiEfCoreLibrary.csproj b/ApiEfCoreLibrary/ApiEfCoreLibrary.csproj new file mode 100644 index 0000000..8f09324 --- /dev/null +++ b/ApiEfCoreLibrary/ApiEfCoreLibrary.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/ApiEfCoreLibrary/ApiEfCoreLibrary.http b/ApiEfCoreLibrary/ApiEfCoreLibrary.http new file mode 100644 index 0000000..f17dd79 --- /dev/null +++ b/ApiEfCoreLibrary/ApiEfCoreLibrary.http @@ -0,0 +1,6 @@ +@ApiEfCoreLibrary_HostAddress = http://localhost:5228 + +GET {{ApiEfCoreLibrary_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/ApiEfCoreLibrary/DTO/Author/Request/CreateAuthorDto.cs b/ApiEfCoreLibrary/DTO/Author/Request/CreateAuthorDto.cs new file mode 100644 index 0000000..4117694 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Author/Request/CreateAuthorDto.cs @@ -0,0 +1,7 @@ +namespace ApiEfCoreLibrary.DTO.Author.Request; + +public class CreateAuthorDto +{ + public string? Name { get; set; } + public string? FirstName { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Author/Request/UpdateAuthorDto.cs b/ApiEfCoreLibrary/DTO/Author/Request/UpdateAuthorDto.cs new file mode 100644 index 0000000..c2ee8d8 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Author/Request/UpdateAuthorDto.cs @@ -0,0 +1,8 @@ +namespace ApiEfCoreLibrary.DTO.Author.Request; + +public class UpdateAuthorDto +{ + public int Id { get; set; } + public string? Name { get; set; } + public string? FirstName { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Author/Response/GetAuthorDto.cs b/ApiEfCoreLibrary/DTO/Author/Response/GetAuthorDto.cs new file mode 100644 index 0000000..517676c --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Author/Response/GetAuthorDto.cs @@ -0,0 +1,11 @@ +using ApiEfCoreLibrary.DTO.Book.Response; + +namespace ApiEfCoreLibrary.DTO.Author.Response; + +public class GetAuthorDto +{ + public int Id { get; set; } + public string? Name { get; set; } + public string? FirstName { get; set; } + public List? Books { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Book/Request/CreateBookDto.cs b/ApiEfCoreLibrary/DTO/Book/Request/CreateBookDto.cs new file mode 100644 index 0000000..74e6474 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Book/Request/CreateBookDto.cs @@ -0,0 +1,9 @@ +namespace ApiEfCoreLibrary.DTO.Book.Request; + +public class CreateBookDto +{ + public string? Title { get; set; } + public int? ReleaseYear { get; set; } + public string? Isbn { get; set; } + public int AuthorId { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Book/Request/UpdateBookDto.cs b/ApiEfCoreLibrary/DTO/Book/Request/UpdateBookDto.cs new file mode 100644 index 0000000..d7e5997 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Book/Request/UpdateBookDto.cs @@ -0,0 +1,10 @@ +namespace ApiEfCoreLibrary.DTO.Book.Request; + +public class UpdateBookDto +{ + public int Id { get; set; } + public string? Title { get; set; } + public int? ReleaseYear { get; set; } + public string? Isbn { get; set; } + public int AuthorId { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Book/Response/GetBookDto.cs b/ApiEfCoreLibrary/DTO/Book/Response/GetBookDto.cs new file mode 100644 index 0000000..ce41438 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Book/Response/GetBookDto.cs @@ -0,0 +1,12 @@ +namespace ApiEfCoreLibrary.DTO.Book.Response; +public class GetBookDto +{ + public int Id { get; set; } + public string? Title { get; set; } + public int AuthorId { get; set; } + public int BookAuthorId { get; set; } + public string? BookAuthorName { get; set; } + public string? BookAuthorFirstName { get; set; } + public int? ReleaseYear { get; set; } + public string? Isbn { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Loan/Request/CreateLoanDto.cs b/ApiEfCoreLibrary/DTO/Loan/Request/CreateLoanDto.cs new file mode 100644 index 0000000..9adf227 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Loan/Request/CreateLoanDto.cs @@ -0,0 +1,8 @@ +namespace ApiEfCoreLibrary.DTO.Loan.Request; + +public class CreateLoanDto +{ + public int BookId { get; set; } + public int UserId { get; set; } + public DateOnly Date { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Loan/Request/PatchLoanDto.cs b/ApiEfCoreLibrary/DTO/Loan/Request/PatchLoanDto.cs new file mode 100644 index 0000000..5b8fec7 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Loan/Request/PatchLoanDto.cs @@ -0,0 +1,7 @@ +namespace ApiEfCoreLibrary.DTO.Loan.Request; + +public class PatchLoanDto +{ + public int Id { get; set; } + public DateOnly EffectiveReturningDate { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Loan/Request/UpdateLoanDto.cs b/ApiEfCoreLibrary/DTO/Loan/Request/UpdateLoanDto.cs new file mode 100644 index 0000000..2ed890f --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Loan/Request/UpdateLoanDto.cs @@ -0,0 +1,11 @@ +namespace ApiEfCoreLibrary.DTO.Loan.Request; + +public class UpdateLoanDto +{ + public int Id { get; set; } + public int BookId { get; set; } + public int UserId { get; set; } + public DateOnly Date { get; set; } + public DateOnly PlannedReturningDate { get; set; } + public DateOnly? EffectiveReturningDate { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/Loan/Response/GetLoanDto.cs b/ApiEfCoreLibrary/DTO/Loan/Response/GetLoanDto.cs new file mode 100644 index 0000000..4ae9608 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/Loan/Response/GetLoanDto.cs @@ -0,0 +1,23 @@ +namespace ApiEfCoreLibrary.DTO.Loan.Response; + +public class GetLoanDto +{ + public int Id { get; set; } + public int BookId { get; set; } + public string? BookTitle { get; set; } + + public int BookAuthorId { get; set; } + public string? BookAuthorName { get; set; } + public string? BookAuthorFirstName { get; set; } + + public int? BookReleaseYear { get; set; } + public string? BookIsbn { get; set; } + public int UserId { get; set; } + public string? UserName { get; set; } + public string? UserFirstName { get; set; } + public string? UserEmail { get; set; } + public DateOnly? UserBirthDate { get; set; } + public DateOnly Date { get; set; } + public DateOnly PlannedReturningDate { get; set; } + public DateOnly? EffectiveReturningDate { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/User/Request/CreateUserDto.cs b/ApiEfCoreLibrary/DTO/User/Request/CreateUserDto.cs new file mode 100644 index 0000000..02d980d --- /dev/null +++ b/ApiEfCoreLibrary/DTO/User/Request/CreateUserDto.cs @@ -0,0 +1,9 @@ +namespace ApiEfCoreLibrary.DTO.User.Request; + +public class CreateUserDto +{ + public string? Name { get; set; } + public string? FirstName { get; set; } + public string? Email { get; set; } + public DateOnly? BirthDate { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/User/Request/UpdateUserDto.cs b/ApiEfCoreLibrary/DTO/User/Request/UpdateUserDto.cs new file mode 100644 index 0000000..df5ce42 --- /dev/null +++ b/ApiEfCoreLibrary/DTO/User/Request/UpdateUserDto.cs @@ -0,0 +1,10 @@ +namespace ApiEfCoreLibrary.DTO.User.Request; + +public class UpdateUserDto +{ + public int Id { get; set; } + public string? Name { get; set; } + public string? FirstName { get; set; } + public string? Email { get; set; } + public DateOnly? BirthDate { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/DTO/User/Response/GetUserDto.cs b/ApiEfCoreLibrary/DTO/User/Response/GetUserDto.cs new file mode 100644 index 0000000..9c09e6d --- /dev/null +++ b/ApiEfCoreLibrary/DTO/User/Response/GetUserDto.cs @@ -0,0 +1,13 @@ +using ApiEfCoreLibrary.DTO.Loan.Response; + +namespace ApiEfCoreLibrary.DTO.User.Response; + +public class GetUserDto +{ + public int Id { get; set; } + public string? Name { get; set; } + public string? FirstName { get; set; } + public string? Email { get; set; } + public DateOnly? BirthDate { get; set; } + public List? Loans { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Author/CreateAuthorEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Author/CreateAuthorEndpoint.cs new file mode 100644 index 0000000..a7428e5 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Author/CreateAuthorEndpoint.cs @@ -0,0 +1,37 @@ +using ApiEfCoreLibrary.DTO.Author.Request; +using ApiEfCoreLibrary.DTO.Author.Response; + +namespace ApiEfCoreLibrary.Endpoints.Author; +using FastEndpoints; + +public class CreateAuthorEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/authors"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateAuthorDto req, CancellationToken ct) + { + var author = new Models.Author() + { + Name = req.Name, + FirstName = req.FirstName + }; + + database.Authors.Add(author); + + await database.SaveChangesAsync(ct); + // Pour renvoyer une erreur : Send.StringAsync("Le message d'erreur", 400); + + GetAuthorDto responseDto = new() + { + Id = author.Id, + Name = author.Name, + FirstName = author.FirstName + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Author/DeleteAuthorEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Author/DeleteAuthorEndpoint.cs new file mode 100644 index 0000000..99a2c7f --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Author/DeleteAuthorEndpoint.cs @@ -0,0 +1,36 @@ +using ApiEfCoreLibrary.DTO.Author.Request; +using ApiEfCoreLibrary.DTO.Author.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Author; + +public class DeleteAuthorRequest +{ + public int Id { get; set; } +} + +public class DeleteAuthorEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/authors/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteAuthorRequest req, CancellationToken ct) + { + var author = await database.Authors.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (author == null) + { + await Send.NotFoundAsync(ct); + return; + } + + database.Authors.Remove(author); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Author/GetAllAuthorsEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Author/GetAllAuthorsEndpoint.cs new file mode 100644 index 0000000..941c819 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Author/GetAllAuthorsEndpoint.cs @@ -0,0 +1,40 @@ +using ApiEfCoreLibrary.DTO.Author.Response; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Author; + +public class GetAllAuthorsEndpoint(LibraryDbContext database) : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/authors"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var authors = await database.Authors + .Include(x => x.Books) + .Select(author => new GetAuthorDto() + { + Id = author.Id, + Name = author.Name, + FirstName = author.FirstName, + Books = author.Books.Select(book => new GetBookDto + { + Id = book.Id, + Title = book.Title, + AuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }).ToList() + }) + .ToListAsync(ct); + + await Send.OkAsync(authors, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Author/GetAuthorEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Author/GetAuthorEndpoint.cs new file mode 100644 index 0000000..dc2de68 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Author/GetAuthorEndpoint.cs @@ -0,0 +1,53 @@ +using ApiEfCoreLibrary.DTO.Author.Request; +using ApiEfCoreLibrary.DTO.Author.Response; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Author; + +public class GetAuthorRequest +{ + public int Id { get; set; } +} + +public class GetAuthorEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Get("/api/authors/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(GetAuthorRequest req, CancellationToken ct) + { + var author = await database.Authors + .Include(x => x.Books) + .SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (author == null) + { + await Send.NotFoundAsync(ct); + return; + } + + GetAuthorDto responseDto = new() + { + Id = author.Id, + Name = author.Name, + FirstName = author.FirstName, + Books = author.Books.Select(book => new GetBookDto + { + Id = book.Id, + Title = book.Title, + AuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }).ToList() + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Author/UpdateAuthorEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Author/UpdateAuthorEndpoint.cs new file mode 100644 index 0000000..9210906 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Author/UpdateAuthorEndpoint.cs @@ -0,0 +1,40 @@ +using ApiEfCoreLibrary.DTO.Author.Request; +using ApiEfCoreLibrary.DTO.Author.Response; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Author; + +public class UpdateAuthorEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Put("/api/authors/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(UpdateAuthorDto req, CancellationToken ct) + { + var author = await database.Authors.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (author == null) + { + await Send.NotFoundAsync(ct); + return; + } + + author.Name = req.Name; + author.FirstName = req.FirstName; + await database.SaveChangesAsync(ct); + + GetAuthorDto responseDto = new() + { + Id = author.Id, + Name = author.Name, + FirstName = author.FirstName, + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Book/CreateBookEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Book/CreateBookEndpoint.cs new file mode 100644 index 0000000..01c3597 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Book/CreateBookEndpoint.cs @@ -0,0 +1,52 @@ +using ApiEfCoreLibrary.DTO.Book.Request; +using ApiEfCoreLibrary.DTO.Book.Response; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Book; +using FastEndpoints; + +public class CreateBookEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/books"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateBookDto req, CancellationToken ct) + { + var authorExists = await database.Authors.FirstOrDefaultAsync(a => a.Id == req.AuthorId, ct); + + if (authorExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + var book = new Models.Book() + { + Title = req.Title, + AuthorId = req.AuthorId, + ReleaseYear = req.ReleaseYear, + Isbn = req.Isbn + }; + + database.Books.Add(book); + + await database.SaveChangesAsync(ct); + // Pour renvoyer une erreur : Send.StringAsync("Le message d'erreur", 400); + + GetBookDto responseDto = new() + { + Id = book.Id, + Title = book.Title, + BookAuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Book/DeleteBookEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Book/DeleteBookEndpoint.cs new file mode 100644 index 0000000..cdab61a --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Book/DeleteBookEndpoint.cs @@ -0,0 +1,37 @@ +using ApiEfCoreLibrary.DTO.Author.Request; +using ApiEfCoreLibrary.DTO.Author.Response; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Book; + +public class DeleteBookRequest +{ + public int Id { get; set; } +} + +public class DeleteBookEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/books/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteBookRequest req, CancellationToken ct) + { + var book = await database.Books.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (book == null) + { + await Send.NotFoundAsync(ct); + return; + } + + database.Books.Remove(book); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Book/GetAllBooksEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Book/GetAllBooksEndpoint.cs new file mode 100644 index 0000000..d1ea5f8 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Book/GetAllBooksEndpoint.cs @@ -0,0 +1,33 @@ +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Book; + +public class GetAllBooksEndpoint(LibraryDbContext database) : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/books"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var books = await database.Books + .Include(b => b.Author) + .Select(book => new GetBookDto() + { + Id = book.Id, + Title = book.Title, + BookAuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }) + .ToListAsync(ct); + + await Send.OkAsync(books, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Book/GetBookEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Book/GetBookEndpoint.cs new file mode 100644 index 0000000..8e6495d --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Book/GetBookEndpoint.cs @@ -0,0 +1,43 @@ +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Book; + +public class GetBookRequest +{ + public int Id { get; set; } +} + +public class GetBookEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Get("/api/books/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(GetBookRequest req, CancellationToken ct) + { + var book = await database.Books.Include(b => b.Author).SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (book == null) + { + await Send.NotFoundAsync(ct); + return; + } + + GetBookDto responseDto = new() + { + Id = book.Id, + Title = book.Title, + BookAuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Book/UpdateBookEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Book/UpdateBookEndpoint.cs new file mode 100644 index 0000000..49f1207 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Book/UpdateBookEndpoint.cs @@ -0,0 +1,53 @@ +using ApiEfCoreLibrary.DTO.Book.Request; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Book; + +public class UpdateBookEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Put("/api/books/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(UpdateBookDto req, CancellationToken ct) + { + var book = await database.Books.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (book == null) + { + await Send.NotFoundAsync(ct); + return; + } + + var authorExists = await database.Authors.FirstOrDefaultAsync(a => a.Id == req.AuthorId, ct); + + if (authorExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + book.Title = req.Title; + book.AuthorId = req.AuthorId; + book.ReleaseYear = req.ReleaseYear; + book.Isbn = req.Isbn; + await database.SaveChangesAsync(ct); + + GetBookDto responseDto = new() + { + Id = book.Id, + Title = book.Title, + BookAuthorId = book.AuthorId, + BookAuthorName = book.Author.Name, + BookAuthorFirstName = book.Author.FirstName, + ReleaseYear = book.ReleaseYear, + Isbn = book.Isbn + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/CreateLoanEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/CreateLoanEndpoint.cs new file mode 100644 index 0000000..e170484 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/CreateLoanEndpoint.cs @@ -0,0 +1,58 @@ +using ApiEfCoreLibrary.DTO.Loan.Request; +using ApiEfCoreLibrary.DTO.Loan.Response; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; +using FastEndpoints; + +public class CreateLoanEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/loans"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateLoanDto req, CancellationToken ct) + { + var bookExists = await database.Books.FirstOrDefaultAsync(a => a.Id == req.BookId, ct); + + if (bookExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + var userExists = await database.Users.FirstOrDefaultAsync(a => a.Id == req.UserId, ct); + + if (userExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + var loan = new Models.Loan() + { + BookId = req.BookId, + UserId = req.UserId, + Date = req.Date, + PlannedReturningDate = req.Date.AddMonths(2) + }; + + database.Loans.Add(loan); + + await database.SaveChangesAsync(ct); + // Pour renvoyer une erreur : Send.StringAsync("Le message d'erreur", 400); + + GetLoanDto responseDto = new() + { + Id = loan.Id, + BookId = loan.BookId, + UserId = loan.UserId, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/DeleteLoanEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/DeleteLoanEndpoint.cs new file mode 100644 index 0000000..768ba4a --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/DeleteLoanEndpoint.cs @@ -0,0 +1,37 @@ +using ApiEfCoreLibrary.DTO.Loan.Request; +using ApiEfCoreLibrary.DTO.Loan.Response; +using ApiEfCoreLibrary.DTO.Book.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; + +public class DeleteLoanRequest +{ + public int Id { get; set; } +} + +public class DeleteLoanEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/loans/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteLoanRequest req, CancellationToken ct) + { + var loan = await database.Loans.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (loan == null) + { + await Send.NotFoundAsync(ct); + return; + } + + database.Loans.Remove(loan); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/GetAllLoansEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/GetAllLoansEndpoint.cs new file mode 100644 index 0000000..124ded8 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/GetAllLoansEndpoint.cs @@ -0,0 +1,44 @@ +using ApiEfCoreLibrary.DTO.Loan.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; + +public class GetAllLoanEndpoint(LibraryDbContext database) : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/loans"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var loans = await database.Loans + .Include(l => l.Book) + .ThenInclude(b => b.Author) + .Include(l => l.User) + .Select(loan => new GetLoanDto() + { + Id = loan.Id, + BookId = loan.BookId, + BookTitle = loan.Book.Title, + BookAuthorId = loan.Book.AuthorId, + BookAuthorName = loan.Book.Author.Name, + BookAuthorFirstName = loan.Book.Author.FirstName, + BookReleaseYear = loan.Book.ReleaseYear, + BookIsbn = loan.Book.Isbn, + UserId = loan.UserId, + UserName = loan.User.Name, + UserFirstName = loan.User.FirstName, + UserEmail = loan.User.Email, + UserBirthDate = loan.User.BirthDate, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }) + .ToListAsync(ct); + + await Send.OkAsync(loans, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/GetLoanEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/GetLoanEndpoint.cs new file mode 100644 index 0000000..c120d16 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/GetLoanEndpoint.cs @@ -0,0 +1,55 @@ +using ApiEfCoreLibrary.DTO.Loan.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; + +public class GetLoanRequest +{ + public int Id { get; set; } +} + +public class GetLoanEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Get("/api/loans/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(GetLoanRequest req, CancellationToken ct) + { + var loan = await database.Loans.Include(l => l.Book) + .ThenInclude(b => b.Author) + .Include(l => l.User) + .SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (loan == null) + { + await Send.NotFoundAsync(ct); + return; + } + + GetLoanDto responseDto = new() + { + Id = loan.Id, + BookId = loan.BookId, + BookTitle = loan.Book.Title, + BookAuthorId = loan.Book.AuthorId, + BookAuthorName = loan.Book.Author.Name, + BookAuthorFirstName = loan.Book.Author.FirstName, + BookReleaseYear = loan.Book.ReleaseYear, + BookIsbn = loan.Book.Isbn, + UserId = loan.UserId, + UserName = loan.User.Name, + UserFirstName = loan.User.FirstName, + UserEmail = loan.User.Email, + UserBirthDate = loan.User.BirthDate, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/PatchLoanEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/PatchLoanEndpoint.cs new file mode 100644 index 0000000..1c8bb5d --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/PatchLoanEndpoint.cs @@ -0,0 +1,53 @@ +using ApiEfCoreLibrary.DTO.Loan.Request; +using ApiEfCoreLibrary.DTO.Loan.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; + +public class PatchLoanEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Patch("/api/loans/{@Id}/EffectiveReturningDate", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchLoanDto req, CancellationToken ct) + { + var loan = await database.Loans.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (loan == null) + { + await Send.NotFoundAsync(ct); + return; + } + + if (req.EffectiveReturningDate <= DateOnly.FromDateTime(DateTime.Now)) + { + await Send.StringAsync("Erreur de date. La date est inférieure à la date actuelle.", 400); + return; + } + + if (loan.EffectiveReturningDate != null) + { + await Send.StringAsync("Impossible de modifier la date de retour.", 400); + return; + } + + loan.EffectiveReturningDate = req.EffectiveReturningDate; + await database.SaveChangesAsync(ct); + + GetLoanDto responseDto = new() + { + Id = loan.Id, + BookId = loan.BookId, + UserId = loan.UserId, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/Loan/UpdateLoanEndpoint.cs b/ApiEfCoreLibrary/Endpoints/Loan/UpdateLoanEndpoint.cs new file mode 100644 index 0000000..7bd9d75 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/Loan/UpdateLoanEndpoint.cs @@ -0,0 +1,61 @@ +using ApiEfCoreLibrary.DTO.Loan.Request; +using ApiEfCoreLibrary.DTO.Loan.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.Loan; + +public class UpdateLoanEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Put("/api/loans/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(UpdateLoanDto req, CancellationToken ct) + { + var loan = await database.Loans.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (loan == null) + { + await Send.NotFoundAsync(ct); + return; + } + + var bookExists = await database.Books.FirstOrDefaultAsync(a => a.Id == req.BookId, ct); + + if (bookExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + var userExists = await database.Users.FirstOrDefaultAsync(a => a.Id == req.UserId, ct); + + if (userExists == null) + { + await Send.NoContentAsync(ct); + return; + } + + loan.BookId = req.BookId; + loan.UserId = req.UserId; + loan.Date = req.Date; + loan.PlannedReturningDate = req.PlannedReturningDate; + loan.EffectiveReturningDate = req.EffectiveReturningDate; + await database.SaveChangesAsync(ct); + + GetLoanDto responseDto = new() + { + Id = loan.Id, + BookId = loan.BookId, + UserId = loan.UserId, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/User/CreateUserEndpoint.cs b/ApiEfCoreLibrary/Endpoints/User/CreateUserEndpoint.cs new file mode 100644 index 0000000..55c0a24 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/User/CreateUserEndpoint.cs @@ -0,0 +1,40 @@ +using ApiEfCoreLibrary.DTO.User.Request; +using ApiEfCoreLibrary.DTO.User.Response; + +namespace ApiEfCoreLibrary.Endpoints.User; +using FastEndpoints; + +public class CreateUserEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/users"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateUserDto req, CancellationToken ct) + { + var user = new Models.User() + { + Name = req.Name, + FirstName = req.FirstName, + Email = req.Email, + BirthDate = req.BirthDate, + }; + + database.Users.Add(user); + + await database.SaveChangesAsync(ct); + + GetUserDto responseDto = new() + { + Id = user.Id, + Name = user.Name, + FirstName = user.FirstName, + Email = user.Email, + BirthDate = user.BirthDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/User/DeleteUserEndpoint.cs b/ApiEfCoreLibrary/Endpoints/User/DeleteUserEndpoint.cs new file mode 100644 index 0000000..d61aa3b --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/User/DeleteUserEndpoint.cs @@ -0,0 +1,36 @@ +using ApiEfCoreLibrary.DTO.User.Request; +using ApiEfCoreLibrary.DTO.User.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.User; + +public class DeleteUserRequest +{ + public int Id { get; set; } +} + +public class DeleteUserEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/users/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct) + { + var user = await database.Users.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (user == null) + { + await Send.NotFoundAsync(ct); + return; + } + + database.Users.Remove(user); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/User/GetAllUsersEndpoint.cs b/ApiEfCoreLibrary/Endpoints/User/GetAllUsersEndpoint.cs new file mode 100644 index 0000000..7e4236a --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/User/GetAllUsersEndpoint.cs @@ -0,0 +1,52 @@ +using ApiEfCoreLibrary.DTO.Loan.Response; +using ApiEfCoreLibrary.DTO.User.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.User; + +public class GetAllUsersEndpoint(LibraryDbContext database) : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/users"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var user = await database.Users + .Include(x => x.Loans)! + .ThenInclude(l => l.Book) + .ThenInclude(b => b!.Author) + .Select(user => new GetUserDto() + { + Id = user.Id, + Name = user.Name, + FirstName = user.FirstName, + Email = user.Email, + BirthDate = user.BirthDate, + Loans = user.Loans.Select(loan => new GetLoanDto + { + Id = loan.Id, + BookId = loan.BookId, + BookTitle = loan.Book.Title, + BookAuthorId = loan.Book.AuthorId, + BookAuthorName = loan.Book.Author.Name, + BookAuthorFirstName = loan.Book.Author.FirstName, + BookReleaseYear = loan.Book.ReleaseYear, + BookIsbn = loan.Book.Isbn, + UserId = loan.UserId, + UserName = loan.User.Name, + UserFirstName = loan.User.FirstName, + UserEmail = loan.User.Email, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }).ToList() + }) + .ToListAsync(ct); + + await Send.OkAsync(user, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/User/GetUserEndpoint.cs b/ApiEfCoreLibrary/Endpoints/User/GetUserEndpoint.cs new file mode 100644 index 0000000..98d4bf8 --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/User/GetUserEndpoint.cs @@ -0,0 +1,64 @@ +using ApiEfCoreLibrary.DTO.Loan.Response; +using ApiEfCoreLibrary.DTO.User.Request; +using ApiEfCoreLibrary.DTO.User.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.User; + +public class GetUserRequest +{ + public int Id { get; set; } +} + +public class GetUserEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Get("/api/users/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(GetUserRequest req, CancellationToken ct) + { + var user = await database.Users + .Include(x => x.Loans)! + .ThenInclude(l => l.Book) + .ThenInclude(b => b!.Author) + .SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (user == null) + { + await Send.NotFoundAsync(ct); + return; + } + + GetUserDto responseDto = new() + { + Id = user.Id, + Name = user.Name, + FirstName = user.FirstName, + Email = user.Email, + BirthDate = user.BirthDate, + Loans = user.Loans?.Select(loan => new GetLoanDto + { + Id = loan.Id, + BookId = loan.BookId, + BookTitle = loan.Book.Title, + BookAuthorName = loan.Book.Author.Name, + BookAuthorFirstName = loan.Book.Author.FirstName, + BookReleaseYear = loan.Book.ReleaseYear, + BookIsbn = loan.Book.Isbn, + UserId = loan.UserId, + UserName = loan.User?.Name, + UserFirstName = loan.User?.FirstName, + UserEmail = loan.User?.Email, + Date = loan.Date, + PlannedReturningDate = loan.PlannedReturningDate, + EffectiveReturningDate = loan.EffectiveReturningDate + }).ToList() + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Endpoints/User/UpdateUserEndpoint.cs b/ApiEfCoreLibrary/Endpoints/User/UpdateUserEndpoint.cs new file mode 100644 index 0000000..71ed1bc --- /dev/null +++ b/ApiEfCoreLibrary/Endpoints/User/UpdateUserEndpoint.cs @@ -0,0 +1,43 @@ +using ApiEfCoreLibrary.DTO.User.Request; +using ApiEfCoreLibrary.DTO.User.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary.Endpoints.User; + +public class UpdateUserEndpoint(LibraryDbContext database) : Endpoint +{ + public override void Configure() + { + Put("/api/users/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(UpdateUserDto req, CancellationToken ct) + { + var user = await database.Users.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (user == null) + { + await Send.NotFoundAsync(ct); + return; + } + + user.Name = req.Name; + user.FirstName = req.FirstName; + user.Email = req.Email; + user.BirthDate = req.BirthDate; + await database.SaveChangesAsync(ct); + + GetUserDto responseDto = new() + { + Id = user.Id, + Name = user.Name, + FirstName = user.FirstName, + Email = user.Email, + BirthDate = user.BirthDate + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/LibraryDbContext.cs b/ApiEfCoreLibrary/LibraryDbContext.cs new file mode 100644 index 0000000..3f10f25 --- /dev/null +++ b/ApiEfCoreLibrary/LibraryDbContext.cs @@ -0,0 +1,32 @@ +using ApiEfCoreLibrary.Models; +using Microsoft.EntityFrameworkCore; + +namespace ApiEfCoreLibrary; + +public class LibraryDbContext : DbContext +{ + // Tables représentées par les entités + public DbSet Books { get; set; } // Table des livres + public DbSet Authors { get; set; } // Table des auteurs + public DbSet Loans { get; set; } // Table des prêts + public DbSet Users { get; set; } // Table des utilisateurs + public DbSet Logins { get; set; } // Table des logins + + // Configuration de la connexion à la base de données + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + string connectionString = + "Server=romaric-thibault.fr;" + // Serveur SQL + "Database=mathys_EfCoreLibrary;" + // Nom de la base + "User Id=mathys;" + // Utilisateur + "Password=Onto9-Cage-Afflicted;" + // Mot de passe + "TrustServerCertificate=true;"; // Accepte certificat auto-signé + + optionsBuilder.UseSqlServer(connectionString); + } + + // Personnalisation du modèle (non utilisée ici) + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + } +} diff --git a/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.Designer.cs b/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.Designer.cs new file mode 100644 index 0000000..a0077a2 --- /dev/null +++ b/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.Designer.cs @@ -0,0 +1,187 @@ +// +using System; +using ApiEfCoreLibrary; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ApiEfCoreLibrary.Migrations +{ + [DbContext(typeof(LibraryDbContext))] + [Migration("20250923063940_InitialDatabase")] + partial class InitialDatabase + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("EfCoreLibrary.Models.Author", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Authors"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("int"); + + b.Property("Isbn") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("ReleaseYear") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.Loan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BookId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("EffectiveReturningDate") + .HasColumnType("date"); + + b.Property("PlannedReturningDate") + .HasColumnType("date"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BookId"); + + b.HasIndex("UserId"); + + b.ToTable("Loans"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BirthDate") + .HasColumnType("date"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.Book", b => + { + b.HasOne("EfCoreLibrary.Models.Author", "Author") + .WithMany("Books") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.Loan", b => + { + b.HasOne("EfCoreLibrary.Models.Book", "Book") + .WithMany() + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("EfCoreLibrary.Models.User", "User") + .WithMany("Loans") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.Author", b => + { + b.Navigation("Books"); + }); + + modelBuilder.Entity("EfCoreLibrary.Models.User", b => + { + b.Navigation("Loans"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.cs b/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.cs new file mode 100644 index 0000000..c62e8a2 --- /dev/null +++ b/ApiEfCoreLibrary/Migrations/20250923063940_InitialDatabase.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ApiEfCoreLibrary.Migrations +{ + /// + public partial class InitialDatabase : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Authors", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + FirstName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Authors", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + FirstName = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: false), + Email = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: false), + BirthDate = table.Column(type: "date", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Books", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: false), + AuthorId = table.Column(type: "int", nullable: false), + ReleaseYear = table.Column(type: "int", nullable: true), + Isbn = table.Column(type: "nvarchar(20)", maxLength: 20, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Books", x => x.Id); + table.ForeignKey( + name: "FK_Books_Authors_AuthorId", + column: x => x.AuthorId, + principalTable: "Authors", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Loans", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + BookId = table.Column(type: "int", nullable: false), + UserId = table.Column(type: "int", nullable: false), + Date = table.Column(type: "date", nullable: false), + PlannedReturningDate = table.Column(type: "date", nullable: false), + EffectiveReturningDate = table.Column(type: "date", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Loans", x => x.Id); + table.ForeignKey( + name: "FK_Loans_Books_BookId", + column: x => x.BookId, + principalTable: "Books", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Loans_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Books_AuthorId", + table: "Books", + column: "AuthorId"); + + migrationBuilder.CreateIndex( + name: "IX_Loans_BookId", + table: "Loans", + column: "BookId"); + + migrationBuilder.CreateIndex( + name: "IX_Loans_UserId", + table: "Loans", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Loans"); + + migrationBuilder.DropTable( + name: "Books"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.DropTable( + name: "Authors"); + } + } +} diff --git a/ApiEfCoreLibrary/Migrations/LibraryDbContextModelSnapshot.cs b/ApiEfCoreLibrary/Migrations/LibraryDbContextModelSnapshot.cs new file mode 100644 index 0000000..a919bb2 --- /dev/null +++ b/ApiEfCoreLibrary/Migrations/LibraryDbContextModelSnapshot.cs @@ -0,0 +1,217 @@ +// +using System; +using ApiEfCoreLibrary; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ApiEfCoreLibrary.Migrations +{ + [DbContext(typeof(LibraryDbContext))] + partial class LibraryDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Author", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Authors"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Book", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("int"); + + b.Property("Isbn") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("ReleaseYear") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Books"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Loan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BookId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("EffectiveReturningDate") + .HasColumnType("date"); + + b.Property("PlannedReturningDate") + .HasColumnType("date"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("BookId"); + + b.HasIndex("UserId"); + + b.ToTable("Loans"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Login", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Salt") + .IsRequired() + .HasMaxLength(24) + .HasColumnType("nvarchar(24)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Logins"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BirthDate") + .HasColumnType("date"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Book", b => + { + b.HasOne("ApiEfCoreLibrary.Models.Author", "Author") + .WithMany("Books") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Loan", b => + { + b.HasOne("ApiEfCoreLibrary.Models.Book", "Book") + .WithMany() + .HasForeignKey("BookId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ApiEfCoreLibrary.Models.User", "User") + .WithMany("Loans") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Book"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.Author", b => + { + b.Navigation("Books"); + }); + + modelBuilder.Entity("ApiEfCoreLibrary.Models.User", b => + { + b.Navigation("Loans"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ApiEfCoreLibrary/Models/Author.cs b/ApiEfCoreLibrary/Models/Author.cs new file mode 100644 index 0000000..6cba3cd --- /dev/null +++ b/ApiEfCoreLibrary/Models/Author.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace ApiEfCoreLibrary.Models; + +public class Author +{ + [Key] public int Id { get; set; } + [Required, MaxLength(100)] public string? Name { get; set; } + [Required, MaxLength(100)] public string? FirstName { get; set; } + public List? Books { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Models/Book.cs b/ApiEfCoreLibrary/Models/Book.cs new file mode 100644 index 0000000..892b160 --- /dev/null +++ b/ApiEfCoreLibrary/Models/Book.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace ApiEfCoreLibrary.Models; + +public class Book +{ + [Key] public int Id { get; set; } + [Required, MaxLength(255)] public string? Title { get; set; } + [Required] public int AuthorId { get; set; } + public int? ReleaseYear { get; set; } + [Required, MaxLength(20)] public string? Isbn { get; set; } + public Author? Author { get; set; } +} diff --git a/ApiEfCoreLibrary/Models/Loan.cs b/ApiEfCoreLibrary/Models/Loan.cs new file mode 100644 index 0000000..0e05d7d --- /dev/null +++ b/ApiEfCoreLibrary/Models/Loan.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace ApiEfCoreLibrary.Models; + +public class Loan +{ + [Key] public int Id { get; set; } + [Required] public int BookId { get; set; } + [Required] public int UserId { get; set; } + [Required] public DateOnly Date { get; set; } + [Required] public DateOnly PlannedReturningDate { get; set; } + public DateOnly? EffectiveReturningDate { get; set; } + public Book? Book { get; set; } + public User? User { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Models/Login.cs b/ApiEfCoreLibrary/Models/Login.cs new file mode 100644 index 0000000..1adaca1 --- /dev/null +++ b/ApiEfCoreLibrary/Models/Login.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; +namespace ApiEfCoreLibrary.Models; + +public class Login +{ + [Key] public int Id { get; set; } + [Required, MaxLength(100)] public string? Username { get; set; } + [Required, MaxLength(200)] public string? FullName { get; set; } + [Required, MaxLength(255)] public string? Password { get; set; } + [Required, MaxLength(24)] public string? Salt { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Models/User.cs b/ApiEfCoreLibrary/Models/User.cs new file mode 100644 index 0000000..81108cf --- /dev/null +++ b/ApiEfCoreLibrary/Models/User.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace ApiEfCoreLibrary.Models; + +public class User +{ + [Key] public int Id { get; set; } + [Required, MaxLength(100)] public string? Name { get; set; } + [Required, MaxLength(100)] public string? FirstName { get; set; } + [Required, MaxLength(255)] public string? Email { get; set; } + public DateOnly? BirthDate { get; set; } + public List? Loans { get; set; } +} \ No newline at end of file diff --git a/ApiEfCoreLibrary/Program.cs b/ApiEfCoreLibrary/Program.cs new file mode 100644 index 0000000..012e0dc --- /dev/null +++ b/ApiEfCoreLibrary/Program.cs @@ -0,0 +1,27 @@ +using ApiEfCoreLibrary; +using FastEndpoints; +using FastEndpoints.Swagger; +using FastEndpoints.Security; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +// On ajoute ici FastEndpoints, un framework REPR et Swagger aux services disponibles dans le projet +builder.Services + .AddAuthenticationJwtBearer(s => s.SigningKey = "The secret used to sign tokens") + .AddAuthorization() + .AddFastEndpoints() + .SwaggerDocument(); + +// On ajoute ici la configuration de la base de données +builder.Services.AddDbContext(); + +// On construit l'application en lui donnant vie +WebApplication app = builder.Build(); +app.UseAuthentication() + .UseAuthorization() + .UseFastEndpoints() + .UseSwaggerGen(); + +app.UseHttpsRedirection(); + +app.Run(); \ No newline at end of file diff --git a/ApiEfCoreLibrary/Properties/launchSettings.json b/ApiEfCoreLibrary/Properties/launchSettings.json new file mode 100644 index 0000000..f87b03a --- /dev/null +++ b/ApiEfCoreLibrary/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49674", + "sslPort": 44390 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5228", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7214;http://localhost:5228", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/ApiEfCoreLibrary/appsettings.Development.json b/ApiEfCoreLibrary/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/ApiEfCoreLibrary/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/ApiEfCoreLibrary/appsettings.json b/ApiEfCoreLibrary/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/ApiEfCoreLibrary/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}