]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Revert "Game server api" (#26871)
authorPieter-Jan Briers <pieterjan.briers+git@gmail.com>
Wed, 10 Apr 2024 12:19:32 +0000 (14:19 +0200)
committerGitHub <noreply@github.com>
Wed, 10 Apr 2024 12:19:32 +0000 (14:19 +0200)
Revert "Game server api (#24015)"

This reverts commit 297853929b7b3859760dcdda95e21888672ce8e1.

Content.Server/Administration/ServerAPI.cs [deleted file]
Content.Server/Administration/Systems/AdminSystem.cs
Content.Server/Entry/EntryPoint.cs
Content.Server/IoC/ServerContentIoC.cs
Content.Shared/CCVar/CCVars.cs

diff --git a/Content.Server/Administration/ServerAPI.cs b/Content.Server/Administration/ServerAPI.cs
deleted file mode 100644 (file)
index d7591fb..0000000
+++ /dev/null
@@ -1,1033 +0,0 @@
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using System.Threading.Tasks;
-using Content.Server.Administration.Systems;
-using Content.Server.GameTicking;
-using Content.Server.GameTicking.Presets;
-using Content.Server.GameTicking.Rules.Components;
-using Content.Server.Maps;
-using Content.Server.RoundEnd;
-using Content.Shared.Administration.Events;
-using Content.Shared.Administration.Managers;
-using Content.Shared.CCVar;
-using Content.Shared.Prototypes;
-using Robust.Server.ServerStatus;
-using Robust.Shared.Asynchronous;
-using Robust.Shared.Configuration;
-using Robust.Shared.Network;
-using Robust.Shared.Player;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
-
-namespace Content.Server.Administration;
-
-public sealed class ServerApi : IPostInjectInit
-{
-    [Dependency] private readonly IStatusHost _statusHost = default!;
-    [Dependency] private readonly IConfigurationManager _config = default!;
-    [Dependency] private readonly ISharedPlayerManager _playerManager = default!; // Players
-    [Dependency] private readonly ISharedAdminManager _adminManager = default!; // Admins
-    [Dependency] private readonly IGameMapManager _gameMapManager = default!; // Map name
-    [Dependency] private readonly IServerNetManager _netManager = default!; // Kick
-    [Dependency] private readonly IPrototypeManager _prototypeManager = default!; // Game rules
-    [Dependency] private readonly IComponentFactory _componentFactory = default!;
-    [Dependency] private readonly ITaskManager _taskManager = default!; // game explodes when calling stuff from the non-game thread
-    [Dependency] private readonly EntityManager _entityManager = default!;
-
-    [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
-
-    private string _token = string.Empty;
-    private ISawmill _sawmill = default!;
-
-    public static Dictionary<string, string> PanicPunkerCvarNames = new()
-    {
-        { "Enabled", "game.panic_bunker.enabled" },
-        { "DisableWithAdmins", "game.panic_bunker.disable_with_admins" },
-        { "EnableWithoutAdmins", "game.panic_bunker.enable_without_admins" },
-        { "CountDeadminnedAdmins", "game.panic_bunker.count_deadminned_admins" },
-        { "ShowReason", "game.panic_bunker.show_reason" },
-        { "MinAccountAgeHours", "game.panic_bunker.min_account_age" },
-        { "MinOverallHours", "game.panic_bunker.min_overall_hours" },
-        { "CustomReason", "game.panic_bunker.custom_reason" }
-    };
-
-    void IPostInjectInit.PostInject()
-    {
-        _sawmill = Logger.GetSawmill("serverApi");
-
-        // Get
-        _statusHost.AddHandler(InfoHandler);
-        _statusHost.AddHandler(GetGameRules);
-        _statusHost.AddHandler(GetForcePresets);
-
-        // Post
-        _statusHost.AddHandler(ActionRoundStatus);
-        _statusHost.AddHandler(ActionKick);
-        _statusHost.AddHandler(ActionAddGameRule);
-        _statusHost.AddHandler(ActionEndGameRule);
-        _statusHost.AddHandler(ActionForcePreset);
-        _statusHost.AddHandler(ActionForceMotd);
-        _statusHost.AddHandler(ActionPanicPunker);
-    }
-
-    public void Initialize()
-    {
-        _config.OnValueChanged(CCVars.AdminApiToken, UpdateToken, true);
-    }
-
-    public void Shutdown()
-    {
-        _config.UnsubValueChanged(CCVars.AdminApiToken, UpdateToken);
-    }
-
-    private void UpdateToken(string token)
-    {
-        _token = token;
-    }
-
-
-#region Actions
-
-    /// <summary>
-    ///     Changes the panic bunker settings.
-    /// </summary>
-    private async Task<bool> ActionPanicPunker(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Patch || context.Url.AbsolutePath != "/admin/actions/panic_bunker")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var body = await ReadJson<Dictionary<string, object>>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        foreach (var panicPunkerActions in body!.Select(x => new { Action = x.Key, Value = x.Value.ToString() }))
-        {
-            if (panicPunkerActions.Action == null || panicPunkerActions.Value == null)
-            {
-                await context.RespondJsonAsync(new BaseResponse()
-                {
-                    Message = "Action and value are required to perform this action.",
-                    Exception = new ExceptionData()
-                    {
-                        Message = "Action and value are required to perform this action.",
-                        ErrorType = ErrorTypes.ActionNotSpecified
-                    }
-                }, HttpStatusCode.BadRequest);
-                return true;
-            }
-
-            if (!PanicPunkerCvarNames.TryGetValue(panicPunkerActions.Action, out var cvarName))
-            {
-                await context.RespondJsonAsync(new BaseResponse()
-                {
-                    Message = $"Cannot set: Action {panicPunkerActions.Action} does not exist.",
-                    Exception = new ExceptionData()
-                    {
-                        Message = $"Cannot set: Action {panicPunkerActions.Action} does not exist.",
-                        ErrorType = ErrorTypes.ActionNotSupported
-                    }
-                }, HttpStatusCode.BadRequest);
-                return true;
-            }
-
-            // Since the CVar can be of different types, we need to parse it to the correct type
-            // First, I try to parse it as a bool, if it fails, I try to parse it as an int
-            // And as a last resort, I do nothing and put it as a string
-            if (bool.TryParse(panicPunkerActions.Value, out var boolValue))
-            {
-                await RunOnMainThread(() => _config.SetCVar(cvarName, boolValue));
-            }
-            else if (int.TryParse(panicPunkerActions.Value, out var intValue))
-            {
-                await RunOnMainThread(() => _config.SetCVar(cvarName, intValue));
-            }
-            else
-            {
-                await RunOnMainThread(() => _config.SetCVar(cvarName, panicPunkerActions.Value));
-            }
-            _sawmill.Info($"Panic bunker property {panicPunkerActions} changed to {panicPunkerActions.Value} by {actor!.Name} ({actor.Guid}).");
-        }
-
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///     Sets the current MOTD.
-    /// </summary>
-    private async Task<bool> ActionForceMotd(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || context.Url.AbsolutePath != "/admin/actions/set_motd")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var motd = await ReadJson<MotdActionBody>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-
-        if (motd!.Motd == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A motd is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A motd is required to perform this action.",
-                    ErrorType = ErrorTypes.MotdNotSpecified
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-
-        _sawmill.Info($"MOTD changed to \"{motd.Motd}\" by {actor!.Name} ({actor.Guid}).");
-
-        await RunOnMainThread(() => _config.SetCVar(CCVars.MOTD, motd.Motd));
-        // A hook in the MOTD system sends the changes to each client
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///     Forces the next preset-
-    /// </summary>
-    private async Task<bool> ActionForcePreset(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || context.Url.AbsolutePath != "/admin/actions/force_preset")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var body = await ReadJson<PresetActionBody>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        var ticker = await RunOnMainThread(() => _entitySystemManager.GetEntitySystem<GameTicker>());
-
-        if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Round already started",
-                Exception = new ExceptionData()
-                {
-                    Message = "Round already started",
-                    ErrorType = ErrorTypes.RoundAlreadyStarted
-                }
-            }, HttpStatusCode.Conflict);
-            return true;
-        }
-
-        if (body!.PresetId == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A preset is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A preset is required to perform this action.",
-                    ErrorType = ErrorTypes.PresetNotSpecified
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-
-        var result = await RunOnMainThread(() => ticker.FindGamePreset(body.PresetId));
-        if (result == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Preset not found",
-                Exception = new ExceptionData()
-                {
-                    Message = "Preset not found",
-                    ErrorType = ErrorTypes.PresetNotSpecified
-                }
-            }, HttpStatusCode.UnprocessableContent);
-            return true;
-        }
-
-        await RunOnMainThread(() =>
-        {
-            ticker.SetGamePreset(result);
-        });
-        _sawmill.Info($"Forced the game to start with preset {body.PresetId} by {actor!.Name}({actor.Guid}).");
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///     Ends an active game rule.
-    /// </summary>
-    private async Task<bool> ActionEndGameRule(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || context.Url.AbsolutePath != "/admin/actions/end_game_rule")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var body = await ReadJson<GameRuleActionBody>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        if (body!.GameRuleId == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A game rule is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A game rule is required to perform this action.",
-                    ErrorType = ErrorTypes.GuidNotSpecified
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-        var ticker = await RunOnMainThread(() => _entitySystemManager.GetEntitySystem<GameTicker>());
-
-        var gameRuleEntity = await RunOnMainThread(() => ticker
-            .GetActiveGameRules()
-            .FirstOrNull(rule => _entityManager.MetaQuery.GetComponent(rule).EntityPrototype?.ID == body.GameRuleId));
-
-        if (gameRuleEntity == null) // Game rule not found
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Game rule not found or not active",
-                Exception = new ExceptionData()
-                {
-                    Message = "Game rule not found or not active",
-                    ErrorType = ErrorTypes.GameRuleNotFound
-                }
-            }, HttpStatusCode.Conflict);
-            return true;
-        }
-
-        _sawmill.Info($"Ended game rule {body.GameRuleId} by {actor!.Name} ({actor.Guid}).");
-        await RunOnMainThread(() => ticker.EndGameRule((EntityUid) gameRuleEntity));
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///     Adds a game rule to the current round.
-    /// </summary>
-    private async Task<bool> ActionAddGameRule(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || context.Url.AbsolutePath != "/admin/actions/add_game_rule")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var body = await ReadJson<GameRuleActionBody>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        if (body!.GameRuleId == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A game rule is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A game rule is required to perform this action.",
-                    ErrorType = ErrorTypes.GuidNotSpecified
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-
-        var ruleEntity = await RunOnMainThread<EntityUid?>(() =>
-        {
-            var ticker = _entitySystemManager.GetEntitySystem<GameTicker>();
-            // See if prototype exists
-            try
-            {
-                _prototypeManager.Index(body.GameRuleId);
-            }
-            catch (KeyNotFoundException e)
-            {
-                return null;
-            }
-
-            var ruleEntity = ticker.AddGameRule(body.GameRuleId);
-            _sawmill.Info($"Added game rule {body.GameRuleId} by {actor!.Name} ({actor.Guid}).");
-            if (ticker.RunLevel == GameRunLevel.InRound)
-            {
-                ticker.StartGameRule(ruleEntity);
-                _sawmill.Info($"Started game rule {body.GameRuleId} by {actor.Name} ({actor.Guid}).");
-            }
-            return ruleEntity;
-        });
-        if (ruleEntity == null)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Game rule not found",
-                Exception = new ExceptionData()
-                {
-                    Message = "Game rule not found",
-                    ErrorType = ErrorTypes.GameRuleNotFound
-                }
-            }, HttpStatusCode.UnprocessableContent);
-            return true;
-        }
-
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///     Kicks a player.
-    /// </summary>
-    private async Task<bool> ActionKick(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || context.Url.AbsolutePath != "/admin/actions/kick")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var body = await ReadJson<KickActionBody>(context);
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        if (body == null)
-        {
-            _sawmill.Info($"Attempted to kick player without supplying a body by {actor!.Name}({actor.Guid}).");
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A body is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A body is required to perform this action.",
-                    ErrorType = ErrorTypes.BodyUnableToParse
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-
-        if (body.Guid == null)
-        {
-            _sawmill.Info($"Attempted to kick player without supplying a username by {actor!.Name}({actor.Guid}).");
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "A player is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "A player is required to perform this action.",
-                    ErrorType = ErrorTypes.GuidNotSpecified
-                }
-            }, HttpStatusCode.BadRequest);
-            return true;
-        }
-
-        var session = await RunOnMainThread(() =>
-        {
-            _playerManager.TryGetSessionById(new NetUserId(new Guid(body.Guid)), out var player);
-            return player;
-        });
-
-        if (session == null)
-        {
-            _sawmill.Info($"Attempted to kick player {body.Guid} by {actor!.Name} ({actor.Guid}), but they were not found.");
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Player not found",
-                Exception = new ExceptionData()
-                {
-                    Message = "Player not found",
-                    ErrorType = ErrorTypes.PlayerNotFound
-                }
-            }, HttpStatusCode.UnprocessableContent);
-            return true;
-        }
-
-        var reason = body.Reason ?? "No reason supplied";
-        reason += " (kicked by admin)";
-
-        await RunOnMainThread(() =>
-        {
-            _netManager.DisconnectChannel(session.Channel, reason);
-        });
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        _sawmill.Info("Kicked player {0} ({1}) for {2} by {3}({4})", session.Name, session.UserId.UserId.ToString(), reason, actor!.Name, actor.Guid);
-        return true;
-    }
-
-    /// <summary>
-    ///     Round restart/end
-    /// </summary>
-    private async Task<bool> ActionRoundStatus(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Post || !context.Url.AbsolutePath.StartsWith("/admin/actions/round/"))
-        {
-            return false;
-        }
-
-        // Make sure paths like /admin/actions/round/lol/start don't work
-        if (context.Url.AbsolutePath.Split('/').Length != 5)
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-
-        var (ticker, roundEndSystem) = await RunOnMainThread(() =>
-        {
-            var ticker = _entitySystemManager.GetEntitySystem<GameTicker>();
-            var roundEndSystem = _entitySystemManager.GetEntitySystem<RoundEndSystem>();
-            return (ticker, roundEndSystem);
-        });
-
-        // Action is the last part of the URL path (e.g. /admin/actions/round/start -> start)
-        var action = context.Url.AbsolutePath.Split('/').Last();
-
-        switch (action)
-        {
-            case "start":
-                if (ticker.RunLevel != GameRunLevel.PreRoundLobby)
-                {
-                    await context.RespondJsonAsync(new BaseResponse()
-                    {
-                        Message = "Round already started",
-                        Exception = new ExceptionData()
-                        {
-                            Message = "Round already started",
-                            ErrorType = ErrorTypes.RoundAlreadyStarted
-                        }
-                    }, HttpStatusCode.Conflict);
-                    _sawmill.Debug("Forced round start failed: round already started");
-                    return true;
-                }
-
-                await RunOnMainThread(() =>
-                {
-                    ticker.StartRound();
-                });
-                _sawmill.Info("Forced round start");
-                break;
-            case "end":
-                if (ticker.RunLevel != GameRunLevel.InRound)
-                {
-                    await context.RespondJsonAsync(new BaseResponse()
-                    {
-                        Message = "Round already ended",
-                        Exception = new ExceptionData()
-                        {
-                            Message = "Round already ended",
-                            ErrorType = ErrorTypes.RoundAlreadyEnded
-                        }
-                    }, HttpStatusCode.Conflict);
-                    _sawmill.Debug("Forced round end failed: round is not in progress");
-                    return true;
-                }
-                await RunOnMainThread(() =>
-                {
-                    roundEndSystem.EndRound();
-                });
-                _sawmill.Info("Forced round end");
-                break;
-            case "restart":
-                if (ticker.RunLevel != GameRunLevel.InRound)
-                {
-                    await context.RespondJsonAsync(new BaseResponse()
-                    {
-                        Message = "Round not in progress",
-                        Exception = new ExceptionData()
-                        {
-                            Message = "Round not in progress",
-                            ErrorType = ErrorTypes.RoundNotInProgress
-                        }
-                    }, HttpStatusCode.Conflict);
-                    _sawmill.Debug("Forced round restart failed: round is not in progress");
-                    return true;
-                }
-                await RunOnMainThread(() =>
-                {
-                    roundEndSystem.EndRound();
-                });
-                _sawmill.Info("Forced round restart");
-                break;
-            case "restartnow": // You should restart yourself NOW!!!
-                await RunOnMainThread(() =>
-                {
-                    ticker.RestartRound();
-                });
-                _sawmill.Info("Forced instant round restart");
-                break;
-            default:
-                return false;
-        }
-
-        _sawmill.Info($"Round {action} by {actor!.Name} ({actor.Guid}).");
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "OK"
-        });
-        return true;
-    }
-#endregion
-
-#region Fetching
-
-    /// <summary>
-    ///     Returns an array containing all available presets.
-    /// </summary>
-    private async Task<bool> GetForcePresets(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Get || context.Url.AbsolutePath != "/admin/force_presets")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var presets = new List<(string id, string desc)>();
-        foreach (var preset in _prototypeManager.EnumeratePrototypes<GamePresetPrototype>())
-        {
-            presets.Add((preset.ID, preset.Description));
-        }
-
-        await context.RespondJsonAsync(new PresetResponse()
-        {
-            Presets = presets
-        });
-        return true;
-    }
-
-    /// <summary>
-    ///    Returns an array containing all game rules.
-    /// </summary>
-    private async Task<bool> GetGameRules(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Get || context.Url.AbsolutePath != "/admin/game_rules")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var gameRules = new List<string>();
-        foreach (var gameRule in _prototypeManager.EnumeratePrototypes<EntityPrototype>())
-        {
-            if (gameRule.Abstract)
-                continue;
-
-            if (gameRule.HasComponent<GameRuleComponent>(_componentFactory))
-                gameRules.Add(gameRule.ID);
-        }
-
-        await context.RespondJsonAsync(new GameruleResponse()
-        {
-            GameRules = gameRules
-        });
-        return true;
-    }
-
-
-    /// <summary>
-    ///     Handles fetching information.
-    /// </summary>
-    private async Task<bool> InfoHandler(IStatusHandlerContext context)
-    {
-        if (context.RequestMethod != HttpMethod.Get || context.Url.AbsolutePath != "/admin/info")
-        {
-            return false;
-        }
-
-        if (!CheckAccess(context))
-            return true;
-
-        var (success, actor) = await CheckActor(context);
-        if (!success)
-            return true;
-
-        /*  Information to display
-            Round number
-            Connected players
-            Active admins
-            Active game rules
-            Active game preset
-            Active map
-            MOTD
-            Panic bunker status
-         */
-
-        var (ticker, adminSystem) = await RunOnMainThread(() =>
-        {
-            var ticker = _entitySystemManager.GetEntitySystem<GameTicker>();
-            var adminSystem = _entitySystemManager.GetEntitySystem<AdminSystem>();
-            return (ticker, adminSystem);
-        });
-
-        var players = new List<Actor>();
-        await RunOnMainThread(async () =>
-        {
-            foreach (var player in _playerManager.Sessions)
-            {
-                var isAdmin = _adminManager.IsAdmin(player);
-                var isDeadmined = _adminManager.IsAdmin(player, true) && !isAdmin;
-
-                players.Add(new Actor()
-                {
-                    Guid = player.UserId.UserId.ToString(),
-                    Name = player.Name,
-                    IsAdmin = isAdmin,
-                    IsDeadmined = isDeadmined
-                });
-            }
-        });
-        var gameRules = await RunOnMainThread(() =>
-        {
-            var gameRules = new List<string>();
-            foreach (var addedGameRule in ticker.GetActiveGameRules())
-            {
-                var meta = _entityManager.MetaQuery.GetComponent(addedGameRule);
-                gameRules.Add(meta.EntityPrototype?.ID ?? meta.EntityPrototype?.Name ?? "Unknown");
-            }
-
-            return gameRules;
-        });
-
-        _sawmill.Info($"Info requested by {actor!.Name} ({actor.Guid}).");
-        await context.RespondJsonAsync(new InfoResponse()
-        {
-            Players = players,
-            RoundId = ticker.RoundId,
-            Map = await RunOnMainThread(() => _gameMapManager.GetSelectedMap()?.MapName ?? "Unknown"),
-            PanicBunker = adminSystem.PanicBunker,
-            GamePreset = ticker.CurrentPreset?.ID,
-            GameRules = gameRules,
-            MOTD = _config.GetCVar(CCVars.MOTD)
-        });
-        return true;
-    }
-
-#endregion
-
-    private bool CheckAccess(IStatusHandlerContext context)
-    {
-        var auth = context.RequestHeaders.TryGetValue("Authorization", out var authToken);
-        if (!auth)
-        {
-            context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "An authorization header is required to perform this action.",
-                Exception = new ExceptionData()
-                {
-                    Message = "An authorization header is required to perform this action.",
-                    ErrorType = ErrorTypes.MissingAuthentication
-                }
-            });
-            return false;
-        }
-
-
-        if (CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(authToken.ToString()), Encoding.UTF8.GetBytes(_token)))
-            return true;
-
-        context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "Invalid authorization header.",
-            Exception = new ExceptionData()
-            {
-                Message = "Invalid authorization header.",
-                ErrorType = ErrorTypes.InvalidAuthentication
-            }
-        });
-        // Invalid auth header, no access
-        _sawmill.Info("Unauthorized access attempt to admin API.");
-        return false;
-    }
-
-    /// <summary>
-    /// Async helper function which runs a task on the main thread and returns the result.
-    /// </summary>
-    private async Task<T> RunOnMainThread<T>(Func<T> func)
-    {
-        var taskCompletionSource = new TaskCompletionSource<T>();
-        _taskManager.RunOnMainThread(() =>
-        {
-            try
-            {
-                taskCompletionSource.TrySetResult(func());
-            }
-            catch (Exception e)
-            {
-                taskCompletionSource.TrySetException(e);
-            }
-        });
-
-        var result = await taskCompletionSource.Task;
-        return result;
-    }
-
-    /// <summary>
-    /// Runs an action on the main thread. This does not return any value and is meant to be used for void functions. Use <see cref="RunOnMainThread{T}"/> for functions that return a value.
-    /// </summary>
-    private async Task RunOnMainThread(Action action)
-    {
-        var taskCompletionSource = new TaskCompletionSource<bool>();
-        _taskManager.RunOnMainThread(() =>
-        {
-            try
-            {
-                action();
-                taskCompletionSource.TrySetResult(true);
-            }
-            catch (Exception e)
-            {
-                taskCompletionSource.TrySetException(e);
-            }
-        });
-
-        await taskCompletionSource.Task;
-    }
-
-    private async Task<(bool, Actor? actor)> CheckActor(IStatusHandlerContext context)
-    {
-        // The actor is JSON encoded in the header
-        var actor = context.RequestHeaders.TryGetValue("Actor", out var actorHeader) ? actorHeader.ToString() : null;
-        if (actor != null)
-        {
-            var actionData = JsonSerializer.Deserialize<Actor>(actor);
-            if (actionData == null)
-            {
-                await context.RespondJsonAsync(new BaseResponse()
-                {
-                    Message = "Unable to parse actor.",
-                    Exception = new ExceptionData()
-                    {
-                        Message = "Unable to parse actor.",
-                        ErrorType = ErrorTypes.BodyUnableToParse
-                    }
-                }, HttpStatusCode.BadRequest);
-                return (false, null);
-            }
-            // Check if the actor is valid, like if all the required fields are present
-            if (string.IsNullOrWhiteSpace(actionData.Guid) || string.IsNullOrWhiteSpace(actionData.Name))
-            {
-                await context.RespondJsonAsync(new BaseResponse()
-                {
-                    Message = "Invalid actor supplied.",
-                    Exception = new ExceptionData()
-                    {
-                        Message = "Invalid actor supplied.",
-                        ErrorType = ErrorTypes.InvalidActor
-                    }
-                }, HttpStatusCode.BadRequest);
-                return (false, null);
-            }
-
-            // See if the parsed GUID is a valid GUID
-            if (!Guid.TryParse(actionData.Guid, out _))
-            {
-                await context.RespondJsonAsync(new BaseResponse()
-                {
-                    Message = "Invalid GUID supplied.",
-                    Exception = new ExceptionData()
-                    {
-                        Message = "Invalid GUID supplied.",
-                        ErrorType = ErrorTypes.InvalidActor
-                    }
-                }, HttpStatusCode.BadRequest);
-                return (false, null);
-            }
-
-            return (true, actionData);
-        }
-
-        await context.RespondJsonAsync(new BaseResponse()
-        {
-            Message = "An actor is required to perform this action.",
-            Exception = new ExceptionData()
-            {
-                Message = "An actor is required to perform this action.",
-                ErrorType = ErrorTypes.MissingActor
-            }
-        }, HttpStatusCode.BadRequest);
-        return (false, null);
-    }
-
-    /// <summary>
-    /// Helper function to read JSON encoded data from the request body.
-    /// </summary>
-    private async Task<T?> ReadJson<T>(IStatusHandlerContext context)
-    {
-        try
-        {
-            var json = await context.RequestBodyJsonAsync<T>();
-            return json;
-        }
-        catch (Exception e)
-        {
-            await context.RespondJsonAsync(new BaseResponse()
-            {
-                Message = "Unable to parse request body.",
-                Exception = new ExceptionData()
-                {
-                    Message = e.Message,
-                    ErrorType = ErrorTypes.BodyUnableToParse,
-                    StackTrace = e.StackTrace
-                }
-            }, HttpStatusCode.BadRequest);
-            return default;
-        }
-    }
-
-#region From Client
-
-    private record Actor
-    {
-        public string? Guid { get; init; }
-        public string? Name { get; init; }
-        public bool IsAdmin { get; init; } = false;
-        public bool IsDeadmined { get; init; } = false;
-    }
-
-    private record KickActionBody
-    {
-        public string? Guid { get; init; }
-        public string? Reason { get; init; }
-    }
-
-    private record GameRuleActionBody
-    {
-        public string? GameRuleId { get; init; }
-    }
-
-    private record PresetActionBody
-    {
-        public string? PresetId { get; init; }
-    }
-
-    private record MotdActionBody
-    {
-        public string? Motd { get; init; }
-    }
-
-#endregion
-
-#region Responses
-
-    private record BaseResponse
-    {
-        public string? Message { get; init; } = "OK";
-        public ExceptionData? Exception { get; init; } = null;
-    }
-
-    private record ExceptionData
-    {
-        public string Message { get; init; } = string.Empty;
-        public ErrorTypes ErrorType { get; init; } = ErrorTypes.None;
-        public string? StackTrace { get; init; } = null;
-    }
-
-    private enum ErrorTypes
-    {
-        BodyUnableToParse = -2,
-        None = -1,
-        MissingAuthentication = 0,
-        InvalidAuthentication = 1,
-        MissingActor = 2,
-        InvalidActor = 3,
-        RoundNotInProgress = 4,
-        RoundAlreadyStarted = 5,
-        RoundAlreadyEnded = 6,
-        ActionNotSpecified = 7,
-        ActionNotSupported = 8,
-        GuidNotSpecified = 9,
-        PlayerNotFound = 10,
-        GameRuleNotFound = 11,
-        PresetNotSpecified = 12,
-        MotdNotSpecified = 13
-    }
-
-#endregion
-
-#region Misc
-
-    /// <summary>
-    /// Record used to send the response for the info endpoint.
-    /// </summary>
-    private record InfoResponse
-    {
-        public int RoundId { get; init; } = 0;
-        public List<Actor> Players { get; init; } = new();
-        public List<string> GameRules { get; init; } = new();
-        public string? GamePreset { get; init; } = null;
-        public string? Map { get; init; } = null;
-        public string? MOTD { get; init; } = null;
-        public PanicBunkerStatus PanicBunker { get; init; } = new();
-    }
-
-    private record PresetResponse : BaseResponse
-    {
-        public List<(string id, string desc)> Presets { get; init; } = new();
-    }
-
-    private record GameruleResponse : BaseResponse
-    {
-        public List<string> GameRules { get; init; } = new();
-    }
-
-#endregion
-
-}
index b7ca4e915b5d20ae66230cbb9912f7530098fecb..c3c024174ab3a297f3c0843bf7aa842529c044f6 100644 (file)
@@ -61,7 +61,7 @@ namespace Content.Server.Administration.Systems
         public IReadOnlySet<NetUserId> RoundActivePlayers => _roundActivePlayers;
 
         private readonly HashSet<NetUserId> _roundActivePlayers = new();
-        public readonly PanicBunkerStatus PanicBunker = new();
+        private readonly PanicBunkerStatus _panicBunker = new();
 
         public override void Initialize()
         {
@@ -240,7 +240,7 @@ namespace Content.Server.Administration.Systems
 
         private void OnPanicBunkerChanged(bool enabled)
         {
-            PanicBunker.Enabled = enabled;
+            _panicBunker.Enabled = enabled;
             _chat.SendAdminAlert(Loc.GetString(enabled
                 ? "admin-ui-panic-bunker-enabled-admin-alert"
                 : "admin-ui-panic-bunker-disabled-admin-alert"
@@ -251,52 +251,52 @@ namespace Content.Server.Administration.Systems
 
         private void OnPanicBunkerDisableWithAdminsChanged(bool enabled)
         {
-            PanicBunker.DisableWithAdmins = enabled;
+            _panicBunker.DisableWithAdmins = enabled;
             UpdatePanicBunker();
         }
 
         private void OnPanicBunkerEnableWithoutAdminsChanged(bool enabled)
         {
-            PanicBunker.EnableWithoutAdmins = enabled;
+            _panicBunker.EnableWithoutAdmins = enabled;
             UpdatePanicBunker();
         }
 
         private void OnPanicBunkerCountDeadminnedAdminsChanged(bool enabled)
         {
-            PanicBunker.CountDeadminnedAdmins = enabled;
+            _panicBunker.CountDeadminnedAdmins = enabled;
             UpdatePanicBunker();
         }
 
         private void OnShowReasonChanged(bool enabled)
         {
-            PanicBunker.ShowReason = enabled;
+            _panicBunker.ShowReason = enabled;
             SendPanicBunkerStatusAll();
         }
 
         private void OnPanicBunkerMinAccountAgeChanged(int minutes)
         {
-            PanicBunker.MinAccountAgeHours = minutes / 60;
+            _panicBunker.MinAccountAgeHours = minutes / 60;
             SendPanicBunkerStatusAll();
         }
 
         private void OnPanicBunkerMinOverallHoursChanged(int hours)
         {
-            PanicBunker.MinOverallHours = hours;
+            _panicBunker.MinOverallHours = hours;
             SendPanicBunkerStatusAll();
         }
 
         private void UpdatePanicBunker()
         {
-            var admins = PanicBunker.CountDeadminnedAdmins
+            var admins = _panicBunker.CountDeadminnedAdmins
                 ? _adminManager.AllAdmins
                 : _adminManager.ActiveAdmins;
             var hasAdmins = admins.Any();
 
-            if (hasAdmins && PanicBunker.DisableWithAdmins)
+            if (hasAdmins && _panicBunker.DisableWithAdmins)
             {
                 _config.SetCVar(CCVars.PanicBunkerEnabled, false);
             }
-            else if (!hasAdmins && PanicBunker.EnableWithoutAdmins)
+            else if (!hasAdmins && _panicBunker.EnableWithoutAdmins)
             {
                 _config.SetCVar(CCVars.PanicBunkerEnabled, true);
             }
@@ -306,7 +306,7 @@ namespace Content.Server.Administration.Systems
 
         private void SendPanicBunkerStatusAll()
         {
-            var ev = new PanicBunkerChangedEvent(PanicBunker);
+            var ev = new PanicBunkerChangedEvent(_panicBunker);
             foreach (var admin in _adminManager.AllAdmins)
             {
                 RaiseNetworkEvent(ev, admin);
index 3cdf3bfe8e2e27dfbc8f160e4a9e2a6148e99803..bf7f3ea84abfd9fbccb38db8a0ddf529ce607128 100644 (file)
@@ -102,7 +102,6 @@ namespace Content.Server.Entry
                 IoCManager.Resolve<ContentNetworkResourceManager>().Initialize();
                 IoCManager.Resolve<GhostKickManager>().Initialize();
                 IoCManager.Resolve<ServerInfoManager>().Initialize();
-                IoCManager.Resolve<ServerApi>().Initialize();
 
                 _voteManager.Initialize();
                 _updateManager.Initialize();
@@ -168,7 +167,6 @@ namespace Content.Server.Entry
         {
             _playTimeTracking?.Shutdown();
             _dbManager?.Shutdown();
-            IoCManager.Resolve<ServerApi>().Shutdown();
         }
 
         private static void LoadConfigPresets(IConfigurationManager cfg, IResourceManager res, ISawmill sawmill)
index 25bb1072a52c9ee8a19a91c27d865b2ca08a8f4b..2a63ace8e30dd884a42c9c14010fd511da33d800 100644 (file)
@@ -58,7 +58,6 @@ namespace Content.Server.IoC
             IoCManager.Register<PoissonDiskSampler>();
             IoCManager.Register<DiscordWebhook>();
             IoCManager.Register<ServerDbEntryManager>();
-            IoCManager.Register<ServerApi>();
         }
     }
 }
index aa14c565a014ef3b00fafa929418c55d0f2d2cbd..c9271331f31c4546bdbb58108049564f507aa063 100644 (file)
@@ -773,13 +773,6 @@ namespace Content.Shared.CCVar
         public static readonly CVarDef<bool> AdminAnnounceLogout =
             CVarDef.Create("admin.announce_logout", true, CVar.SERVERONLY);
 
-        /// <summary>
-        ///     The token used to authenticate with the admin API. Leave empty to disable the admin API. This is a secret! Do not share!
-        /// </summary>
-        public static readonly CVarDef<string> AdminApiToken =
-            CVarDef.Create("admin.api_token", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL);
-
-
         /// <summary>
         /// Should users be able to see their own notes? Admins will be able to see and set notes regardless
         /// </summary>