Server ban exemption system (#15076)
This commit is contained in:
committed by
GitHub
parent
e037d12899
commit
c8e90e561b
@@ -12,12 +12,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.5">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="6.0.5" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="7.0.4" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.3" />
|
||||
|
||||
<!-- Necessary at design time -->
|
||||
<PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' != 'True' and '$(Configuration)' != 'Release'" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.4" Condition="'$(UseSystemSqlite)' != 'True' and '$(Configuration)' != 'Release'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
#if TOOLS
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using SQLitePCL;
|
||||
|
||||
// ReSharper disable UnusedType.Global
|
||||
|
||||
namespace Content.Server.Database;
|
||||
@@ -18,8 +22,14 @@ public sealed class DesignTimeContextFactorySqlite : IDesignTimeDbContextFactory
|
||||
{
|
||||
public SqliteServerDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
#if !USE_SYSTEM_SQLITE
|
||||
raw.SetProvider(new SQLite3Provider_e_sqlite3());
|
||||
#endif
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<SqliteServerDbContext>();
|
||||
optionsBuilder.UseSqlite("Data Source=:memory:");
|
||||
return new SqliteServerDbContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
1333
Content.Server.Database/Migrations/Postgres/20230319110655_ProfileTraitIndexUnique.Designer.cs
generated
Normal file
1333
Content.Server.Database/Migrations/Postgres/20230319110655_ProfileTraitIndexUnique.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class ProfileTraitIndexUnique : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_trait_profile_id",
|
||||
table: "trait");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_trait_profile_id_trait_name",
|
||||
table: "trait",
|
||||
columns: new[] { "profile_id", "trait_name" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_trait_profile_id_trait_name",
|
||||
table: "trait");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_trait_profile_id",
|
||||
table: "trait",
|
||||
column: "profile_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
1356
Content.Server.Database/Migrations/Postgres/20230319112124_ServerBanExemption.Designer.cs
generated
Normal file
1356
Content.Server.Database/Migrations/Postgres/20230319112124_ServerBanExemption.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
public partial class ServerBanExemption : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "exempt_flags",
|
||||
table: "server_ban",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "server_ban_exemption",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
flags = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_server_ban_exemption", x => x.user_id);
|
||||
table.CheckConstraint("FlagsNotZero", "flags != 0");
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "server_ban_exemption");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "exempt_flags",
|
||||
table: "server_ban");
|
||||
}
|
||||
}
|
||||
}
|
||||
1364
Content.Server.Database/Migrations/Postgres/20230402214647_BanAutoDelete.Designer.cs
generated
Normal file
1364
Content.Server.Database/Migrations/Postgres/20230402214647_BanAutoDelete.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class BanAutoDelete : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "auto_delete",
|
||||
table: "server_ban",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "auto_delete",
|
||||
table: "server_ban");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.5")
|
||||
.HasAnnotation("ProductVersion", "7.0.4")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
@@ -302,8 +302,7 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
@@ -408,9 +407,10 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("connection_log", (string)null);
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
b.ToTable("connection_log", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Job", b =>
|
||||
@@ -438,8 +438,7 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
@@ -451,6 +450,37 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayTime", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("play_time_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<TimeSpan>("TimeSpent")
|
||||
.HasColumnType("interval")
|
||||
.HasColumnName("time_spent");
|
||||
|
||||
b.Property<string>("Tracker")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("tracker");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_play_time");
|
||||
|
||||
b.HasIndex("PlayerId", "Tracker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("play_time", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -501,40 +531,10 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("player", (string)null);
|
||||
|
||||
b.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayTime", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("play_time_id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<TimeSpan>("TimeSpent")
|
||||
.HasColumnType("interval")
|
||||
.HasColumnName("time_spent");
|
||||
|
||||
b.Property<string>("Tracker")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("tracker");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_play_time");
|
||||
|
||||
b.HasIndex("PlayerId", "Tracker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("play_time", (string)null);
|
||||
b.ToTable("player", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
@@ -729,6 +729,10 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("inet")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<bool>("AutoDelete")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("auto_delete");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("ban_time");
|
||||
@@ -737,6 +741,10 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<int>("ExemptFlags")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("exempt_flags");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("expiration_time");
|
||||
@@ -761,11 +769,32 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban", (string)null);
|
||||
b.ToTable("server_ban", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
});
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int>("Flags")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("flags");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_server_ban_exemption");
|
||||
|
||||
b.ToTable("server_ban_exemption", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("FlagsNotZero", "flags != 0");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.ServerBanHit", b =>
|
||||
@@ -847,11 +876,12 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_role_ban", (string)null);
|
||||
b.ToTable("server_role_ban", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b =>
|
||||
@@ -935,8 +965,8 @@ namespace Content.Server.Database.Migrations.Postgres
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_trait");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_trait_profile_id");
|
||||
b.HasIndex("ProfileId", "TraitName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("trait", (string)null);
|
||||
});
|
||||
|
||||
1267
Content.Server.Database/Migrations/Sqlite/20230319110651_ProfileTraitIndexUnique.Designer.cs
generated
Normal file
1267
Content.Server.Database/Migrations/Sqlite/20230319110651_ProfileTraitIndexUnique.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class ProfileTraitIndexUnique : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_trait_profile_id",
|
||||
table: "trait");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_trait_profile_id_trait_name",
|
||||
table: "trait",
|
||||
columns: new[] { "profile_id", "trait_name" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_trait_profile_id_trait_name",
|
||||
table: "trait");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_trait_profile_id",
|
||||
table: "trait",
|
||||
column: "profile_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
1290
Content.Server.Database/Migrations/Sqlite/20230319112120_ServerBanExemption.Designer.cs
generated
Normal file
1290
Content.Server.Database/Migrations/Sqlite/20230319112120_ServerBanExemption.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
public partial class ServerBanExemption : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "exempt_flags",
|
||||
table: "server_ban",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "server_ban_exemption",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
flags = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_server_ban_exemption", x => x.user_id);
|
||||
table.CheckConstraint("FlagsNotZero", "flags != 0");
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "server_ban_exemption");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "exempt_flags",
|
||||
table: "server_ban");
|
||||
}
|
||||
}
|
||||
}
|
||||
1296
Content.Server.Database/Migrations/Sqlite/20230402214642_BanAutoDelete.Designer.cs
generated
Normal file
1296
Content.Server.Database/Migrations/Sqlite/20230402214642_BanAutoDelete.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class BanAutoDelete : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "auto_delete",
|
||||
table: "server_ban",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "auto_delete",
|
||||
table: "server_ban");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.5");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.4");
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Admin", b =>
|
||||
{
|
||||
@@ -278,8 +278,7 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_admin_rank_flag");
|
||||
|
||||
b.HasIndex("AdminRankId")
|
||||
.HasDatabaseName("IX_admin_rank_flag_admin_rank_id");
|
||||
b.HasIndex("AdminRankId");
|
||||
|
||||
b.HasIndex("Flag", "AdminRankId")
|
||||
.IsUnique();
|
||||
@@ -404,8 +403,7 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_job");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_job_profile_id");
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.HasIndex("ProfileId", "JobName")
|
||||
.IsUnique();
|
||||
@@ -417,6 +415,35 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.ToTable("job", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayTime", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("play_time_id");
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<TimeSpan>("TimeSpent")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("time_spent");
|
||||
|
||||
b.Property<string>("Tracker")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("tracker");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_play_time");
|
||||
|
||||
b.HasIndex("PlayerId", "Tracker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("play_time", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Player", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -468,35 +495,6 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.ToTable("player", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.PlayTime", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("play_time_id");
|
||||
|
||||
b.Property<Guid>("PlayerId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("player_id");
|
||||
|
||||
b.Property<TimeSpan>("TimeSpent")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("time_spent");
|
||||
|
||||
b.Property<string>("Tracker")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("tracker");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_play_time");
|
||||
|
||||
b.HasIndex("PlayerId", "Tracker")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("play_time", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.Preference", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -679,6 +677,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("address");
|
||||
|
||||
b.Property<bool>("AutoDelete")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("auto_delete");
|
||||
|
||||
b.Property<DateTime>("BanTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("ban_time");
|
||||
@@ -687,6 +689,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("banning_admin");
|
||||
|
||||
b.Property<int>("ExemptFlags")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("exempt_flags");
|
||||
|
||||
b.Property<DateTime?>("ExpirationTime")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("expiration_time");
|
||||
@@ -711,9 +717,30 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_ban", (string)null);
|
||||
b.ToTable("server_ban", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
});
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<int>("Flags")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("flags");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("PK_server_ban_exemption");
|
||||
|
||||
b.ToTable("server_ban_exemption", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("FlagsNotZero", "flags != 0");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.ServerBanHit", b =>
|
||||
@@ -791,9 +818,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("server_role_ban", (string)null);
|
||||
|
||||
b.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
b.ToTable("server_role_ban", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b =>
|
||||
@@ -871,8 +899,8 @@ namespace Content.Server.Database.Migrations.Sqlite
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_trait");
|
||||
|
||||
b.HasIndex("ProfileId")
|
||||
.HasDatabaseName("IX_trait_profile_id");
|
||||
b.HasIndex("ProfileId", "TraitName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("trait", (string)null);
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Content.Server.Database
|
||||
public DbSet<Whitelist> Whitelist { get; set; } = null!;
|
||||
public DbSet<ServerBan> Ban { get; set; } = default!;
|
||||
public DbSet<ServerUnban> Unban { get; set; } = default!;
|
||||
public DbSet<ServerBanExemption> BanExemption { get; set; } = default!;
|
||||
public DbSet<ConnectionLog> ConnectionLog { get; set; } = default!;
|
||||
public DbSet<ServerBanHit> ServerBanHit { get; set; } = default!;
|
||||
public DbSet<ServerRoleBan> RoleBan { get; set; } = default!;
|
||||
@@ -125,8 +126,13 @@ namespace Content.Server.Database
|
||||
.HasIndex(p => p.BanId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<ServerBan>()
|
||||
.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
modelBuilder.Entity<ServerBan>().ToTable(t =>
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL"));
|
||||
|
||||
// Ban exemption can't have flags 0 since that wouldn't exempt anything.
|
||||
// The row should be removed if setting to 0.
|
||||
modelBuilder.Entity<ServerBanExemption>().ToTable(t =>
|
||||
t.HasCheckConstraint("FlagsNotZero", "flags != 0"));
|
||||
|
||||
modelBuilder.Entity<ServerRoleBan>()
|
||||
.HasIndex(p => p.UserId);
|
||||
@@ -141,8 +147,8 @@ namespace Content.Server.Database
|
||||
.HasIndex(p => p.BanId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<ServerRoleBan>()
|
||||
.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL");
|
||||
modelBuilder.Entity<ServerRoleBan>().ToTable(t =>
|
||||
t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR user_id IS NOT NULL OR hwid IS NOT NULL"));
|
||||
|
||||
modelBuilder.Entity<Player>()
|
||||
.HasIndex(p => p.UserId)
|
||||
@@ -440,39 +446,148 @@ namespace Content.Server.Database
|
||||
DateTime UnbanTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flags for use with <see cref="ServerBanExemption"/>.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ServerBanExemptFlags
|
||||
{
|
||||
// @formatter:off
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Ban is a datacenter range, connections usually imply usage of a VPN service.
|
||||
/// </summary>
|
||||
Datacenter = 1 << 0,
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A ban from playing on the server.
|
||||
/// If an incoming connection matches any of UserID, IP, or HWID, they will be blocked from joining the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// At least one of UserID, IP, or HWID must be given (otherwise the ban would match nothing).
|
||||
/// </remarks>
|
||||
[Table("server_ban")]
|
||||
public class ServerBan : IBanCommon<ServerUnban>
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user ID of the banned player.
|
||||
/// </summary>
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CIDR IP address range of the ban. The whole range can match the ban.
|
||||
/// </summary>
|
||||
[Column(TypeName = "inet")] public (IPAddress, int)? Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hardware ID of the banned player.
|
||||
/// </summary>
|
||||
public byte[]? HWId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time when the ban was applied by an administrator.
|
||||
/// </summary>
|
||||
public DateTime BanTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time the ban will expire. If null, the ban is permanent and will not expire naturally.
|
||||
/// </summary>
|
||||
public DateTime? ExpirationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The administrator-stated reason for applying the ban.
|
||||
/// </summary>
|
||||
public string Reason { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// User ID of the admin that applied the ban.
|
||||
/// </summary>
|
||||
public Guid? BanningAdmin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional flags that allow adding exemptions to the ban via <see cref="ServerBanExemption"/>.
|
||||
/// </summary>
|
||||
public ServerBanExemptFlags ExemptFlags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If present, an administrator has manually repealed this ban.
|
||||
/// </summary>
|
||||
public ServerUnban? Unban { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this ban should be automatically deleted from the database when it expires.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This isn't done automatically by the game,
|
||||
/// you will need to set up something like a cron job to clear this from your database,
|
||||
/// using a command like this:
|
||||
/// psql -d ss14 -c "DELETE FROM server_ban WHERE auto_delete AND expiration_time < NOW()"
|
||||
/// </remarks>
|
||||
public bool AutoDelete { get; set; }
|
||||
|
||||
public List<ServerBanHit> BanHits { get; set; } = null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An explicit repeal of a <see cref="ServerBan"/> by an administrator.
|
||||
/// Having an entry for a ban neutralizes it.
|
||||
/// </summary>
|
||||
[Table("server_unban")]
|
||||
public class ServerUnban : IUnbanCommon
|
||||
{
|
||||
[Column("unban_id")] public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of ban that is being repealed.
|
||||
/// </summary>
|
||||
public int BanId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ban that is being repealed.
|
||||
/// </summary>
|
||||
public ServerBan Ban { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The admin that repealed the ban.
|
||||
/// </summary>
|
||||
public Guid? UnbanningAdmin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time the ban repealed.
|
||||
/// </summary>
|
||||
public DateTime UnbanTime { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An exemption for a specific user to a certain type of <see cref="ServerBan"/>.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// Certain players may need to be exempted from VPN bans due to issues with their ISP.
|
||||
/// We would tag all VPN bans with <see cref="ServerBanExemptFlags.Datacenter"/>,
|
||||
/// and then add an exemption for these players to this table with the same flag.
|
||||
/// They will only be exempted from VPN bans, other bans (if they manage to get any) will still apply.
|
||||
/// </example>
|
||||
[Table("server_ban_exemption")]
|
||||
public sealed class ServerBanExemption
|
||||
{
|
||||
/// <summary>
|
||||
/// The UserID of the exempted player.
|
||||
/// </summary>
|
||||
[Key]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ban flags to exempt this player from.
|
||||
/// If any bit overlaps <see cref="ServerBan.ExemptFlags"/>, the ban is ignored.
|
||||
/// </summary>
|
||||
public ServerBanExemptFlags Flags { get; set; }
|
||||
}
|
||||
|
||||
[Table("connection_log")]
|
||||
public class ConnectionLog
|
||||
{
|
||||
|
||||
@@ -46,19 +46,20 @@ namespace Content.Server.Database
|
||||
// ReSharper disable StringLiteralTypo
|
||||
// Enforce that an address cannot be IPv6-mapped IPv4.
|
||||
// So that IPv4 addresses are consistent between separate-socket and dual-stack socket modes.
|
||||
modelBuilder.Entity<ServerBan>()
|
||||
.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
modelBuilder.Entity<ServerBan>().ToTable(t =>
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"));
|
||||
|
||||
modelBuilder.Entity<ServerRoleBan>()
|
||||
.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
modelBuilder.Entity<ServerRoleBan>().ToTable( t =>
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"));
|
||||
|
||||
modelBuilder.Entity<Player>()
|
||||
.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4",
|
||||
"NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address");
|
||||
modelBuilder.Entity<Player>().ToTable(t =>
|
||||
t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4",
|
||||
"NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"));
|
||||
|
||||
modelBuilder.Entity<ConnectionLog>().ToTable(t =>
|
||||
t.HasCheckConstraint("AddressNotIPv6MappedIPv4",
|
||||
"NOT inet '::ffff:0.0.0.0/96' >>= address"));
|
||||
|
||||
modelBuilder.Entity<ConnectionLog>()
|
||||
.HasCheckConstraint("AddressNotIPv6MappedIPv4",
|
||||
"NOT inet '::ffff:0.0.0.0/96' >>= address");
|
||||
// ReSharper restore StringLiteralTypo
|
||||
|
||||
modelBuilder.Entity<AdminLog>()
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Content.Server.Database
|
||||
TypeMappingSourceDependencies dependencies,
|
||||
RelationalTypeMappingSourceDependencies relationalDependencies,
|
||||
ISqlGenerationHelper sqlGenerationHelper,
|
||||
INpgsqlOptions? npgsqlOptions = null)
|
||||
INpgsqlSingletonOptions npgsqlOptions)
|
||||
: base(dependencies, relationalDependencies, sqlGenerationHelper, npgsqlOptions)
|
||||
{
|
||||
StoreTypeMappings["inet"] =
|
||||
|
||||
@@ -200,12 +200,12 @@ namespace Content.Server.Database
|
||||
return;
|
||||
}
|
||||
|
||||
if (entityType.FindPrimaryKey() is IConventionKey primaryKey)
|
||||
if (entityType.FindPrimaryKey() is { } primaryKey)
|
||||
{
|
||||
if (entityType.FindRowInternalForeignKeys(tableIdentifier).FirstOrDefault() is null
|
||||
&& (entityType.BaseType is null || entityType.GetTableName() == entityType.BaseType.GetTableName()))
|
||||
{
|
||||
primaryKey.Builder.HasName(RewriteName(primaryKey.GetDefaultName()));
|
||||
primaryKey.Builder.HasName(RewriteName(primaryKey.GetDefaultName()!));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -215,16 +215,16 @@ namespace Content.Server.Database
|
||||
|
||||
foreach (var foreignKey in entityType.GetForeignKeys())
|
||||
{
|
||||
foreignKey.Builder.HasConstraintName(RewriteName(foreignKey.GetDefaultName()));
|
||||
foreignKey.Builder.HasConstraintName(RewriteName(foreignKey.GetDefaultName()!));
|
||||
}
|
||||
|
||||
foreach (var index in entityType.GetIndexes())
|
||||
{
|
||||
index.Builder.HasDatabaseName(RewriteName(index.GetDefaultDatabaseName()));
|
||||
index.Builder.HasDatabaseName(RewriteName(index.GetDefaultDatabaseName()!));
|
||||
}
|
||||
|
||||
if (annotation?.Value is not null
|
||||
&& entityType.FindOwnership() is IConventionForeignKey ownership
|
||||
&& entityType.FindOwnership() is { } ownership
|
||||
&& (string)annotation.Value != ownership.PrincipalEntityType.GetTableName())
|
||||
{
|
||||
foreach (var property in entityType.GetProperties()
|
||||
@@ -234,9 +234,9 @@ namespace Content.Server.Database
|
||||
RewriteColumnName(property.Builder);
|
||||
}
|
||||
|
||||
if (entityType.FindPrimaryKey() is IConventionKey key)
|
||||
if (entityType.FindPrimaryKey() is { } key)
|
||||
{
|
||||
key.Builder.HasName(RewriteName(key.GetDefaultName()));
|
||||
key.Builder.HasName(RewriteName(key.GetDefaultName()!));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ namespace Content.Server.Database
|
||||
IConventionForeignKeyBuilder relationshipBuilder,
|
||||
IConventionContext<IConventionForeignKeyBuilder> context)
|
||||
{
|
||||
relationshipBuilder.HasConstraintName(RewriteName(relationshipBuilder.Metadata.GetDefaultName()));
|
||||
relationshipBuilder.HasConstraintName(RewriteName(relationshipBuilder.Metadata.GetDefaultName()!));
|
||||
}
|
||||
|
||||
public void ProcessKeyAdded(IConventionKeyBuilder keyBuilder, IConventionContext<IConventionKeyBuilder> context)
|
||||
@@ -257,7 +257,7 @@ namespace Content.Server.Database
|
||||
|
||||
if (entityType.FindOwnership() is null)
|
||||
{
|
||||
keyBuilder.HasName(RewriteName(keyBuilder.Metadata.GetDefaultName()));
|
||||
keyBuilder.HasName(RewriteName(keyBuilder.Metadata.GetDefaultName()!));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace Content.Server.Database
|
||||
|
||||
foreach (var property in entityType.GetProperties())
|
||||
{
|
||||
var columnName = property.GetColumnBaseName();
|
||||
var columnName = property.GetColumnName();
|
||||
if (columnName.StartsWith(entityType.ShortName() + '_', StringComparison.Ordinal))
|
||||
{
|
||||
property.Builder.HasColumnName(
|
||||
@@ -310,11 +310,11 @@ namespace Content.Server.Database
|
||||
|
||||
var baseColumnName = StoreObjectIdentifier.Create(property.DeclaringEntityType, StoreObjectType.Table) is { } tableIdentifier
|
||||
? property.GetDefaultColumnName(tableIdentifier)
|
||||
: property.GetDefaultColumnBaseName();
|
||||
: property.GetDefaultColumnName();
|
||||
|
||||
if (baseColumnName == "Id")
|
||||
baseColumnName = entityType.GetTableName() + baseColumnName;
|
||||
propertyBuilder.HasColumnName(RewriteName(baseColumnName));
|
||||
propertyBuilder.HasColumnName(RewriteName(baseColumnName!));
|
||||
|
||||
foreach (var storeObjectType in _storeObjectTypes)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user