using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
///
public partial class BanRefactor : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ban",
columns: table => new
{
ban_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
type = table.Column(type: "INTEGER", nullable: false),
playtime_at_note = table.Column(type: "TEXT", nullable: false),
ban_time = table.Column(type: "TEXT", nullable: false),
expiration_time = table.Column(type: "TEXT", nullable: true),
reason = table.Column(type: "TEXT", nullable: false),
severity = table.Column(type: "INTEGER", nullable: false),
banning_admin = table.Column(type: "TEXT", nullable: true),
last_edited_by_id = table.Column(type: "TEXT", nullable: true),
last_edited_at = table.Column(type: "TEXT", nullable: true),
exempt_flags = table.Column(type: "INTEGER", nullable: false),
auto_delete = table.Column(type: "INTEGER", nullable: false),
hidden = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban", x => x.ban_id);
table.CheckConstraint("NoExemptOnRoleBan", "type = 0 OR exempt_flags = 0");
table.ForeignKey(
name: "FK_ban_player_banning_admin",
column: x => x.banning_admin,
principalTable: "player",
principalColumn: "user_id",
onDelete: ReferentialAction.SetNull);
table.ForeignKey(
name: "FK_ban_player_last_edited_by_id",
column: x => x.last_edited_by_id,
principalTable: "player",
principalColumn: "user_id",
onDelete: ReferentialAction.SetNull);
});
migrationBuilder.CreateTable(
name: "ban_address",
columns: table => new
{
ban_address_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
address = table.Column(type: "TEXT", nullable: false),
ban_id = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban_address", x => x.ban_address_id);
table.ForeignKey(
name: "FK_ban_address_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ban_hwid",
columns: table => new
{
ban_hwid_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
hwid = table.Column(type: "BLOB", nullable: false),
hwid_type = table.Column(type: "INTEGER", nullable: false),
ban_id = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban_hwid", x => x.ban_hwid_id);
table.ForeignKey(
name: "FK_ban_hwid_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ban_player",
columns: table => new
{
ban_player_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
user_id = table.Column(type: "TEXT", nullable: false),
ban_id = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban_player", x => x.ban_player_id);
table.ForeignKey(
name: "FK_ban_player_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ban_role",
columns: table => new
{
ban_role_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
role_type = table.Column(type: "TEXT", nullable: false),
role_id = table.Column(type: "TEXT", nullable: false),
ban_id = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban_role", x => x.ban_role_id);
table.ForeignKey(
name: "FK_ban_role_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ban_round",
columns: table => new
{
ban_round_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ban_id = table.Column(type: "INTEGER", nullable: false),
round_id = table.Column(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ban_round", x => x.ban_round_id);
table.ForeignKey(
name: "FK_ban_round_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ban_round_round_round_id",
column: x => x.round_id,
principalTable: "round",
principalColumn: "round_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "unban",
columns: table => new
{
unban_id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
ban_id = table.Column(type: "INTEGER", nullable: false),
unbanning_admin = table.Column(type: "TEXT", nullable: true),
unban_time = table.Column(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_unban", x => x.unban_id);
table.ForeignKey(
name: "FK_unban_ban_ban_id",
column: x => x.ban_id,
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ban_banning_admin",
table: "ban",
column: "banning_admin");
migrationBuilder.CreateIndex(
name: "IX_ban_last_edited_by_id",
table: "ban",
column: "last_edited_by_id");
migrationBuilder.CreateIndex(
name: "IX_ban_address_ban_id",
table: "ban_address",
column: "ban_id");
migrationBuilder.CreateIndex(
name: "IX_ban_hwid_ban_id",
table: "ban_hwid",
column: "ban_id");
migrationBuilder.CreateIndex(
name: "IX_ban_player_ban_id",
table: "ban_player",
column: "ban_id");
migrationBuilder.CreateIndex(
name: "IX_ban_player_user_id_ban_id",
table: "ban_player",
columns: new[] { "user_id", "ban_id" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ban_role_ban_id",
table: "ban_role",
column: "ban_id");
migrationBuilder.CreateIndex(
name: "IX_ban_role_role_type_role_id_ban_id",
table: "ban_role",
columns: new[] { "role_type", "role_id", "ban_id" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ban_round_ban_id",
table: "ban_round",
column: "ban_id");
migrationBuilder.CreateIndex(
name: "IX_ban_round_round_id_ban_id",
table: "ban_round",
columns: new[] { "round_id", "ban_id" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_unban_ban_id",
table: "unban",
column: "ban_id",
unique: true);
migrationBuilder.Sql("""
CREATE UNIQUE INDEX "IX_ban_hwid_hwid_ban_id"
ON ban_hwid
(hwid_type, hwid, ban_id);
CREATE UNIQUE INDEX "IX_ban_address_address_ban_id"
ON ban_address
(address, ban_id);
""");
migrationBuilder.Sql("""
--
-- Insert game bans
--
INSERT INTO
ban (ban_id, type, playtime_at_note, ban_time, expiration_time, reason, severity, banning_admin, last_edited_by_id, last_edited_at, exempt_flags, auto_delete, hidden)
SELECT
server_ban_id, 0, playtime_at_note, ban_time, expiration_time, reason, severity, banning_admin, last_edited_by_id, last_edited_at, exempt_flags, auto_delete, hidden
FROM
server_ban;
-- Insert ban player records.
INSERT INTO
ban_player (user_id, ban_id)
SELECT
player_user_id, server_ban_id
FROM
server_ban
WHERE
player_user_id IS NOT NULL;
-- Insert ban address records.
INSERT INTO
ban_address (address, ban_id)
SELECT
address, server_ban_id
FROM
server_ban
WHERE
address IS NOT NULL;
-- Insert ban HWID records.
INSERT INTO
ban_hwid (hwid, hwid_type, ban_id)
SELECT
hwid, hwid_type, server_ban_id
FROM
server_ban
WHERE
hwid IS NOT NULL;
-- Insert ban unban records.
INSERT INTO
unban (ban_id, unbanning_admin, unban_time)
SELECT
ban_id, unbanning_admin, unban_time
FROM server_unban;
-- Insert ban round records.
INSERT INTO
ban_round (round_id, ban_id)
SELECT
round_id, server_ban_id
FROM
server_ban
WHERE
round_id IS NOT NULL;
--
-- Insert role bans
-- This shit is a pain in the ass
-- > Declarative language
-- > Has to write procedural code in it
--
-- Create mapping table from role ban -> server ban.
-- We have to manually calculate the new ban IDs by using the sequence.
-- We also want to merge role ban records because the game code previously did that in some UI,
-- and that code is now gone, expecting the DB to do it.
-- Create a table to store IDs to merge.
CREATE TEMPORARY TABLE _role_ban_import_merge_map (merge_id INTEGER, server_role_ban_id INTEGER UNIQUE);
-- Create a table to store merged IDs -> new ban IDs
CREATE TEMPORARY TABLE _role_ban_import_id_map (ban_id INTEGER UNIQUE, merge_id INTEGER UNIQUE);
-- Calculate merged role bans.
INSERT INTO
_role_ban_import_merge_map
SELECT
(
SELECT
sub.server_role_ban_id
FROM
server_role_ban AS sub
LEFT JOIN server_role_unban AS sub_unban
ON sub_unban.ban_id = sub.server_role_ban_id
WHERE
main.reason IS NOT DISTINCT FROM sub.reason
AND main.player_user_id IS NOT DISTINCT FROM sub.player_user_id
AND main.address IS NOT DISTINCT FROM sub.address
AND main.hwid IS NOT DISTINCT FROM sub.hwid
AND main.hwid_type IS NOT DISTINCT FROM sub.hwid_type
AND main.ban_time = sub.ban_time
AND (
(main.expiration_time IS NULL) = (sub.expiration_time IS NULL)
OR main.expiration_time = sub.expiration_time
)
AND main.round_id IS NOT DISTINCT FROM sub.round_id
AND main.severity IS NOT DISTINCT FROM sub.severity
AND main.hidden IS NOT DISTINCT FROM sub.hidden
AND main.banning_admin IS NOT DISTINCT FROM sub.banning_admin
AND (sub_unban.ban_id IS NULL) = (main_unban.ban_id IS NULL)
ORDER BY
sub.server_role_ban_id ASC
LIMIT 1
), main.server_role_ban_id
FROM
server_role_ban AS main
LEFT JOIN server_role_unban AS main_unban
ON main_unban.ban_id = main.server_role_ban_id;
-- Assign new ban IDs for merged IDs.
INSERT OR IGNORE INTO
_role_ban_import_id_map
SELECT
merge_id + (SELECT seq FROM sqlite_sequence WHERE name = 'ban'),
merge_id
FROM
_role_ban_import_merge_map;
-- I sure fucking wish CTEs could span multiple queries...
-- Insert new ban records
INSERT INTO
ban (ban_id, type, playtime_at_note, ban_time, expiration_time, reason, severity, banning_admin, last_edited_by_id, last_edited_at, exempt_flags, auto_delete, hidden)
SELECT
im.ban_id, 1, playtime_at_note, ban_time, expiration_time, reason, severity, banning_admin, last_edited_by_id, last_edited_at, 0, FALSE, hidden
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = im.merge_id
WHERE mm.merge_id = mm.server_role_ban_id;
-- Insert role ban player records.
INSERT INTO
ban_player (user_id, ban_id)
SELECT
player_user_id, im.ban_id
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = im.merge_id
WHERE mm.merge_id = mm.server_role_ban_id
AND player_user_id IS NOT NULL;
-- Insert role ban address records.
INSERT INTO
ban_address (address, ban_id)
SELECT
address, im.ban_id
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = im.merge_id
WHERE mm.merge_id = mm.server_role_ban_id
AND address IS NOT NULL;
-- Insert role ban HWID records.
INSERT INTO
ban_hwid (hwid, hwid_type, ban_id)
SELECT
hwid, hwid_type, im.ban_id
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = im.merge_id
WHERE mm.merge_id = mm.server_role_ban_id
AND hwid IS NOT NULL;
-- Insert role ban role records.
INSERT INTO
ban_role (role_type, role_id, ban_id)
SELECT
substr(role_id, 1, instr(role_id, ':')-1),
substr(role_id, instr(role_id, ':')+1),
im.ban_id
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = mm.server_role_ban_id
-- Yes, we have some messy ban records which, after merging, end up with duplicate roles.
ON CONFLICT DO NOTHING;
-- Insert role unban records.
INSERT INTO
unban (ban_id, unbanning_admin, unban_time)
SELECT
im.ban_id, unbanning_admin, unban_time
FROM server_role_unban sru
INNER JOIN _role_ban_import_id_map im
ON im.merge_id = sru.ban_id;
-- Insert role rounds
INSERT INTO
ban_round (round_id, ban_id)
SELECT
round_id, im.ban_id
FROM
_role_ban_import_id_map im
INNER JOIN _role_ban_import_merge_map mm
ON im.merge_id = mm.merge_id
INNER JOIN server_role_ban srb
ON srb.server_role_ban_id = im.merge_id
WHERE mm.merge_id = mm.server_role_ban_id
AND round_id IS NOT NULL;
""");
migrationBuilder.AddForeignKey(
name: "FK_server_ban_hit_ban_ban_id",
table: "server_ban_hit",
column: "ban_id",
principalTable: "ban",
principalColumn: "ban_id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.DropForeignKey(
name: "FK_server_ban_hit_server_ban_ban_id",
table: "server_ban_hit");
migrationBuilder.DropTable(
name: "server_role_unban");
migrationBuilder.DropTable(
name: "server_unban");
migrationBuilder.DropTable(
name: "server_role_ban");
migrationBuilder.DropTable(
name: "server_ban");
}
///
protected override void Down(MigrationBuilder migrationBuilder)
{
throw new NotSupportedException("This migration cannot be rolled back");
}
}
}