using XFEExtension.NetCore.ServerInteractive.Interfaces; using XFEExtension.NetCore.ServerInteractive.Models.UserModels; using System.Runtime.InteropServices; using XFEExtension.NetCore.AutoConfig; using XFEExtension.NetCore.ServerInteractive.TServer.Models; using XFEExtension.NetCore.ServerInteractive.TServer.Profiles; using XFEExtension.NetCore.ServerInteractive.TServer.Services; using XFEExtension.NetCore.ServerInteractive.Utilities.DataTable; using XFEExtension.NetCore.ServerInteractive.Utilities.Extensions; using XFEExtension.NetCore.ServerInteractive.Utilities.Server; var configuredRoot = args.FirstOrDefault(argument => argument.StartsWith("--root=", StringComparison.OrdinalIgnoreCase))?[7..]; var rootPath = Path.GetFullPath(configuredRoot ?? AppContext.BaseDirectory); Directory.CreateDirectory(rootPath); foreach (var directoryName in new[] { "certificates", "data", "logs", "temp" }) Directory.CreateDirectory(Path.Combine(rootPath, directoryName)); Directory.SetCurrentDirectory(rootPath); XFEProfile.ProfilesDefaultPath = Path.Combine(rootPath, "data"); XFEProfile.ProfileLoadFailed += static (_, eventArgs) => Console.WriteLine($"[ERROR]AutoConfig 加载 {eventArgs.ProfileType.Name} 失败,原文件已备份到:{eventArgs.BackupPath ?? "<备份失败>"};{eventArgs.Exception.Message}"); ServerProfile.ValidateConfiguration(); ServerProfile.SaveProfile(); var listenUrls = ServerProfile.ListenUrls.ToArray(); var shutdownTimeout = TimeSpan.FromSeconds(ServerProfile.ShutdownTimeoutSeconds); var tlsPassword = args.FirstOrDefault(argument => argument.StartsWith("--tls-password=", StringComparison.OrdinalIgnoreCase))?[15..] ?? Environment.GetEnvironmentVariable("XFE_TLS_PFX_PASSWORD"); if (args.Contains("--tls-password-stdin", StringComparer.OrdinalIgnoreCase)) tlsPassword = Console.ReadLine(); var tlsOptions = ServerProfile.CreateTlsOptions(rootPath, tlsPassword); var transportLimits = ServerProfile.CreateTransportLimits(); await using var server = XFEServerBuilder.CreateBuilder() // 创建服务器构建器 .UseXFEServer() // 使用XFE服务器架构 .AddServerCore( // 添加核心服务器 XFEServerCoreBuilder.CreateBuilder() // 创建核心服务器构建器 .UseXFEStandardServerCore(options => { // 使用XFE标准服务器核心 options.GetUserFunction = static () => UserProfile.UserTable; // 获取用户表的方法 options.AddUserFunction = user => UserProfile.UserTable.Add(user); // 添加用户的方法 options.UpdateUserFunction = static _ => UserProfile.SaveProfile(); // 持久化密码迁移 options.GetEncryptedUserLoginModelFunction = static () => UserProfile.EncryptedUserLoginModelTable; // 获取用户加密模型的方法 options.AddEncryptedUserLoginModelFunction = UserProfile.EncryptedUserLoginModelTable.Add; // 添加用户加密模型的方法 options.RemoveEncryptedUserLoginModelFunction = static user => UserProfile.EncryptedUserLoginModelTable.Remove(user); // 移除用户加密模型的方法 options.GetLoginKeepDays = static () => 7; // 获取登录维持天数方法 options.LoginResultConvertFunction = static user => UserPublicDto.From((IUserInfo)user); // 登录结果使用安全 DTO }) .AddService() .AddService() .AddService() .AddService() .AddService() .AddService() .Build(options => { options.ServerCoreName = "ClientServer"; options.AcceptGet = true; options.AcceptPost = true; options.AcceptNonStandardJson = true; options.MainEntryPoint = "api"; foreach (var url in listenUrls) options.BindIP(url); options.Tls = tlsOptions; options.TransportLimits = transportLimits; })) // 构建核心服务器 .AddServerCore( XFEServerCoreBuilder.CreateBuilder() .UseXFEStandardServerCore(options => { // 使用XFE标准服务器核心 options.GetUserFunction = static () => UserProfile.UserTable; // 获取用户表的方法 options.AddUserFunction = user => UserProfile.UserTable.Add(user); // 添加用户的方法 options.UpdateUserFunction = static _ => UserProfile.SaveProfile(); // 持久化密码迁移 options.GetEncryptedUserLoginModelFunction = static () => UserProfile.EncryptedUserLoginModelTable; // 获取用户加密模型的方法 options.AddEncryptedUserLoginModelFunction = UserProfile.EncryptedUserLoginModelTable.Add; // 添加用户加密模型的方法 options.RemoveEncryptedUserLoginModelFunction = static user => UserProfile.EncryptedUserLoginModelTable.Remove(user); // 移除用户加密模型的方法 options.GetLoginKeepDays = static () => 7; // 获取登录维持天数方法 options.LoginResultConvertFunction = static user => UserPublicDto.From((IUserInfo)user); // 登录结果使用安全 DTO options.DataTableManagerBuilder = XFEDataTableManagerBuilder.CreateBuilder() // 创建DataTable管理器构建器 .AddTable("人物", (int)UserRole.业务员, (int)UserRole.经理, (int)UserRole.业务员, (int)UserRole.业务员) // 添加名为人物的格, Person 类 型, AutoConfig为 DataProfile。添加更改获取权限为业务员,移除权限为经理 .AddTable("订单", (int)UserRole.业务员, (int)UserRole.经理, (int)UserRole.业务员, (int)UserRole.业务员) // 添加名为订单的表格Order 类 型, AutoConfig 为 DataProfile。添加更改获取权限为业务员,移除权限为经理 .AddTable("用户", (int)UserRole.经理, (int)UserRole.经理, (int)UserRole.经理, (int)UserRole.业务员); // 添加名为用户的表格Use类 型, AutoConfig为 UserProfile。获取权限为业务员,添加移除更改权限为经理 }) .Build(options => { options.ServerCoreName = "BackendServer"; options.AcceptGet = true; options.AcceptPost = true; options.AcceptNonStandardJson = true; options.MainEntryPoint = "backend"; foreach (var url in listenUrls) options.BindIP(url); options.Tls = tlsOptions; options.TransportLimits = transportLimits; }) ) .Build(); // 构建服务器 using var shutdown = new CancellationTokenSource(); void RequestShutdown() { if (!shutdown.IsCancellationRequested) shutdown.Cancel(); } ConsoleCancelEventHandler cancelHandler = (_, eventArgs) => { eventArgs.Cancel = true; RequestShutdown(); }; EventHandler processExitHandler = (_, _) => RequestShutdown(); Console.CancelKeyPress += cancelHandler; AppDomain.CurrentDomain.ProcessExit += processExitHandler; using var terminateSignal = !OperatingSystem.IsWindows() ? PosixSignalRegistration.Create(PosixSignal.SIGTERM, context => { context.Cancel = true; RequestShutdown(); }) : null; Console.WriteLine($"[INFO]AutoConfig 配置文件:{ServerProfile.StoragePath}"); Console.WriteLine("[INFO]按 Ctrl+C 可优雅停止服务器"); try { await server.RunAsync(shutdown.Token); } finally { Console.CancelKeyPress -= cancelHandler; AppDomain.CurrentDomain.ProcessExit -= processExitHandler; using var flushTimeout = new CancellationTokenSource(shutdownTimeout); try { await Task.WhenAll( ServerProfile.FlushAsync(flushTimeout.Token), DataProfile.FlushAsync(flushTimeout.Token), UserProfile.FlushAsync(flushTimeout.Token)); } catch (OperationCanceledException) { Console.WriteLine("[WARN]等待 AutoConfig 落盘超时"); } catch (Exception ex) { Console.WriteLine($"[ERROR]AutoConfig 落盘失败:{ex.Message}"); } }