diff --git a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Events/IEventPublisher.cs b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Events/IEventPublisher.cs
index f2276c13..31a708bc 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Events/IEventPublisher.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Events/IEventPublisher.cs
@@ -10,7 +10,7 @@ public interface IEventPublisher
///
Task BroadcastAsync(string channel, string message);
- Task PublishAsync(string channel, string message, EventPriority? priority = null);
+ Task PublishAsync(string channel, string message, EventPriority? priority = null);
Task ReDispatchAsync(string channel, int count = 10, string order = "asc");
diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
index 33be79c1..73577f45 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs
@@ -5,6 +5,7 @@ using BotSharp.Abstraction.Roles.Models;
using BotSharp.Abstraction.Shared;
using BotSharp.Abstraction.Tasks.Models;
using BotSharp.Abstraction.Translation.Models;
+using BotSharp.Abstraction.Users.Enums;
using BotSharp.Abstraction.Users.Models;
using BotSharp.Abstraction.VectorStorage.Models;
@@ -26,7 +27,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
#region User
User? GetUserByEmail(string email) => throw new NotImplementedException();
- User? GetUserByPhone(string phone, string type = "client", string regionCode = "CN") => throw new NotImplementedException();
+ User? GetUserByPhone(string phone, string type = UserType.Client, string regionCode = "CN") => throw new NotImplementedException();
User? GetAffiliateUserByPhone(string phone) => throw new NotImplementedException();
User? GetUserById(string id) => throw new NotImplementedException();
List GetUserByIds(List ids) => throw new NotImplementedException();
diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
index 8d136dc5..df1ff190 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
@@ -23,6 +23,7 @@ public class User
public bool Verified { get; set; }
public string RegionCode { get; set; } = "CN";
public string? AffiliateId { get; set; }
+ public string? AffiliateCode { get; set; }
public string? EmployeeId { get; set; }
public bool IsDisabled { get; set; }
public IEnumerable Permissions { get; set; } = [];
diff --git a/src/Infrastructure/BotSharp.Abstraction/Utilities/Pagination.cs b/src/Infrastructure/BotSharp.Abstraction/Utilities/Pagination.cs
index 8e5c7f23..4d21013b 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Utilities/Pagination.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Utilities/Pagination.cs
@@ -1,7 +1,9 @@
using BotSharp.Abstraction.Infrastructures;
+using System.Diagnostics;
namespace BotSharp.Abstraction.Utilities;
+[DebuggerStepThrough]
public class Pagination : ICacheKey
{
private int _page;
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs
index 27cbf566..32889f4f 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisPublisher.cs
@@ -21,7 +21,7 @@ public class RedisPublisher : IEventPublisher
await _subscriber.PublishAsync(channel, message);
}
- public async Task PublishAsync(string channel, string message, EventPriority? priority = null)
+ public async Task PublishAsync(string channel, string message, EventPriority? priority = null)
{
var db = _redis.GetDatabase();
@@ -34,7 +34,7 @@ public class RedisPublisher : IEventPublisher
if (CheckMessageExists(db, channel, "message", message))
{
_logger.LogError($"The message already exists {channel} {message}");
- return;
+ return null;
}
// Add a message to the stream, keeping only the latest 1 million messages
@@ -46,6 +46,8 @@ public class RedisPublisher : IEventPublisher
maxLength: 1000 * 10000);
_logger.LogInformation($"Published message {channel} {message} ({messageId})");
+
+ return messageId;
}
private bool CheckMessageExists(IDatabase db, string channel, string fieldName, string desiredValue)
@@ -91,7 +93,10 @@ public class RedisPublisher : IEventPublisher
try
{
- var messageId = await db.StreamAddAsync(channel, "message", entry.Values[0].Value);
+ var messageId = await db.StreamAddAsync(channel, [
+ new NameValueEntry("message", entry.Values[0].Value),
+ new NameValueEntry("timestamp", DateTime.UtcNow.ToString("o"))
+ ]);
_logger.LogWarning($"ReDispatched message: {channel} {entry.Values[0].Value} ({messageId})");
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs
index b93c22a2..89b38a8d 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Events/RedisSubscriber.cs
@@ -42,6 +42,8 @@ public class RedisSubscriber : IEventSubscriber
while (true)
{
+ await Task.Delay(100);
+
if (priorityEnabled)
{
if (await HandleGroupMessage(db, $"{channel}-{EventPriority.High}", group, received) > 0)
diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/Utilities.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/Utilities.cs
index 4cb26888..613643f4 100644
--- a/src/Infrastructure/BotSharp.Core/Infrastructures/Utilities.cs
+++ b/src/Infrastructure/BotSharp.Core/Infrastructures/Utilities.cs
@@ -23,7 +23,7 @@ public static class Utilities
var data = sha256.ComputeHash(Encoding.UTF8.GetBytes(text));
var sb = new StringBuilder();
- foreach(var c in data)
+ foreach (var c in data)
{
sb.Append(c.ToString("x2"));
}
@@ -47,4 +47,36 @@ public static class Utilities
memcache.Compact(100);
}
}
+
+ public static string HideMiddleDigits(string input, bool isEmail = false)
+ {
+ if (string.IsNullOrWhiteSpace(input))
+ {
+ return input;
+ }
+
+ if (isEmail)
+ {
+ int atIndex = input.IndexOf('@');
+ if (atIndex > 1)
+ {
+ string localPart = input.Substring(0, atIndex);
+ if (localPart.Length > 2)
+ {
+ string maskedLocalPart = $"{localPart[0]}{new string('*', localPart.Length - 2)}{localPart[^1]}";
+ return $"{maskedLocalPart}@{input.Substring(atIndex + 1)}";
+ }
+ }
+ }
+ else
+ {
+ if (input.Length > 6)
+ {
+ return $"{input.Substring(0, 3)}{new string('*', input.Length - 6)}{input.Substring(input.Length - 3)}";
+ }
+ }
+
+ return input;
+ }
+
}
diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs
index 962bc941..317d6fc2 100644
--- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs
+++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.User.cs
@@ -11,7 +11,7 @@ public partial class FileRepository
return Users.FirstOrDefault(x => x.Email == email.ToLower());
}
- public User? GetUserByPhone(string phone, string? type = "client", string regionCode = "CN")
+ public User? GetUserByPhone(string phone, string? type = UserType.Client, string regionCode = "CN")
{
var query = Users.Where(x => x.Phone == phone);
diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
index 45f22937..3858d63d 100644
--- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
+++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
@@ -172,7 +172,7 @@ public class UserService : IUserService
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
var (id, password) = base64.SplitAsTuple(":");
var db = _services.GetRequiredService();
- var record = db.GetUserByPhone(id, type: "internal");
+ var record = db.GetUserByPhone(id, type: UserType.Internal);
var isCanLogin = record != null && !record.IsDisabled
&& record.Type == UserType.Internal && new List
{
@@ -548,7 +548,7 @@ public class UserService : IUserService
}
var db = _services.GetRequiredService();
- var UserByphone = db.GetUserByPhone(phone, regionCode);
+ var UserByphone = db.GetUserByPhone(phone, regionCode: regionCode);
if (UserByphone != null && UserByphone.Verified)
{
return true;
diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs
index c55da5fa..27bdc0aa 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserCreationModel.cs
@@ -13,6 +13,7 @@ public class UserCreationModel
public string Type { get; set; } = UserType.Client;
public string Role { get; set; } = UserRole.User;
public string RegionCode { get; set; } = "CN";
+ public string? AffiliateCode { get; set; }
public User ToUser()
{
return new User
@@ -25,7 +26,8 @@ public class UserCreationModel
Password = Password,
Role = Role,
Type = Type,
- RegionCode = RegionCode
+ RegionCode = RegionCode,
+ AffiliateCode = AffiliateCode
};
}
}
diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
index fae5873b..ff220e9d 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Users/UserViewModel.cs
@@ -1,4 +1,5 @@
using BotSharp.Abstraction.Users.Enums;
+using BotSharp.Core.Infrastructures;
using System.Text.Json.Serialization;
namespace BotSharp.OpenAPI.ViewModels.Users;
@@ -57,8 +58,8 @@ public class UserViewModel
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
- Email = user.Email,
- Phone = !string.IsNullOrWhiteSpace(user.Phone) ? user.Phone.Replace("+86", String.Empty) : user.Phone,
+ Email = Utilities.HideMiddleDigits(user.Email, true),
+ Phone = Utilities.HideMiddleDigits((!string.IsNullOrWhiteSpace(user.Phone) ? user.Phone.Replace("+86", String.Empty) : user.Phone)),
Type = user.Type,
Role = user.Role,
Source = user.Source,
diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs
index d72247aa..8a381069 100644
--- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs
+++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs
@@ -13,7 +13,7 @@ public partial class MongoRepository
return user != null ? user.ToUser() : null;
}
- public User? GetUserByPhone(string phone, string type = "client", string regionCode = "CN")
+ public User? GetUserByPhone(string phone, string type = UserType.Client, string regionCode = "CN")
{
string phoneSecond = string.Empty;
// if phone number length is less than 4, return null
@@ -24,7 +24,7 @@ public partial class MongoRepository
phoneSecond = phone.StartsWith("+86") ? phone.Replace("+86", "") : $"+86{phone}";
- var user = _dc.Users.AsQueryable().FirstOrDefault(x => (x.Phone == phone || x.Phone == phoneSecond)
+ var user = _dc.Users.AsQueryable().FirstOrDefault(x => (x.Phone == phone || x.Phone == phoneSecond)
&& (x.RegionCode == regionCode || string.IsNullOrWhiteSpace(x.RegionCode))
&& (x.Type == type));
return user != null ? user.ToUser() : null;