Zeeshaun e79f473ce4
All checks were successful
Deploy Promiscuity Auth API / deploy (push) Successful in 45s
Deploy Promiscuity Character API / deploy (push) Successful in 57s
Deploy Promiscuity Locations API / deploy (push) Successful in 44s
k8s smoke test / test (push) Successful in 7s
Updating character location based on occupied tile
2026-03-13 21:34:59 -05:00

148 lines
4.7 KiB
C#

using CharacterApi.Models;
using CharacterApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace CharacterApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class CharactersController : ControllerBase
{
private readonly CharacterStore _characters;
private readonly ILogger<CharactersController> _logger;
public CharactersController(CharacterStore characters, ILogger<CharactersController> logger)
{
_characters = characters;
_logger = logger;
}
[HttpPost]
[Authorize(Roles = "USER,SUPER")]
public async Task<IActionResult> Create([FromBody] CreateCharacterRequest req)
{
if (string.IsNullOrWhiteSpace(req.Name))
return BadRequest("Name required");
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var character = new Character
{
OwnerUserId = userId,
Name = req.Name.Trim(),
Coord = new Coord { X = 0, Y = 0 },
VisionRadius = 3,
CreatedUtc = DateTime.UtcNow
};
await _characters.CreateAsync(character);
return Ok(character);
}
[HttpGet]
[Authorize(Roles = "USER,SUPER")]
public async Task<IActionResult> ListMine()
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var characters = await _characters.GetForOwnerAsync(userId);
return Ok(characters);
}
[HttpGet("{id}/visible-locations")]
[Authorize(Roles = "USER,SUPER")]
public async Task<IActionResult> VisibleLocations(string id)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var allowAnyOwner = User.IsInRole("SUPER");
var character = await _characters.GetByIdAsync(id);
if (character is null)
{
_logger.LogWarning("Visible locations request failed: character {CharacterId} was not found.", id);
return NotFound();
}
if (!allowAnyOwner && character.OwnerUserId != userId)
{
_logger.LogWarning(
"Visible locations request denied: character {CharacterId} belongs to owner {OwnerUserId}, request user was {UserId}",
id,
character.OwnerUserId,
userId
);
return Forbid();
}
_logger.LogInformation(
"Visible locations requested for character {CharacterId} at ({X},{Y}) radius {VisionRadius} by user {UserId}",
character.Id,
character.Coord.X,
character.Coord.Y,
character.VisionRadius,
userId
);
var generation = await _characters.GetOrCreateVisibleLocationsAsync(character);
var locations = generation.Locations;
_logger.LogInformation(
"Visible locations resolved for character {CharacterId}: generated {GeneratedCount}, returned {ReturnedCount}",
character.Id,
generation.GeneratedCount,
locations.Count
);
return Ok(locations);
}
[HttpPut("{id}/coord")]
[Authorize(Roles = "USER,SUPER")]
public async Task<IActionResult> UpdateCoord(string id, [FromBody] UpdateCharacterCoordRequest req)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
if (req.Coord is null)
return BadRequest("Coord required");
var allowAnyOwner = User.IsInRole("SUPER");
var character = await _characters.GetByIdAsync(id);
if (character is null)
return NotFound();
if (!allowAnyOwner && character.OwnerUserId != userId)
return Forbid();
character.Coord = req.Coord;
var updated = await _characters.UpdateCoordAsync(id, req.Coord);
if (!updated)
return NotFound();
return Ok(character);
}
[HttpDelete("{id}")]
[Authorize(Roles = "USER,SUPER")]
public async Task<IActionResult> Delete(string id)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrWhiteSpace(userId))
return Unauthorized();
var allowAnyOwner = User.IsInRole("SUPER");
var deleted = await _characters.DeleteForOwnerAsync(id, userId, allowAnyOwner);
if (!deleted)
return NotFound();
return Ok("Deleted");
}
}