Merge player database models (#5267)

This commit is contained in:
Javier Guardia Fernández
2021-11-11 17:54:02 +01:00
committed by GitHub
parent 57f1e24466
commit 720e750e86
6 changed files with 94 additions and 168 deletions

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Net;
using Microsoft.EntityFrameworkCore;
namespace Content.Server.Database
@@ -27,6 +28,7 @@ namespace Content.Server.Database
public DbSet<Preference> Preference { get; set; } = null!;
public DbSet<Profile> Profile { get; set; } = null!;
public DbSet<AssignedUserId> AssignedUserId { get; set; } = null!;
public DbSet<Player> Player { get; set; } = default!;
public DbSet<Admin> Admin { get; set; } = null!;
public DbSet<AdminRank> AdminRank { get; set; } = null!;
@@ -162,6 +164,22 @@ namespace Content.Server.Database
public Guid UserId { get; set; }
}
[Table("player")]
public class Player
{
public int Id { get; set; }
// Permanent data
public Guid UserId { get; set; }
public DateTime FirstSeenTime { get; set; }
// Data that gets updated on each join.
public string LastSeenUserName { get; set; } = null!;
public DateTime LastSeenTime { get; set; }
public IPAddress LastSeenAddress { get; set; } = null!;
public byte[]? LastSeenHWId { get; set; }
}
public class Admin
{
[Key] public Guid UserId { get; set; }

View File

@@ -22,7 +22,6 @@ namespace Content.Server.Database
public DbSet<PostgresServerBan> Ban { get; set; } = default!;
public DbSet<PostgresServerUnban> Unban { get; set; } = default!;
public DbSet<PostgresPlayer> Player { get; set; } = default!;
public DbSet<PostgresConnectionLog> ConnectionLog { get; set; } = default!;
@@ -70,16 +69,16 @@ namespace Content.Server.Database
.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address")
.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
modelBuilder.Entity<PostgresPlayer>()
modelBuilder.Entity<Player>()
.HasIndex(p => p.UserId)
.IsUnique();
// ReSharper disable once StringLiteralTypo
modelBuilder.Entity<PostgresPlayer>()
modelBuilder.Entity<Player>()
.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4",
"NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
modelBuilder.Entity<PostgresPlayer>()
modelBuilder.Entity<Player>()
.HasIndex(p => p.LastSeenUserName);
modelBuilder.Entity<PostgresConnectionLog>()
@@ -131,25 +130,6 @@ namespace Content.Server.Database
public DateTime UnbanTime { get; set; }
}
[Table("player")]
public class PostgresPlayer
{
public int Id { get; set; }
// Permanent data
public Guid UserId { get; set; }
public DateTime FirstSeenTime { get; set; }
// Data that gets updated on each join.
public string LastSeenUserName { get; set; } = null!;
public DateTime LastSeenTime { get; set; }
public IPAddress LastSeenAddress { get; set; } = null!;
public byte[]? LastSeenHWId { get; set; }
}
[Table("connection_log")]
public class PostgresConnectionLog
{

View File

@@ -13,7 +13,6 @@ namespace Content.Server.Database
{
public DbSet<SqliteServerBan> Ban { get; set; } = default!;
public DbSet<SqliteServerUnban> Unban { get; set; } = default!;
public DbSet<SqlitePlayer> Player { get; set; } = default!;
public DbSet<SqliteConnectionLog> ConnectionLog { get; set; } = default!;
public SqliteServerDbContext()
@@ -37,10 +36,18 @@ namespace Content.Server.Database
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<SqlitePlayer>()
modelBuilder.Entity<Player>()
.HasIndex(p => p.LastSeenUserName);
var converter = new ValueConverter<(IPAddress address, int mask), string>(
var ipConverter = new ValueConverter<IPAddress, string>(
v => v.ToString(),
v => IPAddress.Parse(v));
modelBuilder.Entity<Player>()
.Property(p => p.LastSeenAddress)
.HasConversion(ipConverter);
var ipMaskConverter = new ValueConverter<(IPAddress address, int mask), string>(
v => InetToString(v.address, v.mask),
v => StringToInet(v)
);
@@ -49,7 +56,7 @@ namespace Content.Server.Database
.Entity<SqliteServerBan>()
.Property(e => e.Address)
.HasColumnType("TEXT")
.HasConversion(converter);
.HasConversion(ipMaskConverter);
}
public SqliteServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
@@ -105,22 +112,6 @@ namespace Content.Server.Database
public DateTime UnbanTime { get; set; }
}
[Table("player")]
public class SqlitePlayer
{
public int Id { get; set; }
// Permanent data
public Guid UserId { get; set; }
public DateTime FirstSeenTime { get; set; }
// Data that gets updated on each join.
public string LastSeenUserName { get; set; } = null!;
public DateTime LastSeenTime { get; set; }
public string LastSeenAddress { get; set; } = null!;
public byte[]? LastSeenHWId { get; set; }
}
[Table("connection_log")]
public class SqliteConnectionLog
{

View File

@@ -16,7 +16,6 @@ namespace Content.Server.Database
{
public abstract class ServerDbBase
{
#region Preferences
public async Task<PlayerPreferences?> GetPlayerPreferencesAsync(NetUserId userId)
{
@@ -229,6 +228,7 @@ namespace Content.Server.Database
}
#endregion
#region User Ids
public async Task<NetUserId?> GetAssignedUserIdAsync(string name)
{
await using var db = await GetDb();
@@ -249,8 +249,9 @@ namespace Content.Server.Database
await db.DbContext.SaveChangesAsync();
}
#endregion
#region Bans
/*
* BAN STUFF
*/
@@ -292,18 +293,66 @@ namespace Content.Server.Database
public abstract Task AddServerBanAsync(ServerBanDef serverBan);
public abstract Task AddServerUnbanAsync(ServerUnbanDef serverUnban);
#endregion
#region Player Records
/*
* PLAYER RECORDS
*/
public abstract Task UpdatePlayerRecord(
public async Task UpdatePlayerRecord(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId);
public abstract Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel);
public abstract Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel);
ImmutableArray<byte> hwId)
{
await using var db = await GetDb();
var record = await db.DbContext.Player.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
if (record == null)
{
db.DbContext.Player.Add(record = new Player
{
FirstSeenTime = DateTime.UtcNow,
UserId = userId.UserId,
});
}
record.LastSeenTime = DateTime.UtcNow;
record.LastSeenAddress = address;
record.LastSeenUserName = userName;
record.LastSeenHWId = hwId.ToArray();
await db.DbContext.SaveChangesAsync();
}
public async Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel)
{
await using var db = await GetDb();
// Sort by descending last seen time.
// So if, due to account renames, we have two people with the same username in the DB,
// the most recent one is picked.
var record = await db.DbContext.Player
.OrderByDescending(p => p.LastSeenTime)
.FirstOrDefaultAsync(p => p.LastSeenUserName == userName, cancel);
return record == null ? null : MakePlayerRecord(record);
}
public async Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDb();
var record = await db.DbContext.Player
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
return record == null ? null : MakePlayerRecord(record);
}
protected abstract PlayerRecord MakePlayerRecord(Player player);
#endregion
#region Connection Logs
/*
* CONNECTION LOG
*/
@@ -312,9 +361,11 @@ namespace Content.Server.Database
string userName,
IPAddress address,
ImmutableArray<byte> hwId);
#endregion
#region Admin Ranks
/*
* ADMIN STUFF
* ADMIN RANKS
*/
public async Task<Admin?> GetAdminDataForAsync(NetUserId userId, CancellationToken cancel)
{
@@ -402,6 +453,7 @@ namespace Content.Server.Database
await db.DbContext.SaveChangesAsync(cancel);
}
#endregion
protected abstract Task<DbGuard> GetDb();

View File

@@ -9,7 +9,6 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Robust.Shared.Network;
namespace Content.Server.Database
{
public sealed class ServerDbPostgres : ServerDbBase
@@ -222,63 +221,8 @@ namespace Content.Server.Database
await db.PgDbContext.SaveChangesAsync();
}
public override async Task UpdatePlayerRecord(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId)
protected override PlayerRecord MakePlayerRecord(Player record)
{
await using var db = await GetDbImpl();
var record = await db.PgDbContext.Player.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
if (record == null)
{
db.PgDbContext.Player.Add(record = new PostgresPlayer
{
FirstSeenTime = DateTime.UtcNow,
UserId = userId.UserId,
});
}
record.LastSeenTime = DateTime.UtcNow;
record.LastSeenAddress = address;
record.LastSeenUserName = userName;
record.LastSeenHWId = hwId.ToArray();
await db.PgDbContext.SaveChangesAsync();
}
public override async Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel)
{
await using var db = await GetDbImpl();
// Sort by descending last seen time.
// So if, due to account renames, we have two people with the same username in the DB,
// the most recent one is picked.
var record = await db.PgDbContext.Player
.OrderByDescending(p => p.LastSeenTime)
.FirstOrDefaultAsync(p => p.LastSeenUserName == userName, cancel);
return MakePlayerRecord(record);
}
public override async Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDbImpl();
var record = await db.PgDbContext.Player
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
return MakePlayerRecord(record);
}
private static PlayerRecord? MakePlayerRecord(PostgresPlayer? record)
{
if (record == null)
{
return null;
}
return new PlayerRecord(
new NetUserId(record.UserId),
new DateTimeOffset(record.FirstSeenTime),

View File

@@ -1,22 +1,18 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Content.Server.IP;
using Content.Server.Preferences;
using Content.Server.Preferences.Managers;
using Content.Shared;
using Content.Shared.CCVar;
using Microsoft.EntityFrameworkCore;
using Robust.Shared.Configuration;
using Robust.Shared.IoC;
using Robust.Shared.Network;
namespace Content.Server.Database
{
/// <summary>
@@ -154,69 +150,14 @@ namespace Content.Server.Database
await db.SqliteDbContext.SaveChangesAsync();
}
public override async Task UpdatePlayerRecord(
NetUserId userId,
string userName,
IPAddress address,
ImmutableArray<byte> hwId)
protected override PlayerRecord MakePlayerRecord(Player record)
{
await using var db = await GetDbImpl();
var record = await db.SqliteDbContext.Player.SingleOrDefaultAsync(p => p.UserId == userId.UserId);
if (record == null)
{
db.SqliteDbContext.Player.Add(record = new SqlitePlayer
{
FirstSeenTime = DateTime.UtcNow,
UserId = userId.UserId,
});
}
record.LastSeenTime = DateTime.UtcNow;
record.LastSeenAddress = address.ToString();
record.LastSeenUserName = userName;
record.LastSeenHWId = hwId.ToArray();
await db.SqliteDbContext.SaveChangesAsync();
}
public override async Task<PlayerRecord?> GetPlayerRecordByUserName(string userName, CancellationToken cancel)
{
await using var db = await GetDbImpl();
// Sort by descending last seen time.
// So if due to account renames we have two people with the same username in the DB,
// the most recent one is picked.
var record = await db.SqliteDbContext.Player
.OrderByDescending(p => p.LastSeenTime)
.FirstOrDefaultAsync(p => p.LastSeenUserName == userName, cancel);
return MakePlayerRecord(record);
}
public override async Task<PlayerRecord?> GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel)
{
await using var db = await GetDbImpl();
var record = await db.SqliteDbContext.Player
.SingleOrDefaultAsync(p => p.UserId == userId.UserId, cancel);
return MakePlayerRecord(record);
}
private static PlayerRecord? MakePlayerRecord(SqlitePlayer? record)
{
if (record == null)
{
return null;
}
return new PlayerRecord(
new NetUserId(record.UserId),
new DateTimeOffset(record.FirstSeenTime, TimeSpan.Zero),
record.LastSeenUserName,
new DateTimeOffset(record.LastSeenTime, TimeSpan.Zero),
IPAddress.Parse(record.LastSeenAddress),
record.LastSeenAddress,
record.LastSeenHWId?.ToImmutableArray());
}