BotSharp/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs

880 lines
27 KiB
C#
Raw Normal View History

2024-09-17 09:39:34 +00:00
using BotSharp.Abstraction.Infrastructures;
2024-09-29 11:26:17 +00:00
using BotSharp.Abstraction.Users.Enums;
2023-06-11 23:46:02 +00:00
using BotSharp.Abstraction.Users.Models;
2024-05-26 01:34:29 +00:00
using BotSharp.Abstraction.Users.Settings;
using BotSharp.OpenAPI.ViewModels.Users;
2023-06-11 23:46:02 +00:00
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
2024-01-31 15:15:41 +00:00
using NanoidDotNet;
2023-06-11 23:46:02 +00:00
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
2024-05-31 03:24:34 +00:00
using System.Text.RegularExpressions;
2023-06-11 23:46:02 +00:00
namespace BotSharp.Core.Users.Services;
public class UserService : IUserService
{
private readonly IServiceProvider _services;
2023-06-17 02:42:35 +00:00
private readonly IUserIdentity _user;
2024-01-31 19:57:54 +00:00
private readonly ILogger _logger;
2024-05-26 01:34:29 +00:00
private readonly AccountSetting _setting;
2023-06-11 23:46:02 +00:00
2024-05-30 09:11:42 +00:00
public UserService(IServiceProvider services,
IUserIdentity user,
2024-05-26 01:34:29 +00:00
ILogger<UserService> logger,
AccountSetting setting)
2023-06-11 23:46:02 +00:00
{
_services = services;
_user = user;
2024-01-31 19:57:54 +00:00
_logger = logger;
2024-05-26 01:34:29 +00:00
_setting = setting;
2023-06-11 23:46:02 +00:00
}
public async Task<User> CreateUser(User user)
{
string hasRegisterId = null;
2024-10-12 13:52:33 +00:00
if (string.IsNullOrWhiteSpace(user.UserName))
2024-01-31 19:57:54 +00:00
{
// generate unique name
2024-09-21 13:47:52 +00:00
var name = Nanoid.Generate("0123456789botsharp", 10);
2024-01-31 19:57:54 +00:00
user.UserName = name;
}
else
{
user.UserName = user.UserName.ToLower();
}
2023-08-10 04:53:22 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-10-12 12:20:50 +00:00
User? record = null;
2024-10-14 13:09:06 +00:00
if (!string.IsNullOrWhiteSpace(user.UserName))
{
record = db.GetUserByUserName(user.UserName);
}
2025-01-14 11:34:34 +00:00
if (record == null && !string.IsNullOrWhiteSpace(user.Phone))
2024-10-12 12:20:50 +00:00
{
//if (user.Type != "internal")
//{
// record = db.GetUserByPhoneV2(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode));
//}
record = db.GetUserByPhone(user.Phone, regionCode: (string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode));
2024-10-12 12:20:50 +00:00
}
2024-10-12 13:52:33 +00:00
if (record == null && !string.IsNullOrWhiteSpace(user.Email))
{
record = db.GetUserByEmail(user.Email);
}
2025-01-14 11:34:34 +00:00
if (record != null && record.Verified)
{
// account is already activated
_logger.LogWarning($"User account already exists: {record.Id} {record.UserName}");
return record;
}
2023-06-11 23:46:02 +00:00
if (record != null)
{
hasRegisterId = record.Id;
2023-06-11 23:46:02 +00:00
}
2024-10-12 13:52:33 +00:00
if (string.IsNullOrWhiteSpace(user.Id))
2024-01-31 15:15:41 +00:00
{
2024-10-12 13:52:33 +00:00
if (!string.IsNullOrWhiteSpace(hasRegisterId))
{
user.Id = hasRegisterId;
}
else
{
user.Id = Guid.NewGuid().ToString();
}
2024-01-31 15:15:41 +00:00
}
2024-01-31 19:57:54 +00:00
record = user;
2024-02-14 23:45:28 +00:00
record.Email = user.Email?.ToLower();
2024-09-20 08:16:50 +00:00
if (!string.IsNullOrWhiteSpace(user.Phone))
2024-05-31 03:24:34 +00:00
{
2024-10-21 11:59:05 +00:00
//record.Phone = "+" + Regex.Match(user.Phone, @"\d+").Value;
record.Phone = Regex.Match(user.Phone, @"\d+").Value;
2024-05-31 03:24:34 +00:00
}
2025-01-14 11:34:34 +00:00
2023-06-11 23:46:02 +00:00
record.Salt = Guid.NewGuid().ToString("N");
if (!string.IsNullOrWhiteSpace(user.Password))
{
record.Password = Utilities.HashTextMd5($"{user.Password}{record.Salt}");
}
2023-06-11 23:46:02 +00:00
2024-05-26 01:34:29 +00:00
if (_setting.NewUserVerification)
{
2024-10-14 13:09:06 +00:00
// record.VerificationCode = Nanoid.Generate(alphabet: "0123456789", size: 6);
2024-05-26 01:34:29 +00:00
record.Verified = false;
}
if (hasRegisterId == null)
{
db.CreateUser(record);
}
else
{
db.UpdateExistUser(hasRegisterId, record);
}
2024-01-05 03:20:50 +00:00
2024-12-11 07:02:14 +00:00
_logger.LogWarning($"Created new user account: {record.Id} {record.UserName}, RegionCode: {record.RegionCode}");
2024-01-05 03:20:50 +00:00
Utilities.ClearCache();
2024-05-21 10:51:38 +00:00
var hooks = _services.GetServices<IAuthenticationHook>();
foreach (var hook in hooks)
{
await hook.UserCreated(record);
}
2023-09-07 22:04:34 +00:00
return record;
2023-06-11 23:46:02 +00:00
}
2024-09-17 10:31:38 +00:00
public async Task<bool> UpdatePassword(string password, string verificationCode)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserById(_user.Id);
2024-09-17 10:31:38 +00:00
if (record == null)
{
return false;
}
if (record.VerificationCode != verificationCode)
{
return false;
}
2024-09-18 07:38:44 +00:00
var newPassword = Utilities.HashTextMd5($"{password}{record.Salt}");
2024-09-17 10:31:38 +00:00
2024-09-18 07:38:44 +00:00
db.UpdateUserPassword(record.Id, newPassword);
2024-09-17 10:31:38 +00:00
return true;
}
2024-10-19 09:16:55 +00:00
public async Task<Token?> GetAffiliateToken(string authorization)
2024-09-20 07:48:34 +00:00
{
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
2024-11-27 09:26:21 +00:00
var (id, password, regionCode) = base64.SplitAsTuple(":");
2024-09-20 07:48:34 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-09-25 14:09:43 +00:00
var record = db.GetAffiliateUserByPhone(id);
2024-10-19 09:16:55 +00:00
var isCanLogin = record != null && !record.IsDisabled && record.Type == UserType.Affiliate;
if (!isCanLogin)
2024-09-25 14:09:43 +00:00
{
2024-10-19 09:16:55 +00:00
return default;
2024-09-25 14:09:43 +00:00
}
2024-09-20 07:48:34 +00:00
2024-10-19 09:16:55 +00:00
if (Utilities.HashTextMd5($"{password}{record.Salt}") != record.Password)
2024-09-25 14:09:43 +00:00
{
2024-10-19 09:16:55 +00:00
return default;
2024-09-25 14:09:43 +00:00
}
2024-09-20 07:48:34 +00:00
2024-10-21 16:29:04 +00:00
var (token, jwt) = BuildToken(record);
return await Task.FromResult(token);
2024-10-19 09:16:55 +00:00
}
public async Task<Token?> GetAdminToken(string authorization)
{
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
2024-11-27 09:26:21 +00:00
var (id, password, regionCode) = base64.SplitAsTuple(":");
2024-10-19 09:16:55 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserByPhone(id, type: UserType.Internal);
2024-10-19 09:16:55 +00:00
var isCanLogin = record != null && !record.IsDisabled
&& record.Type == UserType.Internal && new List<string>
{
UserRole.Root,UserRole.Admin
}.Contains(record.Role);
if (!isCanLogin)
2024-09-20 07:48:34 +00:00
{
2024-09-21 07:12:08 +00:00
return default;
}
if (Utilities.HashTextMd5($"{password}{record.Salt}") != record.Password)
{
return default;
2024-09-20 07:48:34 +00:00
}
2024-10-21 16:29:04 +00:00
var (token, jwt) = BuildToken(record);
2024-10-21 16:29:04 +00:00
return await Task.FromResult(token);
2024-10-19 09:16:55 +00:00
}
2024-10-21 16:29:04 +00:00
private (Token, JwtSecurityToken) BuildToken(User record)
2024-10-19 09:16:55 +00:00
{
2024-09-21 07:12:08 +00:00
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"
};
2024-10-21 16:29:04 +00:00
return (token, jwt);
2024-09-20 07:48:34 +00:00
}
2024-05-20 16:35:45 +00:00
public async Task<Token?> GetToken(string authorization)
2023-06-11 23:46:02 +00:00
{
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
2024-11-27 09:26:21 +00:00
var (id, password, regionCode) = base64.SplitAsTuple(":");
2023-06-11 23:46:02 +00:00
2023-08-10 04:53:22 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-01-31 19:57:54 +00:00
var record = id.Contains("@") ? db.GetUserByEmail(id) : db.GetUserByUserName(id);
2024-01-31 15:15:41 +00:00
if (record == null)
2024-01-31 19:57:54 +00:00
{
2024-11-27 09:26:21 +00:00
record = db.GetUserByPhone(id, regionCode: regionCode);
2024-01-31 19:57:54 +00:00
}
2024-09-20 07:48:34 +00:00
if (record != null && record.Type == UserType.Affiliate)
{
return default;
}
var hooks = _services.GetServices<IAuthenticationHook>();
//verify password is correct or not.
2024-07-10 05:17:12 +00:00
if (record != null && !hooks.Any())
{
2024-07-01 19:53:24 +00:00
var hashPassword = Utilities.HashTextMd5($"{password}{record.Salt}");
if (hashPassword != record.Password)
{
return default;
}
}
2024-05-23 12:05:36 +00:00
User? user = record;
2024-06-12 18:40:29 +00:00
var isAuthenticatedByHook = false;
2024-09-21 07:12:08 +00:00
if (record == null || record.Source != UserSource.Internal)
2024-01-31 15:15:41 +00:00
{
// check 3rd party user
2024-02-05 16:00:28 +00:00
foreach (var hook in hooks)
2024-01-31 15:15:41 +00:00
{
2024-05-20 16:35:45 +00:00
user = await hook.Authenticate(id, password);
2025-06-13 02:03:51 +00:00
if (user == null)
2024-01-31 19:57:54 +00:00
{
continue;
}
2024-09-21 07:12:08 +00:00
if (string.IsNullOrEmpty(user.Source) || user.Source == UserSource.Internal)
2024-01-31 19:57:54 +00:00
{
_logger.LogError($"Please set source name in the Authenticate hook.");
return null;
}
if (record == null)
2024-01-31 15:15:41 +00:00
{
// create a local user record
record = new User
{
UserName = user.UserName,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
Source = user.Source,
2024-01-31 19:57:54 +00:00
ExternalId = user.ExternalId,
Password = user.Password,
2024-09-19 00:49:32 +00:00
Type = user.Type,
2024-10-23 06:57:57 +00:00
Role = user.Role,
RegionCode = user.RegionCode
2024-01-31 15:15:41 +00:00
};
await CreateUser(record);
}
2024-06-12 18:40:29 +00:00
isAuthenticatedByHook = true;
2024-01-31 19:57:54 +00:00
break;
2024-01-31 15:15:41 +00:00
}
}
2024-07-10 05:17:12 +00:00
if ((hooks.Any() && user == null) || record == null)
2023-06-11 23:46:02 +00:00
{
return default;
}
2024-06-12 18:40:29 +00:00
if (!isAuthenticatedByHook && _setting.NewUserVerification && !record.Verified)
2024-05-26 01:34:29 +00:00
{
return default;
}
2024-06-26 21:47:59 +00:00
if (!isAuthenticatedByHook && Utilities.HashTextMd5($"{password}{record.Salt}") != record.Password)
2023-06-11 23:46:02 +00:00
{
return default;
}
2024-10-21 16:29:04 +00:00
var (token, jwt) = BuildToken(record);
2024-02-05 16:00:28 +00:00
foreach (var hook in hooks)
{
2024-11-05 12:02:17 +00:00
hook.UserAuthenticated(record, token);
2024-02-05 16:00:28 +00:00
}
return token;
2023-06-11 23:46:02 +00:00
}
2023-09-07 22:04:34 +00:00
private string GenerateJwtToken(User user)
2023-06-11 23:46:02 +00:00
{
2024-01-31 19:57:54 +00:00
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName),
new Claim(JwtRegisteredClaimNames.Email, user?.Email ?? string.Empty),
2024-03-24 01:31:15 +00:00
new Claim(JwtRegisteredClaimNames.GivenName, user?.FirstName ?? string.Empty),
new Claim(JwtRegisteredClaimNames.FamilyName, user?.LastName ?? string.Empty),
2024-01-31 19:57:54 +00:00
new Claim("source", user.Source),
2024-03-24 01:31:15 +00:00
new Claim("external_id", user.ExternalId ?? string.Empty),
2024-09-19 00:49:32 +00:00
new Claim("type", user.Type ?? UserType.Client),
2024-09-19 18:29:42 +00:00
new Claim("role", user.Role ?? UserRole.User),
2024-08-05 11:12:38 +00:00
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("phone", user.Phone ?? string.Empty),
2024-11-08 06:51:56 +00:00
new Claim("affiliate_id", user.AffiliateId ?? string.Empty),
new Claim("employee_id", user.EmployeeId ?? string.Empty),
2024-10-23 06:57:57 +00:00
new Claim("regionCode", user.RegionCode ?? "CN")
2024-01-31 19:57:54 +00:00
};
var validators = _services.GetServices<IAuthenticationHook>();
foreach (var validator in validators)
{
validator.AddClaims(claims);
}
2023-06-11 23:46:02 +00:00
var config = _services.GetRequiredService<IConfiguration>();
var issuer = config["Jwt:Issuer"];
var audience = config["Jwt:Audience"];
2024-08-09 03:44:46 +00:00
var expireInMinutes = int.Parse(config["Jwt:ExpireInMinutes"] ?? "120");
2023-06-11 23:46:02 +00:00
var key = Encoding.ASCII.GetBytes(config["Jwt:Key"]);
2024-09-17 09:39:34 +00:00
var expires = DateTime.UtcNow.AddMinutes(expireInMinutes);
2023-06-11 23:46:02 +00:00
var tokenDescriptor = new SecurityTokenDescriptor
{
2024-01-31 19:57:54 +00:00
Subject = new ClaimsIdentity(claims),
2024-09-17 09:39:34 +00:00
Expires = expires,
2023-06-11 23:46:02 +00:00
Issuer = issuer,
Audience = audience,
2024-01-31 19:57:54 +00:00
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
2024-02-14 23:45:28 +00:00
SecurityAlgorithms.HmacSha256Signature)
2023-06-11 23:46:02 +00:00
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
SaveUserTokenExpiresCache(user.Id, expires, expireInMinutes).GetAwaiter().GetResult();
2023-06-11 23:46:02 +00:00
return tokenHandler.WriteToken(token);
}
private async Task SaveUserTokenExpiresCache(string userId, DateTime expires, int expireInMinutes)
2024-09-17 09:39:34 +00:00
{
2024-09-28 02:05:30 +00:00
var config = _services.GetService<IConfiguration>();
var enableSingleLogin = bool.Parse(config["Jwt:EnableSingleLogin"] ?? "false");
if (enableSingleLogin)
{
var _cacheService = _services.GetRequiredService<ICacheService>();
await _cacheService.SetAsync(GetUserTokenExpiresCacheKey(userId), expires, TimeSpan.FromMinutes(expireInMinutes));
}
2024-09-17 09:39:34 +00:00
}
private string GetUserTokenExpiresCacheKey(string userId)
{
2024-10-21 19:46:09 +00:00
return $"user:{userId}_token_expires";
2024-09-17 09:39:34 +00:00
}
public async Task<DateTime> GetUserTokenExpires()
{
var _cacheService = _services.GetRequiredService<ICacheService>();
return await _cacheService.GetAsync<DateTime>(GetUserTokenExpiresCacheKey(_user.Id));
}
2025-01-22 05:47:32 +00:00
[SharpCache(10, perInstanceCache: true)]
2023-06-11 23:46:02 +00:00
public async Task<User> GetMyProfile()
{
2023-08-10 04:53:22 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-02-15 18:11:56 +00:00
User user = default;
2024-05-31 16:26:23 +00:00
if (_user.Id != null)
{
user = db.GetUserById(_user.Id);
}
else if (_user.UserName != null)
2024-02-15 18:11:56 +00:00
{
user = db.GetUserByUserName(_user.UserName);
}
else if (_user.Email != null)
{
user = db.GetUserByEmail(_user.Email);
}
2023-11-14 01:25:25 +00:00
return user;
}
2025-01-22 05:47:32 +00:00
[SharpCache(10, perInstanceCache: true)]
2023-11-14 01:25:25 +00:00
public async Task<User> GetUser(string id)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var user = db.GetUserById(id);
2023-06-11 23:46:02 +00:00
return user;
}
2024-05-26 01:34:29 +00:00
2024-10-31 19:36:26 +00:00
public async Task<PagedItems<User>> GetUsers(UserFilter filter)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var users = db.GetUsers(filter);
return users;
}
2025-03-10 17:14:44 +00:00
[SharpCache(10, perInstanceCache: true)]
public async Task<(bool, User?)> IsAdminUser(string userId)
2024-10-31 22:32:39 +00:00
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-11-14 23:33:26 +00:00
var user = db.GetUserById(userId);
2025-03-10 17:14:44 +00:00
var isAdmin = user != null && UserConstant.AdminRoles.Contains(user.Role);
return (isAdmin, user);
2024-11-14 23:33:26 +00:00
}
2024-11-15 02:19:53 +00:00
public async Task<UserAuthorization> GetUserAuthorizations(IEnumerable<string>? agentIds = null)
2024-11-14 23:33:26 +00:00
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2025-03-10 17:14:44 +00:00
var (isAdmin, user) = await IsAdminUser(_user.Id);
2024-11-14 23:33:26 +00:00
var auth = new UserAuthorization();
if (user == null) return auth;
2025-03-10 17:14:44 +00:00
auth.IsAdmin = isAdmin;
2024-11-15 02:19:53 +00:00
var role = db.GetRoles(new RoleFilter { Names = [user.Role] }).FirstOrDefault();
var permissions = user.Permissions?.Any() == true ? user.Permissions : role?.Permissions ?? [];
2024-11-14 23:33:26 +00:00
auth.Permissions = permissions;
2024-11-15 02:19:53 +00:00
if (agentIds == null || !agentIds.Any())
2024-11-14 23:33:26 +00:00
{
return auth;
}
2024-11-15 02:19:53 +00:00
var userAgents = db.GetUserDetails(user.Id)?.AgentActions?
.Where(x => agentIds.Contains(x.AgentId) && x.Actions.Any())?.Select(x => new UserAgent
{
AgentId = x.AgentId,
Actions = x.Actions
}).ToList() ?? [];
2024-11-14 23:33:26 +00:00
2024-11-15 02:19:53 +00:00
var userAgentIds = userAgents.Select(x => x.AgentId).ToList();
var roleAgents = db.GetRoleDetails(role?.Id)?.AgentActions?
.Where(x => !userAgentIds.Contains(x.AgentId))?.Select(x => new UserAgent
{
AgentId = x.AgentId,
Actions = x.Actions
})?.ToList() ?? [];
2024-11-14 23:33:26 +00:00
2024-11-15 02:19:53 +00:00
auth.AgentActions = userAgents.Concat(roleAgents);
2024-11-14 23:33:26 +00:00
return auth;
}
2024-11-15 16:57:50 +00:00
public async Task<User?> GetUserDetails(string userId, bool includeAgent = false)
2024-10-31 22:32:39 +00:00
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-11-15 16:57:50 +00:00
return db.GetUserDetails(userId, includeAgent);
2024-11-13 23:16:49 +00:00
}
public async Task<bool> UpdateUser(User user, bool isUpdateUserAgents = false)
{
if (user == null) return false;
var db = _services.GetRequiredService<IBotSharpRepository>();
return db.UpdateUser(user, isUpdateUserAgents);
2024-10-31 22:32:39 +00:00
}
2024-05-26 01:34:29 +00:00
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);
2024-05-26 01:34:29 +00:00
if (record == null)
{
record = db.GetUserByPhone(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode));
2024-05-26 01:34:29 +00:00
}
//if (record == null)
//{
// record = db.GetUserByPhoneV2(id, regionCode: (string.IsNullOrWhiteSpace(model.RegionCode) ? "CN" : model.RegionCode));
//}
2024-05-26 01:34:29 +00:00
if (record == null)
{
return default;
}
2025-01-07 03:40:01 +00:00
if (record.VerificationCode != model.VerificationCode || (record.VerificationCodeExpireAt != null && DateTime.UtcNow > record.VerificationCodeExpireAt))
2024-05-26 01:34:29 +00:00
{
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;
}
2024-05-28 11:47:48 +00:00
2024-12-14 10:36:51 +00:00
public async Task<Token> CreateTokenByUser(User user)
{
var accessToken = GenerateJwtToken(user);
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
var token = new Token
{
AccessToken = accessToken,
ExpireTime = jwt.Payload.Exp.Value,
TokenType = "Bearer",
Scope = "api"
};
return token;
}
2025-01-09 14:30:19 +00:00
public async Task<Token> RenewToken()
{
var newToken = GenerateJwtToken(await GetMyProfile());
var newJwt = new JwtSecurityTokenHandler().ReadJwtToken(newToken);
Token token = new Token();
token.AccessToken = newToken;
token.ExpireTime = newJwt.Payload.Exp.Value;
return token;
}
2024-05-30 09:11:42 +00:00
public async Task<bool> VerifyUserNameExisting(string userName)
2024-05-28 11:47:48 +00:00
{
if (string.IsNullOrEmpty(userName))
{
2024-05-30 09:11:42 +00:00
return true;
}
2024-05-28 11:47:48 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-05-28 11:47:48 +00:00
var user = db.GetUserByUserName(userName);
if (user != null && user.Verified)
{
2024-05-28 11:47:48 +00:00
return true;
}
2024-05-30 09:11:42 +00:00
2024-05-28 11:47:48 +00:00
return false;
}
2024-05-30 09:11:42 +00:00
public async Task<bool> VerifyEmailExisting(string email)
2024-05-28 11:47:48 +00:00
{
2024-11-26 11:33:54 +00:00
if (string.IsNullOrWhiteSpace(email))
{
2024-05-30 09:11:42 +00:00
return true;
}
2024-05-28 11:47:48 +00:00
var db = _services.GetRequiredService<IBotSharpRepository>();
var emailName = db.GetUserByEmail(email);
if (emailName != null && emailName.Verified)
{
2024-05-28 11:47:48 +00:00
return true;
}
2024-05-28 11:47:48 +00:00
return false;
}
2025-01-20 11:44:33 +00:00
public async Task<List<User>> SearchLoginUsers(User filter)
{
if (filter == null)
{
return new List<User>();
}
var db = _services.GetRequiredService<IBotSharpRepository>();
return db.SearchLoginUsers(filter);
}
public async Task<bool> VerifyPhoneExisting(string phone, string regionCode)
{
2024-11-26 11:33:54 +00:00
if (string.IsNullOrWhiteSpace(phone))
{
return true;
}
var db = _services.GetRequiredService<IBotSharpRepository>();
2024-11-25 02:32:03 +00:00
var UserByphone = db.GetUserByPhone(phone, regionCode: regionCode);
if (UserByphone != null && UserByphone.Verified)
{
return true;
}
return false;
}
2025-01-14 11:34:34 +00:00
public async Task<bool> SendVerificationCodeNoLogin(User user)
{
User? record = await ResetVerificationCode(user);
if (record == null)
{
return false;
}
//send code to user Email.
var hooks = _services.GetServices<IAuthenticationHook>();
foreach (var hook in hooks)
{
await hook.SendVerificationCode(record);
}
return true;
}
public async Task<User> ResetVerificationCode(User user)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
if (!string.IsNullOrWhiteSpace(user.Email) && !string.IsNullOrWhiteSpace(user.Phone))
{
return null;
}
User? record = GetLoginUserByUniqueFilter(user, db);
if (record == null)
{
return null;
}
record.VerificationCode = Nanoid.Generate(alphabet: "0123456789", size: 6);
//update current verification code.
db.UpdateUserVerificationCode(record.Id, record.VerificationCode);
return record;
}
private static User? GetLoginUserByUniqueFilter(User user, IBotSharpRepository db)
{
User? record = null;
if (!string.IsNullOrWhiteSpace(user.Id))
{
record = db.GetUserById(user.Id);
}
if (record == null && !string.IsNullOrWhiteSpace(user.Phone))
{
record = db.GetUserByPhone(user.Phone, regionCode: string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode);
//if (record == null)
//{
// record = db.GetUserByPhoneV2(user.Phone, regionCode: string.IsNullOrWhiteSpace(user.RegionCode) ? "CN" : user.RegionCode);
//}
}
if (record == null && !string.IsNullOrWhiteSpace(user.Email))
{
record = db.GetUserByEmail(user.Email);
}
if (record == null && !string.IsNullOrWhiteSpace(user.UserName))
{
record = db.GetUserByUserName(user.UserName);
}
return record;
}
2025-01-14 11:34:34 +00:00
public async Task<bool> SendVerificationCodeLogin()
{
var db = _services.GetRequiredService<IBotSharpRepository>();
User? record = null;
if (!string.IsNullOrWhiteSpace(_user.Id))
{
record = db.GetUserById(_user.Id);
}
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<IAuthenticationHook>();
foreach (var hook in hooks)
{
2025-01-14 11:34:34 +00:00
await hook.SendVerificationCode(record);
}
return true;
}
public async Task<bool> ResetUserPassword(User user)
{
if (!string.IsNullOrEmpty(user.Email) && !string.IsNullOrEmpty(user.Phone))
{
return false;
}
var db = _services.GetRequiredService<IBotSharpRepository>();
User? record = GetLoginUserByUniqueFilter(user, db);
if (record == null)
{
return false;
}
2025-01-07 03:40:01 +00:00
if (user.VerificationCode != record.VerificationCode || (record.VerificationCodeExpireAt != null && DateTime.UtcNow > record.VerificationCodeExpireAt))
{
return false;
}
var newPassword = Utilities.HashTextMd5($"{user.Password}{record.Salt}");
db.UpdateUserPassword(record.Id, newPassword);
return true;
}
public async Task<bool> SetUserPassword(User user)
{
if (!string.IsNullOrEmpty(user.Id) && !string.IsNullOrEmpty(user.Email) && !string.IsNullOrEmpty(user.Phone))
{
return false;
}
var db = _services.GetRequiredService<IBotSharpRepository>();
User? record = GetLoginUserByUniqueFilter(user, db);
if (record == null)
{
return false;
}
var newPassword = Utilities.HashTextMd5($"{user.Password}{record.Salt}");
db.UpdateUserPassword(record.Id, newPassword);
return true;
}
public async Task<bool> ModifyUserEmail(string email)
{
var curUser = await GetMyProfile();
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserById(curUser.Id);
var existEmail = db.GetUserByEmail(email);
if (record == null || existEmail != null)
{
return false;
}
2024-10-13 23:24:36 +00:00
record.Email = email;
var hooks = _services.GetServices<IAuthenticationHook>();
foreach (var hook in hooks)
{
await hook.UserUpdating(record);
}
db.UpdateUserEmail(record.Id, record.Email);
return true;
}
public async Task<bool> ModifyUserPhone(string phone, string regionCode)
{
if (string.IsNullOrWhiteSpace(regionCode))
{
throw new Exception("regionCode is required");
}
var curUser = await GetMyProfile();
var db = _services.GetRequiredService<IBotSharpRepository>();
var record = db.GetUserById(curUser.Id);
var existPhone = db.GetUserByPhone(phone, regionCode: regionCode);
2024-10-30 10:42:23 +00:00
if (record == null || (existPhone != null && existPhone.RegionCode == regionCode))
{
return false;
}
2024-10-13 23:24:36 +00:00
record.Phone = phone;
record.RegionCode = regionCode;
2024-10-22 10:56:00 +00:00
record.UserName = phone;
record.FirstName = phone;
2024-10-13 23:24:36 +00:00
var hooks = _services.GetServices<IAuthenticationHook>();
foreach (var hook in hooks)
{
2024-10-13 23:24:36 +00:00
await hook.UserUpdating(record);
}
db.UpdateUserPhone(record.Id, record.Phone, regionCode);
2024-10-13 23:24:36 +00:00
return true;
}
2024-09-29 11:26:17 +00:00
public async Task<bool> UpdateUsersIsDisable(List<string> userIds, bool isDisable)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
db.UpdateUsersIsDisable(userIds, isDisable);
if (!isDisable)
{
return true;
}
// del membership
var hooks = _services.GetServices<IAuthenticationHook>();
foreach (var hook in hooks)
{
await hook.DelUsers(userIds);
}
return true;
}
2025-01-31 20:49:38 +00:00
public async Task<bool> AddDashboardConversation(string conversationId)
{
2025-01-31 20:49:38 +00:00
var user = await GetUser(_user.Id);
var db = _services.GetRequiredService<IBotSharpRepository>();
2025-01-31 20:49:38 +00:00
db.AddDashboardConversation(user?.Id, conversationId);
await Task.CompletedTask;
return true;
}
2024-11-29 09:08:27 +00:00
2025-01-31 20:49:38 +00:00
public async Task<bool> RemoveDashboardConversation(string conversationId)
{
2025-01-31 20:49:38 +00:00
var user = await GetUser(_user.Id);
var db = _services.GetRequiredService<IBotSharpRepository>();
2025-01-31 20:49:38 +00:00
db.RemoveDashboardConversation(user?.Id, conversationId);
await Task.CompletedTask;
return true;
}
2025-01-31 20:49:38 +00:00
public async Task UpdateDashboardConversation(DashboardConversation newDashConv)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2025-01-31 20:49:38 +00:00
var user = await GetUser(_user.Id);
var dashConv = db.GetDashboard(user?.Id)?
.ConversationList
.FirstOrDefault(x => string.Equals(x.ConversationId, newDashConv.ConversationId));
if (dashConv == null) return;
2025-01-31 20:49:38 +00:00
dashConv.Name = newDashConv.Name ?? dashConv.Name;
dashConv.Instruction = newDashConv.Instruction ?? dashConv.Instruction;
2025-01-31 20:49:38 +00:00
db.UpdateDashboardConversation(user?.Id, dashConv);
await Task.CompletedTask;
return;
}
2025-01-31 20:49:38 +00:00
public async Task<Dashboard?> GetDashboard()
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2025-01-31 20:49:38 +00:00
var user = await GetUser(_user.Id);
var dash = db.GetDashboard(user?.Id);
await Task.CompletedTask;
return dash;
}
2023-06-11 23:46:02 +00:00
}