using System.ComponentModel.DataAnnotations; using System.Runtime.CompilerServices; using API.Context; using API.DTO; using API.Validation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Model; using Services; [assembly: InternalsVisibleTo("UnitTests")] namespace API.Controllers; [ApiController] public class UsersController(IUserService users, ITeamService teams, ITacticService tactics, IContextAccessor accessor) : ControllerBase { public const string DefaultProfilePicture = "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png"; [Authorize] [HttpGet("/user")] public async Task GetUser() { var userId = accessor.CurrentUserId(HttpContext); return (await users.GetUser(userId))!; } public record GetUserDataResponse(Team[] Teams, TacticDto[] Tactics, TacticDto[] SharedTactics); [Authorize] [HttpGet("/user-data")] public async Task GetUserData() { var userId = accessor.CurrentUserId(HttpContext); var userTeams = await teams.ListTeamsOf(userId).ToArray(); var userTactics = await tactics.ListTacticsOf(userId).Select(t => t.ToDto()).ToArray(); var sharedTacticsToUser = await users.GetSharedTacticsToUser(userId); var sharedTacticsToTeam = await teams.GetSharedTacticsToTeams(userId); var sharedTactics = sharedTacticsToTeam.Concat(sharedTacticsToUser).Select(t => t.ToDto()).ToArray(); return new GetUserDataResponse(userTeams, userTactics, sharedTactics); } public record ChangeUserInformationRequest( [EmailAddress] string? Email = null, [Name] string? Name = null, [StringLength(1024)] string? ProfilePicture = null, [StringLength(256, MinimumLength = 4, ErrorMessage = "password length must be between 4 and 256")] string? Password = null ); [HttpPut("/user")] [Authorize] public async Task ChangeUserInformation([FromBody] ChangeUserInformationRequest req) { var userId = accessor.CurrentUserId(HttpContext); var currentUser = (await users.GetUser(userId))!; try { await users.UpdateUser( new User( userId, req.Name ?? currentUser.Name, req.Email ?? currentUser.Email, req.ProfilePicture ?? currentUser.ProfilePicture, currentUser.IsAdmin ), req.Password ); } catch (ServiceException e) { return BadRequest(e.FailuresMessages()); } return Ok(); } public record ShareTacticToUserRequest( int TacticId, int UserId ); [HttpPost("/user/share-tactic")] [Authorize] public async Task ShareTactic([FromBody] ShareTacticToUserRequest sharedTactic) { var currentUserId = accessor.CurrentUserId(HttpContext); var tactic = await tactics.GetTactic(sharedTactic.TacticId); if (tactic == null) { return NotFound(); } if (currentUserId != tactic.OwnerId) { return Unauthorized(); } var result = await tactics.ShareTactic(sharedTactic.TacticId, sharedTactic.UserId, null); return result ? Ok() : NotFound(); } [HttpDelete("/tactics/shared/{tacticId:int}/user/{userId:int}")] [Authorize] public async Task UnshareTactic(int tacticId, int userId) { 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, userId, null); return success ? Ok() : NotFound(); } [HttpGet("/tactics/shared/user/{userId:int}")] [Authorize] public async Task GetSharedTacticsToUser(int userId) { var currentUserId = accessor.CurrentUserId(HttpContext); if (currentUserId != userId) { return Unauthorized(); } var sharedTactics = await users.GetSharedTacticsToUser(userId); return Ok(sharedTactics); } }