Difference between revisions of "Checking Admin Flags (SourceMod Scripting)"

From AlliedModders Wiki
Jump to: navigation, search
(Fixed the argument list for CheckCommandAccess)
m (The last fallback: GetAdminFlag / GetUserFlagBits: Update highlighting)
 
(One intermediate revision by the same user not shown)
Line 107: Line 107:
 
To make a command have the same override as earlier, it would look like this:
 
To make a command have the same override as earlier, it would look like this:
  
<pawn>if (CheckCommandAccess(client, "mycommand", ADMFLAG_GENERIC))
+
<sourcepawn>if (CheckCommandAccess(client, "mycommand", ADMFLAG_GENERIC))
 
{
 
{
 
     // They have the "mycommand" override or the generic admin flag if no override exists
 
     // They have the "mycommand" override or the generic admin flag if no override exists
 
}
 
}
</pawn>
+
</sourcepawn>
  
 
[https://sm.alliedmods.net/new-api/console/CheckAccess CheckAccess] is a variation of this command if you have an AdminId from an admin lookup already.
 
[https://sm.alliedmods.net/new-api/console/CheckAccess CheckAccess] is a variation of this command if you have an AdminId from an admin lookup already.
Line 129: Line 129:
 
For example, if you want to check if a user has both the Generic and Kick flags, you can do so like this:
 
For example, if you want to check if a user has both the Generic and Kick flags, you can do so like this:
  
<pawn>if (GetUserFlagBits(client) & (ADMFLAG_GENERIC | ADMFLAG_KICK) == (ADMFLAG_GENERIC | ADMFLAG_KICK))
+
<sourcepawn>if (GetUserFlagBits(client) & (ADMFLAG_GENERIC | ADMFLAG_KICK) == (ADMFLAG_GENERIC | ADMFLAG_KICK))
 
{
 
{
 
     // User has both flags
 
     // User has both flags
}</pawn>
+
}</sourcepawn>
  
 
If you're reading flags from a string somewhere, such as from a convar (which is a terrible idea, you should go back up and read the [[#Checking inside an existing command: CheckCommandAccess|CheckCommandAccess]] section above), you can use the [https://sm.alliedmods.net/new-api/admin/ReadFlagString ReadFlagString] section command to turn a string into a set of flag bits, which you can use in place of the flags in the previous section, such as this:
 
If you're reading flags from a string somewhere, such as from a convar (which is a terrible idea, you should go back up and read the [[#Checking inside an existing command: CheckCommandAccess|CheckCommandAccess]] section above), you can use the [https://sm.alliedmods.net/new-api/admin/ReadFlagString ReadFlagString] section command to turn a string into a set of flag bits, which you can use in place of the flags in the previous section, such as this:
  
<pawn>int flags = ReadFlagString(myflags);
+
<sourcepawn>int flags = ReadFlagString(myflags);
 
if (GetUserFlagBits(client) & flags == flags)
 
if (GetUserFlagBits(client) & flags == flags)
 
{
 
{
 
     // User has all the flags in the myflags string.
 
     // User has all the flags in the myflags string.
}</pawn>
+
}</sourcepawn>

Latest revision as of 18:19, 29 March 2020

Admin flags control which users can use particular commands.

They also interact with the Overrides system.

There are multiple different ways to check flags. The major ones are documented below.

List of Admin Flag Bits

Most of the admin related functions in SourceMod use a bitmask of admin flag bits. As such, here is the list of constants located in admin.inc that you can use.

Note: Do not include this list of defines in your own code, just the ADMFLAG_WHATEVER name.

/**
 * @section Bitwise values definitions for admin flags.
 */
#define ADMFLAG_RESERVATION			(1<<0)		/**< Convenience macro for Admin_Reservation as a FlagBit */
#define ADMFLAG_GENERIC				(1<<1)		/**< Convenience macro for Admin_Generic as a FlagBit */
#define ADMFLAG_KICK				(1<<2)		/**< Convenience macro for Admin_Kick as a FlagBit */
#define ADMFLAG_BAN					(1<<3)		/**< Convenience macro for Admin_Ban as a FlagBit */
#define ADMFLAG_UNBAN				(1<<4)		/**< Convenience macro for Admin_Unban as a FlagBit */
#define ADMFLAG_SLAY				(1<<5)		/**< Convenience macro for Admin_Slay as a FlagBit */
#define ADMFLAG_CHANGEMAP			(1<<6)		/**< Convenience macro for Admin_Changemap as a FlagBit */
#define ADMFLAG_CONVARS				(1<<7)		/**< Convenience macro for Admin_Convars as a FlagBit */
#define ADMFLAG_CONFIG				(1<<8)		/**< Convenience macro for Admin_Config as a FlagBit */
#define ADMFLAG_CHAT				(1<<9)		/**< Convenience macro for Admin_Chat as a FlagBit */
#define ADMFLAG_VOTE				(1<<10)		/**< Convenience macro for Admin_Vote as a FlagBit */
#define ADMFLAG_PASSWORD			(1<<11)		/**< Convenience macro for Admin_Password as a FlagBit */
#define ADMFLAG_RCON				(1<<12)		/**< Convenience macro for Admin_RCON as a FlagBit */
#define ADMFLAG_CHEATS				(1<<13)		/**< Convenience macro for Admin_Cheats as a FlagBit */
#define ADMFLAG_ROOT				(1<<14)		/**< Convenience macro for Admin_Root as a FlagBit */
#define ADMFLAG_CUSTOM1				(1<<15)		/**< Convenience macro for Admin_Custom1 as a FlagBit */
#define ADMFLAG_CUSTOM2				(1<<16)		/**< Convenience macro for Admin_Custom2 as a FlagBit */
#define ADMFLAG_CUSTOM3				(1<<17)		/**< Convenience macro for Admin_Custom3 as a FlagBit */
#define ADMFLAG_CUSTOM4				(1<<18)		/**< Convenience macro for Admin_Custom4 as a FlagBit */
#define ADMFLAG_CUSTOM5				(1<<19)		/**< Convenience macro for Admin_Custom5 as a FlagBit */
#define ADMFLAG_CUSTOM6				(1<<20)		/**< Convenience macro for Admin_Custom6 as a FlagBit */

Since these are just bits, you can combine them to make a command require more than one admin flag:

ADMFLAG_GENERIC | ADMFLAG_KICK

Creating Admin Commands instead of Commands

The simplest form of flag checking is to create an admin command instead of a normal command.

The standard syntax for creating a command looks something like this:

RegConsoleCmd("mycommand", Cmd_MyCommand, "This is my great command");

If you want to restrict this to admin users only, first you need to select an admin flag from the above list.

Now, change the RegConsoleCmd to a RegAdminCmd and add the required flag(s) as the third argument:

RegAdminCmd("mycommand", Cmd_MyCommand, ADMFLAG_GENERIC, "This is my great command");

Now you have a command that requires the generic admin flag!

Command and Group Overrides

Any normal or admin command can have a command override placed on it using either Command Overrides or Group Overrides.

Command Overrides

Command overrides are used to change the admin flag that a command checks. For example, to override the admin command created in one of the previous sections, I could open addons/sourcemod/configs/admin_overrides.cfg and put this somewhere before the last bracket:

"mycommand"   "a"

"a" can be any of the admin flags SourceMod uses. "a" itself is Reserved slot access.

If a command is part of a Command Group, you can override the entire command group by putting the command group name with a @ before it. Only admin commands can have a command group.

"@mycommandgroup"      "a"

Admin Group Overrides

Admin Group overrides are a bit different than Command overrides. First, they only apply to admin groups.

Second, they are listed as "allow" or "deny".

For example, if I wanted to make it so that the "badgroup" cannot use "mycommand", I would do this in admin/sourcemod/configs/admin_groups.cfg:

    "badgroup"
    {
        Overrides
        {
            "mycommand"    "deny"
        }
    }

and then I would assign users to this group.

Checking inside an existing command: CheckCommandAccess

Sometimes, you may want to treat a command differently if a user has a specific flag. This may even be something you enable and disable using a cvar.

The best way to do this is the CheckCommandAccess command.

CheckCommandAccess takes four arguments.

  1. The client index who you want to check.
  2. The name of the override that this command should use. It can either be a new override or an existing override or command name.
  3. The default admin flag(s) that you want to use for this. This flag(s) are used when no overrides are present.
  4. (Optional) A boolean that tells SourceMod whether it should look for a command with the override's name (false) or if it should just look for the override in the overrides table (true). Default is false.

CheckCommandAccess returns true if the client has the appropriate permissions or false if they do not.

To make a command have the same override as earlier, it would look like this:

if (CheckCommandAccess(client, "mycommand", ADMFLAG_GENERIC))
{
    // They have the "mycommand" override or the generic admin flag if no override exists
}

CheckAccess is a variation of this command if you have an AdminId from an admin lookup already.

The last fallback: GetAdminFlag / GetUserFlagBits

These two commands are the brute force method and should only be used as a last resort. You should always use CheckCommandAccess in preference to this.

These commands do not participate in the overrides system.

In order to use GetAdminFlag, you need to first get a client's AdminId. This is done using the GetUserAdmin command. This will return an AdminId or the value INVALID_ADMIN_ID if the user is not an admin.

Then, you can use GetAdminFlag to see if a user has a particular AdminFlag. Note: This uses the AdminFlag enum instead of the Admin flag bits shown earlier.

If you need to check for the existence of multiple flags, you can use GetUserFlagBits instead. GetUserFlagBits takes a client index and will return a value that contains all the flags that a user has.

For example, if you want to check if a user has both the Generic and Kick flags, you can do so like this:

if (GetUserFlagBits(client) & (ADMFLAG_GENERIC | ADMFLAG_KICK) == (ADMFLAG_GENERIC | ADMFLAG_KICK))
{
    // User has both flags
}

If you're reading flags from a string somewhere, such as from a convar (which is a terrible idea, you should go back up and read the CheckCommandAccess section above), you can use the ReadFlagString section command to turn a string into a set of flag bits, which you can use in place of the flags in the previous section, such as this:

int flags = ReadFlagString(myflags);
if (GetUserFlagBits(client) & flags == flags)
{
    // User has all the flags in the myflags string.
}