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);
|
||||
Reference in New Issue
Block a user