SS14-28662 Add Baby Jail: a Jail for Babies (inverse panic bunker) (#28763)

This commit is contained in:
Hannah Giovanna Dawson
2024-06-09 19:58:10 +01:00
committed by GitHub
parent f4e80b0dae
commit 3ceb92a0c4
19 changed files with 530 additions and 5 deletions

View File

@@ -0,0 +1,139 @@
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Server)]
public sealed class BabyJailCommand : LocalizedCommands
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override string Command => "babyjail";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = Toggle(CCVars.BabyJailEnabled, shell, args, _cfg);
if (toggle == null)
return;
shell.WriteLine(Loc.GetString(toggle.Value ? "babyjail-command-enabled" : "babyjail-command-disabled"));
}
public static bool? Toggle(CVarDef<bool> cvar, IConsoleShell shell, string[] args, IConfigurationManager config)
{
if (args.Length > 1)
{
shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
return null;
}
var enabled = config.GetCVar(cvar);
switch (args.Length)
{
case 0:
enabled = !enabled;
break;
case 1 when !bool.TryParse(args[0], out enabled):
shell.WriteError(Loc.GetString("shell-argument-must-be-boolean"));
return null;
}
config.SetCVar(cvar, enabled);
return enabled;
}
}
[AdminCommand(AdminFlags.Server)]
public sealed class BabyJailShowReasonCommand : LocalizedCommands
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override string Command => "babyjail_show_reason";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
var toggle = BabyJailCommand.Toggle(CCVars.BabyJailShowReason, shell, args, _cfg);
if (toggle == null)
return;
shell.WriteLine(Loc.GetString(toggle.Value
? "babyjail-command-show-reason-enabled"
: "babyjail-command-show-reason-disabled"
));
}
}
[AdminCommand(AdminFlags.Server)]
public sealed class BabyJailMinAccountAgeCommand : LocalizedCommands
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override string Command => "babyjail_max_account_age";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
switch (args.Length)
{
case 0:
{
var current = _cfg.GetCVar(CCVars.BabyJailMaxAccountAge);
shell.WriteLine(Loc.GetString("babyjail-command-max-account-age-is", ("minutes", current)));
break;
}
case > 1:
shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
return;
}
if (!int.TryParse(args[0], out var minutes))
{
shell.WriteError(Loc.GetString("shell-argument-must-be-number"));
return;
}
_cfg.SetCVar(CCVars.BabyJailMaxAccountAge, minutes);
shell.WriteLine(Loc.GetString("babyjail-command-max-account-age-set", ("minutes", minutes)));
}
}
[AdminCommand(AdminFlags.Server)]
public sealed class BabyJailMinOverallHoursCommand : LocalizedCommands
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override string Command => "babyjail_max_overall_minutes";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
switch (args.Length)
{
case 0:
{
var current = _cfg.GetCVar(CCVars.BabyJailMaxOverallMinutes);
shell.WriteLine(Loc.GetString("babyjail-command-max-overall-minutes-is", ("minutes", current)));
break;
}
case > 1:
shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
return;
}
if (!int.TryParse(args[0], out var hours))
{
shell.WriteError(Loc.GetString("shell-argument-must-be-number"));
return;
}
_cfg.SetCVar(CCVars.BabyJailMaxOverallMinutes, hours);
shell.WriteLine(Loc.GetString("babyjail-command-overall-minutes-set", ("hours", hours)));
}
}

View File

@@ -62,6 +62,7 @@ namespace Content.Server.Administration.Systems
private readonly HashSet<NetUserId> _roundActivePlayers = new();
public readonly PanicBunkerStatus PanicBunker = new();
public readonly BabyJailStatus BabyJail = new();
public override void Initialize()
{
@@ -70,14 +71,25 @@ namespace Content.Server.Administration.Systems
_playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
_adminManager.OnPermsChanged += OnAdminPermsChanged;
// Panic Bunker Settings
Subs.CVar(_config, CCVars.PanicBunkerEnabled, OnPanicBunkerChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerDisableWithAdmins, OnPanicBunkerDisableWithAdminsChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerEnableWithoutAdmins, OnPanicBunkerEnableWithoutAdminsChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerCountDeadminnedAdmins, OnPanicBunkerCountDeadminnedAdminsChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerShowReason, OnShowReasonChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerShowReason, OnPanicBunkerShowReasonChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerMinAccountAge, OnPanicBunkerMinAccountAgeChanged, true);
Subs.CVar(_config, CCVars.PanicBunkerMinOverallHours, OnPanicBunkerMinOverallHoursChanged, true);
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
// Baby Jail Settings
Subs.CVar(_config, CCVars.BabyJailEnabled, OnBabyJailChanged, true);
Subs.CVar(_config, CCVars.BabyJailShowReason, OnBabyJailShowReasonChanged, true);
Subs.CVar(_config, CCVars.BabyJailMaxAccountAge, OnBabyJailMaxAccountAgeChanged, true);
Subs.CVar(_config, CCVars.BabyJailMaxOverallMinutes, OnBabyJailMaxOverallMinutesChanged, true);
SubscribeLocalEvent<IdentityChangedEvent>(OnIdentityChanged);
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<PlayerDetachedEvent>(OnPlayerDetached);
@@ -249,6 +261,17 @@ namespace Content.Server.Administration.Systems
SendPanicBunkerStatusAll();
}
private void OnBabyJailChanged(bool enabled)
{
BabyJail.Enabled = enabled;
_chat.SendAdminAlert(Loc.GetString(enabled
? "admin-ui-baby-jail-enabled-admin-alert"
: "admin-ui-baby-jail-disabled-admin-alert"
));
SendBabyJailStatusAll();
}
private void OnPanicBunkerDisableWithAdminsChanged(bool enabled)
{
PanicBunker.DisableWithAdmins = enabled;
@@ -267,24 +290,42 @@ namespace Content.Server.Administration.Systems
UpdatePanicBunker();
}
private void OnShowReasonChanged(bool enabled)
private void OnPanicBunkerShowReasonChanged(bool enabled)
{
PanicBunker.ShowReason = enabled;
SendPanicBunkerStatusAll();
}
private void OnBabyJailShowReasonChanged(bool enabled)
{
BabyJail.ShowReason = enabled;
SendBabyJailStatusAll();
}
private void OnPanicBunkerMinAccountAgeChanged(int minutes)
{
PanicBunker.MinAccountAgeHours = minutes / 60;
SendPanicBunkerStatusAll();
}
private void OnBabyJailMaxAccountAgeChanged(int minutes)
{
BabyJail.MaxAccountAgeMinutes = minutes;
SendBabyJailStatusAll();
}
private void OnPanicBunkerMinOverallHoursChanged(int hours)
{
PanicBunker.MinOverallHours = hours;
SendPanicBunkerStatusAll();
}
private void OnBabyJailMaxOverallMinutesChanged(int minutes)
{
BabyJail.MaxOverallMinutes = minutes;
SendBabyJailStatusAll();
}
private void UpdatePanicBunker()
{
var admins = PanicBunker.CountDeadminnedAdmins
@@ -326,6 +367,15 @@ namespace Content.Server.Administration.Systems
}
}
private void SendBabyJailStatusAll()
{
var ev = new BabyJailChangedEvent(BabyJail);
foreach (var admin in _adminManager.AllAdmins)
{
RaiseNetworkEvent(ev, admin);
}
}
/// <summary>
/// Erases a player from the round.
/// This removes them and any trace of them from the round, deleting their

View File

@@ -13,6 +13,9 @@ using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Timing;
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
namespace Content.Server.Connection
{
@@ -125,6 +128,10 @@ namespace Content.Server.Connection
}
}
/*
* TODO: Jesus H Christ what is this utter mess of a function
* TODO: Break this apart into is constituent steps.
*/
private async Task<(ConnectionDenyReason, string, List<ServerBanDef>? bansHit)?> ShouldDeny(
NetConnectingArgs e)
{
@@ -202,6 +209,14 @@ namespace Content.Server.Connection
}
}
if (_cfg.GetCVar(CCVars.BabyJailEnabled) && adminData == null)
{
var result = await IsInvalidConnectionDueToBabyJail(userId, e);
if (result.IsInvalid)
return (ConnectionDenyReason.BabyJail, result.Reason, null);
}
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
status == PlayerGameStatus.JoinedGame;
@@ -231,6 +246,57 @@ namespace Content.Server.Connection
return null;
}
private async Task<(bool IsInvalid, string Reason)> IsInvalidConnectionDueToBabyJail(NetUserId userId, NetConnectingArgs e)
{
// If you're whitelisted then bypass this whole thing
if (await _db.GetWhitelistStatusAsync(userId))
return (false, "");
// Initial cvar retrieval
var showReason = _cfg.GetCVar(CCVars.BabyJailShowReason);
var reason = _cfg.GetCVar(CCVars.BabyJailCustomReason);
var maxAccountAgeMinutes = _cfg.GetCVar(CCVars.BabyJailMaxAccountAge);
var maxPlaytimeMinutes = _cfg.GetCVar(CCVars.BabyJailMaxOverallMinutes);
// Wait some time to lookup data
var record = await _dbManager.GetPlayerRecordByUserId(userId);
var isAccountAgeInvalid = record == null || record.FirstSeenTime.CompareTo(DateTimeOffset.Now - TimeSpan.FromMinutes(maxAccountAgeMinutes)) <= 0;
if (isAccountAgeInvalid && showReason)
{
var locAccountReason = reason != string.Empty
? reason
: Loc.GetString("baby-jail-account-denied-reason",
("reason",
Loc.GetString(
"baby-jail-account-reason-account",
("minutes", maxAccountAgeMinutes))));
return (true, locAccountReason);
}
var overallTime = ( await _db.GetPlayTimes(e.UserId)).Find(p => p.Tracker == PlayTimeTrackingShared.TrackerOverall);
var isTotalPlaytimeInvalid = overallTime == null || overallTime.TimeSpent.TotalMinutes >= maxPlaytimeMinutes;
if (isTotalPlaytimeInvalid && showReason)
{
var locPlaytimeReason = reason != string.Empty
? reason
: Loc.GetString("baby-jail-account-denied-reason",
("reason",
Loc.GetString(
"baby-jail-account-reason-overall",
("minutes", maxPlaytimeMinutes))));
return (true, locPlaytimeReason);
}
if (!showReason && isTotalPlaytimeInvalid || isAccountAgeInvalid)
return (true, Loc.GetString("baby-jail-account-denied"));
return (false, "");
}
private bool HasTemporaryBypass(NetUserId user)
{
return _temporaryBypasses.TryGetValue(user, out var time) && time > _gameTiming.RealTime;

View File

@@ -46,6 +46,12 @@ namespace Content.Server.GameTicking
jObject["players"] = _playerManager.PlayerCount;
jObject["soft_max_players"] = _cfg.GetCVar(CCVars.SoftMaxPlayers);
jObject["panic_bunker"] = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
/*
* TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
*/
jObject["baby_jail"] = _cfg.GetCVar(CCVars.BabyJailEnabled);
jObject["run_level"] = (int) _runLevel;
if (preset != null)
jObject["preset"] = Loc.GetString(preset.ModeTitle);