/// <summary> /// 用户注册 /// </summary> /// <param name="userDto">用于注册的用户信息</param> /// <returns>异步获取Token的任务,如果发生异常则会返回错误信息</returns> public async Task <(AccessTokenResponseDto, Dictionary <string, string>)> RegisterAsync(UserRegisterRequestDto userDto) { // 如果用户不是通过浏览器在请求接口,失去焦点时验证用户名的动作就没意义 var error = await ValidateUsernameAsync(userDto.Username); if (!string.IsNullOrEmpty(error)) { return(null, new Dictionary <string, string> { ["username"] = error }); } // 验证验证码 error = await ValidateCaptchaAsync(userDto.CaptchaId, userDto.CaptchaText); if (!string.IsNullOrEmpty(error)) { return(null, new Dictionary <string, string> { ["captcha"] = error }); } try { Guid salt = Guid.NewGuid(); var user = new User { Username = userDto.Username, PasswordHash = GeneratePasswordHash(userDto.Password, salt.ToString()), Salt = salt.ToString(), // 默认为普通用户 RoleId = (int)Roles.User }; _dbContext.User.Add(user); await _dbContext.SaveChangesAsync(); var token = new AccessTokenResponseDto { AccessToken = await _tokenAuthService.GenerateAccessTokenAsync(user), RefreshToken = await _tokenAuthService.GenerateRefreshTokenAsync(user) }; return(token, null); } catch { // 因为是多线程,依旧可能用户名重复 // 用户名重复会导致异常 return(null, new Dictionary <string, string> { ["username"] = _msg.GetMessage("E003", "用户名") }); } }
/// <summary> /// 创建房间 /// </summary> /// <param name="uid">用户ID</param> /// <param name="roomDto">用户输入的用于创建房间的信息</param> /// <returns>表示异步创建房间的任务,如果创建失败则返回错误信息</returns> public async Task <ChatRoomCreateResponseDto> CreateRoomAsync(int uid, ChatRoomDto roomDto) { // 防止用户打开多个窗口创建房间 var error = await ApplyForCreatingRoomAsync(uid); if (!string.IsNullOrEmpty(error)) { return(new ChatRoomCreateResponseDto { Error = error, CloseModalIfError = true }); } try { var room = new ChatRoom { OwnerId = uid, Name = roomDto.Name, MaxUsers = roomDto.MaxUsers, IsEncrypted = roomDto.IsEncrypted, IsPermanent = roomDto.IsPermanent, IsHidden = roomDto.IsHidden, AllowGuest = roomDto.AllowGuest }; // 如果房间被加密 if (roomDto.IsEncrypted) { Guid salt = Guid.NewGuid(); room.Salt = salt.ToString(); room.PasswordHash = PasswordHelper.GeneratePasswordHash(roomDto.Password, room.Salt); } _dbContext.ChatRoom.Add(room); await _dbContext.SaveChangesAsync(); return(new ChatRoomCreateResponseDto { RoomId = HashidsHelper.Encode(room.Id) }); } catch (Exception) { // 因为是多线程,任然可能发生异常 // 房间名重复 return(new ChatRoomCreateResponseDto { Error = _msg.GetMessage("E003", "房间名"), CloseModalIfError = false }); } }
/// <summary> /// 更新用户密码 /// </summary> /// <param name="uid">用户ID</param> /// <param name="newPassword">新密码</param> /// <returns>用于更新密码的任务,如果成功则返回新的TOKEN</returns> public async Task <AccessTokenResponseDto> UpdatePasswordAsync(int uid, string newPassword) { var user = await _dbContext.User.FindAsync(uid); Guid salt = Guid.NewGuid(); user.Salt = salt.ToString(); user.PasswordHash = PasswordHelper.GeneratePasswordHash(newPassword, user.Salt); _dbContext.User.Update(user); await _dbContext.SaveChangesAsync(); return(new AccessTokenResponseDto { AccessToken = await _tokenAuthService.GenerateAccessTokenAsync(user), RefreshToken = await _tokenAuthService.GenerateRefreshTokenAsync(user) }); }
/// <summary> /// 发送消息 /// </summary> /// <param name="roomHashid">房间哈希ID</param> /// <param name="message">消息</param> /// <returns>表示发送消息的任务</returns> public async Task SendMessageAsync(string roomHashid, string message) { var userHashId = Context.User.FindFirst("uid").Value; var username = HttpUtility.UrlDecode(Context.User.Identity.Name); var unixTimeMilliseconds = new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds(); await Clients.Group(roomHashid) .InvokeAsync("receiveMessage", userHashId, username, message, unixTimeMilliseconds, false); // 将消息保存到数据库 var history = new ChatHistory { RoomId = HashidsHelper.Decode(roomHashid), UserId = HashidsHelper.Decode(userHashId), UnixTimeMilliseconds = unixTimeMilliseconds, Username = username, Message = message }; _dbContext.ChatHistory.Add(history); await _dbContext.SaveChangesAsync(); }