diff --git a/Controllers/LocationController.cs b/Controllers/LocationController.cs index 7d7274f..4d586a7 100644 --- a/Controllers/LocationController.cs +++ b/Controllers/LocationController.cs @@ -45,6 +45,30 @@ public class LocationController : ControllerBase return Ok(newLoc); } + [HttpPut("{id}")] + [Authorize(Roles = "SUPER")] + public async Task Update(string id, [FromBody] UpdateLocationRequest req) + { + var location = await _locationService.GetByIdAsync(id); + if (location == null) + return NotFound("Location not found."); + + location.X = req.X; + location.Y = req.Y; + location.Z = req.Z; + location.N = req.N; + location.NE = req.NE; + location.E = req.E; + location.SE = req.SE; + location.S = req.S; + location.SW = req.SW; + location.W = req.W; + location.NW = req.NW; + + await _locationService.UpdateAsync(location); + return Ok(location); + } + [HttpDelete("{id}")] [Authorize(Roles = "SUPER")] public async Task Delete(string id) diff --git a/Controllers/PlayerController.cs b/Controllers/PlayerController.cs index 1b5bc33..cf27e55 100644 --- a/Controllers/PlayerController.cs +++ b/Controllers/PlayerController.cs @@ -93,6 +93,21 @@ public class PlayerController : ControllerBase return Ok(player); } + [HttpPut] + [Authorize(Roles = "USER,SUPER")] + public async Task Update([FromBody] UpdatePlayerRequest req) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var player = await _playerService.GetByUserIdAsync(userId); + if (player == null) + return NotFound("Player not found."); + + player.Name = req.Name; + player.Climbing = req.Climbing; + await _playerService.UpdateAsync(player); + return Ok(player); + } + [HttpDelete] [Authorize(Roles = "USER,SUPER")] public async Task Delete() diff --git a/Controllers/SpawnableController.cs b/Controllers/SpawnableController.cs index c339ae9..75256da 100644 --- a/Controllers/SpawnableController.cs +++ b/Controllers/SpawnableController.cs @@ -33,6 +33,23 @@ public class SpawnableController : ControllerBase return Ok(spawnable); } + [HttpPut("{id}")] + [Authorize(Roles = "SUPER")] + public async Task Update(string id, [FromBody] UpdateSpawnableRequest req) + { + var spawnable = await _spawnableService.GetByIdAsync(id); + if (spawnable == null) + return NotFound("Spawnable not found."); + + spawnable.Name = req.Name.ToLower(); + spawnable.SpawnRate = req.SpawnRate; + spawnable.CollectAction = req.CollectAction; + spawnable.CollectResults = req.CollectResults; + + await _spawnableService.UpdateAsync(spawnable); + return Ok(spawnable); + } + [HttpGet] [Authorize(Roles = "SUPER")] public async Task GetAll() diff --git a/Controllers/UserController.cs b/Controllers/UserController.cs index 2a4ba05..33b4c47 100644 --- a/Controllers/UserController.cs +++ b/Controllers/UserController.cs @@ -26,6 +26,20 @@ public class UserController : ControllerBase return Ok(users); } + [HttpPut] + [Authorize(Roles = "SUPER")] + public async Task UpdateUser([FromQuery] string username, [FromBody] UpdateUserRequest req) + { + var user = await _userService.GetByUsernameAsync(username); + if (user == null) + return NotFound($"User '{username}' not found."); + + user.Role = req.Role; + user.Email = req.Email; + await _userService.UpdateAsync(user); + return Ok(user); + } + // DELETE: /api/User?username=foo [HttpDelete] [Authorize(Roles = "SUPER")] diff --git a/GameAuthApi.Tests/LocationControllerTests.cs b/GameAuthApi.Tests/LocationControllerTests.cs index 67efa85..81413be 100644 --- a/GameAuthApi.Tests/LocationControllerTests.cs +++ b/GameAuthApi.Tests/LocationControllerTests.cs @@ -37,4 +37,16 @@ public class LocationControllerTests Assert.IsType(result); } + + [Fact] + public async Task Update_NotFound() + { + var svc = new Mock(config); + svc.Setup(l => l.GetByIdAsync("id")).ReturnsAsync((Location?)null); + var controller = new LocationController(svc.Object, new Mock(config).Object); + + var result = await controller.Update("id", new UpdateLocationRequest()); + + Assert.IsType(result); + } } diff --git a/GameAuthApi.Tests/PlayerControllerTests.cs b/GameAuthApi.Tests/PlayerControllerTests.cs index 9fc342c..abfc656 100644 --- a/GameAuthApi.Tests/PlayerControllerTests.cs +++ b/GameAuthApi.Tests/PlayerControllerTests.cs @@ -61,6 +61,21 @@ public class PlayerControllerTests Assert.IsType(result); } + [Fact] + public async Task Update_PlayerNotFound() + { + var svc = new Mock(cfg); + svc.Setup(p => p.GetByUserIdAsync("u")).ReturnsAsync((Player?)null); + var controller = new PlayerController(svc.Object, new Mock(cfg).Object, new Mock(cfg).Object, new Mock(cfg).Object) + { + ControllerContext = ContextWithUser("u") + }; + + var result = await controller.Update(new UpdatePlayerRequest { Name="n", Climbing=1 }); + + Assert.IsType(result); + } + [Fact] public async Task AdminTeleport_PlayerNotFound() { diff --git a/GameAuthApi.Tests/SpawnableControllerTests.cs b/GameAuthApi.Tests/SpawnableControllerTests.cs index a774a81..70d0926 100644 --- a/GameAuthApi.Tests/SpawnableControllerTests.cs +++ b/GameAuthApi.Tests/SpawnableControllerTests.cs @@ -66,4 +66,16 @@ public class SpawnableControllerTests Assert.IsType(result); } + + [Fact] + public async Task Update_NotFound() + { + var svc = new Mock(config); + svc.Setup(s => s.GetByIdAsync("id")).ReturnsAsync((Spawnable)null); + var controller = new SpawnableController(svc.Object); + + var result = await controller.Update("id", new UpdateSpawnableRequest { Name="n", SpawnRate=1, CollectAction="a" }); + + Assert.IsType(result); + } } diff --git a/GameAuthApi.Tests/UserControllerTests.cs b/GameAuthApi.Tests/UserControllerTests.cs index 6e544d3..4d6b372 100644 --- a/GameAuthApi.Tests/UserControllerTests.cs +++ b/GameAuthApi.Tests/UserControllerTests.cs @@ -43,4 +43,22 @@ public class UserControllerTests Assert.IsType(result); } + + [Fact] + public async Task UpdateUser_NotFound() + { + var config = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + {"MongoDB:ConnectionString","mongodb://localhost"}, + {"MongoDB:DatabaseName","test"} + }).Build(); + var mockService = new Mock(config); + mockService.Setup(s => s.GetByUsernameAsync("no")).ReturnsAsync((User)null); + var controller = new UserController(mockService.Object); + + var result = await controller.UpdateUser("no", new UpdateUserRequest { Email="e", Role="USER" }); + + Assert.IsType(result); + } } diff --git a/Models/DTOs/UpdateLocationRequest.cs b/Models/DTOs/UpdateLocationRequest.cs new file mode 100644 index 0000000..4bde447 --- /dev/null +++ b/Models/DTOs/UpdateLocationRequest.cs @@ -0,0 +1,17 @@ +namespace GameAuthApi.Models; + +public class UpdateLocationRequest +{ + public int? X { get; set; } + public int? Y { get; set; } + public int? Z { get; set; } + + public string N { get; set; } + public string NE { get; set; } + public string E { get; set; } + public string SE { get; set; } + public string S { get; set; } + public string SW { get; set; } + public string W { get; set; } + public string NW { get; set; } +} diff --git a/Models/DTOs/UpdatePlayerRequest.cs b/Models/DTOs/UpdatePlayerRequest.cs new file mode 100644 index 0000000..adeba2e --- /dev/null +++ b/Models/DTOs/UpdatePlayerRequest.cs @@ -0,0 +1,7 @@ +namespace GameAuthApi.Models; + +public class UpdatePlayerRequest +{ + public string Name { get; set; } + public int Climbing { get; set; } +} diff --git a/Models/DTOs/UpdateSpawnableRequest.cs b/Models/DTOs/UpdateSpawnableRequest.cs new file mode 100644 index 0000000..f1170c7 --- /dev/null +++ b/Models/DTOs/UpdateSpawnableRequest.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace GameAuthApi.Models; + +public class UpdateSpawnableRequest +{ + public string Name { get; set; } + public int SpawnRate { get; set; } + public string CollectAction { get; set; } + public List CollectResults { get; set; } = []; +} diff --git a/Models/DTOs/UpdateUserRequest.cs b/Models/DTOs/UpdateUserRequest.cs new file mode 100644 index 0000000..bc5e258 --- /dev/null +++ b/Models/DTOs/UpdateUserRequest.cs @@ -0,0 +1,7 @@ +namespace GameAuthApi.Models; + +public class UpdateUserRequest +{ + public string Role { get; set; } + public string Email { get; set; } +} diff --git a/Services/SpawnableService.cs b/Services/SpawnableService.cs index 9d05c17..df8f16e 100644 --- a/Services/SpawnableService.cs +++ b/Services/SpawnableService.cs @@ -45,4 +45,9 @@ public class SpawnableService { await _spawnables.DeleteOneAsync(s => s.Id == id); } + + public virtual async Task UpdateAsync(Spawnable spawnable) + { + await _spawnables.ReplaceOneAsync(s => s.Id == spawnable.Id, spawnable); + } }