using Flawless.Communication.Request; using Flawless.Communication.Response; using Flawless.Server.Models; using Flawless.Server.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Flawless.Server.Controllers; [ApiController, Authorize, Route("api/admin")] public class AdminController( UserManager userManager, AccessControlService accessControlService, ILogger logger, AppDbContext dbContext) : ControllerBase { private async ValueTask TestIfValid() { var user = (await userManager.GetUserAsync(HttpContext.User))!; if (user.Admin == false) return BadRequest(new FailedResponse("Only admin can do this!")); return null; } [HttpPost("add_user")] public async Task AddUserAsync(RegisterRequest request) { var user = new AppUser { UserName = request.Username, Email = request.Email, EmailConfirmed = true, CreatedOn = DateTime.UtcNow }; user.RenewSecurityStamp(); var result = await userManager.CreateAsync(user, request.Password); if (result.Succeeded) { await userManager.SetLockoutEnabledAsync(user, false); logger.LogInformation("User '{0}' created (SUPERUSER REGISTER)", user.UserName); return Ok(); } logger.LogInformation("User '{0}' NOT created (SUPERUSER REGISTER) : {1}", user.UserName, result.Errors); return BadRequest(new FailedResponse(result.Errors)); } [HttpPost("superuser/{username}")] public async Task SetSuperuserAsync(string username, bool toSuper) { var t = await TestIfValid(); if (t != null) return t; var user = await userManager.FindByNameAsync(username); var optUser = (await userManager.GetUserAsync(HttpContext.User))!; if (user == null) return BadRequest(new FailedResponse("User does not exist!")); if (optUser == user) return BadRequest(new FailedResponse("You cannot set/unset yourself to superuser!")); user.Admin = toSuper; await userManager.UpdateAsync(user); return Ok(); } [HttpGet("superuser/{username}")] public async Task> GetSuperuserAsync(string username) { var t = await TestIfValid(); if (t != null) return t; var user = await userManager.FindByNameAsync(username); if (user == null) return BadRequest(new FailedResponse("User does not exist!")); return user.Admin; } [HttpGet("user/list")] public async Task>> GetUsersAsync() { var t = await TestIfValid(); if (t != null) return t; var r = await userManager.Users.Select(x => new UserInfoResponse { Authorized = true, Username = x.UserName, CreatedAt = x.CreatedOn, Bio = x.Bio, Gender = x.Gender, NickName = x.NickName, PublicEmail = x.PublicEmail, Email = x.Email, Phone = x.PhoneNumber, IsAdmin = x.Admin, IsActive = !x.LockoutEnabled }).ToArrayAsync(); return r; } [HttpPost("user/delete/{username}")] public async Task DeleteUserAsync(string username) { var t = await TestIfValid(); if (t != null) return t; var user = await userManager.FindByNameAsync(username); if (user == null) return BadRequest(new FailedResponse("User does not exist!")); var result = await userManager.DeleteAsync(user); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpPost("user/enable/{username}")] public async Task EnableUserAsync(string username) { var t = await TestIfValid(); if (t != null) return t; var user = await userManager.FindByNameAsync(username); if (user == null) return BadRequest(new FailedResponse("User does not exist!")); var result = await userManager.SetLockoutEnabledAsync(user, false); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpPost("user/disable/{username}")] public async Task DisableUserAsync(string username) { var t = await TestIfValid(); if (t != null) return t; var user = await userManager.FindByNameAsync(username); if (user == null) return BadRequest(new FailedResponse("User does not exist!")); var result = await userManager.SetLockoutEnabledAsync(user, true); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpPost("user/reset_password")] public async Task ResetPasswordAsync(ResetPasswordRequest r) { var t = await TestIfValid(); if (t != null) return t; if (r.Identity == null) return BadRequest(new FailedResponse("Identity (User Id) is not set!")); var user = await userManager.FindByNameAsync(r.Identity); if (user == null) return BadRequest(new FailedResponse("Identity (User Id) does not exist!")); var result = await userManager.ResetPasswordAsync(user, "", r.NewPassword); if (!result.Succeeded) return BadRequest(new FailedResponse(result.Errors)); return Ok(); } [HttpPost("access_control/ip_whitelist")] public async Task SetIpWhitelistAsync([FromBody] string[] ips) { var t = await TestIfValid(); if (t != null) return t; await accessControlService.UpdatePolicyAsync(IpPolicyType.Whitelist, ips); return Ok(); } [HttpGet("access_control/ip_whitelist")] public async Task>> GetIpWhitelistAsync() { var t = await TestIfValid(); if (t != null) return t; return Ok(await accessControlService.GetIpListAsync(IpPolicyType.Whitelist)); } [HttpPost("access_control/ip_blacklist")] public async Task SetIpBlacklistAsync([FromBody] string[] ips) { var t = await TestIfValid(); if (t != null) return t; await accessControlService.UpdatePolicyAsync(IpPolicyType.Blacklist, ips); return Ok(); } [HttpGet("access_control/ip_blacklist")] public async Task>> GetIpBlacklistAsync() { var t = await TestIfValid(); if (t != null) return t; return Ok(await accessControlService.GetIpListAsync(IpPolicyType.Blacklist)); } [HttpGet("logs")] public async Task>> GetSystemLogsAsync( [FromQuery] DateTime startTime, [FromQuery] DateTime endTime, [FromQuery] int level, [FromQuery] int page, [FromQuery] int pageSize) { var t = await TestIfValid(); if (t != null) return t; var query = dbContext.SystemLogs.Where(x => x.Timestamp >= startTime && x.Timestamp <= endTime && (int) x.LogLevel >= level ).AsQueryable(); // 分页处理 // var totalCount = await query.CountAsync(); var results = await query .OrderByDescending(l => l.Timestamp) .Skip((page - 1) * pageSize) .Take(pageSize) .Select(l => new LogEntryResponse( l.Timestamp, l.LogLevel.ToString(), l.Message, l.Exception)) .ToListAsync(); return Ok(results); } }