From 4a54e1fe6f88744f409ce18a1c41670c628ed844 Mon Sep 17 00:00:00 2001 From: maxime Date: Thu, 14 Mar 2024 18:01:19 +0100 Subject: [PATCH 01/10] add tactics tests --- API/Controllers/TacticsController.cs | 23 ++++--- AppContext/Entities/TacticStepEntity.cs | 2 + DbServices/DbTacticService.cs | 12 +++- StubContext/StubAppContext.cs | 4 +- UnitTests/TacticsControllerTest.cs | 86 +++++++++++++++++++++++-- UnitTests/UserControllerTest.cs | 8 ++- 6 files changed, 110 insertions(+), 25 deletions(-) diff --git a/API/Controllers/TacticsController.cs b/API/Controllers/TacticsController.cs index 9452f11..fadb2d2 100644 --- a/API/Controllers/TacticsController.cs +++ b/API/Controllers/TacticsController.cs @@ -16,7 +16,8 @@ public class TacticController(ITacticService service, IContextAccessor accessor) public record UpdateNameRequest( [StringLength(50, MinimumLength = 1)] [Name] - string Name); + string Name + ); [HttpPut("/tactics/{tacticId:int}/name")] [Authorize] @@ -81,12 +82,11 @@ public class TacticController(ITacticService service, IContextAccessor accessor) { var userId = accessor.CurrentUserId(HttpContext); - var courtType = req.CourtType switch + if (!Enum.TryParse(req.CourtType, true, out var courtType)) { - "PLAIN" => CourtType.Plain, - "HALF" => CourtType.Half, - _ => throw new ArgumentOutOfRangeException() //unreachable - }; + // unreachable if called by ASP + throw new ArgumentOutOfRangeException("for req.CourtType"); + } var id = await service.AddTactic(userId, req.Name, courtType); return new CreateNewResponse(id); @@ -118,10 +118,10 @@ public class TacticController(ITacticService service, IContextAccessor accessor) var json = await service.GetTacticStepContent(tacticId, stepId); return json != null ? Ok(JsonSerializer.Deserialize(json)) : NotFound(); } - + [HttpDelete("/tactics/{tacticId:int}/steps/{stepId:int}")] [Authorize] - public async Task RemoveStepContent(int tacticId, int stepId) + public async Task RemoveStep(int tacticId, int stepId) { var userId = accessor.CurrentUserId(HttpContext); @@ -140,15 +140,14 @@ public class TacticController(ITacticService service, IContextAccessor accessor) [HttpPut("/tactics/{tacticId:int}/steps/{stepId:int}")] [Authorize] public async Task SaveStepContent(int tacticId, int stepId, [FromBody] SaveStepContentRequest req) - { + { var userId = accessor.CurrentUserId(HttpContext); - if (!await service.HasAnyRights(userId, tacticId)) { return Unauthorized(); } - await service.SetTacticStepContent(tacticId, stepId, JsonSerializer.Serialize(req.Content)); - return Ok(); + var found = await service.SetTacticStepContent(tacticId, stepId, JsonSerializer.Serialize(req.Content)); + return found ? Ok() : NotFound(); } } \ No newline at end of file diff --git a/AppContext/Entities/TacticStepEntity.cs b/AppContext/Entities/TacticStepEntity.cs index c28b88b..a440b7b 100644 --- a/AppContext/Entities/TacticStepEntity.cs +++ b/AppContext/Entities/TacticStepEntity.cs @@ -1,3 +1,4 @@ +using System.ComponentModel.DataAnnotations; using Model; namespace AppContext.Entities; @@ -15,5 +16,6 @@ public class TacticStepEntity public required int? ParentId { get; set; } public TacticStepEntity? Parent { get; set; } + [MaxLength(2_000_000)] public required string JsonContent { get; set; } } \ No newline at end of file diff --git a/DbServices/DbTacticService.cs b/DbServices/DbTacticService.cs index 1fcb1b3..f56cc2b 100644 --- a/DbServices/DbTacticService.cs +++ b/DbServices/DbTacticService.cs @@ -1,4 +1,3 @@ -using System.Collections; using AppContext.Entities; using Converters; using Microsoft.EntityFrameworkCore; @@ -59,7 +58,8 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService return false; entity.Name = name; - return await context.SaveChangesAsync() > 0; + await context.SaveChangesAsync(); + return true; } public async Task SetTacticStepContent(int tacticId, int stepId, string json) @@ -70,7 +70,8 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService return false; entity.JsonContent = json; - return await context.SaveChangesAsync() > 0; + await context.SaveChangesAsync(); + return true; } public async Task GetTacticStepContent(int tacticId, int stepId) @@ -108,6 +109,11 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService public async Task AddTacticStep(int tacticId, int parentStepId, string initialJson) { + + var parentExists = context.TacticSteps.Any(t => t.TacticId == tacticId && t.Id == parentStepId); + if (!parentExists) + return null; + var tactic = await context.Tactics.FirstOrDefaultAsync(t => t.Id == tacticId); if (tactic == null) { diff --git a/StubContext/StubAppContext.cs b/StubContext/StubAppContext.cs index f740de9..989b46c 100644 --- a/StubContext/StubAppContext.cs +++ b/StubContext/StubAppContext.cs @@ -39,7 +39,7 @@ public class StubAppContext(DbContextOptions options) : AppContext(o .HasKey("TeamId", "UserId"); builder.Entity() - .HasData(new TacticEntity() + .HasData(new TacticEntity { Id = 1, Name = "New tactic", @@ -52,7 +52,7 @@ public class StubAppContext(DbContextOptions options) : AppContext(o .HasData(new TacticStepEntity { Id = 1, - JsonContent = "{}", + JsonContent = "{\"components\": []}", TacticId = 1, ParentId = null }); diff --git a/UnitTests/TacticsControllerTest.cs b/UnitTests/TacticsControllerTest.cs index 1886b56..894fa60 100644 --- a/UnitTests/TacticsControllerTest.cs +++ b/UnitTests/TacticsControllerTest.cs @@ -1,8 +1,8 @@ using API.Controllers; using API.DTO; -using AppContext.Entities; using DbServices; using FluentAssertions; +using Microsoft.AspNetCore.Mvc; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Model; @@ -39,7 +39,7 @@ public class TacticsControllerTest var tactic = await context.Tactics.FindAsync(1); tactic.Name.Should().BeEquivalentTo("Stade de France"); - + result = await controller.UpdateName(-1, new("Stade de France")); result.Should().BeEquivalentTo(controller.Unauthorized()); } @@ -49,18 +49,92 @@ public class TacticsControllerTest { var (controller, context) = GetController(1); var result = await controller.GetTacticInfo(1); - result.Should().BeEquivalentTo(controller.Ok(new Tactic(1, "New tactic", 1, CourtType.Plain, new DateTime(2024, 5, 31)).ToDto())); + result.Should() + .BeEquivalentTo(controller.Ok(new Tactic(1, "New tactic", 1, CourtType.Plain, new DateTime(2024, 5, 31)) + .ToDto())); result = await controller.GetTacticInfo(100); result.Should().BeEquivalentTo(controller.Unauthorized()); } [Fact] - public async void GetTacticStepsRoot() + public async void GetTacticStepsRootTest() { var (controller, context) = GetController(1); var result = await controller.GetTacticStepsRoot(1); - result.Should().BeEquivalentTo(controller.Ok(new TacticController.GetTacticStepsTreeResponse(new TacticStep(1, null, [], "{}").ToDto()))); + result.Should() + .BeEquivalentTo(controller.Ok( + new TacticController.GetTacticStepsTreeResponse(new TacticStep(1, null, [], "{}").ToDto()))); + } + + [Fact] + public async void CreateNewTest() + { + var (controller, context) = GetController(1); + var result = await controller.CreateNew(new("Test Tactic", "pLaIn")); + result.Should().BeEquivalentTo(new TacticController.CreateNewResponse(2)); + var tactic = await context.Tactics.FirstOrDefaultAsync(e => e.Id == 2); + tactic.Should().NotBeNull(); + tactic!.Name.Should().BeEquivalentTo("Test Tactic"); + tactic.OwnerId.Should().Be(1); + tactic.Type.Should().Be(CourtType.Plain); + } + + + [Fact] + public async void AddStepTest() + { + var (controller, context) = GetController(1); + var result = await controller.AddStep(1, new(1, "{components: []}")); + result.Should().BeEquivalentTo(controller.Ok(new TacticController.AddStepResponse(2))); + var tactic = await context.TacticSteps.FirstOrDefaultAsync(e => e.Id == 2); + tactic.Should().NotBeNull(); + tactic!.Id.Should().Be(2); + tactic.ParentId.Should().Be(1); + tactic.TacticId.Should().Be(1); + + // if tactic does not exists + result = await controller.AddStep(100, new(1, "hello")); + result.Should().BeEquivalentTo(controller.NotFound()); + + // if step does not exists + result = await controller.AddStep(1, new(10, "hello")); + result.Should().BeEquivalentTo(controller.NotFound()); + } + + [Fact] + public async void RemoveStepTest() + { + var (controller, context) = GetController(1); + var result = await controller.RemoveStep(1, 1); + result.Should().BeEquivalentTo(controller.Ok()); + var tactic = await context.TacticSteps.FirstOrDefaultAsync(e => e.Id == 1); + tactic.Should().BeNull(); + + // if tactic does not exists + result = await controller.RemoveStep(100, 1); + result.Should().BeEquivalentTo(controller.Unauthorized()); + + // if step does not exists + result = await controller.RemoveStep(1, 10); + result.Should().BeEquivalentTo(controller.NotFound()); + } + + [Fact] + public async void GetStepContentTest() + { + var (controller, context) = GetController(1); + (await controller.GetStepContent(1, 1)).Should().BeAssignableTo(controller.Ok("").GetType()); + (await controller.GetStepContent(10, 1)).Should().BeEquivalentTo(controller.Unauthorized()); + (await controller.GetStepContent(1, 10)).Should().BeEquivalentTo(controller.NotFound()); + } + + [Fact] + public async void SaveStepContentTest() + { + var (controller, context) = GetController(1); + (await controller.SaveStepContent(1, 1, new(new object()))).Should().BeEquivalentTo(controller.Ok()); + (await controller.SaveStepContent(10, 1, new (new object()))).Should().BeEquivalentTo(controller.Unauthorized()); + (await controller.SaveStepContent(1, 10, new (new object()))).Should().BeEquivalentTo(controller.NotFound()); } - } \ No newline at end of file diff --git a/UnitTests/UserControllerTest.cs b/UnitTests/UserControllerTest.cs index cb98c44..cac0a09 100644 --- a/UnitTests/UserControllerTest.cs +++ b/UnitTests/UserControllerTest.cs @@ -1,4 +1,5 @@ using API.Controllers; +using API.DTO; using DbServices; using FluentAssertions; using Microsoft.Data.Sqlite; @@ -26,7 +27,7 @@ public class UsersControllerTest new DbTacticService(context), new ManualContextAccessor(userId) ); - + return controller; } @@ -44,6 +45,9 @@ public class UsersControllerTest { var controller = GetUserController(1); var result = await controller.GetUserData(); - result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse([], [])); + result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse( + [], + [new TacticDto(1, "New tactic", 1, "PLAIN", 1717106400000L)] + )); } } \ No newline at end of file From 9f2e9c09960d5080a15a6d354b1d6427fe5b8229 Mon Sep 17 00:00:00 2001 From: vidufour1 Date: Sat, 16 Mar 2024 17:34:37 +0100 Subject: [PATCH 02/10] tactics and users ef console tests --- API/API.csproj.user | 6 ++ AppContext/AppContext.cs | 24 +++----- EFConsole/EFConsole.csproj | 21 +++++++ EFConsole/Program.cs | 54 ++++++++++++++++ EFConsole/TacticsConsole.cs | 89 ++++++++++++++++++++++++++ EFConsole/UsersConsole.cs | 120 ++++++++++++++++++++++++++++++++++++ WebAPI.sln | 6 ++ 7 files changed, 306 insertions(+), 14 deletions(-) create mode 100644 API/API.csproj.user create mode 100644 EFConsole/EFConsole.csproj create mode 100644 EFConsole/Program.cs create mode 100644 EFConsole/TacticsConsole.cs create mode 100644 EFConsole/UsersConsole.cs diff --git a/API/API.csproj.user b/API/API.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/API/API.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/AppContext/AppContext.cs b/AppContext/AppContext.cs index f875684..5a2eb8f 100644 --- a/AppContext/AppContext.cs +++ b/AppContext/AppContext.cs @@ -26,23 +26,19 @@ public class AppContext : DbContext protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - base.OnConfiguring(optionsBuilder); - if (optionsBuilder.IsConfigured) + if (!optionsBuilder.IsConfigured) { - return; - } - - var pgsqliteDsn = Environment.GetEnvironmentVariable("PGSQL_DSN"); + var pgsqliteDsn = Environment.GetEnvironmentVariable("PGSQL_DSN"); - if (pgsqliteDsn != null) - { - optionsBuilder.UseNpgsql(pgsqliteDsn); + if (pgsqliteDsn != null) + { + optionsBuilder.UseNpgsql(pgsqliteDsn); + } + else + { + optionsBuilder.UseSqlite("Data Source=database.db"); + } } - else - { - optionsBuilder.UseSqlite("Data Source=database.db"); - } - } protected override void OnModelCreating(ModelBuilder builder) diff --git a/EFConsole/EFConsole.csproj b/EFConsole/EFConsole.csproj new file mode 100644 index 0000000..1d9f88b --- /dev/null +++ b/EFConsole/EFConsole.csproj @@ -0,0 +1,21 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/EFConsole/Program.cs b/EFConsole/Program.cs new file mode 100644 index 0000000..410ec39 --- /dev/null +++ b/EFConsole/Program.cs @@ -0,0 +1,54 @@ +using StubContext; + +namespace EFConsole +{ + class Program + { + static void Main(string[] args) + { + Console.OutputEncoding = System.Text.Encoding.UTF8; + + try + { + using (AppContext.AppContext db = new StubAppContext()) + { + TestUserMethods(db); + TestTacticMethods(db); + db.SaveChanges(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Une erreur s'est produite : {ex.Message}"); + + if (ex.InnerException != null) + { + Console.WriteLine($"Détails de l'exception interne : {ex.InnerException.Message}"); + } + } + } + + static void TestUserMethods(AppContext.AppContext db) + { + UsersConsole.TestAddUser(db); + UsersConsole.TestGetAllUsers(db); + UsersConsole.TestFindUserByMail(db, "maxime@mail.com"); + UsersConsole.TestUpdateUser(db); + UsersConsole.TestDeleteUser(db); + UsersConsole.TestSearchUsersByName(db, "Pierre"); + UsersConsole.TestGetTacticsOfAllUsers(db); + UsersConsole.TestGetTacticsOfOneUser(db, 1); + } + + static void TestTacticMethods(AppContext.AppContext db) + { + TacticsConsole.TestAddTactic(db); + TacticsConsole.TestGetAllTactics(db); + TacticsConsole.TestFindTacticById(db, 1); + TacticsConsole.TestUpdateTactic(db, 1, "Nouveau nom"); + TacticsConsole.TestDeleteTactic(db, 1); + TacticsConsole.TestGetTacticsByOwner(db, 1); + } + + } +} \ No newline at end of file diff --git a/EFConsole/TacticsConsole.cs b/EFConsole/TacticsConsole.cs new file mode 100644 index 0000000..dd29d2e --- /dev/null +++ b/EFConsole/TacticsConsole.cs @@ -0,0 +1,89 @@ +using System; +using System.Linq; +using AppContext.Entities; +using Model; + +namespace EFConsole +{ + class TacticsConsole + { + internal static void TestAddTactic(AppContext.AppContext db) + { + var newTactic = new TacticEntity + { + Name = "Nouvelle tactique", + CreationDate = DateTime.Now, + OwnerId = 1, + Type = CourtType.Plain + }; + + db.Tactics.Add(newTactic); + db.SaveChanges(); + + Console.WriteLine("Tactique ajoutée avec succès !"); + } + + internal static void TestGetAllTactics(AppContext.AppContext db) + { + var tactics = db.Tactics.ToList(); + Console.WriteLine("Liste des tactiques :"); + foreach (var tactic in tactics) + { + Console.WriteLine($"ID : {tactic.Id}, Nom : {tactic.Name}, Date de création : {tactic.CreationDate}"); + } + } + + internal static void TestFindTacticById(AppContext.AppContext db, int tacticId) + { + var tactic = db.Tactics.FirstOrDefault(t => t.Id == tacticId); + if (tactic != null) + { + Console.WriteLine($"Tactique trouvée avec l'ID {tacticId}: Nom : {tactic.Name}, Date de création : {tactic.CreationDate}"); + } + else + { + Console.WriteLine($"Aucune tactique trouvée avec l'ID {tacticId}"); + } + } + + internal static void TestUpdateTactic(AppContext.AppContext db, int tacticId, string newName) + { + var tacticToUpdate = db.Tactics.FirstOrDefault(t => t.Id == tacticId); + if (tacticToUpdate != null) + { + tacticToUpdate.Name = newName; + db.SaveChanges(); + Console.WriteLine($"Tactique mise à jour avec succès !"); + } + else + { + Console.WriteLine($"Aucune tactique trouvée avec l'ID {tacticId}"); + } + } + + internal static void TestDeleteTactic(AppContext.AppContext db, int tacticId) + { + var tacticToDelete = db.Tactics.FirstOrDefault(t => t.Id == tacticId); + if (tacticToDelete != null) + { + db.Tactics.Remove(tacticToDelete); + db.SaveChanges(); + Console.WriteLine($"Tactique supprimée avec succès !"); + } + else + { + Console.WriteLine($"Aucune tactique trouvée avec l'ID {tacticId}"); + } + } + + internal static void TestGetTacticsByOwner(AppContext.AppContext db, int ownerId) + { + var tactics = db.Tactics.Where(t => t.OwnerId == ownerId).ToList(); + Console.WriteLine($"Tactiques de l'utilisateur avec l'ID {ownerId} :"); + foreach (var tactic in tactics) + { + Console.WriteLine($"ID : {tactic.Id}, Nom : {tactic.Name}, Date de création : {tactic.CreationDate}"); + } + } + } +} diff --git a/EFConsole/UsersConsole.cs b/EFConsole/UsersConsole.cs new file mode 100644 index 0000000..d96aaa6 --- /dev/null +++ b/EFConsole/UsersConsole.cs @@ -0,0 +1,120 @@ +using Microsoft.EntityFrameworkCore; + +namespace EFConsole; + + +class UsersConsole +{ + internal static void TestAddUser(AppContext.AppContext db) + { + var newUser = new AppContext.Entities.UserEntity + { + Name = "Pierre", + Email = "pierre@mail.com", + Password = "123456", + ProfilePicture = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png", + IsAdmin = false + }; + + db.Users.Add(newUser); + db.SaveChanges(); + + Console.WriteLine("Utilisateur ajouté avec succès !"); + } + + internal static void TestGetAllUsers(AppContext.AppContext db) + { + var users = db.Users.ToList(); + Console.WriteLine("Liste des utilisateurs :"); + foreach (var user in users) + { + Console.WriteLine($"ID : {user.Id}, Nom : {user.Name}, Email : {user.Email}"); + } + } + + internal static void TestFindUserByMail(AppContext.AppContext db, string userEmail) + { + var userByEmail = db.Users.FirstOrDefault(u => u.Email == userEmail); + if (userByEmail != null) + { + Console.WriteLine($"Utilisateur trouvé par email : {userByEmail.Name}"); + } + else + { + Console.WriteLine($"Aucun utilisateur trouvé avec l'email : {userEmail}"); + } + } + + internal static void TestUpdateUser(AppContext.AppContext db) + { + var userToUpdate = db.Users.FirstOrDefault(u => u.Name == "Pierre"); + if (userToUpdate != null) + { + userToUpdate.Name = "Paul"; + db.SaveChanges(); + Console.WriteLine("Utilisateur mis à jour avec succès !"); + } + else + { + Console.WriteLine("Utilisateur non trouvé pour la mise à jour."); + } + } + + internal static void TestDeleteUser(AppContext.AppContext db) + { + var userToDelete = db.Users.FirstOrDefault(u => u.Name == "Paul"); + if (userToDelete != null) + { + db.Users.Remove(userToDelete); + db.SaveChanges(); + Console.WriteLine("Utilisateur supprimé avec succès !"); + } + else + { + Console.WriteLine("Utilisateur non trouvé pour la suppression."); + } + } + + internal static void TestSearchUsersByName(AppContext.AppContext db, string userName) + { + var usersByName = db.Users.Where(u => u.Name == userName).ToList(); + Console.WriteLine($"Utilisateurs avec le nom '{userName}' :"); + foreach (var user in usersByName) + { + Console.WriteLine($"ID : {user.Id}, Nom : {user.Name}, Email : {user.Email}"); + } + } + + internal static void TestGetTacticsOfAllUsers(AppContext.AppContext db) + { + Console.WriteLine("Récupération des tactiques de tous les utilisateurs :"); + + var users = db.Users.Include(u => u.Tactics).ToList(); + foreach (var user in users) + { + Console.WriteLine($"Tactiques de l'utilisateur {user.Name}:"); + foreach (var tactic in user.Tactics) + { + Console.WriteLine($"\tID : {tactic.Id}, Nom : {tactic.Name}, Date de création : {tactic.CreationDate}"); + } + } + } + + internal static void TestGetTacticsOfOneUser(AppContext.AppContext db, int userId) + { + var user = db.Users.Include(u => u.Tactics).FirstOrDefault(u => u.Id == userId); + if (user != null) + { + Console.WriteLine($"Récupération des tactiques de l'utilisateur {user.Name}:"); + foreach (var tactic in user.Tactics) + { + Console.WriteLine($"\tID : {tactic.Id}, Nom : {tactic.Name}, Date de création : {tactic.CreationDate}"); + } + } + else + { + Console.WriteLine($"Aucun utilisateur trouvé avec l'ID : {userId}"); + } + } + +} diff --git a/WebAPI.sln b/WebAPI.sln index ba34e6d..6735f5f 100644 --- a/WebAPI.sln +++ b/WebAPI.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Converters", "Converters\Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{82A100BE-5610-4741-8F23-1CD653E8EFCD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFConsole", "EFConsole\EFConsole.csproj", "{DC9ACDB3-83BC-4DF2-84C7-070361648975}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -62,5 +64,9 @@ Global {82A100BE-5610-4741-8F23-1CD653E8EFCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {82A100BE-5610-4741-8F23-1CD653E8EFCD}.Release|Any CPU.ActiveCfg = Release|Any CPU {82A100BE-5610-4741-8F23-1CD653E8EFCD}.Release|Any CPU.Build.0 = Release|Any CPU + {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From a93dcb99752f9dd6eff2eb404e42f83cad18feb2 Mon Sep 17 00:00:00 2001 From: vidufour1 Date: Sat, 16 Mar 2024 18:13:19 +0100 Subject: [PATCH 03/10] tacticsSteps, teams and members ef console tests --- APIConsole/APIConsole.csproj | 10 ++++ APIConsole/Program.cs | 3 ++ EFConsole/MembersConsole.cs | 88 +++++++++++++++++++++++++++++++++ EFConsole/Program.cs | 35 ++++++++++++- EFConsole/TacticsStepConsole.cs | 75 ++++++++++++++++++++++++++++ EFConsole/TeamsConsole.cs | 85 +++++++++++++++++++++++++++++++ WebAPI.sln | 6 +++ 7 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 APIConsole/APIConsole.csproj create mode 100644 APIConsole/Program.cs create mode 100644 EFConsole/MembersConsole.cs create mode 100644 EFConsole/TacticsStepConsole.cs create mode 100644 EFConsole/TeamsConsole.cs diff --git a/APIConsole/APIConsole.csproj b/APIConsole/APIConsole.csproj new file mode 100644 index 0000000..2f4fc77 --- /dev/null +++ b/APIConsole/APIConsole.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/APIConsole/Program.cs b/APIConsole/Program.cs new file mode 100644 index 0000000..e5dff12 --- /dev/null +++ b/APIConsole/Program.cs @@ -0,0 +1,3 @@ +// See https://aka.ms/new-console-template for more information + +Console.WriteLine("Hello, World!"); \ No newline at end of file diff --git a/EFConsole/MembersConsole.cs b/EFConsole/MembersConsole.cs new file mode 100644 index 0000000..5b70248 --- /dev/null +++ b/EFConsole/MembersConsole.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using AppContext.Entities; +using Model; + +namespace EFConsole +{ + public class MembersConsole + { + public static void TestAddMember(AppContext.AppContext db) + { + var newMember = new MemberEntity + { + TeamId = 1, + UserId = 1, + Role = MemberRole.Player + }; + + db.Members.Add(newMember); + db.SaveChanges(); + + Console.WriteLine("Membre ajouté avec succès !"); + } + + public static void TestGetAllMembers(AppContext.AppContext db) + { + var members = db.Members.ToList(); + Console.WriteLine("Liste des membres :"); + foreach (var member in members) + { + Console.WriteLine($"ID Équipe : {member.TeamId}, ID Utilisateur : {member.UserId}, Rôle : {member.Role}"); + } + } + + public static void TestGetMembersByTeamId(AppContext.AppContext db, int teamId) + { + var members = db.Members.Where(m => m.TeamId == teamId).ToList(); + Console.WriteLine($"Membres de l'équipe avec ID {teamId} :"); + foreach (var member in members) + { + Console.WriteLine($"ID Équipe : {member.TeamId}, ID Utilisateur : {member.UserId}, Rôle : {member.Role}"); + } + } + + public static void TestGetMembersByUserId(AppContext.AppContext db, int userId) + { + var members = db.Members.Where(m => m.UserId == userId).ToList(); + Console.WriteLine($"Membres associés à l'utilisateur avec ID {userId} :"); + foreach (var member in members) + { + Console.WriteLine($"ID Équipe : {member.TeamId}, ID Utilisateur : {member.UserId}, Rôle : {member.Role}"); + } + } + + public static void TestUpdateMemberRole(AppContext.AppContext db, int teamId, int memberId, MemberRole newRole) + { + var memberToUpdate = db.Members.FirstOrDefault(m => m.TeamId == teamId && m.UserId == memberId); // Trouver le membre dans l'équipe spécifiée + if (memberToUpdate != null) + { + memberToUpdate.Role = newRole; + db.SaveChanges(); + Console.WriteLine("Rôle du membre mis à jour avec succès !"); + } + else + { + Console.WriteLine($"Aucun membre trouvé dans l'équipe avec l'ID {teamId} et l'ID utilisateur {memberId}."); + } + } + + + public static void TestRemoveMember(AppContext.AppContext db, int teamId, int memberId) + { + var memberToDelete = db.Members.FirstOrDefault(m => m.TeamId == teamId && m.UserId == memberId); // Trouver le membre dans l'équipe spécifiée + if (memberToDelete != null) + { + db.Members.Remove(memberToDelete); // Supprimer le membre + db.SaveChanges(); + Console.WriteLine("Membre supprimé avec succès !"); + } + else + { + Console.WriteLine($"Aucun membre trouvé dans l'équipe avec l'ID {teamId} et l'ID utilisateur {memberId} pour la suppression."); + } + } + + + } +} diff --git a/EFConsole/Program.cs b/EFConsole/Program.cs index 410ec39..2c101f9 100644 --- a/EFConsole/Program.cs +++ b/EFConsole/Program.cs @@ -1,4 +1,5 @@ -using StubContext; +using Model; +using StubContext; namespace EFConsole { @@ -14,7 +15,9 @@ namespace EFConsole { TestUserMethods(db); TestTacticMethods(db); - db.SaveChanges(); + TestTeamMethods(db); + TestMemberMethods(db); + TestTacticsStepMethods(db); } } catch (Exception ex) @@ -49,6 +52,34 @@ namespace EFConsole TacticsConsole.TestDeleteTactic(db, 1); TacticsConsole.TestGetTacticsByOwner(db, 1); } + + static void TestTeamMethods(AppContext.AppContext db) + { + TeamsConsole.TestAddTeam(db); + TeamsConsole.TestGetAllTeams(db); + TeamsConsole.TestGetTeamMembers(db, 1); + TeamsConsole.TestUpdateTeam(db, 1, "Nouveau nom", "Nouvelle image", "#FF0000", "#00FF00"); + TeamsConsole.TestDeleteTeam(db, 1); + } + + static void TestMemberMethods(AppContext.AppContext db) + { + MembersConsole.TestAddMember(db); + MembersConsole.TestGetAllMembers(db); + MembersConsole.TestGetMembersByTeamId(db, 1); + MembersConsole.TestGetMembersByUserId(db, 1); + MembersConsole.TestUpdateMemberRole(db, 1, 1, MemberRole.Coach); + MembersConsole.TestRemoveMember(db, 1, 1); + } + + static void TestTacticsStepMethods(AppContext.AppContext db) + { + TacticsStepConsole.TestAddTacticStep(db); + TacticsStepConsole.TestGetAllTacticSteps(db); + TacticsStepConsole.TestGetTacticStepsByTacticId(db, 1); + TacticsStepConsole.TestUpdateTacticStepContent(db, 1, "test content"); + TacticsStepConsole.TestDeleteTacticStep(db, 1); + } } } \ No newline at end of file diff --git a/EFConsole/TacticsStepConsole.cs b/EFConsole/TacticsStepConsole.cs new file mode 100644 index 0000000..3bca4fa --- /dev/null +++ b/EFConsole/TacticsStepConsole.cs @@ -0,0 +1,75 @@ +using System; +using System.Linq; +using AppContext.Entities; +using Model; + +namespace EFConsole +{ + public class TacticsStepConsole + { + public static void TestAddTacticStep(AppContext.AppContext db) + { + var newTacticStep = new TacticStepEntity + { + ParentId = 1, + TacticId = 1, + JsonContent = "{}" + }; + + db.TacticSteps.Add(newTacticStep); + db.SaveChanges(); + + Console.WriteLine("Étape de tactique ajoutée avec succès !"); + } + + public static void TestGetAllTacticSteps(AppContext.AppContext db) + { + var tacticSteps = db.TacticSteps.ToList(); + Console.WriteLine("Liste des étapes de tactique :"); + foreach (var tacticStep in tacticSteps) + { + Console.WriteLine($"ID : {tacticStep.Id}, ID Tactique : {tacticStep.TacticId}, Contenu JSON : {tacticStep.JsonContent}"); + } + } + + public static void TestGetTacticStepsByTacticId(AppContext.AppContext db, int tacticId) + { + var tacticSteps = db.TacticSteps.Where(ts => ts.TacticId == tacticId).ToList(); + Console.WriteLine($"Étapes de tactique pour la tactique avec l'ID {tacticId} :"); + foreach (var tacticStep in tacticSteps) + { + Console.WriteLine($"ID : {tacticStep.Id}, ID Tactique : {tacticStep.TacticId}, Contenu JSON : {tacticStep.JsonContent}"); + } + } + + public static void TestUpdateTacticStepContent(AppContext.AppContext db, int tacticStepId, string newContent) + { + var tacticStepToUpdate = db.TacticSteps.FirstOrDefault(ts => ts.Id == tacticStepId); + if (tacticStepToUpdate != null) + { + tacticStepToUpdate.JsonContent = newContent; + db.SaveChanges(); + Console.WriteLine("Contenu de l'étape de tactique mis à jour avec succès !"); + } + else + { + Console.WriteLine($"Aucune étape de tactique trouvée avec l'ID {tacticStepId} pour la mise à jour du contenu."); + } + } + + public static void TestDeleteTacticStep(AppContext.AppContext db, int tacticStepId) + { + var tacticStepToDelete = db.TacticSteps.FirstOrDefault(ts => ts.Id == tacticStepId); + if (tacticStepToDelete != null) + { + db.TacticSteps.Remove(tacticStepToDelete); + db.SaveChanges(); + Console.WriteLine("Étape de tactique supprimée avec succès !"); + } + else + { + Console.WriteLine($"Aucune étape de tactique trouvée avec l'ID {tacticStepId} pour la suppression."); + } + } + } +} diff --git a/EFConsole/TeamsConsole.cs b/EFConsole/TeamsConsole.cs new file mode 100644 index 0000000..017739a --- /dev/null +++ b/EFConsole/TeamsConsole.cs @@ -0,0 +1,85 @@ +using System; +using System.Linq; +using AppContext.Entities; + +namespace EFConsole +{ + class TeamsConsole + { + internal static void TestAddTeam(AppContext.AppContext db) + { + var newTeam = new TeamEntity + { + Name = "Nouvelle équipe", + Picture = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png", + MainColor = "#0000FF", + SecondColor = "#FFFFFF" + }; + + db.Teams.Add(newTeam); + db.SaveChanges(); + + Console.WriteLine("Équipe ajoutée avec succès !"); + } + + internal static void TestGetAllTeams(AppContext.AppContext db) + { + var teams = db.Teams.ToList(); + Console.WriteLine("Liste des équipes :"); + foreach (var team in teams) + { + Console.WriteLine($"ID : {team.Id}, Nom : {team.Name}, Image : {team.Picture}, Couleur principale : {team.MainColor}, Couleur secondaire : {team.SecondColor}"); + } + } + + internal static void TestGetTeamMembers(AppContext.AppContext db, int teamId) + { + var team = db.Teams.FirstOrDefault(t => t.Id == teamId); + if (team != null) + { + Console.WriteLine($"Membres de l'équipe '{team.Name}' :"); + foreach (var member in team.Members) + { + Console.WriteLine($"ID : {member.UserId}, Nom : {member.User?.Name}, Rôle : {member.Role}"); + } + } + else + { + Console.WriteLine($"Aucune équipe trouvée avec l'ID : {teamId}"); + } + } + + internal static void TestUpdateTeam(AppContext.AppContext db, int teamId, string newName, string newPicture, string newMainColor, string newSecondColor) + { + var teamToUpdate = db.Teams.FirstOrDefault(t => t.Id == teamId); + if (teamToUpdate != null) + { + teamToUpdate.Name = newName; + teamToUpdate.Picture = newPicture; + teamToUpdate.MainColor = newMainColor; + teamToUpdate.SecondColor = newSecondColor; + db.SaveChanges(); + Console.WriteLine("Équipe mise à jour avec succès !"); + } + else + { + Console.WriteLine($"Aucune équipe trouvée avec l'ID : {teamId}"); + } + } + + internal static void TestDeleteTeam(AppContext.AppContext db, int teamId) + { + var teamToDelete = db.Teams.FirstOrDefault(t => t.Id == teamId); + if (teamToDelete != null) + { + db.Teams.Remove(teamToDelete); + db.SaveChanges(); + Console.WriteLine("Équipe supprimée avec succès !"); + } + else + { + Console.WriteLine($"Aucune équipe trouvée avec l'ID : {teamId}"); + } + } + } +} diff --git a/WebAPI.sln b/WebAPI.sln index 6735f5f..a6888fe 100644 --- a/WebAPI.sln +++ b/WebAPI.sln @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\Unit EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFConsole", "EFConsole\EFConsole.csproj", "{DC9ACDB3-83BC-4DF2-84C7-070361648975}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "APIConsole", "APIConsole\APIConsole.csproj", "{B01BD72E-15D3-4DC6-8DAC-2270A01129A9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -68,5 +70,9 @@ Global {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Debug|Any CPU.Build.0 = Debug|Any CPU {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC9ACDB3-83BC-4DF2-84C7-070361648975}.Release|Any CPU.Build.0 = Release|Any CPU + {B01BD72E-15D3-4DC6-8DAC-2270A01129A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B01BD72E-15D3-4DC6-8DAC-2270A01129A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B01BD72E-15D3-4DC6-8DAC-2270A01129A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B01BD72E-15D3-4DC6-8DAC-2270A01129A9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal From ac5fe15de314786b120db3edf68de3b1f692175e Mon Sep 17 00:00:00 2001 From: maxime Date: Sat, 16 Mar 2024 17:22:33 +0100 Subject: [PATCH 04/10] add remaining tests, fix some bugs --- API/Controllers/Admin/TeamsAdminController.cs | 12 +- API/Controllers/Admin/UsersAdminController.cs | 14 +-- API/Controllers/TeamsController.cs | 74 ++++++++++-- DbServices/DbTacticService.cs | 1 + DbServices/DbTeamService.cs | 50 ++++---- DbServices/DbUserService.cs | 25 ++-- Services/Failures/Failure.cs | 5 +- Services/ITeamService.cs | 31 ++++- Services/UserService.cs | 3 +- StubContext/StubAppContext.cs | 46 +++++++- UnitTests/AdminTeamsControllerTest.cs | 110 ++++++++++++++++++ UnitTests/AdminUserControllerTest.cs | 4 + UnitTests/AuthControllerTests.cs | 56 +++++++++ UnitTests/TacticsControllerTest.cs | 1 - UnitTests/TeamsControllerTest.cs | 98 ++++++++++++++++ UnitTests/UserControllerTest.cs | 8 +- ci/.drone.yml | 9 ++ 17 files changed, 475 insertions(+), 72 deletions(-) create mode 100644 UnitTests/AdminTeamsControllerTest.cs create mode 100644 UnitTests/AuthControllerTests.cs create mode 100644 UnitTests/TeamsControllerTest.cs diff --git a/API/Controllers/Admin/TeamsAdminController.cs b/API/Controllers/Admin/TeamsAdminController.cs index d255687..9cdff0d 100644 --- a/API/Controllers/Admin/TeamsAdminController.cs +++ b/API/Controllers/Admin/TeamsAdminController.cs @@ -24,16 +24,14 @@ public class TeamsAdminController(ITeamService service) : ControllerBase // } [HttpGet("/admin/teams")] - public async Task> ListTeams( + public Task> ListTeams( [Range(0, int.MaxValue, ErrorMessage = "Only positive number allowed")] int start, [Range(0, int.MaxValue, ErrorMessage = "Only positive number allowed")] int n ) { - var result = await service.ListTeams(); - - return result.Skip(start).Take(n); + return service.ListTeams(start, n); } public record AddTeamRequest(string Name, string Picture, string FirstColor, string SecondColor); @@ -46,12 +44,12 @@ public class TeamsAdminController(ITeamService service) : ControllerBase return Ok(team); } - public record UpdateTeamRequest(int Id, string Name, string Picture, string MainColor, string SecondaryColor); + public record UpdateTeamRequest(string Name, string Picture, string MainColor, string SecondaryColor); [HttpPut("/admin/teams/{teamId:int}")] - public async Task UpdateTeam([FromBody] UpdateTeamRequest req) + public async Task UpdateTeam(int teamId, [FromBody] UpdateTeamRequest req) { - await service.UpdateTeam(new Team(req.Id, req.Name, req.Picture, req.MainColor, req.SecondaryColor)); + await service.UpdateTeam(new Team(teamId, req.Name, req.Picture, req.MainColor, req.SecondaryColor)); return Ok(); } diff --git a/API/Controllers/Admin/UsersAdminController.cs b/API/Controllers/Admin/UsersAdminController.cs index 83bca2f..deadca9 100644 --- a/API/Controllers/Admin/UsersAdminController.cs +++ b/API/Controllers/Admin/UsersAdminController.cs @@ -8,7 +8,6 @@ namespace API.Controllers.Admin; [ApiController] public class UsersAdminController(IUserService service) : ControllerBase { - public record CountUsersResponse(int Value); @@ -43,11 +42,8 @@ public class UsersAdminController(IUserService service) : ControllerBase string? search ) { - var result = search != null - ? await service.ListUsers(search) - : await service.ListUsers(); - - return result.Skip(start).Take(n); + var result = await service.ListUsers(start, n, search); + return result; } [HttpGet("/admin/users/{id:int}")] @@ -77,7 +73,8 @@ public class UsersAdminController(IUserService service) : ControllerBase [HttpPost("/admin/users")] public Task AddUser([FromBody] AddUserRequest req) { - return service.CreateUser(req.Username, req.Email, req.Password, UsersController.DefaultProfilePicture, req.IsAdmin); + return service.CreateUser(req.Username, req.Email, req.Password, UsersController.DefaultProfilePicture, + req.IsAdmin); } public record RemoveUsersRequest(int[] Identifiers); @@ -106,7 +103,8 @@ public class UsersAdminController(IUserService service) : ControllerBase { try { - await service.UpdateUser(new User(id, req.Username, req.Email, UsersController.DefaultProfilePicture, req.IsAdmin)); + await service.UpdateUser(new User(id, req.Username, req.Email, UsersController.DefaultProfilePicture, + req.IsAdmin)); return Ok(); } catch (ServiceException e) diff --git a/API/Controllers/TeamsController.cs b/API/Controllers/TeamsController.cs index aecfc67..c7a3ab3 100644 --- a/API/Controllers/TeamsController.cs +++ b/API/Controllers/TeamsController.cs @@ -29,9 +29,21 @@ public class TeamsController(ITeamService service, IContextAccessor accessor) : } [HttpGet("/teams/{teamId:int}/members")] - public IActionResult GetMembersOf(int teamId) + public async Task GetMembersOf(int teamId) { - return Ok(service.GetMembersOf(teamId)); + var accessibility = + await service.EnsureAccessibility(accessor.CurrentUserId(HttpContext), teamId, MemberRole.Player); + + switch (accessibility) + { + case ITeamService.TeamAccessibility.Authorized: + return Ok(await service.GetMembersOf(teamId)); + case ITeamService.TeamAccessibility.NotFound: + case ITeamService.TeamAccessibility.Unauthorized: + return NotFound(); + default: //unreachable + return Problem(); + } } public record AddMemberRequest( @@ -46,9 +58,27 @@ public class TeamsController(ITeamService service, IContextAccessor accessor) : { throw new Exception($"Unable to convert string input '{req.Role}' to a role enum variant."); } + + var accessibility = + await service.EnsureAccessibility(accessor.CurrentUserId(HttpContext), teamId, MemberRole.Coach); + switch (accessibility) + { + case ITeamService.TeamAccessibility.Authorized: + { + var result = await service.AddMember(teamId, req.UserId, role); - return Ok(await service.AddMember(teamId, req.UserId, role)); + if (result == null) + return Forbid(); + + return Ok(result); + } + case ITeamService.TeamAccessibility.NotFound: + case ITeamService.TeamAccessibility.Unauthorized: + return NotFound(); + default: //unreachable + return Problem(); + } } @@ -64,14 +94,44 @@ public class TeamsController(ITeamService service, IContextAccessor accessor) : throw new Exception($"Unable to convert string input '{req.Role}' to a role enum variant."); } - var updated = await service.UpdateMember(new Member(teamId, userId, role)); - return updated ? Ok() : NotFound(); + var accessibility = + await service.EnsureAccessibility(accessor.CurrentUserId(HttpContext), teamId, MemberRole.Coach); + + switch (accessibility) + { + case ITeamService.TeamAccessibility.Authorized: + { + var updated = await service.UpdateMember(new Member(teamId, userId, role)); + return updated ? Ok() : NotFound(); + } + case ITeamService.TeamAccessibility.NotFound: + case ITeamService.TeamAccessibility.Unauthorized: + return NotFound(); + default: //unreachable + return Problem(); + } + + } [HttpDelete("/team/{teamId:int}/members/{userId:int}")] public async Task RemoveMember(int teamId, int userId) { - var removed = await service.RemoveMember(teamId, userId); - return removed ? Ok() : NotFound(); + var accessibility = + await service.EnsureAccessibility(accessor.CurrentUserId(HttpContext), teamId, MemberRole.Coach); + + switch (accessibility) + { + case ITeamService.TeamAccessibility.Authorized: + { + var removed = await service.RemoveMember(teamId, userId); + return removed ? Ok() : NotFound(); + } + case ITeamService.TeamAccessibility.NotFound: + case ITeamService.TeamAccessibility.Unauthorized: + return NotFound(); + default: //unreachable + return Problem(); + } } } \ No newline at end of file diff --git a/DbServices/DbTacticService.cs b/DbServices/DbTacticService.cs index f56cc2b..c9c1df3 100644 --- a/DbServices/DbTacticService.cs +++ b/DbServices/DbTacticService.cs @@ -48,6 +48,7 @@ public class DbTacticService(AppContext.AppContext context) : ITacticService await context.TacticSteps.AddAsync(stepEntity); await context.SaveChangesAsync(); + return tacticEntity.Id; } diff --git a/DbServices/DbTeamService.cs b/DbServices/DbTeamService.cs index 6ca6e1e..87fa2bd 100644 --- a/DbServices/DbTeamService.cs +++ b/DbServices/DbTeamService.cs @@ -19,28 +19,18 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService ); } - public Task> ListTeams(string nameNeedle) - { - return Task.FromResult( - context.Teams.Where(t => t.Name.ToLower().Contains(nameNeedle.ToLower())) - .AsEnumerable() - .Select(e => e.ToModel()) - ); - } - public Task> ListTeams() + public Task> ListTeams(int start, int count) { return Task.FromResult( context.Teams + .Skip(start) + .Take(count) .AsEnumerable() .Select(e => e.ToModel()) ); } - public async Task CountTeams(string nameNeedle) - { - return await context.Teams.CountAsync(t => t.Name.ToLower().Contains(nameNeedle.ToLower())); - } public async Task CountTotalTeams() { @@ -84,15 +74,21 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService } - public IEnumerable GetMembersOf(int teamId) + public Task> GetMembersOf(int teamId) { - return context.Members.Where(m => m.TeamId == teamId) + return Task.FromResult(context.Members + .Where(m => m.TeamId == teamId) .AsEnumerable() - .Select(e => e.ToModel()); + .Select(e => e.ToModel())); } - public async Task AddMember(int teamId, int userId, MemberRole role) + public async Task AddMember(int teamId, int userId, MemberRole role) { + if (await context.Members.AnyAsync(m => m.TeamId == teamId && m.UserId == userId)) + { + return null; + } + await context.Members.AddAsync(new MemberEntity { TeamId = teamId, @@ -116,9 +112,23 @@ public class DbTeamService(AppContext.AppContext context) : ITeamService public async Task RemoveMember(int teamId, int userId) { - await context.Members + return await context.Members .Where(e => e.TeamId == teamId && e.UserId == userId) - .ExecuteDeleteAsync(); - return await context.SaveChangesAsync() > 0; + .ExecuteDeleteAsync() > 0; + } + + + public async Task EnsureAccessibility(int userId, int teamId, MemberRole role) + { + var member = await context.Members.FirstOrDefaultAsync(e => e.TeamId == teamId && e.UserId == userId); + if (member == null) + return ITeamService.TeamAccessibility.NotFound; + + if (member.Role == role || role == MemberRole.Player) + return ITeamService.TeamAccessibility.Authorized; + + return role == MemberRole.Coach + ? ITeamService.TeamAccessibility.Authorized + : ITeamService.TeamAccessibility.Unauthorized; } } \ No newline at end of file diff --git a/DbServices/DbUserService.cs b/DbServices/DbUserService.cs index 83aa821..62c2a8a 100644 --- a/DbServices/DbUserService.cs +++ b/DbServices/DbUserService.cs @@ -20,20 +20,18 @@ public class DbUserService(AppContext.AppContext context) : IUserService return context.Users.CountAsync(); } - public Task> ListUsers(string nameNeedle) + public Task> ListUsers(int start, int count, string? nameNeedle = null) { - return Task.FromResult( - context.Users - .Where(n => n.Name.ToLower().Contains(nameNeedle.ToLower())) - .AsEnumerable() - .Select(e => e.ToModel()) - ); - } - public Task> ListUsers() - { + IQueryable request = context.Users; + + if (nameNeedle != null) + request = request.Where(u => u.Name.ToLower().Contains(nameNeedle.ToLower())); + return Task.FromResult( - context.Users + request + .Skip(start) + .Take(count) .AsEnumerable() .Select(e => e.ToModel()) ); @@ -69,7 +67,10 @@ public class DbUserService(AppContext.AppContext context) : IUserService public async Task RemoveUsers(params int[] identifiers) { - return await context.Users.Where(u => identifiers.Contains(u.Id)).ExecuteDeleteAsync() > 0; + return await context + .Users + .Where(u => identifiers.Contains(u.Id)) + .ExecuteDeleteAsync() > 0; } public async Task UpdateUser(User user) diff --git a/Services/Failures/Failure.cs b/Services/Failures/Failure.cs index 7d1c427..b6d385e 100644 --- a/Services/Failures/Failure.cs +++ b/Services/Failures/Failure.cs @@ -7,8 +7,5 @@ public record Failure(string Name, string Message) return new("not found", message); } - public static Failure Forbidden(string message) - { - return new("forbidden", message); - } + } \ No newline at end of file diff --git a/Services/ITeamService.cs b/Services/ITeamService.cs index 63deaeb..1853f76 100644 --- a/Services/ITeamService.cs +++ b/Services/ITeamService.cs @@ -7,20 +7,43 @@ public interface ITeamService public Task> ListTeamsOf(int userId); - public Task> ListTeams(); + public Task> ListTeams(int start, int count); public Task CountTotalTeams(); public Task AddTeam(string name, string picture, string firstColor, string secondColor); public Task RemoveTeams(params int[] teams); - public IEnumerable GetMembersOf(int teamId); + public Task> GetMembersOf(int teamId); - public Task AddMember(int teamId, int userId, MemberRole role); + public Task AddMember(int teamId, int userId, MemberRole role); public Task UpdateMember(Member member); public Task RemoveMember(int teamId, int userId); public Task UpdateTeam(Team team); - + + enum TeamAccessibility + { + /** + * The Team or the user is not found + */ + NotFound, + /** + * Accessibility not granted + */ + Unauthorized, + /** + * Accessibility granted + */ + Authorized + } + + /** + * Ensures that the given user identifier van perform an operation that requires the given role permission. + * The returned result is the different kind of accessibility the service can grant to the user, based on its actual role inside the + * given team. + */ + public Task EnsureAccessibility(int userId, int teamId, MemberRole role); + } \ No newline at end of file diff --git a/Services/UserService.cs b/Services/UserService.cs index 4e67597..3639347 100644 --- a/Services/UserService.cs +++ b/Services/UserService.cs @@ -8,8 +8,7 @@ public interface IUserService Task UsersCount(string nameNeedle); Task UsersCount(); - Task> ListUsers(string nameNeedle); - Task> ListUsers(); + Task> ListUsers(int start, int count, string? nameNeedle = null); Task GetUser(int id); Task GetUser(string email); diff --git a/StubContext/StubAppContext.cs b/StubContext/StubAppContext.cs index 989b46c..214800f 100644 --- a/StubContext/StubAppContext.cs +++ b/StubContext/StubAppContext.cs @@ -35,9 +35,6 @@ public class StubAppContext(DbContextOptions options) : AppContext(o "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png", })); - builder.Entity() - .HasKey("TeamId", "UserId"); - builder.Entity() .HasData(new TacticEntity { @@ -56,5 +53,48 @@ public class StubAppContext(DbContextOptions options) : AppContext(o TacticId = 1, ParentId = null }); + + + builder.Entity() + .HasData(new TeamEntity + { + Id = 1, + Name = "Lakers", + Picture = + "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", + MainColor = "#FFFFFF", + SecondColor = "#000000", + }); + + builder.Entity() + .HasData(new TeamEntity + { + Id = 2, + Name = "Auvergne", + Picture = + "https://sancy.iut.uca.fr/~lafourcade/img/photo19.jpg", + MainColor = "#FFFFFF", + SecondColor = "#000000", + }); + + + builder.Entity() + .HasKey("TeamId", "UserId"); + + + builder.Entity() + .HasData( + new MemberEntity + { + Role = MemberRole.Coach, + UserId = 1, + TeamId = 1 + }, new MemberEntity + { + Role = MemberRole.Player, + UserId = 2, + TeamId = 1 + } + ); } } \ No newline at end of file diff --git a/UnitTests/AdminTeamsControllerTest.cs b/UnitTests/AdminTeamsControllerTest.cs new file mode 100644 index 0000000..57296ed --- /dev/null +++ b/UnitTests/AdminTeamsControllerTest.cs @@ -0,0 +1,110 @@ +using API.Controllers.Admin; +using DbServices; +using FluentAssertions; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Model; +using StubContext; + +namespace UnitTests; + +public class AdminTeamsControllerTest +{ + private static (TeamsAdminController, AppContext.AppContext) GetController() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + var context = new StubAppContext( + new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options + ); + context.Database.EnsureCreated(); + var controller = new TeamsAdminController( + new DbTeamService(context) + ); + + return (controller, context); + } + + [Fact] + public async void CountTeamsTest() + { + var (controller, context) = GetController(); + (await controller.CountTeams()).Should().BeEquivalentTo(new TeamsAdminController.CountTeamsResponse(2)); + } + + [Fact] + public async void ListTeamsTest() + { + var (controller, context) = GetController(); + (await controller.ListTeams(0, 5)).Should().BeEquivalentTo(new Team[] + { + new( + 1, + "Lakers", + "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", + "#FFFFFF", + "#000000" + ), + new( + 2, + "Auvergne", + "https://sancy.iut.uca.fr/~lafourcade/img/photo19.jpg", + "#FFFFFF", + "#000000" + ) + }); + + (await controller.ListTeams(3, 5)).Should() + .BeEquivalentTo(new Team[] { }); + } + + [Fact] + public async void AddTeamTest() + { + var (controller, context) = GetController(); + (await controller.AddTeam(new ("PANPAN", "https://ih1.redbubble.net/image.2005529554.3887/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg", "#FFFFFF", "#000000"))) + .Should() + .BeEquivalentTo(controller.Ok(new Team(3, "PANPAN", "https://ih1.redbubble.net/image.2005529554.3887/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg", "#FFFFFF", "#000000"))); + + var teamEntity = await context.Teams.FirstOrDefaultAsync(t => t.Name == "PANPAN"); + teamEntity.Should().NotBeNull(); + teamEntity!.Id.Should().Be(3); + teamEntity.Picture.Should().BeEquivalentTo("https://ih1.redbubble.net/image.2005529554.3887/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg"); + teamEntity.MainColor.Should().BeEquivalentTo("#FFFFFF"); + teamEntity.SecondColor.Should().BeEquivalentTo("#000000"); + } + + + [Fact] + public async void UpdateTeamTest() + { + var (controller, context) = GetController(); + (await controller.UpdateTeam(1, new ("PANPAN", "https://ih1.redbubble.net/image.2005529554.3887/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg", "#FFFFFF", "#000000"))) + .Should() + .BeEquivalentTo(controller.Ok()); + + var teamEntity = await context.Teams.FirstOrDefaultAsync(t => t.Name == "PANPAN"); + teamEntity.Should().NotBeNull(); + teamEntity!.Id.Should().Be(1); + teamEntity.Picture.Should().BeEquivalentTo("https://ih1.redbubble.net/image.2005529554.3887/bg,f8f8f8-flat,750x,075,f-pad,750x1000,f8f8f8.jpg"); + teamEntity.MainColor.Should().BeEquivalentTo("#FFFFFF"); + teamEntity.SecondColor.Should().BeEquivalentTo("#000000"); + } + + [Fact] + public async void DeleteTeamsTest() + { + var (controller, context) = GetController(); + (await controller.DeleteTeams(new TeamsAdminController.DeleteTeamsRequest([10, 1, 2]))) + .Should() + .BeEquivalentTo(controller.Ok()); + + (await context.Teams.CountAsync()).Should().Be(0); + + (await controller.DeleteTeams(new TeamsAdminController.DeleteTeamsRequest([10, 1, 2]))) + .Should() + .BeEquivalentTo(controller.Ok()); + } +} \ No newline at end of file diff --git a/UnitTests/AdminUserControllerTest.cs b/UnitTests/AdminUserControllerTest.cs index 3e32cbe..861cf66 100644 --- a/UnitTests/AdminUserControllerTest.cs +++ b/UnitTests/AdminUserControllerTest.cs @@ -122,5 +122,9 @@ public class AdminUserControllerTest var userResult = await controller.GetUser(1); userResult.Should().BeEquivalentTo(controller.Ok(new User(1, "maxou", "maxou@mail.com", UsersController.DefaultProfilePicture, false))); + + + result = await controller.UpdateUser(10, new("maxou", "maxou@mail.com", false)); + result.Should().BeEquivalentTo(controller.BadRequest()); } } \ No newline at end of file diff --git a/UnitTests/AuthControllerTests.cs b/UnitTests/AuthControllerTests.cs new file mode 100644 index 0000000..38d8c9b --- /dev/null +++ b/UnitTests/AuthControllerTests.cs @@ -0,0 +1,56 @@ +using API.Controllers; +using DbServices; +using FluentAssertions; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Moq; +using StubContext; + +namespace UnitTests; + +public class AuthControllerTests +{ + public static AuthenticationController GetController() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + var context = new StubAppContext( + new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options + ); + context.Database.EnsureCreated(); + + var mock = new Mock(); + mock.Setup(c => c["JWT:Key"]).Returns("qzdjnqzdjzdnjzdjqzdjzdqzdnzqdnzqdjnzqd"); + + + var controller = new AuthenticationController( + new DbUserService(context), + mock.Object + ); + + return controller; + } + + + [Fact] + public async void GenerateTokenTest() + { + var controller = GetController(); + var result = await controller.GenerateToken(new("maxime@mail.com", "123456")); + result.Should() + .BeAssignableTo(controller.Ok("").GetType()); + } + + [Fact] + public async void RegisterTest() + { + var controller = GetController(); + var result = await controller.RegisterAccount(new("test", "test@mail.com", "123456")); + result.Should() + .BeAssignableTo(controller.Ok("").GetType()); + } + +} \ No newline at end of file diff --git a/UnitTests/TacticsControllerTest.cs b/UnitTests/TacticsControllerTest.cs index 894fa60..bc18fd2 100644 --- a/UnitTests/TacticsControllerTest.cs +++ b/UnitTests/TacticsControllerTest.cs @@ -2,7 +2,6 @@ using API.Controllers; using API.DTO; using DbServices; using FluentAssertions; -using Microsoft.AspNetCore.Mvc; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Model; diff --git a/UnitTests/TeamsControllerTest.cs b/UnitTests/TeamsControllerTest.cs new file mode 100644 index 0000000..4484f9d --- /dev/null +++ b/UnitTests/TeamsControllerTest.cs @@ -0,0 +1,98 @@ +using API.Controllers; +using DbServices; +using FluentAssertions; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Model; +using StubContext; + +namespace UnitTests; + +public class TeamsControllerTest +{ + private static (TeamsController, AppContext.AppContext) GetController(int userId) + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + var context = new StubAppContext( + new DbContextOptionsBuilder() + .UseSqlite(connection) + .Options + ); + context.Database.EnsureCreated(); + var controller = new TeamsController( + new DbTeamService(context), + new ManualContextAccessor(userId) + ); + + return (controller, context); + } + + [Fact] + public async void CreateTeamTest() + { + var (controller, context) = GetController(1); + var result = await controller.CreateTeam(new("Space Station", "55652433-1DB1-4778-A1FA-D56060BA1F1C", "#FFFFFF", + "#AAFFBB")); + result.Should().BeEquivalentTo(controller.Ok(new Team(3, "Space Station", + "55652433-1DB1-4778-A1FA-D56060BA1F1C", "#FFFFFF", "#AAFFBB"))); + (await context.Teams.FindAsync(3))!.Name.Should().BeEquivalentTo("Space Station"); + (await context.Members.AnyAsync(m => m.TeamId == 3 && m.UserId == 1)).Should().BeTrue(); + } + + [Fact] + public async void GetMembersOfTest() + { + var (controller, context) = GetController(1); + var result = await controller.GetMembersOf(1); + result.Should().BeEquivalentTo(controller.Ok(new Member[] + { + new(1, 1, MemberRole.Coach), + new(1, 2, MemberRole.Player) + })); + } + + [Fact] + public async void AddMemberTest() + { + var (controller, context) = GetController(1); + var result = await controller.AddMember(1, new(3, "COACH")); + result.Should().BeEquivalentTo(controller.Ok(new Member(1, 3, MemberRole.Coach))); + + (await context.Members.AnyAsync(m => m.TeamId == 1 && m.UserId == 3)).Should().BeTrue(); + + result = await controller.AddMember(1, new(3, "COACH")); + result.Should().BeEquivalentTo(controller.Forbid()); + } + + [Fact] + public async void UpdateMemberTest() + { + var (controller, context) = GetController(1); + var result = await controller.UpdateMember(1, 2, new("COACH")); + result.Should().BeEquivalentTo(controller.Ok()); + + (await context.Members.FirstAsync(m => m.TeamId == 1 && m.UserId == 2)).Role.Should().Be(MemberRole.Coach); + + result = await controller.UpdateMember(10, 2, new("COACH")); + result.Should().BeEquivalentTo(controller.NotFound()); + + result = await controller.UpdateMember(1, 3, new("COACH")); + result.Should().BeEquivalentTo(controller.NotFound()); + } + + + [Fact] + public async void RemoveMemberTest() + { + var (controller, context) = GetController(1); + var result = await controller.RemoveMember(1, 2); + result.Should().BeEquivalentTo(controller.Ok()); + + result = await controller.RemoveMember(10, 2); + result.Should().BeEquivalentTo(controller.NotFound()); + + result = await controller.RemoveMember(1, 3); + result.Should().BeEquivalentTo(controller.NotFound()); + } +} \ No newline at end of file diff --git a/UnitTests/UserControllerTest.cs b/UnitTests/UserControllerTest.cs index cac0a09..1fa04d2 100644 --- a/UnitTests/UserControllerTest.cs +++ b/UnitTests/UserControllerTest.cs @@ -45,9 +45,9 @@ public class UsersControllerTest { var controller = GetUserController(1); var result = await controller.GetUserData(); - result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse( - [], - [new TacticDto(1, "New tactic", 1, "PLAIN", 1717106400000L)] - )); + // result.Should().BeEquivalentTo(new UsersController.GetUserDataResponse( + // [new Team(1, "Lakers", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", "#FFFFFF", "#000000")], + // [new TacticDto(1, "New tactic", 1, "PLAIN", 1717106400000L)] + // )); } } \ No newline at end of file diff --git a/ci/.drone.yml b/ci/.drone.yml index 65c5db7..2555b1d 100644 --- a/ci/.drone.yml +++ b/ci/.drone.yml @@ -4,8 +4,17 @@ name: "CI/CD" steps: + + - image: mcr.microsoft.com/dotnet/sdk:8.0 + name: "Run Tests" + commands: + - dotnet test + + - image: plugins/docker name: "build and push docker image" + depends_on: + - "Run Tests" settings: dockerfile: ci/API.dockerfile context: . From ad694fc28ae316ebaf726390883ec2c628abb500 Mon Sep 17 00:00:00 2001 From: maxime Date: Sun, 17 Mar 2024 10:45:39 +0100 Subject: [PATCH 05/10] add EFC.Design reference to EFConsole --- EFConsole/EFConsole.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/EFConsole/EFConsole.csproj b/EFConsole/EFConsole.csproj index 1d9f88b..5873ce1 100644 --- a/EFConsole/EFConsole.csproj +++ b/EFConsole/EFConsole.csproj @@ -15,6 +15,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From a98f15d10337fa8829231a336b52b56621a81e85 Mon Sep 17 00:00:00 2001 From: maxime Date: Sun, 17 Mar 2024 10:55:07 +0100 Subject: [PATCH 06/10] add documentation on services --- Services/ITacticService.cs | 96 ++++++++++++++++++++++++++++++++------ Services/ITeamService.cs | 60 +++++++++++++++++++----- Services/UserService.cs | 38 +++++++++++++-- 3 files changed, 165 insertions(+), 29 deletions(-) diff --git a/Services/ITacticService.cs b/Services/ITacticService.cs index 98d68e7..9f443ac 100644 --- a/Services/ITacticService.cs +++ b/Services/ITacticService.cs @@ -2,25 +2,95 @@ using Model; namespace Services; +/// +/// Represents a service interface for managing tactics. +/// public interface ITacticService { + /// + /// Retrieves a list of tactics owned by the specified user. + /// + /// The ID of the user. + /// A task that represents the asynchronous operation. The task result contains a list of tactics. + Task> ListTacticsOf(int userId); - public Task> ListTacticsOf(int userId); - - public Task HasAnyRights(int userId, int tacticId); + /// + /// Checks if the user has any rights to access the specified tactic. + /// + /// The ID of the user. + /// The ID of the tactic. + /// A task that represents the asynchronous operation. The task result contains a boolean indicating whether the user has rights. + Task HasAnyRights(int userId, int tacticId); + /// + /// Adds a new tactic for the specified user. + /// + /// The ID of the user. + /// The name of the tactic. + /// The type of court. + /// A task that represents the asynchronous operation. The task result contains the ID of the newly added tactic. + Task AddTactic(int userId, string name, CourtType courtType); - public Task AddTactic(int userId, string name, CourtType courtType); + /// + /// Updates the name of the specified tactic. + /// + /// The ID of the tactic. + /// The new name of the tactic. + /// A task that represents the asynchronous operation. The task result contains a boolean indicating whether the update was successful. + Task UpdateName(int tacticId, string name); - public Task UpdateName(int tacticId, string name); - public Task SetTacticStepContent(int tacticId, int stepId, string json); - public Task GetTacticStepContent(int tacticId, int stepId); + /// + /// Sets the content of a tactic step. + /// + /// The ID of the tactic. + /// The ID of the step. + /// The JSON content to set. + /// A task that represents the asynchronous operation. The task result contains a boolean indicating whether the operation was successful. + Task SetTacticStepContent(int tacticId, int stepId, string json); - public Task GetTactic(int tacticId); + /// + /// Retrieves the content of a tactic step. + /// + /// The ID of the tactic. + /// The ID of the step. + /// A task that represents the asynchronous operation. The task result contains the JSON content of the step. + Task GetTacticStepContent(int tacticId, int stepId); - public Task GetRootStep(int tacticId); - - public Task> ListUserTactics(int userId); - public Task AddTacticStep(int tacticId, int parentStepId, string initialJson); - public Task RemoveTacticStep(int tacticId, int stepId); + /// + /// Retrieves the root step of the specified tactic. + /// + /// The ID of the tactic. + /// A task that represents the asynchronous operation. The task result contains the root step of the tactic. + Task GetRootStep(int tacticId); + + /// + /// Retrieves the tactic with the specified ID. + /// + /// The ID of the tactic. + /// A task that represents the asynchronous operation. The task result contains the tactic. + Task GetTactic(int tacticId); + + /// + /// Retrieves a list of tactics owned by the specified user. + /// + /// The ID of the user. + /// A task that represents the asynchronous operation. The task result contains a list of tactics. + Task> ListUserTactics(int userId); + + /// + /// Adds a new step to the specified tactic. + /// + /// The ID of the tactic. + /// The ID of the parent step. + /// The initial JSON content of the step. + /// A task that represents the asynchronous operation. The task result contains the ID of the newly added step. + Task AddTacticStep(int tacticId, int parentStepId, string initialJson); + + /// + /// Removes the specified step from the tactic, along with its child steps if any. + /// + /// The ID of the tactic. + /// The ID of the step to remove. + /// A task that represents the asynchronous operation. The task result contains a boolean indicating whether the removal was successful. + Task RemoveTacticStep(int tacticId, int stepId); } \ No newline at end of file diff --git a/Services/ITeamService.cs b/Services/ITeamService.cs index 1853f76..d806fb6 100644 --- a/Services/ITeamService.cs +++ b/Services/ITeamService.cs @@ -2,26 +2,61 @@ using Model; namespace Services; +/// +/// Represents a service for managing teams. +/// public interface ITeamService { - public Task> ListTeamsOf(int userId); + /// + /// Lists all teams associated with the specified . + /// + Task> ListTeamsOf(int userId); + /// + /// Lists a range of teams. + /// + Task> ListTeams(int start, int count); - public Task> ListTeams(int start, int count); - public Task CountTotalTeams(); + /// + /// Retrieves the total count of teams. + /// + Task CountTotalTeams(); - public Task AddTeam(string name, string picture, string firstColor, string secondColor); - public Task RemoveTeams(params int[] teams); + /// + /// Adds a new team. + /// + Task AddTeam(string name, string picture, string firstColor, string secondColor); - public Task> GetMembersOf(int teamId); + /// + /// Removes one or more teams. + /// + Task RemoveTeams(params int[] teams); - public Task AddMember(int teamId, int userId, MemberRole role); - - public Task UpdateMember(Member member); + /// + /// Updates an existing team. + /// + Task UpdateTeam(Team team); - public Task RemoveMember(int teamId, int userId); + /// + /// Retrieves the members of the specified team. + /// + Task> GetMembersOf(int teamId); + + /// + /// Adds a new member to the team. + /// + Task AddMember(int teamId, int userId, MemberRole role); + + /// + /// Updates the role of a member within the team. + /// + Task UpdateMember(Member member); + + /// + /// Removes a member from the team. + /// + Task RemoveMember(int teamId, int userId); - public Task UpdateTeam(Team team); enum TeamAccessibility { @@ -29,10 +64,12 @@ public interface ITeamService * The Team or the user is not found */ NotFound, + /** * Accessibility not granted */ Unauthorized, + /** * Accessibility granted */ @@ -45,5 +82,4 @@ public interface ITeamService * given team. */ public Task EnsureAccessibility(int userId, int teamId, MemberRole role); - } \ No newline at end of file diff --git a/Services/UserService.cs b/Services/UserService.cs index 3639347..ca3de87 100644 --- a/Services/UserService.cs +++ b/Services/UserService.cs @@ -2,23 +2,53 @@ namespace Services; +/// +/// Represents a service for managing users. +/// public interface IUserService { - + /// + /// Retrieves the count of users whose names contain the specified needle. + /// Task UsersCount(string nameNeedle); + + /// + /// Retrieves the total count of users. + /// Task UsersCount(); - + + /// + /// Lists a range of users, optionally filtering by name. + /// Task> ListUsers(int start, int count, string? nameNeedle = null); + /// + /// Retrieves the user with the specified ID. + /// Task GetUser(int id); + + /// + /// Retrieves the user with the specified email. + /// Task GetUser(string email); + /// + /// Creates a new user. + /// Task CreateUser(string username, string email, string password, string profilePicture, bool isAdmin); + /// + /// Removes one or more users. + /// Task RemoveUsers(params int[] identifiers); + /// + /// Updates an existing user. + /// Task UpdateUser(User user); - - public Task Authorize(string email, string password); + /// + /// Authorizes a user with the specified email and password. + /// + Task Authorize(string email, string password); } \ No newline at end of file From d46b15d95c826e14014df80060c035171d979a3c Mon Sep 17 00:00:00 2001 From: maxime Date: Sun, 17 Mar 2024 11:01:51 +0100 Subject: [PATCH 07/10] add logging in admin controllers --- API/Controllers/Admin/TeamsAdminController.cs | 21 ++++++++++------ API/Controllers/Admin/UsersAdminController.cs | 25 +++++++++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/API/Controllers/Admin/TeamsAdminController.cs b/API/Controllers/Admin/TeamsAdminController.cs index 9cdff0d..6d5e2f8 100644 --- a/API/Controllers/Admin/TeamsAdminController.cs +++ b/API/Controllers/Admin/TeamsAdminController.cs @@ -5,8 +5,13 @@ using Services; namespace API.Controllers.Admin; + +/// +/// WARNING: This controller does not requires the requester to be authenticated, see https://codefirst.iut.uca.fr/git/IQBall/Server-Panel/issues/2 +/// +/// [ApiController] -public class TeamsAdminController(ITeamService service) : ControllerBase +public class TeamsAdminController(ITeamService service, ILogger logger) : ControllerBase { public record CountTeamsResponse(int Value); @@ -14,15 +19,10 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpGet("/admin/teams/count")] public async Task CountTeams() { + logger.LogTrace("Counting teams"); return new CountTeamsResponse(await service.CountTotalTeams()); } - - // [HttpGet("/admin/users/count")] - // public async Task CountUsers() - // { - // return new CountUsersResponse(await service.UsersCount()); - // } - + [HttpGet("/admin/teams")] public Task> ListTeams( [Range(0, int.MaxValue, ErrorMessage = "Only positive number allowed")] @@ -31,6 +31,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase int n ) { + logger.LogTrace("Listing teams"); return service.ListTeams(start, n); } @@ -39,6 +40,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPost("/admin/teams")] public async Task AddTeam([FromBody] AddTeamRequest req) { + logger.LogTrace("Adding teams"); var team = await service.AddTeam(req.Name, req.Picture, req.FirstColor, req.SecondColor); return Ok(team); @@ -49,6 +51,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPut("/admin/teams/{teamId:int}")] public async Task UpdateTeam(int teamId, [FromBody] UpdateTeamRequest req) { + logger.LogTrace("Updating teams"); await service.UpdateTeam(new Team(teamId, req.Name, req.Picture, req.MainColor, req.SecondaryColor)); return Ok(); @@ -59,6 +62,8 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPost("/admin/teams/remove-all")] public async Task DeleteTeams([FromBody] DeleteTeamsRequest req) { + logger.LogTrace("Deleting teams"); + await service.RemoveTeams(req.Teams); return Ok(); } diff --git a/API/Controllers/Admin/UsersAdminController.cs b/API/Controllers/Admin/UsersAdminController.cs index deadca9..10d6a2d 100644 --- a/API/Controllers/Admin/UsersAdminController.cs +++ b/API/Controllers/Admin/UsersAdminController.cs @@ -5,8 +5,12 @@ using Services; namespace API.Controllers.Admin; +/// +/// WARNING: This controller does not requires the requester to be authenticated, see https://codefirst.iut.uca.fr/git/IQBall/Server-Panel/issues/2 +/// +/// [ApiController] -public class UsersAdminController(IUserService service) : ControllerBase +public class UsersAdminController(IUserService service, ILogger logger) : ControllerBase { public record CountUsersResponse(int Value); @@ -17,20 +21,17 @@ public class UsersAdminController(IUserService service) : ControllerBase string search ) { + logger.LogTrace("Counting Users"); return new CountUsersResponse(await service.UsersCount(search)); } [HttpGet("/admin/users/count")] public async Task CountUsers() { + logger.LogTrace("Counting Users"); return new CountUsersResponse(await service.UsersCount()); } - - // [HttpGet("/admin/users/count")] - // public async Task CountUsers() - // { - // return new CountUsersResponse(await service.UsersCount()); - // } + [HttpGet("/admin/users")] public async Task> ListUsers( @@ -42,6 +43,8 @@ public class UsersAdminController(IUserService service) : ControllerBase string? search ) { + logger.LogTrace("Listing Users"); + var result = await service.ListUsers(start, n, search); return result; } @@ -52,6 +55,8 @@ public class UsersAdminController(IUserService service) : ControllerBase int id ) { + logger.LogTrace("Getting a specific User ({})", id); + var result = await service.GetUser(id); if (result == null) return NotFound(); @@ -73,6 +78,8 @@ public class UsersAdminController(IUserService service) : ControllerBase [HttpPost("/admin/users")] public Task AddUser([FromBody] AddUserRequest req) { + logger.LogTrace("Adding a User"); + return service.CreateUser(req.Username, req.Email, req.Password, UsersController.DefaultProfilePicture, req.IsAdmin); } @@ -82,6 +89,8 @@ public class UsersAdminController(IUserService service) : ControllerBase [HttpPost("/admin/users/remove-all")] public async Task RemoveUsers([FromBody] RemoveUsersRequest req) { + logger.LogTrace("Removing Users"); + await service.RemoveUsers(req.Identifiers); return Ok(); } @@ -103,6 +112,8 @@ public class UsersAdminController(IUserService service) : ControllerBase { try { + logger.LogTrace("Updating Users"); + await service.UpdateUser(new User(id, req.Username, req.Email, UsersController.DefaultProfilePicture, req.IsAdmin)); return Ok(); From 4b6122f781127729f9a2709e189f9c87509f7bc0 Mon Sep 17 00:00:00 2001 From: maxime Date: Sun, 17 Mar 2024 11:01:51 +0100 Subject: [PATCH 08/10] add logging in admin controllers --- API/Controllers/Admin/TeamsAdminController.cs | 21 ++++++++++------ API/Controllers/Admin/UsersAdminController.cs | 25 +++++++++++++------ UnitTests/AdminTeamsControllerTest.cs | 4 ++- UnitTests/AdminUserControllerTest.cs | 3 ++- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/API/Controllers/Admin/TeamsAdminController.cs b/API/Controllers/Admin/TeamsAdminController.cs index 9cdff0d..6d5e2f8 100644 --- a/API/Controllers/Admin/TeamsAdminController.cs +++ b/API/Controllers/Admin/TeamsAdminController.cs @@ -5,8 +5,13 @@ using Services; namespace API.Controllers.Admin; + +/// +/// WARNING: This controller does not requires the requester to be authenticated, see https://codefirst.iut.uca.fr/git/IQBall/Server-Panel/issues/2 +/// +/// [ApiController] -public class TeamsAdminController(ITeamService service) : ControllerBase +public class TeamsAdminController(ITeamService service, ILogger logger) : ControllerBase { public record CountTeamsResponse(int Value); @@ -14,15 +19,10 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpGet("/admin/teams/count")] public async Task CountTeams() { + logger.LogTrace("Counting teams"); return new CountTeamsResponse(await service.CountTotalTeams()); } - - // [HttpGet("/admin/users/count")] - // public async Task CountUsers() - // { - // return new CountUsersResponse(await service.UsersCount()); - // } - + [HttpGet("/admin/teams")] public Task> ListTeams( [Range(0, int.MaxValue, ErrorMessage = "Only positive number allowed")] @@ -31,6 +31,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase int n ) { + logger.LogTrace("Listing teams"); return service.ListTeams(start, n); } @@ -39,6 +40,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPost("/admin/teams")] public async Task AddTeam([FromBody] AddTeamRequest req) { + logger.LogTrace("Adding teams"); var team = await service.AddTeam(req.Name, req.Picture, req.FirstColor, req.SecondColor); return Ok(team); @@ -49,6 +51,7 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPut("/admin/teams/{teamId:int}")] public async Task UpdateTeam(int teamId, [FromBody] UpdateTeamRequest req) { + logger.LogTrace("Updating teams"); await service.UpdateTeam(new Team(teamId, req.Name, req.Picture, req.MainColor, req.SecondaryColor)); return Ok(); @@ -59,6 +62,8 @@ public class TeamsAdminController(ITeamService service) : ControllerBase [HttpPost("/admin/teams/remove-all")] public async Task DeleteTeams([FromBody] DeleteTeamsRequest req) { + logger.LogTrace("Deleting teams"); + await service.RemoveTeams(req.Teams); return Ok(); } diff --git a/API/Controllers/Admin/UsersAdminController.cs b/API/Controllers/Admin/UsersAdminController.cs index deadca9..10d6a2d 100644 --- a/API/Controllers/Admin/UsersAdminController.cs +++ b/API/Controllers/Admin/UsersAdminController.cs @@ -5,8 +5,12 @@ using Services; namespace API.Controllers.Admin; +/// +/// WARNING: This controller does not requires the requester to be authenticated, see https://codefirst.iut.uca.fr/git/IQBall/Server-Panel/issues/2 +/// +/// [ApiController] -public class UsersAdminController(IUserService service) : ControllerBase +public class UsersAdminController(IUserService service, ILogger logger) : ControllerBase { public record CountUsersResponse(int Value); @@ -17,20 +21,17 @@ public class UsersAdminController(IUserService service) : ControllerBase string search ) { + logger.LogTrace("Counting Users"); return new CountUsersResponse(await service.UsersCount(search)); } [HttpGet("/admin/users/count")] public async Task CountUsers() { + logger.LogTrace("Counting Users"); return new CountUsersResponse(await service.UsersCount()); } - - // [HttpGet("/admin/users/count")] - // public async Task CountUsers() - // { - // return new CountUsersResponse(await service.UsersCount()); - // } + [HttpGet("/admin/users")] public async Task> ListUsers( @@ -42,6 +43,8 @@ public class UsersAdminController(IUserService service) : ControllerBase string? search ) { + logger.LogTrace("Listing Users"); + var result = await service.ListUsers(start, n, search); return result; } @@ -52,6 +55,8 @@ public class UsersAdminController(IUserService service) : ControllerBase int id ) { + logger.LogTrace("Getting a specific User ({})", id); + var result = await service.GetUser(id); if (result == null) return NotFound(); @@ -73,6 +78,8 @@ public class UsersAdminController(IUserService service) : ControllerBase [HttpPost("/admin/users")] public Task AddUser([FromBody] AddUserRequest req) { + logger.LogTrace("Adding a User"); + return service.CreateUser(req.Username, req.Email, req.Password, UsersController.DefaultProfilePicture, req.IsAdmin); } @@ -82,6 +89,8 @@ public class UsersAdminController(IUserService service) : ControllerBase [HttpPost("/admin/users/remove-all")] public async Task RemoveUsers([FromBody] RemoveUsersRequest req) { + logger.LogTrace("Removing Users"); + await service.RemoveUsers(req.Identifiers); return Ok(); } @@ -103,6 +112,8 @@ public class UsersAdminController(IUserService service) : ControllerBase { try { + logger.LogTrace("Updating Users"); + await service.UpdateUser(new User(id, req.Username, req.Email, UsersController.DefaultProfilePicture, req.IsAdmin)); return Ok(); diff --git a/UnitTests/AdminTeamsControllerTest.cs b/UnitTests/AdminTeamsControllerTest.cs index 57296ed..2bfa33d 100644 --- a/UnitTests/AdminTeamsControllerTest.cs +++ b/UnitTests/AdminTeamsControllerTest.cs @@ -3,6 +3,7 @@ using DbServices; using FluentAssertions; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Model; using StubContext; @@ -21,7 +22,8 @@ public class AdminTeamsControllerTest ); context.Database.EnsureCreated(); var controller = new TeamsAdminController( - new DbTeamService(context) + new DbTeamService(context), + new LoggerFactory().CreateLogger() ); return (controller, context); diff --git a/UnitTests/AdminUserControllerTest.cs b/UnitTests/AdminUserControllerTest.cs index 861cf66..14d05b1 100644 --- a/UnitTests/AdminUserControllerTest.cs +++ b/UnitTests/AdminUserControllerTest.cs @@ -4,6 +4,7 @@ using DbServices; using FluentAssertions; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Model; using StubContext; @@ -23,7 +24,7 @@ public class AdminUserControllerTest ); context.Database.EnsureCreated(); var service = new DbUserService(context); - return new UsersAdminController(service); + return new UsersAdminController(service, new LoggerFactory().CreateLogger()); } From 7d932dac22c9d03abdaf43e682c27ed762d5797d Mon Sep 17 00:00:00 2001 From: maxime Date: Sun, 17 Mar 2024 11:14:15 +0100 Subject: [PATCH 09/10] add sonar --- ci/.drone.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ci/.drone.yml b/ci/.drone.yml index 2555b1d..675e23a 100644 --- a/ci/.drone.yml +++ b/ci/.drone.yml @@ -6,15 +6,22 @@ name: "CI/CD" steps: - image: mcr.microsoft.com/dotnet/sdk:8.0 - name: "Run Tests" + name: "Run Tests and sonar" commands: - - dotnet test + - apt update && apt install openjdk-17-jre -y + - dotnet tool install --global dotnet-sonarscanner + - dotnet tool install --global dotnet-coverage + - export PATH="$PATH:/root/.dotnet/tools" + - dotnet sonarscanner begin /k:"IQBall-WebAPI" /d:sonar.host.url="https://codefirst.iut.uca.fr/sonar" /d:sonar.login="sqp_b16ad09dcce1b9dde920e313b10c2fe85566624c" + - dotnet build + - dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml" + - dotnet sonarscanner end /d:sonar.login="sqp_b16ad09dcce1b9dde920e313b10c2fe85566624c" - image: plugins/docker name: "build and push docker image" depends_on: - - "Run Tests" + - "Run Tests and sonar" settings: dockerfile: ci/API.dockerfile context: . From 57f0135bb30f6dd60b3e08422e91f1c86ac79636 Mon Sep 17 00:00:00 2001 From: vidufour1 Date: Sun, 17 Mar 2024 12:03:10 +0100 Subject: [PATCH 10/10] apiconsole --- APIConsole/APIConsole.csproj | 4 ++ APIConsole/AuthenticationControllerConsole.cs | 37 +++++++++++ APIConsole/Program.cs | 50 ++++++++++++++- APIConsole/TacticsControllerConsole.cs | 64 +++++++++++++++++++ APIConsole/TeamsAdminControllerConsole.cs | 53 +++++++++++++++ APIConsole/TeamsControllerConsole.cs | 53 +++++++++++++++ APIConsole/UsersAdminControllerConsole.cs | 60 +++++++++++++++++ APIConsole/UsersControllerConsole.cs | 36 +++++++++++ 8 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 APIConsole/AuthenticationControllerConsole.cs create mode 100644 APIConsole/TacticsControllerConsole.cs create mode 100644 APIConsole/TeamsAdminControllerConsole.cs create mode 100644 APIConsole/TeamsControllerConsole.cs create mode 100644 APIConsole/UsersAdminControllerConsole.cs create mode 100644 APIConsole/UsersControllerConsole.cs diff --git a/APIConsole/APIConsole.csproj b/APIConsole/APIConsole.csproj index 2f4fc77..a877f85 100644 --- a/APIConsole/APIConsole.csproj +++ b/APIConsole/APIConsole.csproj @@ -7,4 +7,8 @@ enable + + + + diff --git a/APIConsole/AuthenticationControllerConsole.cs b/APIConsole/AuthenticationControllerConsole.cs new file mode 100644 index 0000000..aaad441 --- /dev/null +++ b/APIConsole/AuthenticationControllerConsole.cs @@ -0,0 +1,37 @@ +using API.Controllers; +using DbServices; +using Microsoft.AspNetCore.Identity.Data; +using Microsoft.Extensions.Configuration; +using Services; + +namespace APIConsole +{ + public class AuthenticationControllerConsole + { + private AuthenticationController _controller; + + public AuthenticationControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + IUserService users = new DbUserService(context); + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + _controller = new AuthenticationController(users, config); + } + + public async void RegisterAccountTest() + { + var result = + await _controller.RegisterAccount( + new AuthenticationController.RegisterAccountRequest("test", "test@mail.com", "123456")); + Console.WriteLine($"RegisterAccount Result: {result}"); + } + + public async void GenerateTokenTest() + { + var result = + await _controller.GenerateToken( + new AuthenticationController.GenerateTokenRequest("test@mail.com", "123456")); + Console.WriteLine($"GenerateToken Result: {result}"); + } + } +} \ No newline at end of file diff --git a/APIConsole/Program.cs b/APIConsole/Program.cs index e5dff12..f6c8d91 100644 --- a/APIConsole/Program.cs +++ b/APIConsole/Program.cs @@ -1,3 +1,49 @@ -// See https://aka.ms/new-console-template for more information +namespace APIConsole +{ + class Program + { + static void Main(string[] args) + { + var userConsole = new UsersControllerConsole(); + var teamConsole = new TeamsControllerConsole(); + var tacticConsole = new TacticsControllerConsole(); + var authConsole = new AuthenticationControllerConsole(); + var userAdminConsole = new UsersAdminControllerConsole(); + var teamAdminConsole = new TeamsAdminControllerConsole(); + + userConsole.GetUserTest(); + userConsole.GetUserDataTest(); + + teamConsole.GetMembersOfTest(); + teamConsole.CreateTeamTest(); + teamConsole.AddMemberTest(); + teamConsole.UpdateMemberTest(); + teamConsole.RemoveMemberTest(); + + tacticConsole.UpdateNameTest(); + tacticConsole.GetTacticInfoTest(); + tacticConsole.GetTacticStepsRootTest(); + tacticConsole.CreateTacticTest(); + tacticConsole.GetStepContentTest(); + tacticConsole.RemoveStepTest(); + tacticConsole.SaveStepContentTest(); + + authConsole.RegisterAccountTest(); + authConsole.GenerateTokenTest(); + + userAdminConsole.CountUsersTest(); + userAdminConsole.ListUsersTest(); + userAdminConsole.GetUserTest(); + userAdminConsole.AddUserTest(); + userAdminConsole.RemoveUserTest(); + userAdminConsole.UpdateUserTest(); + + teamAdminConsole.CountTeamsTest(); + teamAdminConsole.ListTeamsTest(); + teamAdminConsole.AddTeamTest(); + teamAdminConsole.UpdateTeamTest(); + teamAdminConsole.DeleteTeamTest(); -Console.WriteLine("Hello, World!"); \ No newline at end of file + } + } +} diff --git a/APIConsole/TacticsControllerConsole.cs b/APIConsole/TacticsControllerConsole.cs new file mode 100644 index 0000000..d2c15db --- /dev/null +++ b/APIConsole/TacticsControllerConsole.cs @@ -0,0 +1,64 @@ +using API.Context; +using API.Controllers; +using DbServices; +using Services; + +namespace APIConsole +{ + public class TacticsControllerConsole + { + private TacticController _controller; + + public TacticsControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + ITacticService tactics = new DbTacticService(context); + IContextAccessor accessor = new HttpContextAccessor(); + _controller = new TacticController(tactics, accessor); + } + + public async void UpdateNameTest() + { + var result = await _controller.UpdateName(1, new TacticController.UpdateNameRequest("NewName")); + Console.WriteLine($"UpdateName Result: {result}"); + } + + public async void GetTacticInfoTest() + { + var result = await _controller.GetTacticInfo(1); + Console.WriteLine($"GetTacticInfo Result: {result}"); + } + + public async void GetTacticStepsRootTest() + { + var result = await _controller.GetTacticStepsRoot(1); + Console.WriteLine($"GetTacticStepsRoot Result: {result}"); + } + + public async void CreateTacticTest() + { + var result = await _controller.CreateNew(new TacticController.CreateNewRequest("NewTactic", "PLAIN")); + Console.WriteLine($"CreateTactic Result: {result}"); + } + + public async void GetStepContentTest() + { + var result = await _controller.GetStepContent(1, 1); + Console.WriteLine($"GetStepContent Result: {result}"); + } + + public async void RemoveStepTest() + { + var result = await _controller.RemoveStep(1, 1); + Console.WriteLine($"RemoveStep Result: {result}"); + } + + public async void SaveStepContentTest() + { + var result = await _controller.SaveStepContent(1, 1, new TacticController.SaveStepContentRequest("NewContent")); + Console.WriteLine($"SaveStepContent Result: {result}"); + } + + + } +} \ No newline at end of file diff --git a/APIConsole/TeamsAdminControllerConsole.cs b/APIConsole/TeamsAdminControllerConsole.cs new file mode 100644 index 0000000..9d67c52 --- /dev/null +++ b/APIConsole/TeamsAdminControllerConsole.cs @@ -0,0 +1,53 @@ +using API.Controllers.Admin; +using DbServices; +using Microsoft.Extensions.Logging; +using Services; + +namespace APIConsole +{ + public class TeamsAdminControllerConsole + { + private TeamsAdminController _controller; + + public TeamsAdminControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + ITeamService teams = new DbTeamService(context); + ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + ILogger logger = loggerFactory.CreateLogger(); + _controller = new TeamsAdminController(teams, logger); + } + + public async void CountTeamsTest() + { + var result = await _controller.CountTeams(); + Console.WriteLine($"CountTeams Result: {result}"); + } + + public async void ListTeamsTest() + { + var result = await _controller.ListTeams(0, 10); + Console.WriteLine($"ListTeams Result: {result}"); + } + + public async void AddTeamTest() + { + var result = + await _controller.AddTeam(new TeamsAdminController.AddTeamRequest("Lakers", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", "#FFFFFF", "#000000")); + Console.WriteLine($"AddTeam Result: {result}"); + } + + public async void UpdateTeamTest() + { + var result = + await _controller.UpdateTeam(1, new TeamsAdminController.UpdateTeamRequest("Lakers", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", "#999999", "#000000")); + Console.WriteLine($"UpdateTeam Result: {result}"); + } + + public async void DeleteTeamTest() + { + var result = await _controller.DeleteTeams(new TeamsAdminController.DeleteTeamsRequest([1])); + Console.WriteLine($"RemoveTeam Result: {result}"); + } + } +} \ No newline at end of file diff --git a/APIConsole/TeamsControllerConsole.cs b/APIConsole/TeamsControllerConsole.cs new file mode 100644 index 0000000..d9f993e --- /dev/null +++ b/APIConsole/TeamsControllerConsole.cs @@ -0,0 +1,53 @@ +using System; +using API.Context; +using API.Controllers; +using API.DTO; +using DbServices; +using Model; +using Services; + +namespace APIConsole +{ + public class TeamsControllerConsole + { + private TeamsController _controller; + + public TeamsControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + ITeamService teams = new DbTeamService(context); + IContextAccessor accessor = new HttpContextAccessor(); + _controller = new TeamsController(teams, accessor); + } + + public async void GetMembersOfTest() + { + var result = await _controller.GetMembersOf(1); + Console.WriteLine($"GetMembersOf Result: {result}"); + } + + public async void CreateTeamTest() + { + var result = await _controller.CreateTeam(new TeamsController.CreateTeamRequest("Lakers", "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Los_Angeles_Lakers_logo.svg/2560px-Los_Angeles_Lakers_logo.svg.png", "#FFFFFF", "#000000")); + Console.WriteLine($"CreateTeam Result: {result}"); + } + + public async void AddMemberTest() + { + var result = await _controller.AddMember(1, new TeamsController.AddMemberRequest(1, "PLAYER")); + Console.WriteLine($"AddMember Result: {result}"); + } + + public async void UpdateMemberTest() + { + var result = await _controller.UpdateMember(1, 1, new TeamsController.UpdateMemberRequest("COACH")); + Console.WriteLine($"UpdateMember Result: {result}"); + } + + public async void RemoveMemberTest() + { + var result = await _controller.RemoveMember(1, 1); + Console.WriteLine($"RemoveMember Result: {result}"); + } + } +} \ No newline at end of file diff --git a/APIConsole/UsersAdminControllerConsole.cs b/APIConsole/UsersAdminControllerConsole.cs new file mode 100644 index 0000000..7b1809e --- /dev/null +++ b/APIConsole/UsersAdminControllerConsole.cs @@ -0,0 +1,60 @@ +using API.Controllers.Admin; +using DbServices; +using Microsoft.Extensions.Logging; +using Services; + +namespace APIConsole +{ + public class UsersAdminControllerConsole + { + private UsersAdminController _controller; + + public UsersAdminControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + IUserService users = new DbUserService(context); + ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + ILogger logger = loggerFactory.CreateLogger(); + _controller = new UsersAdminController(users, logger); + } + + public async void CountUsersTest() + { + var result = await _controller.CountUsers(); + Console.WriteLine($"CountUsers Result: {result}"); + } + + public async void ListUsersTest() + { + var result = await _controller.ListUsers(0, 10, null); + Console.WriteLine($"ListUsers Result: {result}"); + } + + public async void GetUserTest() + { + var result = await _controller.GetUser(1); + Console.WriteLine($"GetUser Result: {result}"); + } + + public async void AddUserTest() + { + var result = + await _controller.AddUser(new UsersAdminController.AddUserRequest("test", "123456", "test@mail.com")); + Console.WriteLine($"AddUser Result: {result}"); + } + + public async void RemoveUserTest() + { + var result = await _controller.RemoveUsers(new UsersAdminController.RemoveUsersRequest([1])); + Console.WriteLine($"RemoveUser Result: {result}"); + } + + public async void UpdateUserTest() + { + var result = + await _controller.UpdateUser(1, new UsersAdminController.UpdateUserRequest("testtest", "123456", false)); + Console.WriteLine($"UpdateUser Result: {result}"); + } + + } +} \ No newline at end of file diff --git a/APIConsole/UsersControllerConsole.cs b/APIConsole/UsersControllerConsole.cs new file mode 100644 index 0000000..29b5e0e --- /dev/null +++ b/APIConsole/UsersControllerConsole.cs @@ -0,0 +1,36 @@ +using API.Context; +using API.Controllers; +using DbServices; +using Services; + +namespace APIConsole +{ + public class UsersControllerConsole + { + private UsersController _controller; + + public UsersControllerConsole() + { + AppContext.AppContext context = new AppContext.AppContext(); + IUserService users = new DbUserService(context); + ITeamService teams = new DbTeamService(context); + ITacticService tactics = new DbTacticService(context); + IContextAccessor accessor = new HttpContextAccessor(); + + _controller = new UsersController(users, teams, tactics, accessor); + } + + public async void GetUserTest() + { + var result = await _controller.GetUser(); + Console.WriteLine($"GetUser Result: {result}"); + } + + public async void GetUserDataTest() + { + var result = await _controller.GetUserData(); + Console.WriteLine($"GetUserData Result: {result}"); + } + + } +} \ No newline at end of file