using HaloPixelToolBox.Backend.Profiles.CacheProfiles; using HaloPixelToolBox.Backend.Profiles.CrossVersionProfiles; using HaloPixelToolBox.Core.Models.User; using HaloPixelToolBox.Core.Utilities; using System.Net; using XFEExtension.NetCore.ServerInteractive.Models.RequesterModels; namespace HaloPixelToolBox.Backend.Utilities; /// /// 统一维护管理端登录状态,并负责启动时恢复或重新创建管理员会话。 /// public static class AdministratorSessionManager { private static readonly SemaphoreSlim s_authenticationLock = new(1, 1); public static event EventHandler? StateChanged; public static MyUserFaceInfo? CurrentUser { get; private set; } public static bool IsLoggedIn { get; private set; } public static bool IsBusy { get; private set; } public static string StatusText { get; private set; } = "正在准备自动登录..."; public static string DisplayName => CurrentUser?.NickName ?? (IsLoggedIn ? CacheProfile.Account : "未登录"); /// /// 优先恢复现有会话;会话失效时,使用本机保存的账号密码自动重新登录。 /// public static async Task InitializeAsync(bool forceReconnect = false) { await s_authenticationLock.WaitAsync(); try { if (IsLoggedIn && !forceReconnect) return true; SetBusy(true, forceReconnect ? "正在重新连接服务器..." : "正在自动登录..."); if (!await ConnectAsync(forceReconnect)) { SetLoggedOut("服务器连接失败,请在设置中检查服务器地址"); return false; } if (!string.IsNullOrWhiteSpace(CacheProfile.Session)) { DataManager.ClientRequester.Session = CacheProfile.Session; var restoredUser = await RestoreSessionCoreAsync(); if (restoredUser is not null) { CompleteLogin(restoredUser, CacheProfile.Session, "已自动恢复登录"); return true; } ClearSession(); StatusText = "登录会话已过期,正在使用保存的凭据重新登录..."; NotifyStateChanged(); } if (string.IsNullOrWhiteSpace(CacheProfile.Account) || string.IsNullOrWhiteSpace(CacheProfile.Password)) { SetLoggedOut("请输入管理员账号和密码,成功后将自动登录"); return false; } return await LoginCoreAsync(CacheProfile.Account, CacheProfile.Password, "已自动登录"); } catch (Exception ex) { SetLoggedOut($"自动登录失败:{ex.Message}"); return false; } finally { SetBusy(false); s_authenticationLock.Release(); } } /// /// 使用用户输入的管理员凭据登录,并在成功后保存用于下次自动登录。 /// public static async Task LoginAsync(string account, string password) { account = account.Trim(); if (string.IsNullOrWhiteSpace(account) || string.IsNullOrWhiteSpace(password)) { SetLoggedOut("请输入管理员账号和密码"); return false; } await s_authenticationLock.WaitAsync(); try { SetBusy(true, "正在登录管理员账号..."); if (!await ConnectAsync(true)) { SetLoggedOut("服务器连接失败,请在设置中检查服务器地址"); return false; } return await LoginCoreAsync(account, password, "已登录"); } catch (Exception ex) { SetLoggedOut($"登录失败:{ex.Message}"); return false; } finally { SetBusy(false); s_authenticationLock.Release(); } } /// /// 退出管理端,并清除本机保存的密码,防止随后再次自动登录。 /// public static async Task LogoutAsync() { await s_authenticationLock.WaitAsync(); try { ClearSession(); CacheProfile.Password = string.Empty; SetLoggedOut("已退出登录;下次需要重新输入密码"); } finally { s_authenticationLock.Release(); } } private static async Task ConnectAsync(bool forceReconnect) { var serverAddress = SystemProfile.ServerAddress.Trim(); if (!Uri.TryCreate(serverAddress, UriKind.Absolute, out var uri) || (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)) { StatusText = "服务器地址无效,请输入完整的 HTTP 或 HTTPS 地址"; NotifyStateChanged(); return false; } return await DataManager.InitializeAsync([serverAddress], forceReconnect); } private static async Task RestoreSessionCoreAsync() { var response = await DataManager.ClientRequester.Request("relogin"); return response.StatusCode == HttpStatusCode.OK && IsAdministrator(response.Result) ? response.Result : null; } private static async Task LoginCoreAsync(string account, string password, string successMessage) { ClearSession(); var response = await DataManager.ClientRequester.Request>("login", account, password); if (response.StatusCode != HttpStatusCode.OK || response.Result?.UserInfo is null) { SetLoggedOut("登录失败,请检查账号或密码"); return false; } if (!IsAdministrator(response.Result.UserInfo)) { ClearSession(); SetLoggedOut("该账号没有管理员权限"); return false; } CacheProfile.Account = account; CacheProfile.Password = password; CompleteLogin(response.Result.UserInfo, response.Result.Session, successMessage); return true; } private static bool IsAdministrator(MyUserFaceInfo? user) => user is not null && user.PermissionLevel >= (int)UserRole.管理员; private static void CompleteLogin(MyUserFaceInfo user, string session, string successMessage) { DataManager.ClientRequester.Session = session; CacheProfile.Session = session; CurrentUser = user; IsLoggedIn = true; StatusText = $"{successMessage}:{user.NickName}({(UserRole)user.PermissionLevel})"; NotifyStateChanged(); } private static void ClearSession() { DataManager.ClientRequester.Session = string.Empty; CacheProfile.Session = string.Empty; CurrentUser = null; IsLoggedIn = false; } private static void SetLoggedOut(string statusText) { CurrentUser = null; IsLoggedIn = false; StatusText = statusText; NotifyStateChanged(); } private static void SetBusy(bool isBusy, string? statusText = null) { IsBusy = isBusy; if (statusText is not null) StatusText = statusText; NotifyStateChanged(); } private static void NotifyStateChanged() => StateChanged?.Invoke(null, EventArgs.Empty); }