Add permission override support for menus

Menus can now specify a command name for permission override checking, allowing server admins to control menu visibility via CounterStrikeSharp's admin system. Updated API, MenuManager, and FunCommands module to support this feature. Also updated slap command to emit a sound, fixed SQL migration for IP address type, and bumped version to 1.7.8-beta-2.
This commit is contained in:
Dawid Bepierszcz
2025-10-19 16:06:03 +02:00
parent 78318102fe
commit 206c18db66
12 changed files with 94 additions and 27 deletions

View File

@@ -16,6 +16,8 @@ env:
PROJECT_NAME_CS2_SIMPLEADMIN: "CS2-SimpleAdmin"
PROJECT_PATH_CS2_SIMPLEADMINAPI: "CS2-SimpleAdminApi/CS2-SimpleAdminApi.csproj"
PROJECT_NAME_CS2_SIMPLEADMINAPI: "CS2-SimpleAdminApi"
PROJECT_PATH_FUNCOMMANDSMODULE: "Modules/CS2-SimpleAdmin_FunCommands/CS2-SimpleAdmin_FunCommands.csproj"
PROJECT_NAME_FUNCOMMANDSMODULE: "CS2-SimpleAdmin_FunCommands"
PROJECT_PATH_STEALTHMODULE: "Modules/CS2-SimpleAdmin_StealthModule/CS2-SimpleAdmin_StealthModule.csproj"
PROJECT_NAME_STEALTHMODULE: "CS2-SimpleAdmin_StealthModule"
OUTPUT_PATH: "./counterstrikesharp"
@@ -45,16 +47,20 @@ jobs:
dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMIN }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}
dotnet restore ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }}
dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}
dotnet restore ${{ env.PROJECT_PATH_FUNCOMMANDSMODULE }}
dotnet build ${{ env.PROJECT_PATH_FUNCOMMANDSMODULE }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_FUNCOMMANDSMODULE }}
dotnet restore ${{ env.PROJECT_PATH_STEALTHMODULE }}
dotnet build ${{ env.PROJECT_PATH_STEALTHMODULE }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_STEALTHMODULE }}
- name: Combine projects
run: |
mkdir -p ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin
mkdir -p ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin_FunCommands
mkdir -p ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin_StealthModule
mkdir -p ${{ env.OUTPUT_PATH }}/shared/CS2-SimpleAdminApi
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/* ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin/
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_FUNCOMMANDSMODULE }}/* ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin_FunCommands
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_STEALTHMODULE }}/* ${{ env.OUTPUT_PATH }}/plugins/CS2-SimpleAdmin_StealthModule
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}/* ${{ env.OUTPUT_PATH }}/shared/CS2-SimpleAdminApi/

View File

@@ -206,9 +206,9 @@ public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
}
public void RegisterMenu(string categoryId, string menuId, string menuName,
Func<CCSPlayerController, object> menuFactory, string? permission = null)
Func<CCSPlayerController, object> menuFactory, string? permission = null, string? commandName = null)
{
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuName, BuilderFactory, permission);
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuName, BuilderFactory, permission, commandName);
return;
MenuBuilder BuilderFactory(CCSPlayerController player)

View File

@@ -22,7 +22,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
public override string ModuleAuthor => "daffyy & Dliix66";
public override string ModuleVersion => "1.7.8-beta-1";
public override string ModuleVersion => "1.7.8-beta-2";
public override void Load(bool hotReload)
{

View File

@@ -120,6 +120,7 @@ public partial class CS2_SimpleAdmin
// Apply slap damage to the player
player.Pawn.Value?.Slap(damage);
player.EmitSound("BaseGrenade.JumpThrowM");
// Log the command
if (command == null)

View File

@@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS `sa_players_ips` (
`steamid` INTEGER NOT NULL,
`address` VARCHAR(64) NOT NULL,
`address` INTEGER NOT NULL
`used_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`steamid`, `address`)
);

View File

@@ -1,9 +1,4 @@
DELETE FROM `sa_players_ips`
WHERE `id` NOT IN (
SELECT MIN(`id`)
FROM `sa_players_ips`
GROUP BY `steamid`
);
TRUNCATE TABLE `sa_players_ips`;
ALTER TABLE `sa_players_ips` ADD `name` VARCHAR(64) NULL DEFAULT NULL;
CREATE INDEX IF NOT EXISTS `idx_sa_players_ips_used_at` ON `sa_players_ips` (`used_at` DESC);

View File

@@ -46,7 +46,8 @@ public class MenuManager
/// <param name="menuName">Display name of the menu.</param>
/// <param name="menuFactory">Factory function that creates the menu for a player.</param>
/// <param name="permission">Required permission to access this menu (optional).</param>
public void RegisterMenu(string categoryId, string menuId, string menuName, Func<CCSPlayerController, MenuBuilder> menuFactory, string? permission = null)
/// <param name="commandName">Command name for permission override checking (optional, e.g., "css_god").</param>
public void RegisterMenu(string categoryId, string menuId, string menuName, Func<CCSPlayerController, MenuBuilder> menuFactory, string? permission = null, string? commandName = null)
{
if (!_menuCategories.ContainsKey(categoryId))
{
@@ -59,6 +60,10 @@ public class MenuManager
{
_menuCategories[categoryId].MenuPermissions[menuId] = permission;
}
if (commandName != null)
{
_menuCategories[categoryId].MenuCommandNames[menuId] = commandName;
}
}
/// <summary>
@@ -72,6 +77,7 @@ public class MenuManager
category.MenuFactories.Remove(menuId);
_menuCategories[categoryId].MenuNames.Remove(menuId);
_menuCategories[categoryId].MenuPermissions.Remove(menuId);
_menuCategories[categoryId].MenuCommandNames.Remove(menuId);
}
/// <summary>
@@ -116,11 +122,39 @@ public class MenuManager
var menuFactory = kvp.Value;
var menuName = category.MenuNames.TryGetValue(menuId, out var name) ? name : menuId;
var permission = category.MenuPermissions.TryGetValue(menuId, out var perm) ? perm : null;
var commandName = category.MenuCommandNames.TryGetValue(menuId, out var cmd) ? cmd : null;
// Check permissions
if (!string.IsNullOrEmpty(permission))
// Check permissions with command override support
var steamId = new SteamID(player.SteamID);
// If commandName is provided, check for permission overrides
if (!string.IsNullOrEmpty(commandName))
{
bool hasPermission;
// Check if command has overridden permissions
if (AdminManager.CommandIsOverriden(commandName))
{
var overriddenPermission = AdminManager.GetPermissionOverrides(commandName);
hasPermission = AdminManager.PlayerHasPermissions(steamId, overriddenPermission);
}
else if (!string.IsNullOrEmpty(permission))
{
// Use default permission if no override exists
hasPermission = AdminManager.PlayerHasPermissions(steamId, permission);
}
else
{
// No permission required
hasPermission = true;
}
if (!hasPermission)
continue;
}
// Fallback to standard permission check if no commandName provided
else if (!string.IsNullOrEmpty(permission))
{
var steamId = new SteamID(player.SteamID);
if (!AdminManager.PlayerHasPermissions(steamId, permission))
continue;
}
@@ -187,4 +221,5 @@ public class MenuCategory
public Dictionary<string, Func<CCSPlayerController, MenuBuilder>> MenuFactories { get; set; } = [];
public Dictionary<string, string> MenuNames { get; set; } = [];
public Dictionary<string, string> MenuPermissions { get; set; } = [];
public Dictionary<string, string> MenuCommandNames { get; set; } = [];
}

View File

@@ -1 +1 @@
1.7.8-beta-1
1.7.8-beta-2

View File

@@ -143,7 +143,13 @@ public interface ICS2_SimpleAdminApi
/// <summary>
/// Registers a menu in a category.
/// </summary>
void RegisterMenu(string categoryId, string menuId, string menuName, Func<CCSPlayerController, object> menuFactory, string? permission = null);
/// <param name="categoryId">The category to add this menu to.</param>
/// <param name="menuId">Unique identifier for the menu.</param>
/// <param name="menuName">Display name of the menu.</param>
/// <param name="menuFactory">Factory function that creates the menu for a player.</param>
/// <param name="permission">Required permission to access this menu (optional).</param>
/// <param name="commandName">Command name for permission override checking (optional, e.g., "css_god").</param>
void RegisterMenu(string categoryId, string menuId, string menuName, Func<CCSPlayerController, object> menuFactory, string? permission = null, string? commandName = null);
/// <summary>
/// Unregisters a menu from a category.

View File

@@ -368,60 +368,64 @@ public partial class CS2_SimpleAdmin_FunCommands : BasePlugin, IPluginConfig<Con
{
_sharedApi.RegisterMenuCategory("fun", Localizer?["fun_category_name"] ?? "Fun Commands", "@css/generic");
// Register menus with command names for permission override support
// Server admins can override default permissions via CounterStrikeSharp admin system
// Example: If "css_god" is overridden to "@css/vip", only VIPs will see the God Mode menu
if (Config.GodCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "god",
Localizer?["fun_menu_god"] ?? "God Mode",
CreateGodModeMenu, "@css/cheats");
CreateGodModeMenu, "@css/cheats", "css_god");
if (Config.NoclipCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "noclip",
Localizer?["fun_menu_noclip"] ?? "No Clip",
CreateNoClipMenu, "@css/cheats");
CreateNoClipMenu, "@css/cheats", "css_noclip");
if (Config.RespawnCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "respawn",
Localizer?["fun_menu_respawn"] ?? "Respawn",
CreateRespawnMenu, "@css/cheats");
CreateRespawnMenu, "@css/cheats", "css_respawn");
if (Config.GiveCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "give",
Localizer?["fun_menu_give"] ?? "Give Weapon",
CreateGiveWeaponMenu, "@css/cheats");
CreateGiveWeaponMenu, "@css/cheats", "css_give");
if (Config.StripCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "strip",
Localizer?["fun_menu_strip"] ?? "Strip Weapons",
CreateStripWeaponsMenu, "@css/slay");
CreateStripWeaponsMenu, "@css/slay", "css_strip");
if (Config.FreezeCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "freeze",
Localizer?["fun_menu_freeze"] ?? "Freeze",
CreateFreezeMenu, "@css/slay");
CreateFreezeMenu, "@css/slay", "css_freeze");
if (Config.HpCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "hp",
Localizer?["fun_menu_hp"] ?? "Set HP",
CreateSetHpMenu, "@css/slay");
CreateSetHpMenu, "@css/slay", "css_hp");
if (Config.SpeedCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "speed",
Localizer?["fun_menu_speed"] ?? "Set Speed",
CreateSetSpeedMenu, "@css/slay");
CreateSetSpeedMenu, "@css/slay", "css_speed");
if (Config.GravityCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "gravity",
Localizer?["fun_menu_gravity"] ?? "Set Gravity",
CreateSetGravityMenu, "@css/slay");
CreateSetGravityMenu, "@css/slay", "css_gravity");
if (Config.MoneyCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "money",
Localizer?["fun_menu_money"] ?? "Set Money",
CreateSetMoneyMenu, "@css/slay");
CreateSetMoneyMenu, "@css/slay", "css_money");
if (Config.ResizeCommands.Count > 0)
_sharedApi.RegisterMenu("fun", "resize",
Localizer?["fun_menu_resize"] ?? "Resize Player",
CreateSetResizeMenu, "@css/slay");
CreateSetResizeMenu, "@css/slay", "css_resize");
_menusRegistered = true;
Logger.LogInformation("Fun menus registered successfully!");

View File

@@ -7,6 +7,26 @@ namespace CS2_SimpleAdmin_FunCommands;
/// <summary>
/// Menu creation methods for Fun Commands module.
/// This file demonstrates different menu patterns using SimpleAdmin API.
///
/// PERMISSION OVERRIDE SUPPORT:
/// ============================
/// When registering menus in RegisterFunMenus(), you can pass a command name (e.g., "css_god")
/// as the last parameter. This enables automatic permission override checking via CounterStrikeSharp's
/// admin system.
///
/// How it works:
/// 1. Server admin overrides a command's permissions (e.g., css_god requires @css/vip instead of @css/cheats)
/// 2. SimpleAdmin's menu system automatically checks for overrides when displaying menus
/// 3. If override exists, it uses the overridden permission; otherwise, uses the default permission
///
/// Example from RegisterFunMenus():
/// _sharedApi.RegisterMenu("fun", "god",
/// Localizer?["fun_menu_god"] ?? "God Mode",
/// CreateGodModeMenu,
/// "@css/cheats", // Default permission
/// "css_god"); // Command name for override checking
///
/// This means developers don't need to manually check permissions in their menu factory methods!
/// </summary>
public partial class CS2_SimpleAdmin_FunCommands
{