修改User模块,同步原始代码
This commit is contained in:
1 parent
4a5fada435
commit
78b0c2bb2e
47 files changed
+2939
-193
No files matched your search
@@ -0,0 +1,103 @@
|
||||
using FreeSql;
|
||||
using MAX.Framework.Security;
|
||||
using Store.Users.Contracts;
|
||||
using Store.Users.Entities;
|
||||
using Store.Users.Services;
|
||||
using System.Security.Claims;
|
||||
using YourNamespace;
|
||||
|
||||
namespace Store.Users.Tests;
|
||||
|
||||
/// <summary>每个测试独享数据库和身份上下文,不读取宿主连接配置,可并行运行。</summary>
|
||||
internal sealed class UserTestContext : IDisposable
|
||||
{
|
||||
private readonly string _path = Path.Combine(Path.GetTempPath(), $"store-user-test-{Guid.NewGuid():N}.db");
|
||||
public IFreeSql Db { get; }
|
||||
public TestCurrentUser CurrentUser { get; } = new();
|
||||
public TestOnlineUsers Sessions { get; } = new();
|
||||
public IUserQueryService Query { get; }
|
||||
public IUserAuthenticationService Authentication { get; }
|
||||
public UserManagementService Users { get; }
|
||||
public UserFundsService Funds { get; }
|
||||
public UserEntity Admin { get; }
|
||||
public UserEntity Main { get; }
|
||||
public UserEntity Other { get; }
|
||||
public UserEntity Child { get; }
|
||||
|
||||
public UserTestContext()
|
||||
{
|
||||
Db = new FreeSqlBuilder()
|
||||
.UseMappingPriority(FreeSql.Internal.MappingPriorityType.Attribute,
|
||||
FreeSql.Internal.MappingPriorityType.Aop, FreeSql.Internal.MappingPriorityType.FluentApi)
|
||||
.UseConnectionString(DataType.Sqlite, $"Data Source={_path};Pooling=False")
|
||||
.Build();
|
||||
// 覆盖业务库 schema,只在临时库建立实体测试表。
|
||||
Db.CodeFirst.ConfigEntity<UserEntity>(e => e.Name("users"));
|
||||
Db.CodeFirst.ConfigEntity<UserPointsRecordEntity>(e => e.Name("points"));
|
||||
Db.CodeFirst.ConfigEntity<UserPaymentRecordEntity>(e => e.Name("payments"));
|
||||
Db.CodeFirst.ConfigEntity<ShopEntity>(e => e.Name("shops"));
|
||||
Db.CodeFirst.ConfigEntity<OEMEntity>(e => e.Name("oems"));
|
||||
Db.CodeFirst.ConfigEntity<UserTopUpMessageEntity>(e => e.Name("messages"));
|
||||
Db.CodeFirst.ConfigEntity<UserTopUpQrcodeEntity>(e => e.Name("qrcodes"));
|
||||
Db.CodeFirst.SyncStructure(typeof(UserEntity), typeof(UserPointsRecordEntity), typeof(UserPaymentRecordEntity),
|
||||
typeof(ShopEntity), typeof(OEMEntity), typeof(UserTopUpMessageEntity), typeof(UserTopUpQrcodeEntity));
|
||||
// 模拟部署脚本提供的唯一索引。
|
||||
Db.Ado.ExecuteNonQuery("CREATE UNIQUE INDEX ux_user_name ON users(user_name)");
|
||||
Admin = Seed("admin", 1);
|
||||
Main = Seed("main");
|
||||
Other = Seed("other");
|
||||
Child = Seed("child", parent: Main.UserName);
|
||||
CurrentUser.UserName = Admin.UserName;
|
||||
|
||||
// 生产实现为 internal;通过反射构造真实仓储和查询服务,无需放宽业务代码可见性。
|
||||
var assembly = typeof(UserManagementService).Assembly;
|
||||
var repository = Activator.CreateInstance(assembly.GetType("Store.Users.Repositories.UserRepository", true)!, Db)!;
|
||||
Query = (IUserQueryService)Activator.CreateInstance(assembly.GetType("Store.Users.Services.UserQueryService", true)!, repository)!;
|
||||
Authentication = (IUserAuthenticationService)Activator.CreateInstance(
|
||||
assembly.GetType("Store.Users.Services.UserAuthenticationService", true)!, Db, Query)!;
|
||||
Users = new(Db, CurrentUser, Query, Sessions);
|
||||
Funds = new(Db, CurrentUser);
|
||||
}
|
||||
|
||||
public UserEntity Seed(string name, short level = 0, string parent = "")
|
||||
{
|
||||
var user = new UserEntity
|
||||
{
|
||||
UserName = name, NickName = name, Password = "legacy-password", ParentUserName = parent,
|
||||
GroupId = string.IsNullOrEmpty(parent) ? (byte)3 : (byte)4, SaLevel = level,
|
||||
Mobile = "", CompanyName = "", Notes = "", CardId = "", Authority = "积分用户,订单",
|
||||
ForbiddenPage = "", OemId = "", Balance = 0, Points = 0, ShopPointsPerMonth = 30,
|
||||
PostagePerOrder = 1m, RefundPostagePerOrder = 1m
|
||||
};
|
||||
user.Id = checked((int)Db.Insert(user).ExecuteIdentity());
|
||||
return user;
|
||||
}
|
||||
|
||||
public Task<UserEntity> Read(string name) => Db.Select<UserEntity>().Where(u => u.UserName == name).FirstAsync();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Db.Dispose();
|
||||
if (File.Exists(_path)) File.Delete(_path);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class TestCurrentUser : ICurrentUser
|
||||
{
|
||||
public bool IsAuthenticated { get; set; } = true;
|
||||
public string? UserName { get; set; }
|
||||
public string? NickName => UserName;
|
||||
public IEnumerable<Claim> Claims => [];
|
||||
public string? GetClaimValue(string claimType) => null;
|
||||
public T? GetClaimValue<T>(string claimType) => default;
|
||||
}
|
||||
|
||||
internal sealed class TestOnlineUsers : IOnlineUserStore
|
||||
{
|
||||
public HashSet<string> SignedOut { get; } = [];
|
||||
public void SignOut(string userName) => SignedOut.Add(userName);
|
||||
public void SignIn(OnlineUserInfo info) { }
|
||||
public bool IsTokenActive(string userName, string jti) => false;
|
||||
public IReadOnlyList<OnlineUserInfo> GetOnlineUsers() => [];
|
||||
public int Count => 0;
|
||||
}
|
||||
Reference in new issue
Block a user