using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using LingAdmin.IdentityService.Data; using LingAdmin.IdentityService.Services; using LingAdmin.Shared.DTOs; namespace LingAdmin.IdentityService.Controllers; /// /// 用户管理控制器 - 管理员操作 /// [ApiController] [Route("api/[controller]")] [Authorize(Roles = "Admin,SuperAdmin")] public class UsersController : ControllerBase { private readonly IdentityDbContext _context; private readonly IPasswordHasher _passwordHasher; private readonly ILogger _logger; public UsersController( IdentityDbContext context, IPasswordHasher passwordHasher, ILogger logger) { _context = context; _passwordHasher = passwordHasher; _logger = logger; } /// /// 获取用户列表(分页) /// [HttpGet] public async Task>>> GetUsers( [FromQuery] PaginationRequest pagination) { var query = _context.Users.AsQueryable(); // Search if (!string.IsNullOrWhiteSpace(pagination.Search)) { var search = pagination.Search.ToLower(); query = query.Where(u => u.Name.ToLower().Contains(search) || u.Email.ToLower().Contains(search)); } // Sort query = pagination.SortBy?.ToLower() switch { "name" => pagination.SortDescending ? query.OrderByDescending(u => u.Name) : query.OrderBy(u => u.Name), "email" => pagination.SortDescending ? query.OrderByDescending(u => u.Email) : query.OrderBy(u => u.Email), "createdat" => pagination.SortDescending ? query.OrderByDescending(u => u.CreatedAt) : query.OrderBy(u => u.CreatedAt), _ => query.OrderByDescending(u => u.CreatedAt) }; var totalCount = await query.CountAsync(); var users = await query .Skip((pagination.Page - 1) * pagination.PageSize) .Take(pagination.PageSize) .Select(u => new UserDto { Id = u.Id, Name = u.Name, Email = u.Email, Status = u.Status, CreatedAt = u.CreatedAt, LastLoginAt = u.LastLoginAt }) .ToListAsync(); var response = new PaginatedResponse { Items = users, TotalCount = totalCount, Page = pagination.Page, PageSize = pagination.PageSize }; return Ok(ApiResponse>.Ok(response)); } /// /// 获取单个用户 /// [HttpGet("{id}")] public async Task>> GetUser(int id) { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.NotFound("User not found")); } var userDto = new UserDto { Id = user.Id, Name = user.Name, Email = user.Email, Status = user.Status, CreatedAt = user.CreatedAt, LastLoginAt = user.LastLoginAt }; return Ok(ApiResponse.Ok(userDto)); } /// /// 更新用户状态 /// [HttpPatch("{id}/status")] public async Task>> UpdateUserStatus(int id, [FromBody] UpdateStatusRequest request) { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.NotFound("User not found")); } if (!new[] { "Active", "Inactive", "Suspended" }.Contains(request.Status)) { return BadRequest(ApiResponse.Error("Invalid status. Must be Active, Inactive, or Suspended")); } user.Status = request.Status; user.UpdatedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); var userDto = new UserDto { Id = user.Id, Name = user.Name, Email = user.Email, Status = user.Status, CreatedAt = user.CreatedAt, LastLoginAt = user.LastLoginAt }; return Ok(ApiResponse.Ok(userDto, "User status updated")); } /// /// 重置用户密码(管理员操作) /// [HttpPost("{id}/reset-password")] public async Task>> ResetUserPassword(int id, [FromBody] AdminResetPasswordRequest request) { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.NotFound("User not found")); } user.PasswordHash = _passwordHasher.HashPassword(request.NewPassword); user.UpdatedAt = DateTime.UtcNow; // Revoke all refresh tokens var tokens = await _context.RefreshTokens .Where(rt => rt.UserId == id && rt.RevokedAt == null) .ToListAsync(); foreach (var token in tokens) { token.RevokedAt = DateTime.UtcNow; } await _context.SaveChangesAsync(); _logger.LogInformation("Admin reset password for user {UserId}", id); return Ok(ApiResponse.Ok(new { }, "Password reset successfully")); } /// /// 删除用户 /// [HttpDelete("{id}")] [Authorize(Roles = "SuperAdmin")] public async Task>> DeleteUser(int id) { var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.NotFound("User not found")); } // Delete all refresh tokens var tokens = await _context.RefreshTokens.Where(rt => rt.UserId == id).ToListAsync(); _context.RefreshTokens.RemoveRange(tokens); _context.Users.Remove(user); await _context.SaveChangesAsync(); _logger.LogInformation("User {UserId} deleted", id); return Ok(ApiResponse.Ok(new { }, "User deleted successfully")); } /// /// [开发用] 重置用户密码 - 仅在开发环境可用 /// [HttpPost("{id}/dev-reset-password")] [AllowAnonymous] public async Task>> DevResetPassword(int id, [FromBody] AdminResetPasswordRequest request) { // Only allow in development var env = HttpContext.RequestServices.GetService(); if (!env!.IsDevelopment()) { return NotFound(); } var user = await _context.Users.FindAsync(id); if (user == null) { return NotFound(ApiResponse.NotFound("User not found")); } user.PasswordHash = _passwordHasher.HashPassword(request.NewPassword); user.UpdatedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); return Ok(ApiResponse.Ok(new { hash = user.PasswordHash }, "Password reset successfully")); } } public class UpdateStatusRequest { public required string Status { get; set; } } public class AdminResetPasswordRequest { public required string NewPassword { get; set; } }