Ban database refactor (#42495)

* Ban DB refactor seems to work at a basic level for PostgreSQL

* New ban creation API

Supports all the new functionality (multiple players/addresses/hwids/roles/rounds per ban).

* Make the migration irreversible

* Re-implement ban notifications

The server ID check is no longer done as admins may want to place bans spanning multiple rounds irrelevant of the source server.

* Fix some split query warnings

* Implement migration on SQLite

* More comments

* Remove required from ban reason

SS14.Admin changes would like this

* More missing AsSplitQuery() calls

* Fix missing ban type filter

* Fix old CreateServerBan API with permanent time

* Fix department and role ban commands with permanent time

* Re-add banhits navigation property

Dropped this on accident, SS14.Admin needs it.

* More ban API fixes.

* Don't fetch ban exemption info for role bans

Not relevant, reduces query performance

* Regenerate migrations

* Fix adminnotes command for players that never connected

Would blow up handling null player records. Not a new bug introduced by the refactor, but I ran into it.

* Great shame... I accidentally committed submodule update...

* Update GDPR scripts

* Fix sandbox violation

* Fix bans with duplicate info causing DB exceptions

Most notably happened with role bans, as multiple departments may include the same role.
This commit is contained in:
Pieter-Jan Briers
2026-06-29 12:43:39 +02:00
committed by Coryler
parent 17d3e83d5a
commit 7419408ec5
65 changed files with 7712 additions and 2698 deletions
+28 -9
View File
@@ -8,7 +8,7 @@ import os
import psycopg2
from uuid import UUID
LATEST_DB_MIGRATION = "20250314222016_ConstructionFavorites"
LATEST_DB_MIGRATION = "20260120200503_BanRefactor"
def main():
parser = argparse.ArgumentParser()
@@ -42,9 +42,8 @@ def main():
dump_player(cur, user_id, arg_output)
dump_preference(cur, user_id, arg_output)
dump_role_whitelists(cur, user_id, arg_output)
dump_server_ban(cur, user_id, arg_output)
dump_ban(cur, user_id, arg_output)
dump_server_ban_exemption(cur, user_id, arg_output)
dump_server_role_ban(cur, user_id, arg_output)
dump_uploaded_resource_log(cur, user_id, arg_output)
dump_whitelist(cur, user_id, arg_output)
@@ -301,7 +300,7 @@ FROM (
f.write(json_data)
def dump_server_ban(cur: "psycopg2.cursor", user_id: str, outdir: str):
def dump_ban(cur: "psycopg2.cursor", user_id: str, outdir: str):
print("Dumping server_ban...")
cur.execute("""
@@ -311,19 +310,39 @@ FROM (
SELECT
*,
(SELECT to_jsonb(unban_sq) - 'ban_id' FROM (
SELECT * FROM server_unban WHERE server_unban.ban_id = server_ban.server_ban_id
SELECT * FROM unban WHERE unban.ban_id = ban.ban_id
) unban_sq)
as unban
as unban,
(SELECT COALESCE(json_agg(to_jsonb(ban_player_subq) - 'ban_id'), '[]') FROM (
SELECT * FROM ban_player WHERE ban_player.ban_id = ban.ban_id
) ban_player_subq)
as ban_player,
(SELECT COALESCE(json_agg(to_jsonb(ban_address_subq) - 'ban_id'), '[]') FROM (
SELECT * FROM ban_address WHERE ban_address.ban_id = ban.ban_id
) ban_address_subq)
as ban_address,
(SELECT COALESCE(json_agg(to_jsonb(ban_role_subq) - 'ban_id'), '[]') FROM (
SELECT * FROM ban_role WHERE ban_role.ban_id = ban.ban_id
) ban_role_subq)
as ban_role,
(SELECT COALESCE(json_agg(to_jsonb(ban_hwid_subq) - 'ban_id'), '[]') FROM (
SELECT * FROM ban_hwid WHERE ban_hwid.ban_id = ban.ban_id
) ban_hwid_subq)
as ban_hwid,
(SELECT COALESCE(json_agg(to_jsonb(ban_round_subq) - 'ban_id'), '[]') FROM (
SELECT * FROM ban_round WHERE ban_round.ban_id = ban.ban_id
) ban_round_subq)
as ban_round
FROM
server_ban
ban
WHERE
player_user_id = %s
ban_id IN (SELECT bp.ban_id FROM ban_player bp WHERE bp.user_id = %s)
) as data
""", (user_id,))
json_data = cur.fetchall()[0][0]
with open(os.path.join(outdir, "server_ban.json"), "w", encoding="utf-8") as f:
with open(os.path.join(outdir, "ban.json"), "w", encoding="utf-8") as f:
f.write(json_data)
+6 -18
View File
@@ -12,7 +12,7 @@ import os
import psycopg2
from uuid import UUID
LATEST_DB_MIGRATION = "20250314222016_ConstructionFavorites"
LATEST_DB_MIGRATION = "20260120200503_BanRefactor"
def main():
parser = argparse.ArgumentParser()
@@ -38,9 +38,8 @@ def main():
clear_play_time(cur, user_id)
clear_player(cur, user_id)
clear_preference(cur, user_id)
clear_server_ban(cur, user_id)
clear_ban(cur, user_id)
clear_server_ban_exemption(cur, user_id)
clear_server_role_ban(cur, user_id)
clear_uploaded_resource_log(cur, user_id)
clear_whitelist(cur, user_id)
clear_blacklist(cur, user_id)
@@ -144,14 +143,14 @@ WHERE
""", (user_id,))
def clear_server_ban(cur: "psycopg2.cursor", user_id: str):
print("Clearing server_ban...")
def clear_ban(cur: "psycopg2.cursor", user_id: str):
print("Clearing ban...")
cur.execute("""
DELETE FROM
server_ban
ban
WHERE
player_user_id = %s
ban_id IN (SELECT bp.ban_id FROM ban_player bp WHERE bp.user_id = %s)
""", (user_id,))
@@ -166,17 +165,6 @@ WHERE
""", (user_id,))
def clear_server_role_ban(cur: "psycopg2.cursor", user_id: str):
print("Clearing server_role_ban...")
cur.execute("""
DELETE FROM
server_role_ban
WHERE
player_user_id = %s
""", (user_id,))
def clear_uploaded_resource_log(cur: "psycopg2.cursor", user_id: str):
print("Clearing uploaded_resource_log...")