From e0dabfcf0ad532a42acdc9888da4e41e2b6ba984 Mon Sep 17 00:00:00 2001 From: Louis DEVIE Date: Tue, 20 May 2025 12:49:35 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20dao=20des=20cat=C3=A9gories=20avec=20ty?= =?UTF-8?q?pe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tests/main.py | 2 +- .tests/tests/access_tests.py | 2 + .tests/tests/category_tests.py | 77 ++++++++++++++---- Core/Data/IBasicDao.cs | 2 +- Core/Exceptions/ErrorCode.cs | 3 +- .../MissingIdentificationException.cs | 8 ++ Core/Exceptions/PermissionDeniedException.cs | 2 +- .../Exceptions/UnauthorisedAccessException.cs | 16 ++++ .../Builders/AuditLogEntryBuilder.Category.cs | 1 + Core/Logs/Builders/AuditLogEntryBuilder.cs | 7 ++ Core/Stocks/Category.cs | 25 ++++-- Core/Stocks/CategoryType.cs | 17 ++++ .../MariaDb/Implementations/CategoryDao.cs | 78 +++++++++---------- .../MariaDb/Implementations/ProductDao.cs | 25 +++--- Fake/Data/Fake/CategoryDao.cs | 14 +++- WebService/Controllers/CategoryController.cs | 22 +++--- WebService/Controllers/GalliumController.cs | 16 +++- WebService/Dto/Legacy/CategoryDetails.cs | 2 +- .../ErrorHandling/ExceptionsFilter.cs | 10 +-- WebService/Program.cs | 4 +- 20 files changed, 230 insertions(+), 103 deletions(-) create mode 100644 Core/Exceptions/MissingIdentificationException.cs create mode 100644 Core/Exceptions/UnauthorisedAccessException.cs create mode 100644 Core/Stocks/CategoryType.cs diff --git a/.tests/main.py b/.tests/main.py index d6e1915..2a89efa 100644 --- a/.tests/main.py +++ b/.tests/main.py @@ -9,4 +9,4 @@ if __name__ == "__main__": decimal.DefaultContext.prec = 2 - Launcher.launch("1.3.1") + Launcher.launch("1.4.0") diff --git a/.tests/tests/access_tests.py b/.tests/tests/access_tests.py index d5ba9b7..6cb1d35 100644 --- a/.tests/tests/access_tests.py +++ b/.tests/tests/access_tests.py @@ -127,6 +127,7 @@ def test_login_permissions_normal(self): 3, id=president_edit_response.json()["id"], name="Catégorie", + type="Category", ), ) @@ -258,6 +259,7 @@ def test_login_permissions_minimum(self): 3, id=president_edit_response.json()["id"], name="Catégorie", + type="Category", ), ) diff --git a/.tests/tests/category_tests.py b/.tests/tests/category_tests.py index ab9be5f..13dd671 100644 --- a/.tests/tests/category_tests.py +++ b/.tests/tests/category_tests.py @@ -22,6 +22,9 @@ def test_category_get_all(self): category = categories[0] self.expect(category).to.have.an_item("id").of.type(int) self.expect(category).to.have.an_item("name").of.type(str) + self.expect(category).to.have.an_item("type").that.is_.one_of( + "Category", "Group" + ) def test_category_get_one(self): existing_id = self.get("categories").json()[0]["id"] @@ -36,6 +39,9 @@ def test_category_get_one(self): self.expect(category).to.be.a(dict) self.expect(category).to.have.an_item("id").of.type(int) self.expect(category).to.have.an_item("name").of.type(str) + self.expect(category).to.have.an_item("type").that.is_.one_of( + "Category", "Group" + ) # Test avec une catégorie inexistante @@ -45,27 +51,54 @@ def test_category_get_one(self): def test_category_create(self): previous_category_count = len(self.get("categories").json()) - valid_category = {"name": "Jus"} + implicit_type = {"name": "Jus"} with self.audit.watch(): - response = self.post("categories", valid_category) + response = self.post("categories", implicit_type) + self.expect(response.status_code).to.be.equal_to(201) location = self.expect(response.headers).to.have.an_item("Location").value created_category = response.json() self.expect(created_category).to.have.an_item("id") self.expect(created_category["name"]).to.be.equal_to("Jus") + self.expect(created_category["type"]).to.be.equal_to("Category") response = self.get(location) self.expect(response.status_code).to.be.equal_to(200) created_category = response.json() self.expect(created_category["name"]).to.be.equal_to("Jus") + self.expect(created_category["type"]).to.be.equal_to("Category") new_category_count = len(self.get("categories").json()) self.expect(new_category_count).to.be.equal_to(previous_category_count + 1) self.audit.expect_entries( - self.audit.entry("CategoryAdded", id=created_category["id"], name="Jus") + self.audit.entry( + "CategoryAdded", id=created_category["id"], name="Jus", type="Category" + ) + ) + + explicit_type = {"name": "Caca-Cola", "type": "Group"} + + with self.audit.watch(): + response = self.post("categories", explicit_type) + + self.expect(response.status_code).to.be.equal_to(201) + location = self.expect(response.headers).to.have.an_item("Location").value + + created_category = response.json() + self.expect(created_category).to.have.an_item("id") + self.expect(created_category["name"]).to.be.equal_to("Caca-Cola") + self.expect(created_category["type"]).to.be.equal_to("Group") + + self.audit.expect_entries( + self.audit.entry( + "CategoryAdded", + id=created_category["id"], + name="Caca-Cola", + type="Group", + ) ) # Informations manquantes @@ -87,22 +120,36 @@ def test_category_create(self): ) def test_category_edit(self): - valid_category = self.get("categories").json()[-1] - valid_category.update(Name="Jus") - category_id = valid_category["id"] + valid_category = {"name": "Jus", "type": "Category"} + response = self.post("categories", valid_category) + category_id = response.json()["id"] + location = response.headers["Location"] + + valid_category.update(name="Jus 2") with self.audit.watch(): - response = self.put(f"categories/{category_id}", valid_category) + response = self.put(location, valid_category) self.expect(response.status_code).to.be.equal_to(200) - edited_category = self.get(f"categories/{category_id}").json() - self.expect(edited_category["name"]).to.be.equal_to("Jus") + edited_category = self.get(location).json() + self.expect(edited_category["name"]).to.be.equal_to("Jus 2") self.audit.expect_entries( - self.audit.entry("CategoryModified", id=category_id, name="Jus") + self.audit.entry( + "CategoryModified", id=category_id, name="Jus 2", type="Category" + ) ) - # category qui n'existe pas + # Changement de type + + valid_category.update(type="Group") + response = self.put(location, valid_category) + self.expect(response.status_code).to.be.equal_to(200) + + edited_category = self.get(location).json() + self.expect(edited_category["type"]).to.be.equal_to("Category") + + # Catégorie qui n'existe pas response = self.put("categories/12345", valid_category) self.expect(response.status_code).to.be.equal_to(404) @@ -110,7 +157,7 @@ def test_category_edit(self): # Informations manquantes invalid_category = {} - response = self.put(f"categories/{category_id}", invalid_category) + response = self.put(location, invalid_category) self.expect(response.status_code).to.be.equal_to(400) self.expect(response.json()).to.have.an_item("code").that._is.equal_to( "InvalidResource" @@ -119,7 +166,7 @@ def test_category_edit(self): # Informations non valides invalid_category = {"name": ""} - response = self.put(f"categories/{category_id}", invalid_category) + response = self.put(location, invalid_category) self.expect(response.status_code).to.be.equal_to(400) self.expect(response.json()).to.have.an_item("code").that._is.equal_to( "InvalidResource" @@ -138,7 +185,9 @@ def test_category_delete(self): self.expect(response.status_code).to.be.equal_to(200) self.audit.expect_entries( - self.audit.entry("CategoryDeleted", id=category_id, name="Jus") + self.audit.entry( + "CategoryDeleted", id=category_id, name="Jus", type="Category" + ) ) # La catégorie n'existe plus diff --git a/Core/Data/IBasicDao.cs b/Core/Data/IBasicDao.cs index d6dcd35..fd8da37 100644 --- a/Core/Data/IBasicDao.cs +++ b/Core/Data/IBasicDao.cs @@ -39,7 +39,7 @@ public interface IBasicDao public TItem Update(TKey key, TItem item); /// - /// Supprimme un item. + /// Supprime un item. /// /// La clé de l'item à supprimer. public void Delete(TKey key); diff --git a/Core/Exceptions/ErrorCode.cs b/Core/Exceptions/ErrorCode.cs index ee10442..5e66e2b 100644 --- a/Core/Exceptions/ErrorCode.cs +++ b/Core/Exceptions/ErrorCode.cs @@ -10,5 +10,6 @@ public enum ErrorCode ServiceUnavailable, FailedPrecondition, AccessMethodNotAllowed, - DisabledApplication + DisabledApplication, + MissingIdentification } \ No newline at end of file diff --git a/Core/Exceptions/MissingIdentificationException.cs b/Core/Exceptions/MissingIdentificationException.cs new file mode 100644 index 0000000..9702987 --- /dev/null +++ b/Core/Exceptions/MissingIdentificationException.cs @@ -0,0 +1,8 @@ +using GalliumPlus.Core.Security; + +namespace GalliumPlus.Core.Exceptions; + +public class MissingIdentificationException(string message) : UnauthorisedAccessException(message) +{ + public override ErrorCode ErrorCode => ErrorCode.MissingIdentification; +} \ No newline at end of file diff --git a/Core/Exceptions/PermissionDeniedException.cs b/Core/Exceptions/PermissionDeniedException.cs index 4e12496..973f9fd 100644 --- a/Core/Exceptions/PermissionDeniedException.cs +++ b/Core/Exceptions/PermissionDeniedException.cs @@ -6,7 +6,7 @@ namespace GalliumPlus.Core.Exceptions; /// Erreur indiquant que l'utilisateur n'a pas les permissions suffisantes /// pour effectuer une action. /// -public class PermissionDeniedException : GalliumException +public class PermissionDeniedException : UnauthorisedAccessException { private readonly Permission required; diff --git a/Core/Exceptions/UnauthorisedAccessException.cs b/Core/Exceptions/UnauthorisedAccessException.cs new file mode 100644 index 0000000..8bf1f55 --- /dev/null +++ b/Core/Exceptions/UnauthorisedAccessException.cs @@ -0,0 +1,16 @@ +namespace GalliumPlus.Core.Exceptions; + +/// +/// Exception de base indiquant qu'une action ne peut pas être effectuée, +/// car le niveau d'autorisation est insuffisant (identification ou permissions manquantes par exemple). +/// +public abstract class UnauthorisedAccessException : GalliumException +{ + protected UnauthorisedAccessException() + { + } + + protected UnauthorisedAccessException(string message) : base(message) + { + } +} \ No newline at end of file diff --git a/Core/Logs/Builders/AuditLogEntryBuilder.Category.cs b/Core/Logs/Builders/AuditLogEntryBuilder.Category.cs index ca311e0..cedf3d1 100644 --- a/Core/Logs/Builders/AuditLogEntryBuilder.Category.cs +++ b/Core/Logs/Builders/AuditLogEntryBuilder.Category.cs @@ -16,6 +16,7 @@ protected override void AddDetails() { this.Root.details.Add("id", category.Id); this.Root.details.Add("name", category.Name); + this.Root.details.Add("type", category.Type.ToString()); } } } \ No newline at end of file diff --git a/Core/Logs/Builders/AuditLogEntryBuilder.cs b/Core/Logs/Builders/AuditLogEntryBuilder.cs index 1486d85..1da4994 100644 --- a/Core/Logs/Builders/AuditLogEntryBuilder.cs +++ b/Core/Logs/Builders/AuditLogEntryBuilder.cs @@ -35,6 +35,13 @@ public AuditLogEntryBuilder By(Client app, User? user = null) return this; } + public AuditLogEntryBuilder By(Session session) + { + this.clientId = session.Client.Id; + this.userId = session.User?.Iuid; + return this; + } + public IGenericEntryBuilder Category(Category category) => new CategoryEntryBuilder(this, category); public IClientEntryBuilder Client(Client client) => new ClientEntryBuilder(this, client); diff --git a/Core/Stocks/Category.cs b/Core/Stocks/Category.cs index e4888fc..4c8ea21 100644 --- a/Core/Stocks/Category.cs +++ b/Core/Stocks/Category.cs @@ -1,12 +1,18 @@ -namespace GalliumPlus.Core.Stocks; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using KiwiQuery.Mapped; + +namespace GalliumPlus.Core.Stocks; /// /// Une catégorie de produits. /// public class Category { - private int id; - private string name; + [PrimaryKey(AutoIncrement = true)] + private readonly int id; + private readonly string name; + private readonly CategoryType type; /// /// L'identifiant de la catégorie. @@ -16,18 +22,25 @@ public class Category /// /// Le nom affiché de la catégorie. /// + [Required] public string Name => this.name; + + /// + /// Le type de catégorie (classique ou groupe). + /// + [EnumDataType(typeof(CategoryType))] + public CategoryType Type => this.type; /// /// Crée une catégorie. /// /// L'identifiant de la catégorie. /// Le nom affiché de la catégorie. - public Category(int id, string name) + /// Le type de catégorie (classique ou groupe). + public Category(int id, string name, CategoryType type = CategoryType.Category) { this.id = id; this.name = name; + this.type = type; } - - public Category WithId(int id) => new(id, this.name); } \ No newline at end of file diff --git a/Core/Stocks/CategoryType.cs b/Core/Stocks/CategoryType.cs new file mode 100644 index 0000000..5ed7293 --- /dev/null +++ b/Core/Stocks/CategoryType.cs @@ -0,0 +1,17 @@ +namespace GalliumPlus.Core.Stocks; + +/// +/// Les différents types de catégories d'articles. +/// +public enum CategoryType +{ + /// + /// Une catégorie classique. + /// + Category = 1, + + /// + /// Un regroupement. + /// + Group = 2 +} \ No newline at end of file diff --git a/External/Data/MariaDb/Implementations/CategoryDao.cs b/External/Data/MariaDb/Implementations/CategoryDao.cs index ddd2a48..b1a31a3 100644 --- a/External/Data/MariaDb/Implementations/CategoryDao.cs +++ b/External/Data/MariaDb/Implementations/CategoryDao.cs @@ -2,81 +2,73 @@ using GalliumPlus.Core.Exceptions; using GalliumPlus.Core.Stocks; using KiwiQuery; +using KiwiQuery.Mapped; +using KiwiQuery.Mapped.Exceptions; using MySqlConnector; namespace GalliumPlus.Data.MariaDb.Implementations { public class CategoryDao : Dao, ICategoryDao { - public CategoryDao(DatabaseConnector connector) : base(connector) { } - - public Category Create(Category client) + public CategoryDao(DatabaseConnector connector) : base(connector) { - using var connection = this.Connect(); - Schema db = new(connection); - - int id = db.InsertInto("Category").Value("name", client.Name).Apply(); - - return client.WithId(id); } - public void Delete(int key) + public Category Create(Category category) { using var connection = this.Connect(); Schema db = new(connection); - - bool ok = db.DeleteFrom("Category").Where(db.Column("id") == key).Apply(); - - if (!ok) throw new ItemNotFoundException("Cette catégorie"); - } - - private static Category Hydrate(MySqlDataReader row) - { - return new Category( - row.GetInt32("id"), - row.GetString("name") - ); + + return db.Table().InsertOne(category); } public IEnumerable Read() { using var connection = this.Connect(); Schema db = new(connection); - - using var results = db - .Select("id", "name") - .From("Category") - .Fetch(); - - return this.ReadResults(results, Hydrate); + + return db.Table().SelectAll(); } public Category Read(int key) { using var connection = this.Connect(); Schema db = new(connection); - - using var result = db - .Select("id", "name") - .From("Category") - .Where(db.Column("id") == key) - .Fetch(); - - if (!result.Read()) throw new ItemNotFoundException("Cette catégorie"); - return Hydrate(result); + try + { + return db.Table().SelectOne(key); + } + catch (NotFoundException) + { + throw new ItemNotFoundException("Cette catégorie"); + } } - public Category Update(int key, Category item) + public Category Update(int key, Category category) { using var connection = this.Connect(); Schema db = new(connection); - bool ok = db.Update("Category").Set("name", item.Name).Where(db.Column("id") == key).Apply(); + if (db.Update().SetOnly(category, "name").Where(db.Column("id") == key).Apply()) + { + return db.Table().SelectOne(key); + } + else + { + throw new ItemNotFoundException("Cette catégorie"); + } + } - if (!ok) throw new ItemNotFoundException("Cette catégorie"); + public void Delete(int key) + { + using var connection = this.Connect(); + Schema db = new(connection); - return item.WithId(key); + if (!db.Table().DeleteOne(key)) + { + throw new ItemNotFoundException("Cette catégorie"); + } } } -} +} \ No newline at end of file diff --git a/External/Data/MariaDb/Implementations/ProductDao.cs b/External/Data/MariaDb/Implementations/ProductDao.cs index a5acba8..1eec0a9 100644 --- a/External/Data/MariaDb/Implementations/ProductDao.cs +++ b/External/Data/MariaDb/Implementations/ProductDao.cs @@ -82,7 +82,8 @@ private static Product Hydrate(MySqlDataReader row) (Availability)row.GetInt32("availability"), new Category( row.GetInt32("categoryId"), - row.GetString("categoryName") + row.GetString("categoryName"), + (CategoryType)row.GetInt32("categoryType") ) ); } @@ -94,20 +95,23 @@ public IEnumerable Read() var cmd = connection.CreateCommand(); cmd.CommandText = @" WITH pv AS ( - SELECT p.price, p.item, pt.requiresMembership FROM Price p JOIN PriceList pt ON p.type = pt.id AND pt.applicableDuring = 1 + SELECT p.price, p.item, pt.requiresMembership + FROM Price p + JOIN PriceList pt ON p.type = pt.id AND pt.applicableDuring = 1 ) SELECT i.id AS productId , i.name AS productName , c.id AS categoryId , c.name AS categoryName + , c.type AS categoryType , i.currentStock AS stock , i.isAvailable AS availability , nmp.price AS nonMemberPrice , mp.price AS memberPrice FROM `Item` i - JOIN Category c ON i.category = c.id - JOIN pv nmp ON nmp.item = i.id AND nmp.requiresMembership = 0 - JOIN pv mp ON mp.item = i.id AND mp.requiresMembership = 1 + JOIN Category c ON i.category = c.id + JOIN pv nmp ON nmp.item = i.id AND nmp.requiresMembership = 0 + JOIN pv mp ON mp.item = i.id AND mp.requiresMembership = 1 WHERE i.deleted = 0 "; using var results = cmd.ExecuteReader(); @@ -123,20 +127,23 @@ public Product Read(int key) var cmd = connection.CreateCommand(); cmd.CommandText = @" WITH pv AS ( - SELECT p.price, p.item, pt.requiresMembership FROM Price p JOIN PriceList pt ON p.type = pt.id AND pt.applicableDuring = 1 + SELECT p.price, p.item, pt.requiresMembership + FROM Price p + JOIN PriceList pt ON p.type = pt.id AND pt.applicableDuring = 1 ) SELECT i.id AS productId , i.name AS productName , c.id AS categoryId , c.name AS categoryName + , c.type AS categoryType , i.currentStock AS stock , i.isAvailable AS availability , nmp.price AS nonMemberPrice , mp.price AS memberPrice FROM `Item` i - JOIN Category c ON i.category = c.id - JOIN pv nmp ON nmp.item = i.id AND nmp.requiresMembership = 0 - JOIN pv mp ON mp.item = i.id AND mp.requiresMembership = 1 + JOIN Category c ON i.category = c.id + JOIN pv nmp ON nmp.item = i.id AND nmp.requiresMembership = 0 + JOIN pv mp ON mp.item = i.id AND mp.requiresMembership = 1 WHERE i.deleted = 0 AND i.id = @key "; cmd.Parameters.AddWithValue("key", key); diff --git a/Fake/Data/Fake/CategoryDao.cs b/Fake/Data/Fake/CategoryDao.cs index 7547558..cd9ddc3 100644 --- a/Fake/Data/Fake/CategoryDao.cs +++ b/Fake/Data/Fake/CategoryDao.cs @@ -7,13 +7,19 @@ public class CategoryDao : BaseDaoWithAutoIncrement, ICategoryDao { public CategoryDao() { - this.Create(new Category(0, "Boissons")); - this.Create(new Category(0, "Snacks")); - this.Create(new Category(0, "Pablo")); + this.Create(new Category(0, "Boissons", CategoryType.Category)); + this.Create(new Category(0, "Snacks", CategoryType.Category)); + this.Create(new Category(0, "Pablo", CategoryType.Category)); + } + + public override Category Update(int key, Category item) + { + CategoryType originalType = this.Read(key).Type; + return base.Update(key, new Category(item.Id, item.Name, originalType)); } protected override int GetKey(Category item) => item.Id; - protected override Category SetKey(Category item, int key) => item.WithId(key); + protected override Category SetKey(Category item, int key) => new(key, item.Name, item.Type); } } diff --git a/WebService/Controllers/CategoryController.cs b/WebService/Controllers/CategoryController.cs index 0add96c..bcede5b 100644 --- a/WebService/Controllers/CategoryController.cs +++ b/WebService/Controllers/CategoryController.cs @@ -15,40 +15,38 @@ namespace GalliumPlus.WebService.Controllers; [ApiController] public class CategoryController(ICategoryDao categoryDao, AuditService auditService) : GalliumController { - private CategoryDetails.Mapper mapper = new(); - [HttpGet] [RequiresPermissions(Permission.SeeProductsAndCategories)] public IActionResult Get() { - return this.Json(this.mapper.FromModel(categoryDao.Read())); + return this.Json(categoryDao.Read()); } [HttpGet("{id}", Name = "category")] [RequiresPermissions(Permission.SeeProductsAndCategories)] public IActionResult Get(int id) { - return this.Json(this.mapper.FromModel(categoryDao.Read(id))); + return this.Json(categoryDao.Read(id)); } [HttpPost] [RequiresPermissions(Permission.ManageCategories)] - public IActionResult Post(CategoryDetails newCategory) + public IActionResult Post(Category newCategory) { - Category category = categoryDao.Create(this.mapper.ToModel(newCategory)); + Category category = categoryDao.Create(newCategory); - auditService.AddEntry(entry => entry.Category(category).Added().By(this.Client!, this.User)); + auditService.AddEntry(entry => entry.Category(category).Added().By(this.RequireSession())); - return this.Created("category", category.Id, this.mapper.FromModel(category)); + return this.Created("category", category.Id, category); } [HttpPut("{id}")] [RequiresPermissions(Permission.ManageCategories)] - public IActionResult Put(int id, CategoryDetails updatedCategory) + public IActionResult Put(int id, Category modifiedCategory) { - Category category = categoryDao.Update(id, this.mapper.ToModel(updatedCategory)); + Category category = categoryDao.Update(id, modifiedCategory); - auditService.AddEntry(entry => entry.Category(category).Modified().By(this.Client!, this.User)); + auditService.AddEntry(entry => entry.Category(category).Modified().By(this.RequireSession())); return this.Ok(); } @@ -60,7 +58,7 @@ public IActionResult Delete(int id) Category category = categoryDao.Read(id); categoryDao.Delete(id); - auditService.AddEntry(entry => entry.Category(category).Deleted().By(this.Client!, this.User)); + auditService.AddEntry(entry => entry.Category(category).Deleted().By(this.RequireSession())); return this.Ok(); } diff --git a/WebService/Controllers/GalliumController.cs b/WebService/Controllers/GalliumController.cs index b674165..3b7107f 100644 --- a/WebService/Controllers/GalliumController.cs +++ b/WebService/Controllers/GalliumController.cs @@ -3,6 +3,7 @@ using GalliumPlus.Core.Security; using GalliumPlus.Core.Users; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Routing; namespace GalliumPlus.WebService.Controllers; @@ -39,16 +40,25 @@ public class GalliumController : ControllerBase /// public new User? User => this.FindContextItem("User"); + public User RequireUser() => this.User + ?? throw new MissingIdentificationException("Cette action requiert un utilisateur."); + /// /// La session de l'utilisateur qui a émis la requête actuelle. /// public Session? Session => this.FindContextItem("Session"); + public Session RequireSession() => this.Session + ?? throw new MissingIdentificationException("Cette action requiert une session active."); + /// /// L'application depuis laquelle la requête actuelle a été émise. /// public Client? Client => this.FindContextItem("Client"); + public Client RequireClient() => this.Client + ?? throw new MissingIdentificationException("Cette action requiert une session active."); + /// /// Crée une réponse avec un corps JSON. /// @@ -65,7 +75,7 @@ public IActionResult Json(object? value, int statusCode = StatusCodes.Status200O /// /// La route de la ressource crée. /// Les paramètres de la route. - /// Le ressource crée. + /// La ressource créée. [NonAction] public IActionResult Created(string route, object routeValues, object? value = null) { @@ -77,7 +87,7 @@ public IActionResult Created(string route, object routeValues, object? value = n /// /// La route de la ressource crée. /// Le paramètre id de la route. - /// Le ressource crée. + /// La ressource créée. [NonAction] public IActionResult Created(string route, int id, object? value = null) => this.Created(route, new { id }, value); @@ -87,7 +97,7 @@ public IActionResult Created(string route, int id, object? value = null) /// /// La route de la ressource crée. /// Le paramètre id de la route. - /// Le ressource crée. + /// La ressource créée. [NonAction] public IActionResult Created(string route, string id, object? value = null) => this.Created(route, new { id }, value); diff --git a/WebService/Dto/Legacy/CategoryDetails.cs b/WebService/Dto/Legacy/CategoryDetails.cs index fcde039..badf0b9 100644 --- a/WebService/Dto/Legacy/CategoryDetails.cs +++ b/WebService/Dto/Legacy/CategoryDetails.cs @@ -23,7 +23,7 @@ public override CategoryDetails FromModel(Category model) public override Category ToModel(CategoryDetails dto) { - return new Category(dto.Id, dto.Name); + return new Category(dto.Id, dto.Name, CategoryType.Category); } } } diff --git a/WebService/Middleware/ErrorHandling/ExceptionsFilter.cs b/WebService/Middleware/ErrorHandling/ExceptionsFilter.cs index a074e70..81fa7fd 100644 --- a/WebService/Middleware/ErrorHandling/ExceptionsFilter.cs +++ b/WebService/Middleware/ErrorHandling/ExceptionsFilter.cs @@ -17,15 +17,15 @@ public class ExceptionsFilter(ILoggerFactory loggerFactory) : IExceptionFilter, public void OnException(ExceptionContext context) { - if (context.Exception is PermissionDeniedException permissionDenied) + if (context.Exception is UnauthorisedAccessException unauthorisedAccess) { this.logger.LogDebug( - "PermissionDeniedException capturée à la sortie de {} {}", + "{} capturée à la sortie de {} {}", + unauthorisedAccess.GetType().Name, context.HttpContext.Request.Method, context.HttpContext.Request.Path ); - this.logger.LogDebug("Les permissions requises étaient {}", permissionDenied.Required); - + string messageAction = context.HttpContext.Request.Method switch { "GET" or "HEAD" => "d'accéder à cette ressource", @@ -33,7 +33,7 @@ public void OnException(ExceptionContext context) }; context.Result = new ErrorResult( - permissionDenied.ErrorCode, + unauthorisedAccess.ErrorCode, $"Vous n'avez pas la permission {messageAction}.", StatusCodes.Status403Forbidden ); diff --git a/WebService/Program.cs b/WebService/Program.cs index 1232970..f4ca90e 100644 --- a/WebService/Program.cs +++ b/WebService/Program.cs @@ -131,7 +131,7 @@ builder.Services.Configure(options => { - // accepte uniquement le format nombre JSON pour les entier et les floats + // accepte uniquement le format nombre JSON pour les entiers et les floats options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.Strict; // accepte les virgules en fin de liste / d'objet options.JsonSerializerOptions.AllowTrailingCommas = true; @@ -210,7 +210,7 @@ app.UseAuthorization(); app.MapControllers(); -ServerInfo.Current.SetVersion(1, 3, 1, "beta"); +ServerInfo.Current.SetVersion(1, 4, 0, "beta"); Console.WriteLine(ServerInfo.Current); #if !FAKE_DB