Add new user verification code.
This commit is contained in:
parent
f584c3190f
commit
e8656a99c0
|
|
@ -17,10 +17,11 @@ public interface IBotSharpRepository
|
|||
#endregion
|
||||
|
||||
#region User
|
||||
User? GetUserByEmail(string email);
|
||||
User? GetUserById(string id);
|
||||
User? GetUserByUserName(string userName);
|
||||
void CreateUser(User user);
|
||||
User? GetUserByEmail(string email) => throw new NotImplementedException();
|
||||
User? GetUserById(string id) => throw new NotImplementedException();
|
||||
User? GetUserByUserName(string userName) => throw new NotImplementedException();
|
||||
void CreateUser(User user) => throw new NotImplementedException();
|
||||
void UpdateUserVerified(string userId) => throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region Agent
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using BotSharp.OpenAPI.ViewModels.Users;
|
||||
|
||||
namespace BotSharp.Abstraction.Users;
|
||||
|
||||
|
|
@ -6,6 +7,7 @@ public interface IUserService
|
|||
{
|
||||
Task<User> GetUser(string id);
|
||||
Task<User> CreateUser(User user);
|
||||
Task<Token> ActiveUser(UserActivationModel model);
|
||||
Task<Token?> GetToken(string authorization);
|
||||
Task<User> GetMyProfile();
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@ public class User
|
|||
public string Source { get; set; } = "internal";
|
||||
public string? ExternalId { get; set; }
|
||||
public string Role { get; set; } = UserRole.Client;
|
||||
public string? VerificationCode { get; set; }
|
||||
public bool Verified { get; set; }
|
||||
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
|
||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
namespace BotSharp.OpenAPI.ViewModels.Users;
|
||||
|
||||
public class UserActivationModel
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string VerificationCode { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Abstraction.Users.Settings;
|
||||
|
||||
public class AccountSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to enable verification code to verify the authenticity of new users
|
||||
/// </summary>
|
||||
public bool NewUserVerification { get; set; }
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using BotSharp.Core.Plugins;
|
|||
using BotSharp.Abstraction.Settings;
|
||||
using BotSharp.Abstraction.Options;
|
||||
using BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
using BotSharp.Abstraction.Users.Settings;
|
||||
|
||||
namespace BotSharp.Core;
|
||||
|
||||
|
|
@ -84,6 +85,10 @@ public static class BotSharpCoreExtensions
|
|||
return settingService.Bind<PluginSettings>("PluginLoader");
|
||||
});
|
||||
|
||||
var accountSettings = new AccountSetting();
|
||||
config.Bind("Account", accountSettings);
|
||||
services.AddScoped(x => accountSettings);
|
||||
|
||||
var loader = new PluginLoader(services, config, pluginSettings);
|
||||
loader.Load(assembly =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
|
@ -176,20 +175,6 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region User
|
||||
public User? GetUserByEmail(string email)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public User? GetUserById(string id)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public User? GetUserByUserName(string userName)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void CreateUser(User user)
|
||||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
#region Execution Log
|
||||
public void AddExecutionLogs(string conversationId, List<string> logs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,4 +32,13 @@ public partial class FileRepository
|
|||
var path = Path.Combine(dir, "user.json");
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
}
|
||||
|
||||
public void UpdateUserVerified(string userId)
|
||||
{
|
||||
var user = GetUserById(userId);
|
||||
user.Verified = true;
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, "users", user.Id);
|
||||
var path = Path.Combine(dir, "user.json");
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(user, _options));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using BotSharp.Abstraction.Users.Settings;
|
||||
using BotSharp.OpenAPI.ViewModels.Users;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NanoidDotNet;
|
||||
|
|
@ -12,12 +14,17 @@ public class UserService : IUserService
|
|||
private readonly IServiceProvider _services;
|
||||
private readonly IUserIdentity _user;
|
||||
private readonly ILogger _logger;
|
||||
private readonly AccountSetting _setting;
|
||||
|
||||
public UserService(IServiceProvider services, IUserIdentity user, ILogger<UserService> logger)
|
||||
public UserService(IServiceProvider services,
|
||||
IUserIdentity user,
|
||||
ILogger<UserService> logger,
|
||||
AccountSetting setting)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
_logger = logger;
|
||||
_setting = setting;
|
||||
}
|
||||
|
||||
public async Task<User> CreateUser(User user)
|
||||
|
|
@ -51,6 +58,12 @@ public class UserService : IUserService
|
|||
record.Salt = Guid.NewGuid().ToString("N");
|
||||
record.Password = Utilities.HashText(user.Password, record.Salt);
|
||||
|
||||
if (_setting.NewUserVerification)
|
||||
{
|
||||
record.VerificationCode = Nanoid.Generate(alphabet: "0123456789", size: 6);
|
||||
record.Verified = false;
|
||||
}
|
||||
|
||||
db.CreateUser(record);
|
||||
|
||||
_logger.LogWarning($"Created new user account: {record.Id} {record.UserName}");
|
||||
|
|
@ -120,6 +133,11 @@ public class UserService : IUserService
|
|||
return default;
|
||||
}
|
||||
|
||||
if (_setting.NewUserVerification && !record.Verified)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
if (Utilities.HashText(password, record.Salt) != record.Password)
|
||||
{
|
||||
|
|
@ -206,4 +224,43 @@ public class UserService : IUserService
|
|||
var user = db.GetUserById(id);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<Token> ActiveUser(UserActivationModel model)
|
||||
{
|
||||
var id = model.UserName;
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id);
|
||||
if (record == null)
|
||||
{
|
||||
record = db.GetUserByUserName(id);
|
||||
}
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (record.VerificationCode != model.VerificationCode)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (record.Verified)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
db.UpdateUserVerified(record.Id);
|
||||
|
||||
var accessToken = GenerateJwtToken(record);
|
||||
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
|
||||
var token = new Token
|
||||
{
|
||||
AccessToken = accessToken,
|
||||
ExpireTime = jwt.Payload.Exp.Value,
|
||||
TokenType = "Bearer",
|
||||
Scope = "api"
|
||||
};
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,18 @@ public class UserController : ControllerBase
|
|||
return UserViewModel.FromUser(createdUser);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("/user/activate")]
|
||||
public async Task<ActionResult<Token>> ActivateUser(UserActivationModel model)
|
||||
{
|
||||
var token = await _userService.ActiveUser(model);
|
||||
if (token == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
return Ok(token);
|
||||
}
|
||||
|
||||
[HttpGet("/user/me")]
|
||||
public async Task<UserViewModel> GetMyUserProfile()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ public class UserDocument : MongoBase
|
|||
public string Source { get; set; } = "internal";
|
||||
public string? ExternalId { get; set; }
|
||||
public string Role { get; set; }
|
||||
|
||||
public string? VerificationCode { get; set; }
|
||||
public bool Verified { get; set; }
|
||||
public DateTime CreatedTime { get; set; }
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
|
||||
|
|
@ -30,7 +31,9 @@ public class UserDocument : MongoBase
|
|||
Salt = Salt,
|
||||
Source = Source,
|
||||
ExternalId = ExternalId,
|
||||
Role = Role
|
||||
Role = Role,
|
||||
VerificationCode = VerificationCode,
|
||||
Verified = Verified,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -40,10 +40,20 @@ public partial class MongoRepository
|
|||
Source = user.Source,
|
||||
ExternalId = user.ExternalId,
|
||||
Role = user.Role,
|
||||
VerificationCode = user.VerificationCode,
|
||||
Verified = user.Verified,
|
||||
CreatedTime = DateTime.UtcNow,
|
||||
UpdatedTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_dc.Users.InsertOne(userCollection);
|
||||
}
|
||||
|
||||
public void UpdateUserVerified(string userId)
|
||||
{
|
||||
var filter = Builders<UserDocument>.Filter.Eq(x => x.Id, userId);
|
||||
var update = Builders<UserDocument>.Update.Set(x => x.Verified, true)
|
||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
_dc.Users.UpdateOne(filter, update);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public partial class PlaywrightWebDriver
|
|||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation($"SendHttpRequest: {args.Url}");
|
||||
var response = await EvaluateScript<object>(message.ContextId, script);
|
||||
result.IsSuccess = true;
|
||||
result.Body = JsonSerializer.Serialize(response);
|
||||
|
|
|
|||
Loading…
Reference in a new issue