using Flawless.Communication.Request; using Flawless.Communication.Response; using Flawless.Communication.Shared; using Flawless.Server.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Flawless.Server.Controllers; [ApiController, Authorize, Route("api/user")] public class UserController( UserManager userManager ) : ControllerBase { [HttpPost("update/info")] public async Task UpdateUserInfoAsync(UserInfoModifyResponse r) { bool update = false; bool renew = false; // Modify content var u = (await userManager.GetUserAsync(HttpContext.User))!; if (r.NickName != null) { update = true; u.NickName = r.NickName; } if (r.Bio != null) { update = true; u.Bio = r.Bio; } if (r.Gender != null) { update = true; u.Gender = r.Gender ?? UserSex.Unset; } if (r.PublicEmail != null) { update = true; u.PublicEmail = r.PublicEmail ?? false; } if (renew) u.RenewSecurityStamp(); if (update || renew) await userManager.UpdateAsync(u); return Ok(); } [HttpPost("update/email")] public async Task UpdateEmailAsync(UserContactModifyResponse r) { if (string.IsNullOrWhiteSpace(r.Email)) return BadRequest(new FailedResponse("No valid email address provided!")); var u = (await userManager.GetUserAsync(HttpContext.User))!; var result = await userManager.SetEmailAsync(u, r.Email); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpPost("update/phone")] public async Task UpdatePhoneAsync(UserContactModifyResponse r) { if (string.IsNullOrWhiteSpace(r.Phone)) return BadRequest(new FailedResponse("No valid phone number provided!")); var u = (await userManager.GetUserAsync(HttpContext.User))!; var result = await userManager.SetPhoneNumberAsync(u, r.Phone); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpGet("get")] public async Task> GetUserInfoAsync() { var self = (await userManager.GetUserAsync(HttpContext.User))!; // Return self as default return Ok(GetUserInfoInternal(self, self)); } [HttpGet("get/{username}")] public async Task> GetUserInfoAsync(string username) { var self = (await userManager.GetUserAsync(HttpContext.User))!; var u = await userManager.FindByNameAsync(username); if (u == null) return BadRequest(new FailedResponse("User is not existed!")); return Ok(GetUserInfoInternal(u, self)); } [HttpGet("query/{keyword}")] public async Task>> GetUserInfoAsync(QueryPagesRequest r, string keyword) { var payload = await userManager.Users .Where(u => u.UserName!.Contains(keyword) || (u.NickName != null && u.NickName.Contains(keyword))) .Skip(r.Offset) .Take(r.Length) .Select(u => GetUserInfoInternal(u, null)) .ToArrayAsync(); // Return self as default return Ok(new PagedResponse { Offset = r.Offset, Length = r.Length, Data = payload }); } [HttpGet("delete")] public async Task DeleteUserAsync() { var self = (await userManager.GetUserAsync(HttpContext.User))!; await userManager.DeleteAsync(self); return Ok(); } private UserInfoResponse GetUserInfoInternal(AppUser queryUser, AppUser? currentUser) { var authorized = queryUser.Id == currentUser?.Id; return new UserInfoResponse { Authorized = authorized, Username = queryUser.UserName, CreatedAt = queryUser.CreatedOn, Bio = queryUser.Bio, Gender = queryUser.Gender, NickName = queryUser.NickName, PublicEmail = authorized ? queryUser.PublicEmail : null, Email = queryUser.PublicEmail || authorized ? queryUser.Email : null, Phone = authorized ? queryUser.PhoneNumber : null, }; } }