Revert "Revert "Log ban hits in DB. ( (#6361)

This commit is contained in:
Pieter-Jan Briers
2022-02-02 22:57:11 +01:00
committed by GitHub
parent aaea5dd2d8
commit 5091c6aa9d
13 changed files with 2229 additions and 61 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Content.Server.Database;
@@ -63,6 +64,35 @@ The ban reason is: ""{ban.Reason}""
*/
private async Task NetMgrOnConnecting(NetConnectingArgs e)
{
var deny = await ShouldDeny(e);
var addr = e.IP.Address;
var userId = e.UserId;
if (deny != null)
{
var (reason, msg, banHits) = deny.Value;
var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, reason);
if (banHits is { Count: > 0 })
await _db.AddServerBanHitsAsync(id, banHits);
e.Deny(msg);
}
else
{
await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, null);
if (!ServerPreferencesManager.ShouldStorePrefs(e.AuthType))
return;
await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, e.UserData.HWId);
}
}
private async Task<(ConnectionDenyReason, string, List<ServerBanDef>? bansHit)?> ShouldDeny(
NetConnectingArgs e)
{
// Check if banned.
var addr = e.IP.Address;
@@ -77,34 +107,26 @@ The ban reason is: ""{ban.Reason}""
var adminData = await _dbManager.GetAdminDataForAsync(e.UserId);
var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) && ticker.PlayersInGame.Contains(userId);
if ((_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && adminData is null) && !wasInGame )
if ((_plyMgr.PlayerCount >= _cfg.GetCVar(CCVars.SoftMaxPlayers) && adminData is null) && !wasInGame)
{
e.Deny(Loc.GetString("soft-player-cap-full"));
return;
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
}
var ban = await _db.GetServerBanAsync(addr, userId, hwId);
if (ban != null)
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
if (bans.Count > 0)
{
e.Deny(ban.DisconnectMessage);
return;
var firstBan = bans[0];
return (ConnectionDenyReason.Ban, firstBan.DisconnectMessage, bans);
}
if (_cfg.GetCVar(CCVars.WhitelistEnabled)
&& await _db.GetWhitelistStatusAsync(userId) == false
&& adminData is null)
{
e.Deny(Loc.GetString("whitelist-not-whitelisted"));
return;
return (ConnectionDenyReason.Whitelist, Loc.GetString("whitelist-not-whitelisted"), null);
}
if (!ServerPreferencesManager.ShouldStorePrefs(e.AuthType))
{
return;
}
await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, e.UserData.HWId);
await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId);
return null;
}
private async Task<NetUserId?> AssignUserIdCallback(string name)

View File

@@ -294,11 +294,13 @@ namespace Content.Server.Database
/// <param name="address">The ip address of the user.</param>
/// <param name="userId">The id of the user.</param>
/// <param name="hwId">The HWId of the user.</param>
/// <param name="includeUnbanned">Include pardoned and expired bans.</param>
/// <returns>The user's ban history.</returns>
public abstract Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId);
ImmutableArray<byte>? hwId,
bool includeUnbanned);
public abstract Task AddServerBanAsync(ServerBanDef serverBan);
public abstract Task AddServerUnbanAsync(ServerUnbanDef serverUnban);
@@ -365,11 +367,28 @@ namespace Content.Server.Database
/*
* CONNECTION LOG
*/
public abstract Task AddConnectionLogAsync(
public abstract Task<int> AddConnectionLogAsync(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId);
ImmutableArray<byte> hwId,
ConnectionDenyReason? denied);
public async Task AddServerBanHitsAsync(int connection, IEnumerable<ServerBanDef> bans)
{
await using var db = await GetDb();
foreach (var ban in bans)
{
db.DbContext.ServerBanHit.Add(new ServerBanHit
{
ConnectionId = connection, BanId = ban.Id!.Value
});
}
await db.DbContext.SaveChangesAsync();
}
#endregion
#region Admin Ranks

View File

@@ -73,17 +73,18 @@ namespace Content.Server.Database
/// <summary>
/// Looks up an user's ban history.
/// This will return pardoned bans as well.
/// One of <see cref="address"/> or <see cref="userId"/> need to not be null.
/// </summary>
/// <param name="address">The ip address of the user.</param>
/// <param name="userId">The id of the user.</param>
/// <param name="hwId">The HWId of the user.</param>
/// <param name="includeUnbanned">If true, bans that have been expired or pardoned are also included.</param>
/// <returns>The user's ban history.</returns>
Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId);
ImmutableArray<byte>? hwId,
bool includeUnbanned=true);
Task AddServerBanAsync(ServerBanDef serverBan);
Task AddServerUnbanAsync(ServerUnbanDef serverBan);
@@ -100,11 +101,16 @@ namespace Content.Server.Database
#endregion
#region Connection Logs
Task AddConnectionLogAsync(
/// <returns>ID of newly inserted connection log row.</returns>
Task<int> AddConnectionLogAsync(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId);
ImmutableArray<byte> hwId,
ConnectionDenyReason? denied);
Task AddServerBanHitsAsync(int connection, IEnumerable<ServerBanDef> bans);
#endregion
#region Admin Ranks
@@ -242,9 +248,10 @@ namespace Content.Server.Database
public Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId)
ImmutableArray<byte>? hwId,
bool includeUnbanned=true)
{
return _db.GetServerBansAsync(address, userId, hwId);
return _db.GetServerBansAsync(address, userId, hwId, includeUnbanned);
}
public Task AddServerBanAsync(ServerBanDef serverBan)
@@ -276,13 +283,19 @@ namespace Content.Server.Database
return _db.GetPlayerRecordByUserId(userId, cancel);
}
public Task AddConnectionLogAsync(
public Task<int> AddConnectionLogAsync(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId)
ImmutableArray<byte> hwId,
ConnectionDenyReason? denied)
{
return _db.AddConnectionLogAsync(userId, userName, address, hwId);
return _db.AddConnectionLogAsync(userId, userName, address, hwId, denied);
}
public Task AddServerBanHitsAsync(int connection, IEnumerable<ServerBanDef> bans)
{
return _db.AddServerBanHitsAsync(connection, bans);
}
public Task<Admin?> GetAdminDataForAsync(NetUserId userId, CancellationToken cancel = default)

View File

@@ -59,8 +59,7 @@ namespace Content.Server.Database
await using var db = await GetDbImpl();
var query = MakeBanLookupQuery(address, userId, hwId, db)
.Where(p => p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.Now))
var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned: false)
.OrderByDescending(b => b.BanTime);
var ban = await query.FirstOrDefaultAsync();
@@ -68,10 +67,9 @@ namespace Content.Server.Database
return ConvertBan(ban);
}
public override async Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
public override async Task<List<ServerBanDef>> GetServerBansAsync(IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId)
ImmutableArray<byte>? hwId, bool includeUnbanned)
{
if (address == null && userId == null && hwId == null)
{
@@ -80,7 +78,7 @@ namespace Content.Server.Database
await using var db = await GetDbImpl();
var query = MakeBanLookupQuery(address, userId, hwId, db);
var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned);
var queryBans = await query.ToArrayAsync();
var bans = new List<ServerBanDef>(queryBans.Length);
@@ -102,7 +100,8 @@ namespace Content.Server.Database
IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId,
DbGuardImpl db)
DbGuardImpl db,
bool includeUnbanned)
{
IQueryable<ServerBan>? query = null;
@@ -133,6 +132,12 @@ namespace Content.Server.Database
query = query == null ? newQ : query.Union(newQ);
}
if (!includeUnbanned)
{
query = query?.Where(p =>
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.Now));
}
query = query!.Distinct();
return query;
}
@@ -232,24 +237,30 @@ namespace Content.Server.Database
record.LastSeenHWId?.ToImmutableArray());
}
public override async Task AddConnectionLogAsync(
public override async Task<int> AddConnectionLogAsync(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId)
ImmutableArray<byte> hwId,
ConnectionDenyReason? denied)
{
await using var db = await GetDbImpl();
db.PgDbContext.ConnectionLog.Add(new ConnectionLog
var connectionLog = new ConnectionLog
{
Address = address,
Time = DateTime.UtcNow,
UserId = userId.UserId,
UserName = userName,
HWId = hwId.ToArray()
});
HWId = hwId.ToArray(),
Denied = denied,
};
db.PgDbContext.ConnectionLog.Add(connectionLog);
await db.PgDbContext.SaveChangesAsync();
return connectionLog.Id;
}
public override async Task<((Admin, string? lastUserName)[] admins, AdminRank[])>

View File

@@ -67,28 +67,22 @@ namespace Content.Server.Database
// SQLite can't do the net masking stuff we need to match IP address ranges.
// So just pull down the whole list into memory.
var bans = await db.SqliteDbContext.Ban
.Include(p => p.Unban)
.Where(p => p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.UtcNow))
.ToListAsync();
var bans = await GetAllBans(db.SqliteDbContext, includeUnbanned: false);
return bans.FirstOrDefault(b => BanMatches(b, address, userId, hwId)) is { } foundBan
? ConvertBan(foundBan)
: null;
}
public override async Task<List<ServerBanDef>> GetServerBansAsync(
IPAddress? address,
public override async Task<List<ServerBanDef>> GetServerBansAsync(IPAddress? address,
NetUserId? userId,
ImmutableArray<byte>? hwId)
ImmutableArray<byte>? hwId, bool includeUnbanned)
{
await using var db = await GetDbImpl();
// SQLite can't do the net masking stuff we need to match IP address ranges.
// So just pull down the whole list into memory.
var queryBans = await db.SqliteDbContext.Ban
.Include(p => p.Unban)
.ToListAsync();
var queryBans = await GetAllBans(db.SqliteDbContext, includeUnbanned);
return queryBans
.Where(b => BanMatches(b, address, userId, hwId))
@@ -96,6 +90,20 @@ namespace Content.Server.Database
.ToList()!;
}
private static async Task<List<ServerBan>> GetAllBans(
SqliteServerDbContext db,
bool includeUnbanned)
{
IQueryable<ServerBan> query = db.Ban.Include(p => p.Unban);
if (!includeUnbanned)
{
query = query.Where(p =>
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.UtcNow));
}
return await query.ToListAsync();
}
private static bool BanMatches(
ServerBan ban,
IPAddress? address,
@@ -215,21 +223,30 @@ namespace Content.Server.Database
unban.UnbanTime);
}
public override async Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address,
ImmutableArray<byte> hwId)
public override async Task<int> AddConnectionLogAsync(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId,
ConnectionDenyReason? denied)
{
await using var db = await GetDbImpl();
db.SqliteDbContext.ConnectionLog.Add(new ConnectionLog
var connectionLog = new ConnectionLog
{
Address = address,
Time = DateTime.UtcNow,
UserId = userId.UserId,
UserName = userName,
HWId = hwId.ToArray()
});
HWId = hwId.ToArray(),
Denied = denied
};
db.SqliteDbContext.ConnectionLog.Add(connectionLog);
await db.SqliteDbContext.SaveChangesAsync();
return connectionLog.Id;
}
public override async Task<((Admin, string? lastUserName)[] admins, AdminRank[])> GetAllAdminAndRanksAsync(