You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
6.1 KiB
185 lines
6.1 KiB
using System.ComponentModel.DataAnnotations;
|
|
using API.Context;
|
|
using API.Validation;
|
|
using AppContext.Entities;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Model;
|
|
using Services;
|
|
|
|
namespace API.Controllers;
|
|
|
|
[ApiController]
|
|
[Authorize]
|
|
public class TeamsController(ITeamService service, ITacticService tactics,IContextAccessor accessor) : ControllerBase
|
|
{
|
|
public record CreateTeamRequest(
|
|
[Name] string Name,
|
|
[Url] string Picture,
|
|
[RegularExpression("^#[0-9A-F]{6}$")] string FirstColor,
|
|
[RegularExpression("^#[0-9A-F]{6}$")] string SecondColor
|
|
);
|
|
|
|
[HttpPost("/teams")]
|
|
public async Task<IActionResult> CreateTeam([FromBody] CreateTeamRequest req)
|
|
{
|
|
var userId = accessor.CurrentUserId(HttpContext);
|
|
var team = await service.AddTeam(req.Name, req.Picture, req.FirstColor, req.SecondColor);
|
|
await service.AddMember(team.Id, userId, MemberRole.Coach);
|
|
return Ok(team);
|
|
}
|
|
|
|
[HttpGet("/teams/{teamId:int}/members")]
|
|
public async Task<IActionResult> GetMembersOf(int 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(
|
|
int UserId,
|
|
[AllowedValues("PLAYER", "COACH")] string Role
|
|
);
|
|
|
|
[HttpPost("/teams/{teamId:int}/members")]
|
|
public async Task<IActionResult> AddMember(int teamId, [FromBody] AddMemberRequest req)
|
|
{
|
|
if (!Enum.TryParse<MemberRole>(req.Role, true, out var role))
|
|
{
|
|
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);
|
|
|
|
if (result == null)
|
|
return Forbid();
|
|
|
|
return Ok(result);
|
|
}
|
|
case ITeamService.TeamAccessibility.NotFound:
|
|
case ITeamService.TeamAccessibility.Unauthorized:
|
|
return NotFound();
|
|
default: //unreachable
|
|
return Problem();
|
|
}
|
|
}
|
|
|
|
|
|
public record UpdateMemberRequest(
|
|
[AllowedValues("PLAYER", "COACH")] string Role
|
|
);
|
|
|
|
[HttpPut("/team/{teamId:int}/members/{userId:int}")]
|
|
public async Task<IActionResult> UpdateMember(int teamId, int userId, [FromBody] UpdateMemberRequest req)
|
|
{
|
|
if (!Enum.TryParse<MemberRole>(req.Role, true, out var role))
|
|
{
|
|
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 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<IActionResult> RemoveMember(int teamId, int userId)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
|
|
public record ShareTacticToTeamRequest(
|
|
int TacticId,
|
|
int TeamId
|
|
);
|
|
|
|
[HttpPost("/team/share-tactic")]
|
|
public async Task<IActionResult> ShareTactic([FromBody] ShareTacticToTeamRequest sharedTactic)
|
|
{
|
|
var userId = accessor.CurrentUserId(HttpContext);
|
|
var success = await tactics.ShareTactic(sharedTactic.TacticId, null, sharedTactic.TeamId);
|
|
|
|
return success ? Ok() : BadRequest();
|
|
}
|
|
|
|
[HttpDelete("/tactics/shared/{tacticId:int}/team/{teamId:int}")]
|
|
public async Task<IActionResult> UnshareTactic(int tacticId, int teamId)
|
|
{
|
|
var currentUserId = accessor.CurrentUserId(HttpContext);
|
|
var tactic = await tactics.GetTactic(tacticId);
|
|
|
|
if (tactic == null)
|
|
{
|
|
return NotFound();
|
|
}
|
|
if (currentUserId != tactic.OwnerId)
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
var success = await tactics.UnshareTactic(tacticId, null, teamId);
|
|
return success ? Ok() : NotFound();
|
|
}
|
|
|
|
[HttpGet("/tactics/shared/team/{teamId:int}")]
|
|
public async Task<IActionResult> GetSharedTacticsToTeam(int teamId)
|
|
{
|
|
var currentUserId = accessor.CurrentUserId(HttpContext);
|
|
|
|
if (!await service.IsUserInTeam(currentUserId, teamId))
|
|
{
|
|
return Unauthorized();
|
|
}
|
|
|
|
var sharedTactics = await service.GetSharedTacticsToTeam(teamId);
|
|
return sharedTactics != null ? Ok(sharedTactics) : NotFound();
|
|
}
|
|
} |