diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 8c3a0e81b..d85b3cae8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -23,6 +23,8 @@ public interface IBotSharpRepository User? GetUserByUserName(string userName) => throw new NotImplementedException(); void CreateUser(User user) => throw new NotImplementedException(); void UpdateUserVerified(string userId) => throw new NotImplementedException(); + void UpdateUserVerificationCode(string userId, string verficationCode) => throw new NotImplementedException(); + void UpdateUserPassword(string userId, string password) => throw new NotImplementedException(); #endregion #region Agent diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs index 0de103280..cbc18dd58 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs @@ -9,4 +9,5 @@ public interface IAuthenticationHook void AddClaims(List claims); void BeforeSending(Token token); Task UserCreated(User user); + Task VerificationCodeResetPassword(User user); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs index 722917cc7..02a7dd9e3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IUserService.cs @@ -12,4 +12,6 @@ public interface IUserService Task GetMyProfile(); Task VerifyUserNameExisting(string userName); Task VerifyEmailExisting(string email); + Task SendVerificationCodeResetPassword(User user); + Task ResetUserPassword(User user); } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index c2b309407..03fe8bc42 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -95,6 +95,13 @@ record = user; record = db.GetUserByUserName(id); } + //verify password is correct or not. + var hashPassword = Utilities.HashTextMd5($"{password}{record.Salt}"); + if (hashPassword != record.Password) + { + return default; + } + User? user = record; var isAuthenticatedByHook = false; var hooks = _services.GetServices(); @@ -280,12 +287,16 @@ record = db.GetUserByUserName(id); public async Task VerifyUserNameExisting(string userName) { if (string.IsNullOrEmpty(userName)) + { return true; + } var db = _services.GetRequiredService(); var user = db.GetUserByUserName(userName); if (user != null) + { return true; + } return false; } @@ -293,13 +304,61 @@ public async Task VerifyUserNameExisting(string userName) public async Task VerifyEmailExisting(string email) { if (string.IsNullOrEmpty(email)) + { return true; + } var db = _services.GetRequiredService(); var emailName = db.GetUserByEmail(email); if (emailName != null) + { return true; + } return false; } + + public async Task SendVerificationCodeResetPassword(User user) + { + var db = _services.GetRequiredService(); + var record = db.GetUserByEmail(user.Email); + if (record == null) + { + return false; + } + + record.VerificationCode = Nanoid.Generate(alphabet: "0123456789", size: 6); + + //update current verification code. + db.UpdateUserVerificationCode(record.Id, record.VerificationCode); + + //send code to user Email. + var hooks = _services.GetServices(); + foreach (var hook in hooks) + { + hook.VerificationCodeResetPassword(record); + } + + return true; + } + + public async Task ResetUserPassword(User user) + { + var db = _services.GetRequiredService(); + var record = db.GetUserByEmail(user.Email); + + if (record == null) + { + return false; + } + + if (user.VerificationCode != record.VerificationCode) + { + return false; + } + + var newPassword = Utilities.HashTextMd5($"{user.Password}{record.Salt}"); + db.UpdateUserPassword(record.Id, newPassword); + return true; + } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs index f0ab46adc..bbef69283 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/UserController.cs @@ -108,6 +108,18 @@ public async Task VerifyEmailExisting([FromQuery] string email) { return await _userService.VerifyEmailExisting(email); } + [AllowAnonymous] + [HttpPost("/user/verifycode")] + public async Task SendVerificationCodeResetPassword([FromQuery] UserCreationModel user) + { + return await _userService.SendVerificationCodeResetPassword(user.ToUser()); + } + [AllowAnonymous] + [HttpPost("/user/resetpassword")] + public async Task ResetUserPassword([FromQuery] UserResetPasswordModel user) + { + return await _userService.ResetUserPassword(user.ToUser()); + } #region Avatar [HttpPost("/user/avatar")] diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserResetPasswordModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserResetPasswordModel.cs new file mode 100644 index 000000000..8a58820a4 --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserResetPasswordModel.cs @@ -0,0 +1,22 @@ +using System.Data; + +namespace BotSharp.OpenAPI.ViewModels.Users; + +public class UserResetPasswordModel +{ + public string? Email { get; set; } + public string? Phone { get; set; } + public string Password { get; set; } = string.Empty; + public string VerificationCode { get; set; } + + public User ToUser() + { + return new User + { + Email = Email, + Phone = Phone, + Password = Password, + VerificationCode = VerificationCode + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 11f482871..4f9e50e41 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -56,4 +56,20 @@ public void UpdateUserVerified(string userId) .Set(x => x.UpdatedTime, DateTime.UtcNow); _dc.Users.UpdateOne(filter, update); } + + public void UpdateUserVerificationCode(string userId, string verficationCode) + { + var filter = Builders.Filter.Eq(x => x.Id, userId); + var update = Builders.Update.Set(x => x.VerificationCode, verficationCode) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + _dc.Users.UpdateOne(filter, update); + } + + public void UpdateUserPassword(string userId, string password) + { + var filter = Builders.Filter.Eq(x => x.Id, userId); + var update = Builders.Update.Set(x => x.Password, password) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + _dc.Users.UpdateOne(filter, update); + } }