using Microsoft.Extensions.Caching.Distributed; using qtc_api.Extensions; using System.Security.Claims; namespace qtc_api.Controllers { [Route("api/users")] [ApiController] public class UsersController : ControllerBase { private readonly IUserService _userService; private readonly IDistributedCache _cache; private readonly IHubContext _chatGWContext; public UsersController(IUserService userService, IDistributedCache distributedCache, IHubContext chatGWContext) { _userService = userService; _cache = distributedCache; _chatGWContext = chatGWContext; } [HttpGet("all")] [Authorize] public async Task>>> GetAllUsers() { var users = await _userService.GetAllUsers(); return Ok(users); } [HttpGet("user-info")] [Authorize] public async Task>> GetUserInformation(string id) { var user = await _userService.GetUserInformationById(id); return Ok(user); } [HttpGet("user-authorized")] [Authorize] public async Task>> UserFromAuthorizeHead() { var identity = HttpContext.User.Identity as ClaimsIdentity; if (identity != null) { IEnumerable claims = identity.Claims; var id = claims.First().Value; if (id != null) { var user = await _userService.GetUserById(id); return Ok(user); } else { return BadRequest("Token did not contain an ID."); } } else { return BadRequest("Header not found."); } } [HttpPut("update")] [Authorize] public async Task>> UpdateUserInformation(UserUpdateInformationDto user) { var identity = HttpContext.User.Identity as ClaimsIdentity; if (identity != null) { IEnumerable claims = identity.Claims; var id = claims.First().Value; if (id != null && id == user.Id) { var updatedUser = await _userService.UpdateUserInfo(user); if (updatedUser.Success && updatedUser.Data != null) { await _chatGWContext.Clients.All.SendAsync("UpdateUser", user); await _chatGWContext.Clients.User(updatedUser.Data.Id).SendAsync("UpdateCurrentUser"); return Ok(updatedUser); } else return Ok(); } else { return Unauthorized("You are not authorized to edit that user."); } } else { return BadRequest("Session Expired."); } } [HttpPost("upload-profile-pic")] [Authorize] public async Task>> UploadOrUpdateProfilePic(string userId, IFormFile file) { var identity = HttpContext.User.Identity as ClaimsIdentity; if (identity != null) { IEnumerable claims = identity.Claims; var id = claims.First().Value; if (id != null && id == userId) { if (file.Length > 3000000) { return BadRequest("File Is Above Limit."); } var response = await _userService.UpdateUserPic(userId, file); var res = await _userService.GetUserById(id); User? user = res.Data; UserInformationDto dto = new(); if (user != null) dto.MapToUser(user); await _chatGWContext.Clients.All.SendAsync("UpdateUser", dto); // always try to overwrite cache when updating pfp string recordId = $"UserPfp_{userId}"; using var stream = file.OpenReadStream(); using var ms = new MemoryStream(); stream.CopyTo(ms); await _cache.SetImageAsync(recordId, ms.ToArray(), TimeSpan.FromHours(1)); await _chatGWContext.Clients.User(id).SendAsync("UpdateCurrentUser"); return Ok(response); } else { return BadRequest("You are not permitted to edit that user."); } } else { return BadRequest("No Identity."); } } [HttpGet("profile-pic/{userId}")] [Authorize] public async Task GetUserProfilePicture(string userId) { string recordId = $"UserPfp_{userId}"; byte[]? pfpBytes = await _cache.GetImageAsync(recordId); var result = new ServiceResponse(); if (pfpBytes == null) { result = await _userService.GetUserPic(userId); if (result != null && result.Success && result.Data != null) { pfpBytes = result.Data.FileContents; await _cache.SetImageAsync(recordId, pfpBytes, TimeSpan.FromHours(1)); } } else { // explicitly set from cache result.Success = true; result.Data = new FileContentResult(pfpBytes, "image/jpeg"); } if (result != null && result.Success != false) { return result.Data!; } else if (result!.Message == "User Does Not Have A Profile Picture." || result!.Message == "User Content Folder Does Not Exist Yet.") { return BadRequest("User has no profile picture."); } else { return BadRequest("Failed To Get Profile Picture."); } } [HttpDelete("delete-user")] [Authorize(Roles = "Admin")] public async Task>> DeleteUserById(string id) { var result = await _userService.DeleteUser(id); await _chatGWContext.Clients.All.SendAsync("RefreshUserLists"); if (result != null && result.Success && result.Data != null) await _chatGWContext.Clients.User(result.Data.Id).SendAsync("ForceSignOut"); return Ok(result); } [HttpPost("update-user-currency")] [Authorize] public async Task>> UpdateUserCurrency(int amount, bool isSpinClaim) { var identity = HttpContext.User.Identity as ClaimsIdentity; if (identity != null) { IEnumerable claims = identity.Claims; var id = claims.First().Value; var _res = await _userService.AddCurrencyToUser(id, amount, isSpinClaim); if (_res.Success) { await _chatGWContext.Clients.User(id).SendAsync("UpdateCurrentUser"); return Ok(_res); } else return Ok(new ServiceResponse { Success = false, Message = "Identity Has No User ID" }); } else return Ok(new ServiceResponse { Success = false, Message = "No Identity" }); } } }