Add multi-server-per-admin support via sa_admins_servers table

This commit is contained in:
Ravid-A 2026-05-31 17:34:53 +03:00
parent eea700bfb4
commit e028441b56
7 changed files with 72 additions and 10 deletions

View file

@ -84,6 +84,9 @@
<None Update="Database\Migrations\Mysql\016_OptimizeTablesAndIndexes.sql"> <None Update="Database\Migrations\Mysql\016_OptimizeTablesAndIndexes.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="Database\Migrations\Mysql\017_CreateAdminsServersTable.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Database\Migrations\Sqlite\001_CreateTables.sql"> <None Update="Database\Migrations\Sqlite\001_CreateTables.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@ -132,6 +135,9 @@
<None Update="Database\Migrations\Sqlite\016_OptimizeTablesAndIndexes.sql"> <None Update="Database\Migrations\Sqlite\016_OptimizeTablesAndIndexes.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="Database\Migrations\Sqlite\017_CreateAdminsServersTable.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -21,6 +21,7 @@ public interface IDatabaseProvider
string GetDeleteAdminQuery(bool globalDelete); string GetDeleteAdminQuery(bool globalDelete);
string GetAddAdminQuery(); string GetAddAdminQuery();
string GetAddAdminFlagsQuery(); string GetAddAdminFlagsQuery();
string GetAddAdminServerQuery();
string GetUpdateAdminGroupQuery(); string GetUpdateAdminGroupQuery();
string GetGroupsQuery(); string GetGroupsQuery();
string GetGroupIdByNameQuery(); string GetGroupIdByNameQuery();

View file

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS `sa_admins_servers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_id` int(11) NOT NULL,
`server_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`admin_id`) REFERENCES `sa_admins` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `sa_admins` ADD `global` TINYINT(1) NOT NULL DEFAULT 0;
INSERT INTO `sa_admins_servers` (`admin_id`, `server_id`)
SELECT `id`, `server_id` FROM `sa_admins` WHERE `server_id` IS NOT NULL;
UPDATE `sa_admins` SET `global` = 1 WHERE `server_id` IS NULL;
ALTER TABLE `sa_admins` DROP COLUMN `server_id`;

View file

@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS `sa_admins_servers` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`admin_id` INTEGER NOT NULL,
`server_id` INTEGER NOT NULL,
FOREIGN KEY (`admin_id`) REFERENCES `sa_admins` (`id`) ON DELETE CASCADE
);
ALTER TABLE `sa_admins` ADD `global` INTEGER NOT NULL DEFAULT 0;
INSERT INTO `sa_admins_servers` (`admin_id`, `server_id`)
SELECT `id`, `server_id` FROM `sa_admins` WHERE `server_id` IS NOT NULL;
UPDATE `sa_admins` SET `global` = 1 WHERE `server_id` IS NULL;
ALTER TABLE `sa_admins` DROP COLUMN `server_id`;

View file

@ -127,7 +127,10 @@ public class MySqlDatabaseProvider(string connectionString) : IDatabaseProvider
FROM sa_admins_flags FROM sa_admins_flags
JOIN sa_admins ON sa_admins_flags.admin_id = sa_admins.id JOIN sa_admins ON sa_admins_flags.admin_id = sa_admins.id
WHERE (sa_admins.ends IS NULL OR sa_admins.ends > @CurrentTime) WHERE (sa_admins.ends IS NULL OR sa_admins.ends > @CurrentTime)
AND (sa_admins.server_id IS NULL OR sa_admins.server_id = @serverid) AND (sa_admins.`global` = 1
OR EXISTS (SELECT 1 FROM sa_admins_servers
WHERE sa_admins_servers.admin_id = sa_admins.id
AND sa_admins_servers.server_id = @serverid))
ORDER BY sa_admins.player_steamid ORDER BY sa_admins.player_steamid
"""; """;
} }
@ -135,11 +138,14 @@ public class MySqlDatabaseProvider(string connectionString) : IDatabaseProvider
public string GetDeleteAdminQuery(bool globalDelete) => public string GetDeleteAdminQuery(bool globalDelete) =>
globalDelete globalDelete
? "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID" ? "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID"
: "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID AND server_id = @ServerId"; : "DELETE FROM sa_admins_servers WHERE server_id = @ServerId AND admin_id IN (SELECT id FROM sa_admins WHERE player_steamid = @PlayerSteamID)";
public string GetAddAdminQuery() => public string GetAddAdminQuery() =>
"INSERT INTO sa_admins (player_steamid, player_name, immunity, ends, created, server_id) " + "INSERT INTO sa_admins (player_steamid, player_name, immunity, ends, created, `global`) " +
"VALUES (@playerSteamId, @playerName, @immunity, @ends, @created, @serverid); SELECT LAST_INSERT_ID();"; "VALUES (@playerSteamId, @playerName, @immunity, @ends, @created, @isGlobal); SELECT LAST_INSERT_ID();";
public string GetAddAdminServerQuery() =>
"INSERT INTO sa_admins_servers (admin_id, server_id) VALUES (@adminId, @server_id);";
public string GetGroupsQuery() public string GetGroupsQuery()
{ {

View file

@ -176,22 +176,28 @@ public class SqliteDatabaseProvider(string filePath) : IDatabaseProvider
FROM sa_admins_flags FROM sa_admins_flags
JOIN sa_admins ON sa_admins_flags.admin_id = sa_admins.id JOIN sa_admins ON sa_admins_flags.admin_id = sa_admins.id
WHERE (sa_admins.ends IS NULL OR sa_admins.ends > @CurrentTime) WHERE (sa_admins.ends IS NULL OR sa_admins.ends > @CurrentTime)
AND (sa_admins.server_id IS NULL OR sa_admins.server_id = @serverid) AND (sa_admins.`global` = 1
OR EXISTS (SELECT 1 FROM sa_admins_servers
WHERE sa_admins_servers.admin_id = sa_admins.id
AND sa_admins_servers.server_id = @serverid))
ORDER BY sa_admins.player_steamid ORDER BY sa_admins.player_steamid
"""; """;
public string GetDeleteAdminQuery(bool globalDelete) => public string GetDeleteAdminQuery(bool globalDelete) =>
globalDelete globalDelete
? "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID" ? "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID"
: "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID AND server_id = @ServerId"; : "DELETE FROM sa_admins_servers WHERE server_id = @ServerId AND admin_id IN (SELECT id FROM sa_admins WHERE player_steamid = @PlayerSteamID)";
public string GetAddAdminQuery() => public string GetAddAdminQuery() =>
""" """
INSERT INTO sa_admins (player_steamid, player_name, immunity, ends, created, server_id) INSERT INTO sa_admins (player_steamid, player_name, immunity, ends, created, `global`)
VALUES (@playerSteamId, @playerName, @immunity, @ends, @created, @serverid); VALUES (@playerSteamId, @playerName, @immunity, @ends, @created, @isGlobal);
SELECT last_insert_rowid(); SELECT last_insert_rowid();
"""; """;
public string GetAddAdminServerQuery() =>
"INSERT INTO sa_admins_servers (admin_id, server_id) VALUES (@adminId, @server_id);";
public string GetGroupsQuery() => public string GetGroupsQuery() =>
""" """
SELECT g.group_id, sg.name AS group_name, sg.immunity, f.flag SELECT g.group_id, sg.name AS group_name, sg.immunity, f.flag

View file

@ -530,7 +530,7 @@ public class PermissionManager(IDatabaseProvider? databaseProvider)
immunity, immunity,
ends = futureTime, ends = futureTime,
created = now, created = now,
serverid = globalAdmin ? null : CS2_SimpleAdmin.ServerId isGlobal = globalAdmin ? 1 : 0
}); });
// Insert flags into sa_admins_flags table // Insert flags into sa_admins_flags table
@ -563,6 +563,18 @@ public class PermissionManager(IDatabaseProvider? databaseProvider)
}); });
} }
// Global admins apply to every server and need no per-server link row.
// Server-specific admins are linked to the current server.
if (!globalAdmin)
{
var insertAdminServerSql = databaseProvider.GetAddAdminServerQuery();
await connection.ExecuteAsync(insertAdminServerSql, new
{
adminId,
server_id = CS2_SimpleAdmin.ServerId
});
}
await Server.NextWorldUpdateAsync(() => await Server.NextWorldUpdateAsync(() =>
{ {
CS2_SimpleAdmin.Instance.ReloadAdmins(null); CS2_SimpleAdmin.Instance.ReloadAdmins(null);