Fix admin notes and database time nonsense. (#25280)
God bloody christ. There's like three layers of shit here. So firstly, apparently we were still using Npgsql.EnableLegacyTimestampBehavior. This means that time values (which are stored UTC in the database) were converted to local time when read out. This meant they were passed around as kind Local to clients (instead of UTC in the case of SQLite). That's easy enough to fix just turn off the flag and fix the couple spots we're passing a local DateTime ez. Oh but it turns out there's a DIFFERENT problem with SQLite: See SQLite we definitely store the DateTimes as UTC, but when Microsoft.Data.Sqlite reads them it reads them as Kind Unspecified instead of Utc. Why are these so bad? Because the admin notes system passes DateTime instances from EF Core straight to the rest of the game code. And that means it's a PAIN IN THE ASS to run the necessary conversions to fix the DateTime instances. GOD DAMNIT now I have to make a whole new set of "Record" entities so we avoid leaking the EF Core model entities. WAAAAAAA. Fixes #19897
This commit is contained in:
committed by
GitHub
parent
2907e84b6f
commit
2e6eaa45c5
127
Content.Server/Database/DatabaseRecords.cs
Normal file
127
Content.Server/Database/DatabaseRecords.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Net;
|
||||
using Content.Shared.Database;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Server.Database;
|
||||
|
||||
// This file contains copies of records returned from the database.
|
||||
// We can't return the raw EF Core entities as they are often unsuited.
|
||||
// (e.g. datetime handling of Microsoft.Data.Sqlite)
|
||||
|
||||
public interface IAdminRemarksRecord
|
||||
{
|
||||
public int Id { get; }
|
||||
|
||||
public RoundRecord? Round { get; }
|
||||
|
||||
public PlayerRecord? Player { get; }
|
||||
public TimeSpan PlaytimeAtNote { get; }
|
||||
|
||||
public string Message { get; }
|
||||
|
||||
public PlayerRecord? CreatedBy { get; }
|
||||
|
||||
public DateTimeOffset CreatedAt { get; }
|
||||
|
||||
public PlayerRecord? LastEditedBy { get; }
|
||||
|
||||
public DateTimeOffset? LastEditedAt { get; }
|
||||
public DateTimeOffset? ExpirationTime { get; }
|
||||
|
||||
public bool Deleted { get; }
|
||||
}
|
||||
|
||||
public sealed record ServerRoleBanNoteRecord(
|
||||
int Id,
|
||||
RoundRecord? Round,
|
||||
PlayerRecord? Player,
|
||||
TimeSpan PlaytimeAtNote,
|
||||
string Message,
|
||||
NoteSeverity Severity,
|
||||
PlayerRecord? CreatedBy,
|
||||
DateTimeOffset CreatedAt,
|
||||
PlayerRecord? LastEditedBy,
|
||||
DateTimeOffset? LastEditedAt,
|
||||
DateTimeOffset? ExpirationTime,
|
||||
bool Deleted,
|
||||
string[] Roles,
|
||||
PlayerRecord? UnbanningAdmin,
|
||||
DateTime? UnbanTime) : IAdminRemarksRecord;
|
||||
|
||||
public sealed record ServerBanNoteRecord(
|
||||
int Id,
|
||||
RoundRecord? Round,
|
||||
PlayerRecord? Player,
|
||||
TimeSpan PlaytimeAtNote,
|
||||
string Message,
|
||||
NoteSeverity Severity,
|
||||
PlayerRecord? CreatedBy,
|
||||
DateTimeOffset CreatedAt,
|
||||
PlayerRecord? LastEditedBy,
|
||||
DateTimeOffset? LastEditedAt,
|
||||
DateTimeOffset? ExpirationTime,
|
||||
bool Deleted,
|
||||
PlayerRecord? UnbanningAdmin,
|
||||
DateTime? UnbanTime) : IAdminRemarksRecord;
|
||||
|
||||
public sealed record AdminNoteRecord(
|
||||
int Id,
|
||||
RoundRecord? Round,
|
||||
PlayerRecord? Player,
|
||||
TimeSpan PlaytimeAtNote,
|
||||
string Message,
|
||||
NoteSeverity Severity,
|
||||
PlayerRecord? CreatedBy,
|
||||
DateTimeOffset CreatedAt,
|
||||
PlayerRecord? LastEditedBy,
|
||||
DateTimeOffset? LastEditedAt,
|
||||
DateTimeOffset? ExpirationTime,
|
||||
bool Deleted,
|
||||
PlayerRecord? DeletedBy,
|
||||
DateTimeOffset? DeletedAt,
|
||||
bool Secret) : IAdminRemarksRecord;
|
||||
|
||||
public sealed record AdminWatchlistRecord(
|
||||
int Id,
|
||||
RoundRecord? Round,
|
||||
PlayerRecord? Player,
|
||||
TimeSpan PlaytimeAtNote,
|
||||
string Message,
|
||||
PlayerRecord? CreatedBy,
|
||||
DateTimeOffset CreatedAt,
|
||||
PlayerRecord? LastEditedBy,
|
||||
DateTimeOffset? LastEditedAt,
|
||||
DateTimeOffset? ExpirationTime,
|
||||
bool Deleted,
|
||||
PlayerRecord? DeletedBy,
|
||||
DateTimeOffset? DeletedAt) : IAdminRemarksRecord;
|
||||
|
||||
public sealed record AdminMessageRecord(
|
||||
int Id,
|
||||
RoundRecord? Round,
|
||||
PlayerRecord? Player,
|
||||
TimeSpan PlaytimeAtNote,
|
||||
string Message,
|
||||
PlayerRecord? CreatedBy,
|
||||
DateTimeOffset CreatedAt,
|
||||
PlayerRecord? LastEditedBy,
|
||||
DateTimeOffset? LastEditedAt,
|
||||
DateTimeOffset? ExpirationTime,
|
||||
bool Deleted,
|
||||
PlayerRecord? DeletedBy,
|
||||
DateTimeOffset? DeletedAt,
|
||||
bool Seen) : IAdminRemarksRecord;
|
||||
|
||||
|
||||
public sealed record PlayerRecord(
|
||||
NetUserId UserId,
|
||||
DateTimeOffset FirstSeenTime,
|
||||
string LastSeenUserName,
|
||||
DateTimeOffset LastSeenTime,
|
||||
IPAddress LastSeenAddress,
|
||||
ImmutableArray<byte>? HWId);
|
||||
|
||||
public sealed record RoundRecord(int Id, DateTimeOffset StartDate, ServerRecord Server);
|
||||
|
||||
public sealed record ServerRecord(int Id, string Name);
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Net;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
public sealed class PlayerRecord
|
||||
{
|
||||
public NetUserId UserId { get; }
|
||||
public ImmutableArray<byte>? HWId { get; }
|
||||
public DateTimeOffset FirstSeenTime { get; }
|
||||
public string LastSeenUserName { get; }
|
||||
public DateTimeOffset LastSeenTime { get; }
|
||||
public IPAddress LastSeenAddress { get; }
|
||||
|
||||
public PlayerRecord(
|
||||
NetUserId userId,
|
||||
DateTimeOffset firstSeenTime,
|
||||
string lastSeenUserName,
|
||||
DateTimeOffset lastSeenTime,
|
||||
IPAddress lastSeenAddress,
|
||||
ImmutableArray<byte>? hwId)
|
||||
{
|
||||
UserId = userId;
|
||||
FirstSeenTime = firstSeenTime;
|
||||
LastSeenUserName = lastSeenUserName;
|
||||
LastSeenTime = lastSeenTime;
|
||||
LastSeenAddress = lastSeenAddress;
|
||||
HWId = hwId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Database;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
public record ServerBanNote(int Id, int? RoundId, Round? Round, Guid? PlayerUserId, Player? Player,
|
||||
TimeSpan PlaytimeAtNote, string Message, NoteSeverity Severity, Player? CreatedBy, DateTime CreatedAt,
|
||||
Player? LastEditedBy, DateTime? LastEditedAt, DateTime? ExpirationTime, bool Deleted, Player? UnbanningAdmin,
|
||||
DateTime? UnbanTime) : IAdminRemarksCommon;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
@@ -356,7 +357,7 @@ 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)
|
||||
public async Task EditServerBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -365,9 +366,9 @@ namespace Content.Server.Database
|
||||
return;
|
||||
ban.Severity = severity;
|
||||
ban.Reason = reason;
|
||||
ban.ExpirationTime = expiration;
|
||||
ban.ExpirationTime = expiration?.UtcDateTime;
|
||||
ban.LastEditedById = editedBy;
|
||||
ban.LastEditedAt = editedAt;
|
||||
ban.LastEditedAt = editedAt.UtcDateTime;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
@@ -448,7 +449,7 @@ namespace Content.Server.Database
|
||||
public abstract Task<ServerRoleBanDef> 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)
|
||||
public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -457,9 +458,9 @@ namespace Content.Server.Database
|
||||
return;
|
||||
ban.Severity = severity;
|
||||
ban.Reason = reason;
|
||||
ban.ExpirationTime = expiration;
|
||||
ban.ExpirationTime = expiration?.UtcDateTime;
|
||||
ban.LastEditedById = editedBy;
|
||||
ban.LastEditedAt = editedAt;
|
||||
ban.LastEditedAt = editedAt.UtcDateTime;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
#endregion
|
||||
@@ -571,7 +572,21 @@ namespace Content.Server.Database
|
||||
return record == null ? null : MakePlayerRecord(record);
|
||||
}
|
||||
|
||||
protected abstract PlayerRecord MakePlayerRecord(Player player);
|
||||
[return: NotNullIfNotNull(nameof(player))]
|
||||
protected PlayerRecord? MakePlayerRecord(Player? player)
|
||||
{
|
||||
if (player == null)
|
||||
return null;
|
||||
|
||||
return new PlayerRecord(
|
||||
new NetUserId(player.UserId),
|
||||
new DateTimeOffset(NormalizeDatabaseTime(player.FirstSeenTime)),
|
||||
player.LastSeenUserName,
|
||||
new DateTimeOffset(NormalizeDatabaseTime(player.LastSeenTime)),
|
||||
player.LastSeenAddress,
|
||||
player.LastSeenHWId?.ToImmutableArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Connection Logs
|
||||
@@ -733,6 +748,18 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[return: NotNullIfNotNull(nameof(round))]
|
||||
protected RoundRecord? MakeRoundRecord(Round? round)
|
||||
{
|
||||
if (round == null)
|
||||
return null;
|
||||
|
||||
return new RoundRecord(
|
||||
round.Id,
|
||||
NormalizeDatabaseTime(round.StartDate),
|
||||
MakeServerRecord(round.Server));
|
||||
}
|
||||
|
||||
public async Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
@@ -772,6 +799,15 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return (server, false);
|
||||
}
|
||||
|
||||
[return: NotNullIfNotNull(nameof(server))]
|
||||
protected ServerRecord? MakeServerRecord(Server? server)
|
||||
{
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
return new ServerRecord(server.Id, server.Name);
|
||||
}
|
||||
|
||||
public async Task AddAdminLogs(List<AdminLog> logs)
|
||||
{
|
||||
DebugTools.Assert(logs.All(x => x.RoundId > 0), "Adding logs with invalid round ids.");
|
||||
@@ -943,17 +979,17 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<DateTime?> GetLastReadRules(NetUserId player)
|
||||
public async Task<DateTimeOffset?> GetLastReadRules(NetUserId player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
return await db.DbContext.Player
|
||||
return NormalizeDatabaseTime(await db.DbContext.Player
|
||||
.Where(dbPlayer => dbPlayer.UserId == player)
|
||||
.Select(dbPlayer => dbPlayer.LastReadRules)
|
||||
.SingleOrDefaultAsync();
|
||||
.SingleOrDefaultAsync());
|
||||
}
|
||||
|
||||
public async Task SetLastReadRules(NetUserId player, DateTime date)
|
||||
public async Task SetLastReadRules(NetUserId player, DateTimeOffset date)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -963,7 +999,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return;
|
||||
}
|
||||
|
||||
dbPlayer.LastReadRules = date;
|
||||
dbPlayer.LastReadRules = date.UtcDateTime;
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
@@ -971,11 +1007,11 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
#region Uploaded Resources Logs
|
||||
|
||||
public async Task AddUploadedResourceLogAsync(NetUserId user, DateTime date, string path, byte[] data)
|
||||
public async Task AddUploadedResourceLogAsync(NetUserId user, DateTimeOffset date, string path, byte[] data)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
db.DbContext.UploadedResourceLog.Add(new UploadedResourceLog() { UserId = user, Date = date, Path = path, Data = data });
|
||||
db.DbContext.UploadedResourceLog.Add(new UploadedResourceLog() { UserId = user, Date = date.UtcDateTime, Path = path, Data = data });
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
@@ -983,7 +1019,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var date = DateTime.Now.Subtract(TimeSpan.FromDays(days));
|
||||
var date = DateTime.UtcNow.Subtract(TimeSpan.FromDays(days));
|
||||
|
||||
await foreach (var log in db.DbContext.UploadedResourceLog
|
||||
.Where(l => date > l.Date)
|
||||
@@ -1023,10 +1059,10 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return message.Id;
|
||||
}
|
||||
|
||||
public async Task<AdminNote?> GetAdminNote(int id)
|
||||
public async Task<AdminNoteRecord?> GetAdminNote(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminNotes
|
||||
var entity = await db.DbContext.AdminNotes
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
@@ -1035,12 +1071,34 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Include(note => note.DeletedBy)
|
||||
.Include(note => note.Player)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
return entity == null ? null : MakeAdminNoteRecord(entity);
|
||||
}
|
||||
|
||||
public async Task<AdminWatchlist?> GetAdminWatchlist(int id)
|
||||
private AdminNoteRecord MakeAdminNoteRecord(AdminNote entity)
|
||||
{
|
||||
return new AdminNoteRecord(
|
||||
entity.Id,
|
||||
MakeRoundRecord(entity.Round),
|
||||
MakePlayerRecord(entity.Player),
|
||||
entity.PlaytimeAtNote,
|
||||
entity.Message,
|
||||
entity.Severity,
|
||||
MakePlayerRecord(entity.CreatedBy),
|
||||
NormalizeDatabaseTime(entity.CreatedAt),
|
||||
MakePlayerRecord(entity.LastEditedBy),
|
||||
NormalizeDatabaseTime(entity.LastEditedAt),
|
||||
NormalizeDatabaseTime(entity.ExpirationTime),
|
||||
entity.Deleted,
|
||||
MakePlayerRecord(entity.DeletedBy),
|
||||
NormalizeDatabaseTime(entity.DeletedAt),
|
||||
entity.Secret);
|
||||
}
|
||||
|
||||
public async Task<AdminWatchlistRecord?> GetAdminWatchlist(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminWatchlists
|
||||
var entity = await db.DbContext.AdminWatchlists
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
@@ -1049,12 +1107,14 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Include(note => note.DeletedBy)
|
||||
.Include(note => note.Player)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
return entity == null ? null : MakeAdminWatchlistRecord(entity);
|
||||
}
|
||||
|
||||
public async Task<AdminMessage?> GetAdminMessage(int id)
|
||||
public async Task<AdminMessageRecord?> GetAdminMessage(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await db.DbContext.AdminMessages
|
||||
var entity = await db.DbContext.AdminMessages
|
||||
.Where(note => note.Id == id)
|
||||
.Include(note => note.Round)
|
||||
.ThenInclude(r => r!.Server)
|
||||
@@ -1063,9 +1123,30 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Include(note => note.DeletedBy)
|
||||
.Include(note => note.Player)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
return entity == null ? null : MakeAdminMessageRecord(entity);
|
||||
}
|
||||
|
||||
public async Task<ServerBanNote?> GetServerBanAsNoteAsync(int id)
|
||||
private AdminMessageRecord MakeAdminMessageRecord(AdminMessage entity)
|
||||
{
|
||||
return new AdminMessageRecord(
|
||||
entity.Id,
|
||||
MakeRoundRecord(entity.Round),
|
||||
MakePlayerRecord(entity.Player),
|
||||
entity.PlaytimeAtNote,
|
||||
entity.Message,
|
||||
MakePlayerRecord(entity.CreatedBy),
|
||||
NormalizeDatabaseTime(entity.CreatedAt),
|
||||
MakePlayerRecord(entity.LastEditedBy),
|
||||
NormalizeDatabaseTime(entity.LastEditedAt),
|
||||
NormalizeDatabaseTime(entity.ExpirationTime),
|
||||
entity.Deleted,
|
||||
MakePlayerRecord(entity.DeletedBy),
|
||||
NormalizeDatabaseTime(entity.DeletedAt),
|
||||
entity.Seen);
|
||||
}
|
||||
|
||||
public async Task<ServerBanNoteRecord?> GetServerBanAsNoteAsync(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1082,22 +1163,37 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
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
|
||||
return new ServerBanNoteRecord(
|
||||
ban.Id,
|
||||
MakeRoundRecord(ban.Round),
|
||||
MakePlayerRecord(player),
|
||||
ban.PlaytimeAtNote,
|
||||
ban.Reason,
|
||||
ban.Severity,
|
||||
MakePlayerRecord(ban.CreatedBy),
|
||||
ban.BanTime,
|
||||
MakePlayerRecord(ban.LastEditedBy),
|
||||
ban.LastEditedAt,
|
||||
ban.ExpirationTime,
|
||||
ban.Hidden,
|
||||
MakePlayerRecord(ban.Unban?.UnbanningAdmin == null
|
||||
? null
|
||||
: await db.DbContext.Player.SingleOrDefaultAsync(p =>
|
||||
p.UserId == ban.Unban.UnbanningAdmin.Value),
|
||||
p.UserId == ban.Unban.UnbanningAdmin.Value)),
|
||||
ban.Unban?.UnbanTime);
|
||||
}
|
||||
|
||||
public async Task<ServerRoleBanNote?> GetServerRoleBanAsNoteAsync(int id)
|
||||
public async Task<ServerRoleBanNoteRecord?> GetServerRoleBanAsNoteAsync(int id)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
var ban = await db.DbContext.RoleBan
|
||||
.Include(b => b.Unban)
|
||||
.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)
|
||||
@@ -1108,36 +1204,48 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
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);
|
||||
|
||||
return new ServerRoleBanNoteRecord(
|
||||
ban.Id,
|
||||
MakeRoundRecord(ban.Round),
|
||||
MakePlayerRecord(player),
|
||||
ban.PlaytimeAtNote,
|
||||
ban.Reason,
|
||||
ban.Severity,
|
||||
MakePlayerRecord(ban.CreatedBy),
|
||||
ban.BanTime,
|
||||
MakePlayerRecord(ban.LastEditedBy),
|
||||
ban.LastEditedAt,
|
||||
ban.ExpirationTime,
|
||||
ban.Hidden,
|
||||
new [] { ban.RoleId.Replace(BanManager.JobPrefix, null) },
|
||||
MakePlayerRecord(unbanningAdmin),
|
||||
ban.Unban?.UnbanTime);
|
||||
}
|
||||
|
||||
public async Task<List<IAdminRemarksCommon>> GetAllAdminRemarks(Guid player)
|
||||
public async Task<List<IAdminRemarksRecord>> GetAllAdminRemarks(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
List<IAdminRemarksCommon> notes = new();
|
||||
List<IAdminRemarksRecord> 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());
|
||||
(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()).Select(MakeAdminNoteRecord));
|
||||
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)
|
||||
public async Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1146,39 +1254,39 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
note.Severity = severity;
|
||||
note.Secret = secret;
|
||||
note.LastEditedById = editedBy;
|
||||
note.LastEditedAt = editedAt;
|
||||
note.ExpirationTime = expiryTime;
|
||||
note.LastEditedAt = editedAt.UtcDateTime;
|
||||
note.ExpirationTime = expiryTime?.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
public async Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? 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;
|
||||
note.LastEditedAt = editedAt.UtcDateTime;
|
||||
note.ExpirationTime = expiryTime?.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task EditAdminMessage(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
public async Task EditAdminMessage(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? 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;
|
||||
note.LastEditedAt = editedAt.UtcDateTime;
|
||||
note.ExpirationTime = expiryTime?.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAdminNote(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public async Task DeleteAdminNote(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1186,12 +1294,12 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
note.Deleted = true;
|
||||
note.DeletedById = deletedBy;
|
||||
note.DeletedAt = deletedAt;
|
||||
note.DeletedAt = deletedAt.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public async Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1199,12 +1307,12 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
watchlist.Deleted = true;
|
||||
watchlist.DeletedById = deletedBy;
|
||||
watchlist.DeletedAt = deletedAt;
|
||||
watchlist.DeletedAt = deletedAt.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAdminMessage(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public async Task DeleteAdminMessage(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1212,12 +1320,12 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
message.Deleted = true;
|
||||
message.DeletedById = deletedBy;
|
||||
message.DeletedAt = deletedAt;
|
||||
message.DeletedAt = deletedAt.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task HideServerBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public async Task HideServerBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1225,12 +1333,12 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
ban.Hidden = true;
|
||||
ban.LastEditedById = deletedBy;
|
||||
ban.LastEditedAt = deletedAt;
|
||||
ban.LastEditedAt = deletedAt.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public async Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
|
||||
@@ -1238,40 +1346,40 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
roleBan.Hidden = true;
|
||||
roleBan.LastEditedById = deletedBy;
|
||||
roleBan.LastEditedAt = deletedAt;
|
||||
roleBan.LastEditedAt = deletedAt.UtcDateTime;
|
||||
|
||||
await db.DbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<List<IAdminRemarksCommon>> GetVisibleAdminRemarks(Guid player)
|
||||
public async Task<List<IAdminRemarksRecord>> GetVisibleAdminRemarks(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
List<IAdminRemarksCommon> notesCol = new();
|
||||
List<IAdminRemarksRecord> 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());
|
||||
(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()).Select(MakeAdminNoteRecord));
|
||||
notesCol.AddRange(await GetMessagesImpl(db, player));
|
||||
return notesCol;
|
||||
}
|
||||
|
||||
public async Task<List<AdminWatchlist>> GetActiveWatchlists(Guid player)
|
||||
public async Task<List<AdminWatchlistRecord>> GetActiveWatchlists(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await GetActiveWatchlistsImpl(db, player);
|
||||
}
|
||||
|
||||
protected async Task<List<AdminWatchlist>> GetActiveWatchlistsImpl(DbGuard db, Guid player)
|
||||
protected async Task<List<AdminWatchlistRecord>> GetActiveWatchlistsImpl(DbGuard db, Guid player)
|
||||
{
|
||||
return await (from watchlist in db.DbContext.AdminWatchlists
|
||||
var entities = await (from watchlist in db.DbContext.AdminWatchlists
|
||||
where watchlist.PlayerUserId == player &&
|
||||
!watchlist.Deleted &&
|
||||
(watchlist.ExpirationTime == null || DateTime.UtcNow < watchlist.ExpirationTime)
|
||||
@@ -1282,27 +1390,34 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Include(note => note.LastEditedBy)
|
||||
.Include(note => note.Player)
|
||||
.ToListAsync();
|
||||
|
||||
return entities.Select(MakeAdminWatchlistRecord).ToList();
|
||||
}
|
||||
|
||||
public async Task<List<AdminMessage>> GetMessages(Guid player)
|
||||
private AdminWatchlistRecord MakeAdminWatchlistRecord(AdminWatchlist entity)
|
||||
{
|
||||
return new AdminWatchlistRecord(entity.Id, MakeRoundRecord(entity.Round), MakePlayerRecord(entity.Player), entity.PlaytimeAtNote, entity.Message, MakePlayerRecord(entity.CreatedBy), NormalizeDatabaseTime(entity.CreatedAt), MakePlayerRecord(entity.LastEditedBy), NormalizeDatabaseTime(entity.LastEditedAt), NormalizeDatabaseTime(entity.ExpirationTime), entity.Deleted, MakePlayerRecord(entity.DeletedBy), NormalizeDatabaseTime(entity.DeletedAt));
|
||||
}
|
||||
|
||||
public async Task<List<AdminMessageRecord>> GetMessages(Guid player)
|
||||
{
|
||||
await using var db = await GetDb();
|
||||
return await GetMessagesImpl(db, player);
|
||||
}
|
||||
|
||||
protected async Task<List<AdminMessage>> GetMessagesImpl(DbGuard db, Guid player)
|
||||
protected async Task<List<AdminMessageRecord>> 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();
|
||||
var entities = 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();
|
||||
|
||||
return entities.Select(MakeAdminMessageRecord).ToList();
|
||||
}
|
||||
|
||||
public async Task MarkMessageAsSeen(int id)
|
||||
@@ -1314,7 +1429,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
}
|
||||
|
||||
// These two are here because they get converted into notes later
|
||||
protected async Task<List<ServerBanNote>> GetServerBansAsNotesForUser(DbGuard db, Guid user)
|
||||
protected async Task<List<ServerBanNoteRecord>> 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
|
||||
@@ -1329,17 +1444,27 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Include(ban => ban.Unban)
|
||||
.ToArrayAsync();
|
||||
|
||||
var banNotes = new List<ServerBanNote>();
|
||||
var banNotes = new List<ServerBanNoteRecord>();
|
||||
foreach (var ban in bans)
|
||||
{
|
||||
var banNote = 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
|
||||
var banNote = new ServerBanNoteRecord(
|
||||
ban.Id,
|
||||
MakeRoundRecord(ban.Round),
|
||||
MakePlayerRecord(player),
|
||||
ban.PlaytimeAtNote,
|
||||
ban.Reason,
|
||||
ban.Severity,
|
||||
MakePlayerRecord(ban.CreatedBy),
|
||||
NormalizeDatabaseTime(ban.BanTime),
|
||||
MakePlayerRecord(ban.LastEditedBy),
|
||||
NormalizeDatabaseTime(ban.LastEditedAt),
|
||||
NormalizeDatabaseTime(ban.ExpirationTime),
|
||||
ban.Hidden,
|
||||
MakePlayerRecord(ban.Unban?.UnbanningAdmin == null
|
||||
? null
|
||||
: await db.DbContext.Player.SingleOrDefaultAsync(
|
||||
p => p.UserId == ban.Unban.UnbanningAdmin.Value),
|
||||
ban.Unban?.UnbanTime);
|
||||
p => p.UserId == ban.Unban.UnbanningAdmin.Value)),
|
||||
NormalizeDatabaseTime(ban.Unban?.UnbanTime));
|
||||
|
||||
banNotes.Add(banNote);
|
||||
}
|
||||
@@ -1347,7 +1472,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
return banNotes;
|
||||
}
|
||||
|
||||
protected async Task<List<ServerRoleBanNote>> GetGroupedServerRoleBansAsNotesForUser(DbGuard db, Guid user)
|
||||
protected async Task<List<ServerRoleBanNoteRecord>> GetGroupedServerRoleBansAsNotesForUser(DbGuard db, Guid user)
|
||||
{
|
||||
// Server side query
|
||||
var bansQuery = await db.DbContext.RoleBan
|
||||
@@ -1366,7 +1491,7 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
.Select(banGroup => banGroup)
|
||||
.ToArray();
|
||||
|
||||
List<ServerRoleBanNote> bans = new();
|
||||
List<ServerRoleBanNoteRecord> bans = new();
|
||||
var player = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == user);
|
||||
foreach (var banGroup in bansEnumerable)
|
||||
{
|
||||
@@ -1376,11 +1501,22 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
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, banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArray(),
|
||||
unbanningAdmin, firstBan.Unban?.UnbanTime));
|
||||
bans.Add(new ServerRoleBanNoteRecord(
|
||||
firstBan.Id,
|
||||
MakeRoundRecord(firstBan.Round),
|
||||
MakePlayerRecord(player),
|
||||
firstBan.PlaytimeAtNote,
|
||||
firstBan.Reason,
|
||||
firstBan.Severity,
|
||||
MakePlayerRecord(firstBan.CreatedBy),
|
||||
NormalizeDatabaseTime(firstBan.BanTime),
|
||||
MakePlayerRecord(firstBan.LastEditedBy),
|
||||
NormalizeDatabaseTime(firstBan.LastEditedAt),
|
||||
NormalizeDatabaseTime(firstBan.ExpirationTime),
|
||||
firstBan.Hidden,
|
||||
banGroup.Select(ban => ban.RoleId.Replace(BanManager.JobPrefix, null)).ToArray(),
|
||||
MakePlayerRecord(unbanningAdmin),
|
||||
NormalizeDatabaseTime(firstBan.Unban?.UnbanTime)));
|
||||
}
|
||||
|
||||
return bans;
|
||||
@@ -1388,6 +1524,16 @@ INSERT INTO player_round (players_id, rounds_id) VALUES ({players[player]}, {id}
|
||||
|
||||
#endregion
|
||||
|
||||
// SQLite returns DateTime as Kind=Unspecified, Npgsql actually knows for sure it's Kind=Utc.
|
||||
// Normalize DateTimes here so they're always Utc. Thanks.
|
||||
protected abstract DateTime NormalizeDatabaseTime(DateTime time);
|
||||
|
||||
[return: NotNullIfNotNull(nameof(time))]
|
||||
protected DateTime? NormalizeDatabaseTime(DateTime? time)
|
||||
{
|
||||
return time != null ? NormalizeDatabaseTime(time.Value) : time;
|
||||
}
|
||||
|
||||
protected abstract Task<DbGuard> GetDb([CallerMemberName] string? name = null);
|
||||
|
||||
protected void LogDbOp(string? name)
|
||||
|
||||
@@ -92,9 +92,9 @@ namespace Content.Server.Database
|
||||
int id,
|
||||
string reason,
|
||||
NoteSeverity severity,
|
||||
DateTime? expiration,
|
||||
DateTimeOffset? expiration,
|
||||
Guid editedBy,
|
||||
DateTime editedAt);
|
||||
DateTimeOffset editedAt);
|
||||
|
||||
/// <summary>
|
||||
/// Update ban exemption information for a player.
|
||||
@@ -146,9 +146,9 @@ namespace Content.Server.Database
|
||||
int id,
|
||||
string reason,
|
||||
NoteSeverity severity,
|
||||
DateTime? expiration,
|
||||
DateTimeOffset? expiration,
|
||||
Guid editedBy,
|
||||
DateTime editedAt);
|
||||
DateTimeOffset editedAt);
|
||||
#endregion
|
||||
|
||||
#region Playtime
|
||||
@@ -239,7 +239,7 @@ namespace Content.Server.Database
|
||||
|
||||
#region Uploaded Resources Logs
|
||||
|
||||
Task AddUploadedResourceLogAsync(NetUserId user, DateTime date, string path, byte[] data);
|
||||
Task AddUploadedResourceLogAsync(NetUserId user, DateTimeOffset date, string path, byte[] data);
|
||||
|
||||
Task PurgeUploadedResourceLogAsync(int days);
|
||||
|
||||
@@ -247,33 +247,33 @@ namespace Content.Server.Database
|
||||
|
||||
#region Rules
|
||||
|
||||
Task<DateTime?> GetLastReadRules(NetUserId player);
|
||||
Task SetLastReadRules(NetUserId player, DateTime time);
|
||||
Task<DateTimeOffset?> GetLastReadRules(NetUserId player);
|
||||
Task SetLastReadRules(NetUserId player, DateTimeOffset time);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Admin Notes
|
||||
|
||||
Task<int> AddAdminNote(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, NoteSeverity severity, bool secret, Guid createdBy, DateTime createdAt, DateTime? expiryTime);
|
||||
Task<int> AddAdminWatchlist(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTime createdAt, DateTime? expiryTime);
|
||||
Task<int> AddAdminMessage(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTime createdAt, DateTime? expiryTime);
|
||||
Task<AdminNote?> GetAdminNote(int id);
|
||||
Task<AdminWatchlist?> GetAdminWatchlist(int id);
|
||||
Task<AdminMessage?> GetAdminMessage(int id);
|
||||
Task<ServerBanNote?> GetServerBanAsNoteAsync(int id);
|
||||
Task<ServerRoleBanNote?> GetServerRoleBanAsNoteAsync(int id);
|
||||
Task<List<IAdminRemarksCommon>> GetAllAdminRemarks(Guid player);
|
||||
Task<List<IAdminRemarksCommon>> GetVisibleAdminNotes(Guid player);
|
||||
Task<List<AdminWatchlist>> GetActiveWatchlists(Guid player);
|
||||
Task<List<AdminMessage>> GetMessages(Guid player);
|
||||
Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTime editedAt, DateTime? expiryTime);
|
||||
Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime);
|
||||
Task EditAdminMessage(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime);
|
||||
Task DeleteAdminNote(int id, Guid deletedBy, DateTime deletedAt);
|
||||
Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTime deletedAt);
|
||||
Task DeleteAdminMessage(int id, Guid deletedBy, DateTime deletedAt);
|
||||
Task HideServerBanFromNotes(int id, Guid deletedBy, DateTime deletedAt);
|
||||
Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTime deletedAt);
|
||||
Task<int> AddAdminNote(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, NoteSeverity severity, bool secret, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime);
|
||||
Task<int> AddAdminWatchlist(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime);
|
||||
Task<int> AddAdminMessage(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime);
|
||||
Task<AdminNoteRecord?> GetAdminNote(int id);
|
||||
Task<AdminWatchlistRecord?> GetAdminWatchlist(int id);
|
||||
Task<AdminMessageRecord?> GetAdminMessage(int id);
|
||||
Task<ServerBanNoteRecord?> GetServerBanAsNoteAsync(int id);
|
||||
Task<ServerRoleBanNoteRecord?> GetServerRoleBanAsNoteAsync(int id);
|
||||
Task<List<IAdminRemarksRecord>> GetAllAdminRemarks(Guid player);
|
||||
Task<List<IAdminRemarksRecord>> GetVisibleAdminNotes(Guid player);
|
||||
Task<List<AdminWatchlistRecord>> GetActiveWatchlists(Guid player);
|
||||
Task<List<AdminMessageRecord>> GetMessages(Guid player);
|
||||
Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime);
|
||||
Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime);
|
||||
Task EditAdminMessage(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime);
|
||||
Task DeleteAdminNote(int id, Guid deletedBy, DateTimeOffset deletedAt);
|
||||
Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTimeOffset deletedAt);
|
||||
Task DeleteAdminMessage(int id, Guid deletedBy, DateTimeOffset deletedAt);
|
||||
Task HideServerBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt);
|
||||
Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt);
|
||||
Task MarkMessageAsSeen(int id);
|
||||
|
||||
#endregion
|
||||
@@ -423,7 +423,7 @@ namespace Content.Server.Database
|
||||
return RunDbCommand(() => _db.AddServerUnbanAsync(serverUnban));
|
||||
}
|
||||
|
||||
public Task EditServerBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt)
|
||||
public Task EditServerBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.EditServerBan(id, reason, severity, expiration, editedBy, editedAt));
|
||||
@@ -470,7 +470,7 @@ namespace Content.Server.Database
|
||||
return RunDbCommand(() => _db.AddServerRoleUnbanAsync(serverRoleUnban));
|
||||
}
|
||||
|
||||
public Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTime? expiration, Guid editedBy, DateTime editedAt)
|
||||
public Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.EditServerRoleBan(id, reason, severity, expiration, editedBy, editedAt));
|
||||
@@ -665,7 +665,7 @@ namespace Content.Server.Database
|
||||
return RunDbCommand(() => _db.RemoveFromWhitelistAsync(player));
|
||||
}
|
||||
|
||||
public Task AddUploadedResourceLogAsync(NetUserId user, DateTime date, string path, byte[] data)
|
||||
public Task AddUploadedResourceLogAsync(NetUserId user, DateTimeOffset date, string path, byte[] data)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.AddUploadedResourceLogAsync(user, date, path, data));
|
||||
@@ -677,19 +677,19 @@ namespace Content.Server.Database
|
||||
return RunDbCommand(() => _db.PurgeUploadedResourceLogAsync(days));
|
||||
}
|
||||
|
||||
public Task<DateTime?> GetLastReadRules(NetUserId player)
|
||||
public Task<DateTimeOffset?> GetLastReadRules(NetUserId player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetLastReadRules(player));
|
||||
}
|
||||
|
||||
public Task SetLastReadRules(NetUserId player, DateTime time)
|
||||
public Task SetLastReadRules(NetUserId player, DateTimeOffset time)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.SetLastReadRules(player, time));
|
||||
}
|
||||
|
||||
public Task<int> AddAdminNote(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, NoteSeverity severity, bool secret, Guid createdBy, DateTime createdAt, DateTime? expiryTime)
|
||||
public Task<int> AddAdminNote(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, NoteSeverity severity, bool secret, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
var note = new AdminNote
|
||||
@@ -702,15 +702,15 @@ namespace Content.Server.Database
|
||||
Message = message,
|
||||
Severity = severity,
|
||||
Secret = secret,
|
||||
CreatedAt = createdAt,
|
||||
LastEditedAt = createdAt,
|
||||
ExpirationTime = expiryTime
|
||||
CreatedAt = createdAt.UtcDateTime,
|
||||
LastEditedAt = createdAt.UtcDateTime,
|
||||
ExpirationTime = expiryTime?.UtcDateTime
|
||||
};
|
||||
|
||||
return RunDbCommand(() => _db.AddAdminNote(note));
|
||||
}
|
||||
|
||||
public Task<int> AddAdminWatchlist(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTime createdAt, DateTime? expiryTime)
|
||||
public Task<int> AddAdminWatchlist(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
var note = new AdminWatchlist
|
||||
@@ -721,15 +721,15 @@ namespace Content.Server.Database
|
||||
PlayerUserId = player,
|
||||
PlaytimeAtNote = playtimeAtNote,
|
||||
Message = message,
|
||||
CreatedAt = createdAt,
|
||||
LastEditedAt = createdAt,
|
||||
ExpirationTime = expiryTime
|
||||
CreatedAt = createdAt.UtcDateTime,
|
||||
LastEditedAt = createdAt.UtcDateTime,
|
||||
ExpirationTime = expiryTime?.UtcDateTime
|
||||
};
|
||||
|
||||
return RunDbCommand(() => _db.AddAdminWatchlist(note));
|
||||
}
|
||||
|
||||
public Task<int> AddAdminMessage(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTime createdAt, DateTime? expiryTime)
|
||||
public Task<int> AddAdminMessage(int? roundId, Guid player, TimeSpan playtimeAtNote, string message, Guid createdBy, DateTimeOffset createdAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
var note = new AdminMessage
|
||||
@@ -740,108 +740,108 @@ namespace Content.Server.Database
|
||||
PlayerUserId = player,
|
||||
PlaytimeAtNote = playtimeAtNote,
|
||||
Message = message,
|
||||
CreatedAt = createdAt,
|
||||
LastEditedAt = createdAt,
|
||||
ExpirationTime = expiryTime
|
||||
CreatedAt = createdAt.UtcDateTime,
|
||||
LastEditedAt = createdAt.UtcDateTime,
|
||||
ExpirationTime = expiryTime?.UtcDateTime
|
||||
};
|
||||
|
||||
return RunDbCommand(() => _db.AddAdminMessage(note));
|
||||
}
|
||||
|
||||
public Task<AdminNote?> GetAdminNote(int id)
|
||||
public Task<AdminNoteRecord?> GetAdminNote(int id)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetAdminNote(id));
|
||||
}
|
||||
public Task<AdminWatchlist?> GetAdminWatchlist(int id)
|
||||
public Task<AdminWatchlistRecord?> GetAdminWatchlist(int id)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetAdminWatchlist(id));
|
||||
}
|
||||
public Task<AdminMessage?> GetAdminMessage(int id)
|
||||
public Task<AdminMessageRecord?> GetAdminMessage(int id)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetAdminMessage(id));
|
||||
}
|
||||
|
||||
public Task<ServerBanNote?> GetServerBanAsNoteAsync(int id)
|
||||
public Task<ServerBanNoteRecord?> GetServerBanAsNoteAsync(int id)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetServerBanAsNoteAsync(id));
|
||||
}
|
||||
|
||||
public Task<ServerRoleBanNote?> GetServerRoleBanAsNoteAsync(int id)
|
||||
public Task<ServerRoleBanNoteRecord?> GetServerRoleBanAsNoteAsync(int id)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetServerRoleBanAsNoteAsync(id));
|
||||
}
|
||||
|
||||
public Task<List<IAdminRemarksCommon>> GetAllAdminRemarks(Guid player)
|
||||
public Task<List<IAdminRemarksRecord>> GetAllAdminRemarks(Guid player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetAllAdminRemarks(player));
|
||||
}
|
||||
|
||||
public Task<List<IAdminRemarksCommon>> GetVisibleAdminNotes(Guid player)
|
||||
public Task<List<IAdminRemarksRecord>> GetVisibleAdminNotes(Guid player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetVisibleAdminRemarks(player));
|
||||
}
|
||||
|
||||
public Task<List<AdminWatchlist>> GetActiveWatchlists(Guid player)
|
||||
public Task<List<AdminWatchlistRecord>> GetActiveWatchlists(Guid player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetActiveWatchlists(player));
|
||||
}
|
||||
|
||||
public Task<List<AdminMessage>> GetMessages(Guid player)
|
||||
public Task<List<AdminMessageRecord>> GetMessages(Guid player)
|
||||
{
|
||||
DbReadOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.GetMessages(player));
|
||||
}
|
||||
public Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
public Task EditAdminNote(int id, string message, NoteSeverity severity, bool secret, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.EditAdminNote(id, message, severity, secret, editedBy, editedAt, expiryTime));
|
||||
}
|
||||
|
||||
public Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
public Task EditAdminWatchlist(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.EditAdminWatchlist(id, message, editedBy, editedAt, expiryTime));
|
||||
}
|
||||
|
||||
public Task EditAdminMessage(int id, string message, Guid editedBy, DateTime editedAt, DateTime? expiryTime)
|
||||
public Task EditAdminMessage(int id, string message, Guid editedBy, DateTimeOffset editedAt, DateTimeOffset? expiryTime)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.EditAdminMessage(id, message, editedBy, editedAt, expiryTime));
|
||||
}
|
||||
|
||||
public Task DeleteAdminNote(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public Task DeleteAdminNote(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.DeleteAdminNote(id, deletedBy, deletedAt));
|
||||
}
|
||||
|
||||
public Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public Task DeleteAdminWatchlist(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.DeleteAdminWatchlist(id, deletedBy, deletedAt));
|
||||
}
|
||||
|
||||
public Task DeleteAdminMessage(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public Task DeleteAdminMessage(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.DeleteAdminMessage(id, deletedBy, deletedAt));
|
||||
}
|
||||
|
||||
public Task HideServerBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public Task HideServerBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.HideServerBanFromNotes(id, deletedBy, deletedAt));
|
||||
}
|
||||
|
||||
public Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTime deletedAt)
|
||||
public Task HideServerRoleBanFromNotes(int id, Guid deletedBy, DateTimeOffset deletedAt)
|
||||
{
|
||||
DbWriteOpsMetric.Inc();
|
||||
return RunDbCommand(() => _db.HideServerRoleBanFromNotes(id, deletedBy, deletedAt));
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace Content.Server.Database
|
||||
if (!includeUnbanned)
|
||||
{
|
||||
query = query.Where(p =>
|
||||
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.Now));
|
||||
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.UtcNow));
|
||||
}
|
||||
|
||||
if (exemptFlags is { } exempt)
|
||||
@@ -354,7 +354,7 @@ namespace Content.Server.Database
|
||||
if (!includeUnbanned)
|
||||
{
|
||||
query = query?.Where(p =>
|
||||
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.Now));
|
||||
p.Unban == null && (p.ExpirationTime == null || p.ExpirationTime.Value > DateTime.UtcNow));
|
||||
}
|
||||
|
||||
query = query!.Distinct();
|
||||
@@ -457,17 +457,6 @@ namespace Content.Server.Database
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override PlayerRecord MakePlayerRecord(Player record)
|
||||
{
|
||||
return new PlayerRecord(
|
||||
new NetUserId(record.UserId),
|
||||
new DateTimeOffset(record.FirstSeenTime),
|
||||
record.LastSeenUserName,
|
||||
new DateTimeOffset(record.LastSeenTime),
|
||||
record.LastSeenAddress,
|
||||
record.LastSeenHWId?.ToImmutableArray());
|
||||
}
|
||||
|
||||
public override async Task<int> AddConnectionLogAsync(
|
||||
NetUserId userId,
|
||||
string userName,
|
||||
@@ -532,6 +521,12 @@ WHERE to_tsvector('english'::regconfig, a.message) @@ websearch_to_tsquery('engl
|
||||
return db.AdminLog;
|
||||
}
|
||||
|
||||
protected override DateTime NormalizeDatabaseTime(DateTime time)
|
||||
{
|
||||
DebugTools.Assert(time.Kind == DateTimeKind.Utc);
|
||||
return time;
|
||||
}
|
||||
|
||||
private async Task<DbGuardImpl> GetDbImpl([CallerMemberName] string? name = null)
|
||||
{
|
||||
LogDbOp(name);
|
||||
|
||||
@@ -12,6 +12,7 @@ using Content.Shared.CCVar;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
@@ -350,17 +351,6 @@ namespace Content.Server.Database
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override PlayerRecord MakePlayerRecord(Player record)
|
||||
{
|
||||
return new PlayerRecord(
|
||||
new NetUserId(record.UserId),
|
||||
new DateTimeOffset(record.FirstSeenTime, TimeSpan.Zero),
|
||||
record.LastSeenUserName,
|
||||
new DateTimeOffset(record.LastSeenTime, TimeSpan.Zero),
|
||||
record.LastSeenAddress,
|
||||
record.LastSeenHWId?.ToImmutableArray());
|
||||
}
|
||||
|
||||
private static ServerBanDef? ConvertBan(ServerBan? ban)
|
||||
{
|
||||
if (ban == null)
|
||||
@@ -546,6 +536,12 @@ namespace Content.Server.Database
|
||||
return await base.AddAdminMessage(message);
|
||||
}
|
||||
|
||||
protected override DateTime NormalizeDatabaseTime(DateTime time)
|
||||
{
|
||||
DebugTools.Assert(time.Kind == DateTimeKind.Unspecified);
|
||||
return DateTime.SpecifyKind(time, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
private async Task<DbGuardImpl> GetDbImpl([CallerMemberName] string? name = null)
|
||||
{
|
||||
LogDbOp(name);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Database;
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
public record ServerRoleBanNote(int Id, int? RoundId, Round? Round, Guid? PlayerUserId, Player? Player,
|
||||
TimeSpan PlaytimeAtNote, string Message, NoteSeverity Severity, Player? CreatedBy, DateTime CreatedAt,
|
||||
Player? LastEditedBy, DateTime? LastEditedAt, DateTime? ExpirationTime, bool Deleted, string[] Roles,
|
||||
Player? UnbanningAdmin, DateTime? UnbanTime) : IAdminRemarksCommon;
|
||||
}
|
||||
Reference in New Issue
Block a user