using System.Collections.Generic; using System.IO; using System.Text.Json.Serialization; using Server.Accounting; using Server.Json; using Server.Logging; using Server.Network; namespace Server.Misc; public static class ServerAccess { private static readonly ILogger logger = LogFactory.GetLogger(typeof(ServerAccess)); private const string _serverAccessConfigurationPath = "Configuration/server-access.json"; public static ServerAccessConfiguration ServerAccessConfiguration { get; private set; } public static void SaveConfiguration() { var path = Path.Join(Core.BaseDirectory, _serverAccessConfigurationPath); JsonConfig.Serialize(path, ServerAccessConfiguration ??= new ServerAccessConfiguration()); } public static void AddProtectedAccount(Account acct, bool save = false) { var username = acct.Username.ToLower(); ServerAccessConfiguration.ProtectedAccounts.Add(username); logger.Information("Protected account added: {Username}", username); if (save) { SaveConfiguration(); } } public static void RemoveProtectedAccount(Account acct, bool save = false) { var username = acct.Username.ToLower(); ServerAccessConfiguration.ProtectedAccounts.Remove(username); logger.Information("Protected account removed: {Username}", username); if (save) { SaveConfiguration(); } } public static void Configure() { var path = Path.Join(Core.BaseDirectory, _serverAccessConfigurationPath); if (!File.Exists(path)) { SaveConfiguration(); return; } ServerAccessConfiguration = JsonConfig.Deserialize(path); if (ServerAccessConfiguration.ProtectedAccounts.Count > 0) { var protectedAccounts = string.Join(", ", ServerAccessConfiguration.ProtectedAccounts); logger.Information("Protected accounts registered: {Count}", protectedAccounts); } } public static void Initialize() { EventSink.AccountLogin += EventSink_ResetProtectedAccount; } public static void EventSink_ResetProtectedAccount(AccountLoginEventArgs e) { var username = e.Username.ToLower(); if (!ServerAccessConfiguration.ProtectedAccounts.Contains(username)) { return; } if (Accounts.GetAccount(username) is not Account acct || !acct.Banned && acct.AccessLevel >= AccessLevel.Owner || !acct.CheckPassword(e.Password)) { return; } acct.Banned = false; acct.AccessLevel = AccessLevel.Owner; logger.Warning("Protected account \"{Username}\" has been reset.", username); if (e.RejectReason is ALRReason.Blocked or ALRReason.BadPass or ALRReason.BadComm) { e.Accepted = true; } } } public record ServerAccessConfiguration { [JsonPropertyName("protectedAccounts")] public HashSet ProtectedAccounts { get; set; } = new(); }