checkpoint
This commit is contained in:
@@ -16,226 +16,239 @@ using System.Threading.Tasks;
|
||||
namespace Gameboard.ShogiUI.Sockets.Controllers
|
||||
{
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Authorize(Roles = "Shogi")]
|
||||
public class GameController : ControllerBase
|
||||
{
|
||||
private readonly IGameboardManager gameboardManager;
|
||||
private readonly IGameboardRepository gameboardRepository;
|
||||
private readonly ISocketConnectionManager communicationManager;
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Authorize(Roles = "Shogi")]
|
||||
public class GameController : ControllerBase
|
||||
{
|
||||
private readonly IGameboardManager gameboardManager;
|
||||
private readonly IGameboardRepository gameboardRepository;
|
||||
private readonly ISocketConnectionManager communicationManager;
|
||||
|
||||
public GameController(
|
||||
IGameboardRepository repository,
|
||||
IGameboardManager manager,
|
||||
ISocketConnectionManager communicationManager)
|
||||
{
|
||||
gameboardManager = manager;
|
||||
gameboardRepository = repository;
|
||||
this.communicationManager = communicationManager;
|
||||
}
|
||||
public GameController(
|
||||
IGameboardRepository repository,
|
||||
IGameboardManager manager,
|
||||
ISocketConnectionManager communicationManager)
|
||||
{
|
||||
gameboardManager = manager;
|
||||
gameboardRepository = repository;
|
||||
this.communicationManager = communicationManager;
|
||||
}
|
||||
|
||||
[HttpPost("JoinCode")]
|
||||
public async Task<IActionResult> PostGameInvitation([FromBody] PostGameInvitation request)
|
||||
{
|
||||
[HttpPost("JoinCode")]
|
||||
public async Task<IActionResult> PostGameInvitation([FromBody] PostGameInvitation request)
|
||||
{
|
||||
|
||||
//var isPlayer1 = await gameboardManager.IsPlayer1(request.SessionName, userName);
|
||||
//if (isPlayer1)
|
||||
//{
|
||||
// var code = await gameboardRepository.PostJoinCode(request.SessionName, userName);
|
||||
// return new CreatedResult("", new PostGameInvitationResponse(code));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
return new UnauthorizedResult();
|
||||
//}
|
||||
}
|
||||
//var isPlayer1 = await gameboardManager.IsPlayer1(request.SessionName, userName);
|
||||
//if (isPlayer1)
|
||||
//{
|
||||
// var code = await gameboardRepository.PostJoinCode(request.SessionName, userName);
|
||||
// return new CreatedResult("", new PostGameInvitationResponse(code));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
return new UnauthorizedResult();
|
||||
//}
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("GuestJoinCode")]
|
||||
public async Task<IActionResult> PostGuestGameInvitation([FromBody] PostGuestGameInvitation request)
|
||||
{
|
||||
[AllowAnonymous]
|
||||
[HttpPost("GuestJoinCode")]
|
||||
public async Task<IActionResult> PostGuestGameInvitation([FromBody] PostGuestGameInvitation request)
|
||||
{
|
||||
|
||||
//var isGuest = gameboardManager.IsGuest(request.GuestId);
|
||||
//var isPlayer1 = gameboardManager.IsPlayer1(request.SessionName, request.GuestId);
|
||||
//if (isGuest && await isPlayer1)
|
||||
//{
|
||||
// var code = await gameboardRepository.PostJoinCode(request.SessionName, request.GuestId);
|
||||
// return new CreatedResult("", new PostGameInvitationResponse(code));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
return new UnauthorizedResult();
|
||||
//}
|
||||
}
|
||||
//var isGuest = gameboardManager.IsGuest(request.GuestId);
|
||||
//var isPlayer1 = gameboardManager.IsPlayer1(request.SessionName, request.GuestId);
|
||||
//if (isGuest && await isPlayer1)
|
||||
//{
|
||||
// var code = await gameboardRepository.PostJoinCode(request.SessionName, request.GuestId);
|
||||
// return new CreatedResult("", new PostGameInvitationResponse(code));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
return new UnauthorizedResult();
|
||||
//}
|
||||
}
|
||||
|
||||
[HttpPost("{gameName}/Move")]
|
||||
public async Task<IActionResult> PostMove([FromRoute] string gameName, [FromBody] PostMove request)
|
||||
{
|
||||
var user = await gameboardManager.ReadUser(User);
|
||||
var session = await gameboardRepository.ReadSession(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (user == null || (session.Player1.Id != user.Id && session.Player2?.Id != user.Id))
|
||||
{
|
||||
return Forbid("User is not seated at this game.");
|
||||
}
|
||||
[HttpPost("{gameName}/Move")]
|
||||
public async Task<IActionResult> PostMove([FromRoute] string gameName, [FromBody] PostMove request)
|
||||
{
|
||||
var user = await gameboardManager.ReadUser(User);
|
||||
var session = await gameboardRepository.ReadSession(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (user == null || (session.Player1.Id != user.Id && session.Player2?.Id != user.Id))
|
||||
{
|
||||
return Forbid("User is not seated at this game.");
|
||||
}
|
||||
|
||||
var move = request.Move;
|
||||
var moveModel = move.PieceFromCaptured.HasValue
|
||||
? new Models.Move(move.PieceFromCaptured.Value, move.To, move.IsPromotion)
|
||||
: new Models.Move(move.From!, move.To, move.IsPromotion);
|
||||
var moveSuccess = session.Shogi.Move(moveModel);
|
||||
var move = request.Move;
|
||||
var moveModel = move.PieceFromCaptured.HasValue
|
||||
? new Models.Move(move.PieceFromCaptured.Value, move.To, move.IsPromotion)
|
||||
: new Models.Move(move.From!, move.To, move.IsPromotion);
|
||||
var moveSuccess = session.Shogi.Move(moveModel);
|
||||
|
||||
if (moveSuccess)
|
||||
{
|
||||
var createSuccess = await gameboardRepository.CreateBoardState(session);
|
||||
if (!createSuccess)
|
||||
{
|
||||
throw new ApplicationException("Unable to persist board state.");
|
||||
}
|
||||
await communicationManager.BroadcastToPlayers(new MoveResponse
|
||||
{
|
||||
GameName = session.Name,
|
||||
PlayerName = user.Id
|
||||
}, session.Player1.Id, session.Player2?.Id);
|
||||
return Ok();
|
||||
}
|
||||
return Conflict("Illegal move.");
|
||||
}
|
||||
if (moveSuccess)
|
||||
{
|
||||
var createSuccess = await gameboardRepository.CreateBoardState(session);
|
||||
if (!createSuccess)
|
||||
{
|
||||
throw new ApplicationException("Unable to persist board state.");
|
||||
}
|
||||
await communicationManager.BroadcastToPlayers(new MoveResponse
|
||||
{
|
||||
GameName = session.Name,
|
||||
PlayerName = user.Id
|
||||
}, session.Player1.Id, session.Player2?.Id);
|
||||
return Ok();
|
||||
}
|
||||
return Conflict("Illegal move.");
|
||||
}
|
||||
|
||||
// TODO: Use JWT tokens for guests so they can authenticate and use API routes, too.
|
||||
//[Route("")]
|
||||
//public async Task<IActionResult> PostSession([FromBody] PostSession request)
|
||||
//{
|
||||
// var model = new Models.Session(request.Name, request.IsPrivate, request.Player1, request.Player2);
|
||||
// var success = await repository.CreateSession(model);
|
||||
// if (success)
|
||||
// {
|
||||
// var message = new ServiceModels.Socket.Messages.CreateGameResponse(ServiceModels.Types.ClientAction.CreateGame)
|
||||
// {
|
||||
// Game = model.ToServiceModel(),
|
||||
// PlayerName =
|
||||
// }
|
||||
// var task = request.IsPrivate
|
||||
// ? communicationManager.BroadcastToPlayers(response, userName)
|
||||
// : communicationManager.BroadcastToAll(response);
|
||||
// return new CreatedResult("", null);
|
||||
// }
|
||||
// return new ConflictResult();
|
||||
//}
|
||||
// TODO: Use JWT tokens for guests so they can authenticate and use API routes, too.
|
||||
//[Route("")]
|
||||
//public async Task<IActionResult> PostSession([FromBody] PostSession request)
|
||||
//{
|
||||
// var model = new Models.Session(request.Name, request.IsPrivate, request.Player1, request.Player2);
|
||||
// var success = await repository.CreateSession(model);
|
||||
// if (success)
|
||||
// {
|
||||
// var message = new ServiceModels.Socket.Messages.CreateGameResponse(ServiceModels.Types.ClientAction.CreateGame)
|
||||
// {
|
||||
// Game = model.ToServiceModel(),
|
||||
// PlayerName =
|
||||
// }
|
||||
// var task = request.IsPrivate
|
||||
// ? communicationManager.BroadcastToPlayers(response, userName)
|
||||
// : communicationManager.BroadcastToAll(response);
|
||||
// return new CreatedResult("", null);
|
||||
// }
|
||||
// return new ConflictResult();
|
||||
//}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> PostSession([FromBody] PostSession request)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = new Models.SessionMetadata(request.Name, request.IsPrivate, user!);
|
||||
var success = await gameboardRepository.CreateSession(session);
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> PostSession([FromBody] PostSession request)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = new Models.SessionMetadata(request.Name, request.IsPrivate, user!);
|
||||
var success = await gameboardRepository.CreateSession(session);
|
||||
|
||||
if (success)
|
||||
{
|
||||
await communicationManager.BroadcastToAll(new CreateGameResponse
|
||||
{
|
||||
Game = session.ToServiceModel(),
|
||||
PlayerName = user.Id
|
||||
}).ContinueWith(cont =>
|
||||
{
|
||||
if (cont.Exception != null)
|
||||
{
|
||||
Console.Error.WriteLine("Yep");
|
||||
}
|
||||
});
|
||||
return Ok();
|
||||
}
|
||||
return Conflict();
|
||||
if (success)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
}
|
||||
await communicationManager.BroadcastToAll(new CreateGameResponse
|
||||
{
|
||||
Game = session.ToServiceModel(),
|
||||
PlayerName = user.Id
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine("Error broadcasting during PostSession");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the board session and subscribes the caller to socket events for that session.
|
||||
/// </summary>
|
||||
[HttpGet("{gameName}")]
|
||||
public async Task<IActionResult> GetSession([FromRoute] string gameName)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = await gameboardRepository.ReadSession(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
return Conflict();
|
||||
|
||||
communicationManager.SubscribeToGame(session, user!.Id);
|
||||
var response = new GetSessionResponse()
|
||||
{
|
||||
Game = new Models.SessionMetadata(session).ToServiceModel(user),
|
||||
BoardState = session.Shogi.ToServiceModel(),
|
||||
MoveHistory = session.Shogi.MoveHistory.Select(_ => _.ToServiceModel()).ToList(),
|
||||
PlayerPerspective = user.Id == session.Player1.Id ? WhichPlayer.Player1 : WhichPlayer.Player2
|
||||
};
|
||||
return new JsonResult(response);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<GetSessionsResponse> GetSessions()
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var sessions = await gameboardRepository.ReadSessionMetadatas();
|
||||
/// <summary>
|
||||
/// Reads the board session and subscribes the caller to socket events for that session.
|
||||
/// </summary>
|
||||
[HttpGet("{gameName}")]
|
||||
public async Task<IActionResult> GetSession([FromRoute] string gameName)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = await gameboardRepository.ReadSession(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var sessionsJoinedByUser = sessions
|
||||
.Where(s => s.IsSeated(user))
|
||||
.Select(s => s.ToServiceModel())
|
||||
.ToList();
|
||||
var sessionsNotJoinedByUser = sessions
|
||||
.Where(s => !s.IsSeated(user))
|
||||
.Select(s => s.ToServiceModel())
|
||||
.ToList();
|
||||
var playerPerspective = WhichPerspective.Spectator;
|
||||
if (session.Player1.Id == user.Id)
|
||||
{
|
||||
playerPerspective = WhichPerspective.Player1;
|
||||
}
|
||||
else if (session.Player2?.Id == user.Id)
|
||||
{
|
||||
playerPerspective = WhichPerspective.Player2;
|
||||
}
|
||||
|
||||
return new GetSessionsResponse
|
||||
{
|
||||
PlayerHasJoinedSessions = new Collection<Game>(sessionsJoinedByUser),
|
||||
AllOtherSessions = new Collection<Game>(sessionsNotJoinedByUser)
|
||||
};
|
||||
}
|
||||
communicationManager.SubscribeToGame(session, user!.Id);
|
||||
var response = new GetSessionResponse()
|
||||
{
|
||||
Game = new Models.SessionMetadata(session).ToServiceModel(),
|
||||
BoardState = session.Shogi.ToServiceModel(),
|
||||
MoveHistory = session.Shogi.MoveHistory.Select(_ => _.ToServiceModel()).ToList(),
|
||||
PlayerPerspective = playerPerspective
|
||||
};
|
||||
return new JsonResult(response);
|
||||
}
|
||||
|
||||
[HttpPut("{gameName}")]
|
||||
public async Task<IActionResult> PutJoinSession([FromRoute] string gameName)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = await gameboardRepository.ReadSessionMetaData(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (session.Player2 != null)
|
||||
{
|
||||
return this.Conflict("This session already has two seated players and is full.");
|
||||
}
|
||||
[HttpGet]
|
||||
public async Task<GetSessionsResponse> GetSessions()
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var sessions = await gameboardRepository.ReadSessionMetadatas();
|
||||
|
||||
session.SetPlayer2(user);
|
||||
var success = await gameboardRepository.UpdateSession(session);
|
||||
if (!success) return this.Problem(detail: "Unable to update session.");
|
||||
var sessionsJoinedByUser = sessions
|
||||
.Where(s => s.IsSeated(user))
|
||||
.Select(s => s.ToServiceModel())
|
||||
.ToList();
|
||||
var sessionsNotJoinedByUser = sessions
|
||||
.Where(s => !s.IsSeated(user))
|
||||
.Select(s => s.ToServiceModel())
|
||||
.ToList();
|
||||
|
||||
var opponentName = user.Id == session.Player1.Id
|
||||
? session.Player2!.Id
|
||||
: session.Player1.Id;
|
||||
await communicationManager.BroadcastToPlayers(new JoinGameResponse
|
||||
{
|
||||
GameName = session.Name,
|
||||
PlayerName = user.Id
|
||||
}, opponentName);
|
||||
return Ok();
|
||||
}
|
||||
return new GetSessionsResponse
|
||||
{
|
||||
PlayerHasJoinedSessions = new Collection<Game>(sessionsJoinedByUser),
|
||||
AllOtherSessions = new Collection<Game>(sessionsNotJoinedByUser)
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<Models.User> ReadUserOrThrow()
|
||||
{
|
||||
var user = await gameboardManager.ReadUser(User);
|
||||
if (user == null)
|
||||
{
|
||||
throw new UnauthorizedAccessException("Unknown user claims.");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
[HttpPut("{gameName}")]
|
||||
public async Task<IActionResult> PutJoinSession([FromRoute] string gameName)
|
||||
{
|
||||
var user = await ReadUserOrThrow();
|
||||
var session = await gameboardRepository.ReadSessionMetaData(gameName);
|
||||
if (session == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (session.Player2 != null)
|
||||
{
|
||||
return this.Conflict("This session already has two seated players and is full.");
|
||||
}
|
||||
|
||||
session.SetPlayer2(user);
|
||||
var success = await gameboardRepository.UpdateSession(session);
|
||||
if (!success) return this.Problem(detail: "Unable to update session.");
|
||||
|
||||
var opponentName = user.Id == session.Player1.Id
|
||||
? session.Player2!.Id
|
||||
: session.Player1.Id;
|
||||
await communicationManager.BroadcastToPlayers(new JoinGameResponse
|
||||
{
|
||||
GameName = session.Name,
|
||||
PlayerName = user.Id
|
||||
}, opponentName);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private async Task<Models.User> ReadUserOrThrow()
|
||||
{
|
||||
var user = await gameboardManager.ReadUser(User);
|
||||
if (user == null)
|
||||
{
|
||||
throw new UnauthorizedAccessException("Unknown user claims.");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user