using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; namespace server.Controllers; /// /// 数据控制器 /// [ApiController] [Route("api/[controller]")] public class DataController : ControllerBase { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// [TODO:description] /// public class UserInfo { /// /// 用户的唯一标识符 /// public Guid ID { get; set; } /// /// 用户的名称 /// public required string Name { get; set; } /// /// 用户的电子邮箱 /// public required string EMail { get; set; } /// /// 用户关联的板卡ID /// public Guid BoardID { get; set; } /// /// 用户绑定板子的过期时间 /// public DateTime? BoardExpireTime { get; set; } } /// /// 用户登录,获取 JWT 令牌 /// /// 用户名 /// 用户密码 /// JWT 令牌字符串 [HttpPost("Login")] [EnableCors("Users")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult Login(string name, string password) { // 验证用户密码 using var db = new Database.AppDataConnection(); var ret = db.CheckUserPassword(name, password); if (!ret.IsSuccessful) return StatusCode(StatusCodes.Status500InternalServerError, "数据库操作失败"); if (!ret.Value.HasValue) return BadRequest("用户名或密码错误"); var user = ret.Value.Value; // 生成 JWT var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes("my secret key 1234567890my secret key 1234567890"); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.Name), new Claim(ClaimTypes.Email, user.EMail), new Claim(ClaimTypes.Role, user.Permission.ToString()) }), Expires = DateTime.UtcNow.AddHours(1), SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), Audience = "dlut.edu.cn", Issuer = "dlut.edu.cn", }; var token = tokenHandler.CreateToken(tokenDescriptor); var jwt = tokenHandler.WriteToken(token); return Ok(jwt); } /// /// 测试用户认证,需携带有效 JWT /// /// 认证成功信息 [Authorize] [HttpGet("TestAuth")] [EnableCors("Users")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public IActionResult TestAuth() { return Ok("认证成功!"); } /// /// 测试管理员用户认证,需携带有效 JWT /// /// 认证成功信息 [Authorize("Admin")] [HttpGet("TestAdminAuth")] [EnableCors("Users")] [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public IActionResult TestAdminAuth() { return Ok("认证成功!"); } /// /// 获取当前用户信息 /// /// 用户信息,包括ID、用户名、邮箱和板卡ID [Authorize] [HttpGet("GetUserInfo")] [EnableCors("Users")] [ProducesResponseType(typeof(UserInfo), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public IActionResult GetUserInfo() { // Get User Name var userName = User.Identity?.Name; if (string.IsNullOrEmpty(userName)) return Unauthorized("未找到用户名信息"); // Get User Info using var db = new Database.AppDataConnection(); var ret = db.GetUserByName(userName); if (!ret.IsSuccessful) return StatusCode(StatusCodes.Status500InternalServerError, "数据库操作失败"); if (!ret.Value.HasValue) return BadRequest("用户不存在"); var user = ret.Value.Value; return Ok(new UserInfo { ID = user.ID, Name = user.Name, EMail = user.EMail, BoardID = user.BoardID, BoardExpireTime = user.BoardExpireTime, }); } /// /// 注册新用户 /// /// 用户名(不超过255个字符) /// 邮箱地址 /// 用户密码 /// 操作结果,成功返回 true,失败返回错误信息 [HttpPost("SignUpUser")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult SignUpUser(string name, string email, string password) { // 验证输入参数 if (string.IsNullOrWhiteSpace(name)) return BadRequest("用户名不能为空"); if (name.Length > 255) return BadRequest("用户名不能超过255个字符"); if (string.IsNullOrWhiteSpace(email)) return BadRequest("邮箱不能为空"); if (string.IsNullOrWhiteSpace(password)) return BadRequest("密码不能为空"); try { using var db = new Database.AppDataConnection(); var ret = db.AddUser(name, email, password); return Ok(ret); } catch (Exception ex) { logger.Error(ex, "注册用户时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "注册失败,请稍后重试"); } } /// /// 获取一个空闲的实验板(普通用户权限) /// /// 绑定持续时间(小时),默认为1小时 [Authorize] [HttpGet("GetAvailableBoard")] [EnableCors("Users")] [ProducesResponseType(typeof(Database.Board), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult GetAvailableBoard(int durationHours = 1) { try { var userName = User.Identity?.Name; if (string.IsNullOrEmpty(userName)) return Unauthorized("未找到用户名信息"); using var db = new Database.AppDataConnection(); var userRet = db.GetUserByName(userName); if (!userRet.IsSuccessful || !userRet.Value.HasValue) return BadRequest("用户不存在"); var user = userRet.Value.Value; var expireTime = DateTime.UtcNow.AddHours(durationHours); var boardOpt = db.GetAvailableBoard(user.ID, expireTime); if (!boardOpt.HasValue) return NotFound("没有可用的实验板"); return Ok(boardOpt.Value); } catch (Exception ex) { logger.Error(ex, "获取空闲实验板时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "获取失败,请稍后重试"); } } /// /// 解除当前用户绑定的实验板(普通用户权限) /// [Authorize] [HttpPost("UnbindBoard")] [EnableCors("Users")] [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult UnbindBoard() { try { var userName = User.Identity?.Name; if (string.IsNullOrEmpty(userName)) return Unauthorized("未找到用户名信息"); using var db = new Database.AppDataConnection(); var userRet = db.GetUserByName(userName); if (!userRet.IsSuccessful || !userRet.Value.HasValue) return BadRequest("用户不存在"); var user = userRet.Value.Value; var result = db.UnbindUserFromBoard(user.ID); return Ok(result > 0); } catch (Exception ex) { logger.Error(ex, "解除实验板绑定时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "解除失败,请稍后重试"); } } /// /// 用户根据实验板ID获取实验板信息(普通用户权限) /// [Authorize] [HttpGet("GetBoardByID")] [EnableCors("Users")] [ProducesResponseType(typeof(Database.Board), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult GetBoardByID(Guid id) { try { using var db = new Database.AppDataConnection(); var ret = db.GetBoardByID(id); if (!ret.IsSuccessful) return StatusCode(StatusCodes.Status500InternalServerError, "数据库操作失败"); if (!ret.Value.HasValue) return NotFound("未找到对应的实验板"); return Ok(ret.Value.Value); } catch (Exception ex) { logger.Error(ex, "获取实验板信息时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "获取失败,请稍后重试"); } } /// /// 新增板子(管理员权限) /// [Authorize("Admin")] [HttpPost("AddBoard")] [EnableCors("Users")] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult AddBoard(string name, string ipAddr, int port) { if (string.IsNullOrWhiteSpace(name)) return BadRequest("板子名称不能为空"); if (string.IsNullOrWhiteSpace(ipAddr)) return BadRequest("IP地址不能为空"); if (port <= 0 || port > 65535) return BadRequest("端口号不合法"); try { using var db = new Database.AppDataConnection(); var ret = db.AddBoard(name, ipAddr, port); return Ok(ret); } catch (Exception ex) { logger.Error(ex, "新增板子时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "新增失败,请稍后重试"); } } /// /// 删除板子(管理员权限) /// [Authorize("Admin")] [HttpDelete("DeleteBoard")] [EnableCors("Users")] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult DeleteBoard(Guid id) { if (id == Guid.Empty) return BadRequest("板子Guid不能为空"); try { using var db = new Database.AppDataConnection(); var ret = db.DeleteBoardByID(id); return Ok(ret); } catch (Exception ex) { logger.Error(ex, "删除板子时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "删除失败,请稍后重试"); } } /// /// 获取全部板子(管理员权限) /// [Authorize("Admin")] [HttpGet("GetAllBoards")] [EnableCors("Users")] [ProducesResponseType(typeof(Database.Board[]), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public IActionResult GetAllBoards() { try { using var db = new Database.AppDataConnection(); var boards = db.GetAllBoard(); return Ok(boards); } catch (Exception ex) { logger.Error(ex, "获取全部板子时发生异常"); return StatusCode(StatusCodes.Status500InternalServerError, "获取失败,请稍后重试"); } } }