Better notes and bans (#14228)
Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,9 @@ using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Preferences;
|
||||
@@ -30,7 +32,8 @@ namespace Content.Server.Database
|
||||
.AsSingleQuery()
|
||||
.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
|
||||
|
||||
if (prefs is null) return null;
|
||||
if (prefs is null)
|
||||
return null;
|
||||
|
||||
var maxSlot = prefs.Profiles.Max(p => p.Slot) + 1;
|
||||
var profiles = new Dictionary<int, ICharacterProfile>(maxSlot);
|
||||
@@ -339,6 +342,21 @@ namespace Content.Server.Database
|
||||
public abstract Task AddServerBanAsync(ServerBanDef serverBan);
|
||||
public abstract Task AddServerUnbanAsync(ServerUnbanDef serverUnban);
|
||||
|
||||
public async Task EditServerBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.Ban.SingleOrDefaultAsync(b => b.Id == id);
|
||||
if (ban is null)
|
||||
return;
|
||||
ban.Severity = severity;
|
||||
ban.Reason = reason;
|
||||
ban.ExpirationTime = expiration;
|
||||
ban.LastEditedById = editedBy;
|
||||
ban.LastEditedAt = editedAt;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
protected static async Task<ServerBanExemptFlags?> GetBanExemptionCore(DbGuard db, NetUserId? userId)
|
||||
{
|
||||
if (userId == null)
|
||||
@@ -415,6 +433,21 @@ namespace Content.Server.Database
|
||||
|
||||
public abstract Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan);
|
||||
public abstract Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverRoleUnban);
|
||||
|
||||
public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.RoleBan.SingleOrDefaultAsync(b => b.Id == id);
|
||||
if (ban is null)
|
||||
return;
|
||||
ban.Severity = severity;
|
||||
ban.Reason = reason;
|
||||
ban.ExpirationTime = expiration;
|
||||
ban.LastEditedById = editedBy;
|
||||
ban.LastEditedAt = editedAt;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Playtime
|
||||
@@ -959,12 +992,29 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return note.Id;
|
||||
}
|
||||
|
||||
public virtual async Task<int> AddAdminWatchlist(AdminWatchlist watchlist)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
db.DbContext.AdminWatchlists.Add(watchlist);
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
return watchlist.Id;
|
||||
}
|
||||
|
||||
public virtual async Task<int> AddAdminMessage(AdminMessage message)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
db.DbContext.AdminMessages.Add(message);
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
return message.Id;
|
||||
}
|
||||
|
||||
public async Task<AdminNote?> GetAdminNote(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminNotes
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.DeletedBy)
|
||||
@@ -972,17 +1022,145 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<AdminNote>> GetAdminNotes(Guid player)
|
||||
public async Task<AdminWatchlist?> GetAdminWatchlist(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminNotes
|
||||
.Where(note => note.PlayerUserId == player)
|
||||
.Where(note => !note.Deleted)
|
||||
return await db.DbContext.AdminWatchlists
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.DeletedBy)
|
||||
.Include(note => note.Player)
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<AdminMessage?> GetAdminMessage(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminMessages
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.DeletedBy)
|
||||
.Include(note => note.Player)
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<ServerBanNote?> GetServerBanAsNoteAsync(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.Ban
|
||||
.Include(ban => ban.Unban)
|
||||
.Include(ban => ban.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(ban => ban.CreatedBy)
|
||||
.Include(ban => ban.LastEditedBy)
|
||||
.Include(ban => ban.Unban)
|
||||
.SingleOrDefaultAsync(b => b.Id == id);
|
||||
|
||||
if (ban is null)
|
||||
return null;
|
||||
|
||||
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.PlayerUserId);
|
||||
return new ServerBanNote(ban.Id, ban.RoundId, ban.Round, ban.PlayerUserId, player,
|
||||
ban.PlaytimeAtNote, ban.Reason, ban.Severity, ban.CreatedBy, ban.BanTime,
|
||||
ban.LastEditedBy, ban.LastEditedAt, ban.ExpirationTime, ban.Hidden,
|
||||
ban.Unban?.UnbanningAdmin == null
|
||||
? null
|
||||
: await db.DbContext.Player.SingleOrDefaultAsync(p =>
|
||||
p.UserId == ban.Unban.UnbanningAdmin.Value),
|
||||
ban.Unban?.UnbanTime);
|
||||
}
|
||||
|
||||
public async Task<ServerRoleBanNote?> GetServerRoleBanAsNoteAsync(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.RoleBan
|
||||
.Include(b => b.Unban)
|
||||
.SingleOrDefaultAsync(b => b.Id == id);
|
||||
|
||||
if (ban is null)
|
||||
return null;
|
||||
|
||||
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.PlayerUserId);
|
||||
var unbanningAdmin =
|
||||
ban.Unban is null
|
||||
? null
|
||||
: await db.DbContext.Player.SingleOrDefaultAsync(b => b.UserId == ban.Unban.UnbanningAdmin);
|
||||
return new ServerRoleBanNote(ban.Id, ban.RoundId, ban.Round, ban.PlayerUserId,
|
||||
player, ban.PlaytimeAtNote, ban.Reason, ban.Severity, ban.CreatedBy,
|
||||
ban.BanTime, ban.LastEditedBy, ban.LastEditedAt, ban.ExpirationTime,
|
||||
ban.Hidden, new [] { ban.RoleId.Replace(BanManager.JobPrefix, null) },
|
||||
unbanningAdmin, ban.Unban?.UnbanTime);
|
||||
}
|
||||
|
||||
public async Task<List<IAdminRemarksCommon>> GetAllAdminRemarks(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
List<IAdminRemarksCommon> notes = new();
|
||||
notes.AddRange(
|
||||
await (from note in db.DbContext.AdminNotes
|
||||
where note.PlayerUserId == player &&
|
||||
!note.Deleted &&
|
||||
(note.ExpirationTime == null || DateTime.UtcNow < note.ExpirationTime)
|
||||
select note)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.Player)
|
||||
.ToListAsync();
|
||||
.ToListAsync());
|
||||
notes.AddRange(await GetActiveWatchlistsImpl(db, player));
|
||||
notes.AddRange(await GetMessagesImpl(db, player));
|
||||
notes.AddRange(await GetServerBansAsNotesForUser(db, player));
|
||||
notes.AddRange(await GetGroupedServerRoleBansAsNotesForUser(db, player));
|
||||
return notes;
|
||||
}
|
||||
public async Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var note = await db.DbContext.AdminNotes.Where(note => note.Id == id).SingleAsync();
|
||||
note.Message = message;
|
||||
note.Severity = severity;
|
||||
note.Secret = secret;
|
||||
note.LastEditedById = editedBy;
|
||||
note.LastEditedAt = editedAt;
|
||||
note.ExpirationTime = expiryTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var note = await db.DbContext.AdminWatchlists.Where(note => note.Id == id).SingleAsync();
|
||||
note.Message = message;
|
||||
note.LastEditedById = editedBy;
|
||||
note.LastEditedAt = editedAt;
|
||||
note.ExpirationTime = expiryTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task EditAdminMessage(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var note = await db.DbContext.AdminMessages.Where(note => note.Id == id).SingleAsync();
|
||||
note.Message = message;
|
||||
note.LastEditedById = editedBy;
|
||||
note.LastEditedAt = editedAt;
|
||||
note.ExpirationTime = expiryTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAdminNote(int id, Guid deletedBy, DateTime deletedAt)
|
||||
@@ -998,18 +1176,204 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task EditAdminNote(int id, string message, Guid editedBy, DateTime editedAt)
|
||||
public async Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTime deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var note = await db.DbContext.AdminNotes.Where(note => note.Id == id).SingleAsync();
|
||||
note.Message = message;
|
||||
note.LastEditedById = editedBy;
|
||||
note.LastEditedAt = editedAt;
|
||||
var watchlist = await db.DbContext.AdminWatchlists.Where(note => note.Id == id).SingleAsync();
|
||||
|
||||
watchlist.Deleted = true;
|
||||
watchlist.DeletedById = deletedBy;
|
||||
watchlist.DeletedAt = deletedAt;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAdminMessage(int id, Guid deletedBy, DateTime deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var message = await db.DbContext.AdminMessages.Where(note => note.Id == id).SingleAsync();
|
||||
|
||||
message.Deleted = true;
|
||||
message.DeletedById = deletedBy;
|
||||
message.DeletedAt = deletedAt;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task HideServerBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.Ban.Where(ban => ban.Id == id).SingleAsync();
|
||||
|
||||
ban.Hidden = true;
|
||||
ban.LastEditedById = deletedBy;
|
||||
ban.LastEditedAt = deletedAt;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var roleBan = await db.DbContext.RoleBan.Where(roleBan => roleBan.Id == id).SingleAsync();
|
||||
|
||||
roleBan.Hidden = true;
|
||||
roleBan.LastEditedById = deletedBy;
|
||||
roleBan.LastEditedAt = deletedAt;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<List<IAdminRemarksCommon>> GetVisibleAdminRemarks(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
List<IAdminRemarksCommon> notesCol = new();
|
||||
notesCol.AddRange(
|
||||
await (from note in db.DbContext.AdminNotes
|
||||
where note.PlayerUserId == player &&
|
||||
!note.Secret &&
|
||||
!note.Deleted &&
|
||||
(note.ExpirationTime == null || DateTime.UtcNow < note.ExpirationTime)
|
||||
select note)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.Player)
|
||||
.ToListAsync());
|
||||
notesCol.AddRange(await GetMessagesImpl(db, player));
|
||||
return notesCol;
|
||||
}
|
||||
|
||||
public async Task<List<AdminWatchlist>> GetActiveWatchlists(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await GetActiveWatchlistsImpl(db, player);
|
||||
}
|
||||
|
||||
protected async Task<List<AdminWatchlist>> GetActiveWatchlistsImpl(DbGuard db, Guid player)
|
||||
{
|
||||
return await (from watchlist in db.DbContext.AdminWatchlists
|
||||
where watchlist.PlayerUserId == player &&
|
||||
!watchlist.Deleted &&
|
||||
(watchlist.ExpirationTime == null || DateTime.UtcNow < watchlist.ExpirationTime)
|
||||
select watchlist)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.Player)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<AdminMessage>> GetMessages(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await GetMessagesImpl(db, player);
|
||||
}
|
||||
|
||||
protected async Task<List<AdminMessage>> GetMessagesImpl(DbGuard db, Guid player)
|
||||
{
|
||||
return await (from message in db.DbContext.AdminMessages
|
||||
where message.PlayerUserId == player &&
|
||||
!message.Deleted &&
|
||||
(message.ExpirationTime == null || DateTime.UtcNow < message.ExpirationTime)
|
||||
select message)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(note => note.CreatedBy)
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.Player)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task MarkMessageAsSeen(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
var message = await db.DbContext.AdminMessages.SingleAsync(m => m.Id == id);
|
||||
message.Seen = true;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// These two are here because they get converted into notes later
|
||||
protected async Task<List<ServerBanNote>> GetServerBansAsNotesForUser(DbGuard db, Guid user)
|
||||
{
|
||||
// You can't group queries, as player will not always exist. When it doesn't, the
|
||||
// whole query returns nothing
|
||||
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user);
|
||||
return await (from ban in db.DbContext.Ban
|
||||
where ban.PlayerUserId == user &&
|
||||
!ban.Hidden
|
||||
select ban)
|
||||
.Include(ban => ban.Unban)
|
||||
.Include(ban => ban.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(ban => ban.CreatedBy)
|
||||
.Include(ban => ban.LastEditedBy)
|
||||
.Include(ban => ban.Unban)
|
||||
.ToAsyncEnumerable()
|
||||
.SelectAwait(async ban =>
|
||||
new ServerBanNote(ban.Id, ban.RoundId, ban.Round, ban.PlayerUserId, player,
|
||||
ban.PlaytimeAtNote, ban.Reason, ban.Severity, ban.CreatedBy, ban.BanTime,
|
||||
ban.LastEditedBy, ban.LastEditedAt, ban.ExpirationTime, ban.Hidden,
|
||||
ban.Unban?.UnbanningAdmin == null
|
||||
? null
|
||||
: await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == ban.Unban.UnbanningAdmin.Value),
|
||||
ban.Unban?.UnbanTime)
|
||||
).ToListAsync();
|
||||
}
|
||||
|
||||
protected async Task<List<ServerRoleBanNote>> GetGroupedServerRoleBansAsNotesForUser(DbGuard db, Guid user)
|
||||
{
|
||||
// Server side query
|
||||
var bansQuery =
|
||||
(from ban in db.DbContext.RoleBan
|
||||
where ban.PlayerUserId == user &&
|
||||
!ban.Hidden
|
||||
select ban)
|
||||
.Include(ban => ban.Unban)
|
||||
.Include(ban => ban.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
.Include(ban => ban.CreatedBy)
|
||||
.Include(ban => ban.LastEditedBy)
|
||||
.Include(ban => ban.Unban)
|
||||
.ToAsyncEnumerable();
|
||||
|
||||
// Client side query, as EF can't do groups yet
|
||||
var bansEnumerable =
|
||||
(from ban in bansQuery
|
||||
group ban by new
|
||||
{
|
||||
ban.BanTime,
|
||||
ban.CreatedBy,
|
||||
ban.Reason,
|
||||
Unbanned = ban.Unban == null
|
||||
}
|
||||
into banGroup
|
||||
select banGroup)
|
||||
.AsAsyncEnumerable();
|
||||
|
||||
List<ServerRoleBanNote> bans = new();
|
||||
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user);
|
||||
await foreach (var banGroup in bansEnumerable)
|
||||
{
|
||||
var firstBan = await banGroup.FirstAsync();
|
||||
Player? unbanningAdmin = null;
|
||||
if (firstBan.Unban?.UnbanningAdmin is not null)
|
||||
unbanningAdmin = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == firstBan.Unban.UnbanningAdmin.Value);
|
||||
bans.Add(new ServerRoleBanNote(firstBan.Id, firstBan.RoundId, firstBan.Round, firstBan.PlayerUserId,
|
||||
player, firstBan.PlaytimeAtNote, firstBan.Reason, firstBan.Severity, firstBan.CreatedBy,
|
||||
firstBan.BanTime, firstBan.LastEditedBy, firstBan.LastEditedAt, firstBan.ExpirationTime,
|
||||
firstBan.Hidden, await banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArrayAsync(),
|
||||
unbanningAdmin, firstBan.Unban?.UnbanTime));
|
||||
}
|
||||
|
||||
return bans;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected abstract Task<DbGuard> GetDb();
|
||||
|
||||
Reference in New Issue
Block a user