Fix role unbans not applying in real time (#20547)

This commit is contained in:
DrSmugleaf
2023-09-28 16:46:39 -07:00
committed by GitHub
parent a44fa86b68
commit f985e7dc5c
7 changed files with 78 additions and 64 deletions

View File

@@ -1,7 +1,5 @@
using System.Text; using Content.Server.Administration.Managers;
using Content.Server.Database;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Server.Player;
using Robust.Shared.Console; using Robust.Shared.Console;
namespace Content.Server.Administration.Commands; namespace Content.Server.Administration.Commands;
@@ -15,9 +13,6 @@ public sealed class RoleUnbanCommand : IConsoleCommand
public async void Execute(IConsoleShell shell, string argStr, string[] args) public async void Execute(IConsoleShell shell, string argStr, string[] args)
{ {
var player = shell.Player as IPlayerSession;
var dbMan = IoCManager.Resolve<IServerDbManager>();
if (args.Length != 1) if (args.Length != 1)
{ {
shell.WriteLine(Help); shell.WriteLine(Help);
@@ -30,32 +25,9 @@ public sealed class RoleUnbanCommand : IConsoleCommand
return; return;
} }
var ban = await dbMan.GetServerRoleBanAsync(banId); var banManager = IoCManager.Resolve<IBanManager>();
var response = await banManager.PardonRoleBan(banId, shell.Player?.UserId, DateTimeOffset.Now);
if (ban == null) shell.WriteLine(response);
{
shell.WriteLine($"No ban found with id {banId}");
return;
}
if (ban.Unban != null)
{
var response = new StringBuilder("This ban has already been pardoned");
if (ban.Unban.UnbanningAdmin != null)
{
response.Append($" by {ban.Unban.UnbanningAdmin.Value}");
}
response.Append($" in {ban.Unban.UnbanTime}.");
shell.WriteLine(response.ToString());
return;
}
await dbMan.AddServerRoleUnbanAsync(new ServerRoleUnbanDef(banId, player?.UserId, DateTimeOffset.Now));
shell.WriteLine($"Pardoned ban with id {banId}");
} }
public CompletionResult GetCompletion(IConsoleShell shell, string[] args) public CompletionResult GetCompletion(IConsoleShell shell, string[] args)

View File

@@ -1,21 +1,22 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Chat.Managers; using Content.Server.Chat.Managers;
using Content.Server.Database; using Content.Server.Database;
using Content.Server.GameTicking; using Content.Server.GameTicking;
using Content.Shared.CCVar;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Players; using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Roles; using Content.Shared.Roles;
using Microsoft.CodeAnalysis;
using Content.Shared.CCVar;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Enums; using Robust.Shared.Enums;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Server.Administration.Managers; namespace Content.Server.Administration.Managers;
@@ -47,28 +48,25 @@ public sealed class BanManager : IBanManager, IPostInjectInit
private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
{ {
if (e.NewStatus != SessionStatus.Connected if (e.NewStatus != SessionStatus.Connected || _cachedRoleBans.ContainsKey(e.Session.UserId))
|| _cachedRoleBans.ContainsKey(e.Session.UserId))
return; return;
var netChannel = e.Session.ConnectedClient; var netChannel = e.Session.ConnectedClient;
await CacheDbRoleBans(e.Session.UserId, netChannel.RemoteEndPoint.Address, netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId); ImmutableArray<byte>? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId;
await CacheDbRoleBans(e.Session.UserId, netChannel.RemoteEndPoint.Address, hwId);
SendRoleBans(e.Session);
} }
private async Task<bool> AddRoleBan(ServerRoleBanDef banDef) private async Task<bool> AddRoleBan(ServerRoleBanDef banDef)
{ {
banDef = await _db.AddServerRoleBanAsync(banDef);
if (banDef.UserId != null) if (banDef.UserId != null)
{ {
if (!_cachedRoleBans.TryGetValue(banDef.UserId.Value, out var roleBans)) _cachedRoleBans.GetOrNew(banDef.UserId.Value).Add(banDef);
{
roleBans = new HashSet<ServerRoleBanDef>();
_cachedRoleBans.Add(banDef.UserId.Value, roleBans);
}
if (!roleBans.Contains(banDef))
roleBans.Add(banDef);
} }
await _db.AddServerRoleBanAsync(banDef);
return true; return true;
} }
@@ -231,6 +229,39 @@ public sealed class BanManager : IBanManager, IPostInjectInit
} }
} }
public async Task<string> PardonRoleBan(int banId, NetUserId? unbanningAdmin, DateTimeOffset unbanTime)
{
var ban = await _db.GetServerRoleBanAsync(banId);
if (ban == null)
{
return $"No ban found with id {banId}";
}
if (ban.Unban != null)
{
var response = new StringBuilder("This ban has already been pardoned");
if (ban.Unban.UnbanningAdmin != null)
{
response.Append($" by {ban.Unban.UnbanningAdmin.Value}");
}
response.Append($" in {ban.Unban.UnbanTime}.");
return response.ToString();
}
await _db.AddServerRoleUnbanAsync(new ServerRoleUnbanDef(banId, unbanningAdmin, DateTimeOffset.Now));
if (ban.UserId is { } player && _cachedRoleBans.TryGetValue(player, out var roleBans))
{
roleBans.RemoveWhere(roleBan => roleBan.Id == ban.Id);
SendRoleBans(player);
}
return $"Pardoned ban with id {banId}";
}
public HashSet<string>? GetJobBans(NetUserId playerUserId) public HashSet<string>? GetJobBans(NetUserId playerUserId)
{ {
if (!_cachedRoleBans.TryGetValue(playerUserId, out var roleBans)) if (!_cachedRoleBans.TryGetValue(playerUserId, out var roleBans))
@@ -254,12 +285,7 @@ public sealed class BanManager : IBanManager, IPostInjectInit
public void SendRoleBans(IPlayerSession pSession) public void SendRoleBans(IPlayerSession pSession)
{ {
if (!_cachedRoleBans.TryGetValue(pSession.UserId, out var roleBans)) var roleBans = _cachedRoleBans.GetValueOrDefault(pSession.UserId) ?? new HashSet<ServerRoleBanDef>();
{
_sawmill.Error($"Tried to send rolebans for {pSession.Name} but none cached?");
return;
}
var bans = new MsgRoleBans() var bans = new MsgRoleBans()
{ {
Bans = roleBans.Select(o => o.Role).ToList() Bans = roleBans.Select(o => o.Role).ToList()

View File

@@ -1,8 +1,9 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Net;
using System.Threading.Tasks;
using Content.Shared.Database; using Content.Shared.Database;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Network; using Robust.Shared.Network;
using System.Net;
namespace Content.Server.Administration.Managers; namespace Content.Server.Administration.Managers;
@@ -24,18 +25,26 @@ public interface IBanManager
public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray<byte>? hwid, uint? minutes, NoteSeverity severity, string reason); public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray<byte>? hwid, uint? minutes, NoteSeverity severity, string reason);
public HashSet<string>? GetRoleBans(NetUserId playerUserId); public HashSet<string>? GetRoleBans(NetUserId playerUserId);
public HashSet<string>? GetJobBans(NetUserId playerUserId); public HashSet<string>? GetJobBans(NetUserId playerUserId);
/// <summary> /// <summary>
/// Creates a job ban for the specified target, username or GUID /// Creates a job ban for the specified target, username or GUID
/// </summary> /// </summary>
/// <param name="shell">Shell reference so we can write messages</param>
/// <param name="target">Target user, username or GUID, null for none</param> /// <param name="target">Target user, username or GUID, null for none</param>
/// <param name="job">Job to be banned from</param> /// <param name="role">Role to be banned from</param>
/// <param name="severity">Severity of the resulting ban note</param> /// <param name="severity">Severity of the resulting ban note</param>
/// <param name="reason">Reason for the ban</param> /// <param name="reason">Reason for the ban</param>
/// <param name="minutes">Number of minutes to ban for. 0 and null mean permanent</param> /// <param name="minutes">Number of minutes to ban for. 0 and null mean permanent</param>
/// <param name="timeOfBan">Time when the ban was applied, used for grouping role bans</param> /// <param name="timeOfBan">Time when the ban was applied, used for grouping role bans</param>
public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray<byte>? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray<byte>? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan);
/// <summary>
/// Pardons a role ban for the specified target, username or GUID
/// </summary>
/// <param name="banId">The id of the role ban to pardon.</param>
/// <param name="unbanningAdmin">The admin, if any, that pardoned the role ban.</param>
/// <param name="unbanTime">The time at which this role ban was pardoned.</param>
public Task<string> PardonRoleBan(int banId, NetUserId? unbanningAdmin, DateTimeOffset unbanTime);
/// <summary> /// <summary>
/// Sends role bans to the target /// Sends role bans to the target
/// </summary> /// </summary>

View File

@@ -432,7 +432,7 @@ namespace Content.Server.Database
ImmutableArray<byte>? hwId, ImmutableArray<byte>? hwId,
bool includeUnbanned); bool includeUnbanned);
public abstract Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan); public abstract Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan);
public abstract Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban); public abstract Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban);
public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt) public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt)

View File

@@ -14,7 +14,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Npgsql; using Npgsql;
using Prometheus; using Prometheus;
using Robust.Shared.Asynchronous;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.ContentPack; using Robust.Shared.ContentPack;
using Robust.Shared.Network; using Robust.Shared.Network;
@@ -140,7 +139,7 @@ namespace Content.Server.Database
ImmutableArray<byte>? hwId, ImmutableArray<byte>? hwId,
bool includeUnbanned = true); bool includeUnbanned = true);
Task AddServerRoleBanAsync(ServerRoleBanDef serverBan); Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverBan);
Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverBan); Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverBan);
public Task EditServerRoleBan( public Task EditServerRoleBan(
@@ -453,7 +452,7 @@ namespace Content.Server.Database
return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, includeUnbanned)); return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, includeUnbanned));
} }
public Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan) public Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan)
{ {
DbWriteOpsMetric.Inc(); DbWriteOpsMetric.Inc();
return RunDbCommand(() => _db.AddServerRoleBanAsync(serverRoleBan)); return RunDbCommand(() => _db.AddServerRoleBanAsync(serverRoleBan));

View File

@@ -1,5 +1,6 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Data; using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
@@ -350,6 +351,7 @@ namespace Content.Server.Database
return query; return query;
} }
[return: NotNullIfNotNull(nameof(ban))]
private static ServerRoleBanDef? ConvertRoleBan(ServerRoleBan? ban) private static ServerRoleBanDef? ConvertRoleBan(ServerRoleBan? ban)
{ {
if (ban == null) if (ban == null)
@@ -406,11 +408,11 @@ namespace Content.Server.Database
unban.UnbanTime); unban.UnbanTime);
} }
public override async Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan) public override async Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan)
{ {
await using var db = await GetDbImpl(); await using var db = await GetDbImpl();
db.PgDbContext.RoleBan.Add(new ServerRoleBan var ban = new ServerRoleBan
{ {
Address = serverRoleBan.Address, Address = serverRoleBan.Address,
HWId = serverRoleBan.HWId?.ToArray(), HWId = serverRoleBan.HWId?.ToArray(),
@@ -423,9 +425,11 @@ namespace Content.Server.Database
PlaytimeAtNote = serverRoleBan.PlaytimeAtNote, PlaytimeAtNote = serverRoleBan.PlaytimeAtNote,
PlayerUserId = serverRoleBan.UserId?.UserId, PlayerUserId = serverRoleBan.UserId?.UserId,
RoleId = serverRoleBan.Role, RoleId = serverRoleBan.Role,
}); };
db.PgDbContext.RoleBan.Add(ban);
await db.PgDbContext.SaveChangesAsync(); await db.PgDbContext.SaveChangesAsync();
return ConvertRoleBan(ban);
} }
public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban) public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban)

View File

@@ -1,4 +1,5 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
@@ -246,11 +247,11 @@ namespace Content.Server.Database
return hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId); return hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId);
} }
public override async Task AddServerRoleBanAsync(ServerRoleBanDef serverBan) public override async Task<ServerRoleBanDef> AddServerRoleBanAsync(ServerRoleBanDef serverBan)
{ {
await using var db = await GetDbImpl(); await using var db = await GetDbImpl();
db.SqliteDbContext.RoleBan.Add(new ServerRoleBan var ban = new ServerRoleBan
{ {
Address = serverBan.Address, Address = serverBan.Address,
Reason = serverBan.Reason, Reason = serverBan.Reason,
@@ -263,9 +264,11 @@ namespace Content.Server.Database
PlaytimeAtNote = serverBan.PlaytimeAtNote, PlaytimeAtNote = serverBan.PlaytimeAtNote,
PlayerUserId = serverBan.UserId?.UserId, PlayerUserId = serverBan.UserId?.UserId,
RoleId = serverBan.Role, RoleId = serverBan.Role,
}); };
db.SqliteDbContext.RoleBan.Add(ban);
await db.SqliteDbContext.SaveChangesAsync(); await db.SqliteDbContext.SaveChangesAsync();
return ConvertRoleBan(ban);
} }
public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverUnban) public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverUnban)
@@ -282,6 +285,7 @@ namespace Content.Server.Database
await db.SqliteDbContext.SaveChangesAsync(); await db.SqliteDbContext.SaveChangesAsync();
} }
[return: NotNullIfNotNull(nameof(ban))]
private static ServerRoleBanDef? ConvertRoleBan(ServerRoleBan? ban) private static ServerRoleBanDef? ConvertRoleBan(ServerRoleBan? ban)
{ {
if (ban == null) if (ban == null)