Files
Shogi/Shogi.Api/Controllers/SessionsController.cs
2024-11-16 12:37:56 -06:00

132 lines
3.7 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Shogi.Api.Application;
using Shogi.Api.Extensions;
using Shogi.Api.Repositories;
using Shogi.Contracts.Api.Commands;
using Shogi.Contracts.Types;
namespace Shogi.Api.Controllers;
[Authorize]
[ApiController]
[Route("[controller]")]
public class SessionsController(
SessionRepository sessionRepository,
ShogiApplication application) : ControllerBase
{
[HttpPost]
public async Task<IActionResult> CreateSession()
{
var id = this.User.GetId();
if (string.IsNullOrEmpty(id))
{
return this.Unauthorized();
}
return await application.CreateSession(id);
}
[HttpDelete("{sessionId}")]
public async Task<IActionResult> DeleteSession(string sessionId)
{
var id = this.User.GetId();
if (id == null)
{
return this.Unauthorized();
}
var (session, _) = await sessionRepository.ReadSessionAndMoves(sessionId);
if (!session.HasValue) return this.NoContent();
if (session.Value.Player1Id == id)
{
await sessionRepository.DeleteSession(sessionId);
return this.NoContent();
}
return this.StatusCode(StatusCodes.Status403Forbidden, "Cannot delete sessions created by others.");
}
/// <summary>
/// Fetch the session and latest board state. Also subscribe the user to socket events for this session.
/// </summary>
/// <param name="sessionId"></param>
/// <returns></returns>
[HttpGet("{sessionId}")]
[AllowAnonymous]
public async Task<ActionResult<Session>> GetSession(Guid sessionId)
{
var session = await application.ReadSession(sessionId.ToString());
if (session == null) return this.NotFound();
return new Session
{
BoardState = new BoardState
{
Board = session.Board.BoardState.State.ToContract(),
Player1Hand = session.Board.BoardState.Player1Hand.Select(p => p.WhichPiece.ToContract()).ToArray(),
Player2Hand = session.Board.BoardState.Player2Hand.Select(p => p.WhichPiece.ToContract()).ToArray(),
PlayerInCheck = session.Board.BoardState.InCheck?.ToContract(),
WhoseTurn = session.Board.BoardState.WhoseTurn.ToContract(),
Victor = session.Board.BoardState.IsCheckmate
? session.Board.BoardState.InCheck == Domain.ValueObjects.WhichPlayer.Player1 ? WhichPlayer.Player2 : WhichPlayer.Player1
: null
},
Player1 = application.GetUsername(session.Player1),
Player2 = application.GetUsername(session.Player2),
SessionId = session.Id
};
}
[HttpGet]
[AllowAnonymous]
public async Task<ActionResult<SessionMetadata[]>> ReadAllSessionsMetadata()
{
var id = this.User.GetId() ?? string.Empty;
var dtos = await application.ReadAllSessionMetadatas(id);
return dtos
.Select(dto => new SessionMetadata
{
Player1 = application.GetUsername(dto.Player1Id),
Player2 = application.GetUsername(dto.Player2Id),
SessionId = Guid.Parse(dto.Id),
})
.ToArray();
}
[HttpPatch("{sessionId}/Join")]
public async Task<IActionResult> JoinSession(string sessionId)
{
var id = this.User.GetId();
if (id == null)
{
return this.Unauthorized();
}
return await application.JoinSession(sessionId, id);
}
[HttpPatch("{sessionId}/Move")]
public async Task<IActionResult> Move([FromRoute] string sessionId, [FromBody] MovePieceCommand command)
{
var id = this.User.GetId();
if (id == null)
{
return this.Unauthorized();
}
return await application.MovePiece(id, sessionId, command);
}
/// <summary>
/// Returns an array of board states, one per player move of the given session, in the same order that player moves occurred.
/// </summary>
[HttpGet("{sessionId}/History")]
[AllowAnonymous]
public async Task<IActionResult> GetHistory([FromRoute] string sessionId)
{
return await application.ReadSessionSnapshots(sessionId);
}
}