diff --git a/configs/admins.cfg b/configs/admins.cfg index 4b7fa1b9..856df670 100644 --- a/configs/admins.cfg +++ b/configs/admins.cfg @@ -11,11 +11,14 @@ * "name" - Name based authentication * "ip" - IP based authentication * Anything else is treated as custom. + * Note: Only one auth method is allowed per entry. * * "identity" - REQUIRED - Identification string, for example, a steamid or name. - * "password" - Optional password to use. - * "group" - Inherits a set of group permissions. - * "flags" - Adds a set of flags. + * Note: Only one identity is allowed per entry. + * + * "password" - Optional password to require. + * "group" - Adds one group to the user's group table. + * "flags" - Adds one or more flags to the user's permissions. * * Example: "BAILOPAN" diff --git a/core/AdminCache.cpp b/core/AdminCache.cpp new file mode 100644 index 00000000..82adfafd --- /dev/null +++ b/core/AdminCache.cpp @@ -0,0 +1,568 @@ +#include +#include +#include "AdminCache.h" +#include "ShareSys.h" + +AdminCache g_Admins; + +AdminCache::AdminCache() +{ + m_pCmdOverrides = NULL; + m_pCmdGrpOverrides = NULL; + m_pStrings = new BaseStringTable(1024); + m_pMemory = m_pStrings->GetMemTable(); + m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; + m_pGroups = sm_trie_create(); +} + +AdminCache::~AdminCache() +{ + if (m_pCmdGrpOverrides) + { + sm_trie_destroy(m_pCmdGrpOverrides); + } + + if (m_pCmdOverrides) + { + sm_trie_destroy(m_pCmdOverrides); + } + + InvalidateGroupCache(); + + if (m_pGroups) + { + sm_trie_destroy(m_pGroups); + } + + delete m_pStrings; +} + +void AdminCache::OnSourceModAllInitialized() +{ + g_ShareSys.AddInterface(NULL, this); +} + +void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag) +{ + if (type == Override_Command) + { + _AddCommandOverride(cmd, flag); + } else if (type == Override_CommandGroup) { + _AddCommandGroupOverride(cmd, flag); + } +} + +bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag) +{ + if (type == Override_Command) + { + return _GetCommandOverride(cmd, pFlag); + } else if (type == Override_CommandGroup) { + return _GetCommandGroupOverride(cmd, pFlag); + } + + return false; +} + +void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type) +{ + if (type == Override_Command) + { + return _UnsetCommandOverride(cmd); + } else if (type == Override_CommandGroup) { + return _UnsetCommandGroupOverride(cmd); + } +} + +void AdminCache::_AddCommandGroupOverride(const char *group, AdminFlag flag) +{ + if (!m_pCmdGrpOverrides) + { + m_pCmdGrpOverrides = sm_trie_create(); + } + + /* :TODO: Notify command system */ + + sm_trie_insert(m_pCmdGrpOverrides, group, (void *)flag); +} + +void AdminCache::_AddCommandOverride(const char *cmd, AdminFlag flag) +{ + if (!m_pCmdOverrides) + { + m_pCmdOverrides = sm_trie_create(); + } + + /* :TODO: Notify command system */ + + sm_trie_insert(m_pCmdOverrides, cmd, (void *)flag); +} + +bool AdminCache::_GetCommandGroupOverride(const char *cmd, AdminFlag *pFlag) +{ + if (!m_pCmdGrpOverrides) + { + return false; + } + + if (!pFlag) + { + return sm_trie_retrieve(m_pCmdGrpOverrides, cmd, NULL); + } else { + void *object; + bool ret; + if (ret=sm_trie_retrieve(m_pCmdGrpOverrides, cmd, &object)) + { + *pFlag = (AdminFlag)(int)object; + } + return ret; + } +} + +bool AdminCache::_GetCommandOverride(const char *cmd, AdminFlag *pFlag) +{ + if (!m_pCmdOverrides) + { + return false; + } + + if (!pFlag) + { + return sm_trie_retrieve(m_pCmdOverrides, cmd, NULL); + } else { + void *object; + bool ret; + if (ret=sm_trie_retrieve(m_pCmdOverrides, cmd, &object)) + { + *pFlag = (AdminFlag)(int)object; + } + return ret; + } +} + +void AdminCache::_UnsetCommandGroupOverride(const char *group) +{ + if (!m_pCmdGrpOverrides) + { + return; + } + + /* :TODO: Notify command system */ + + sm_trie_delete(m_pCmdGrpOverrides, group); +} + +void AdminCache::_UnsetCommandOverride(const char *cmd) +{ + if (!m_pCmdOverrides) + { + return; + } + + /* :TODO: Notify command system */ + + sm_trie_delete(m_pCmdOverrides, cmd); +} + +void AdminCache::DumpCommandOverrideCache(OverrideType type) +{ + if (type == Override_Command && m_pCmdOverrides) + { + sm_trie_clear(m_pCmdOverrides); + } else if (type == Override_CommandGroup && m_pCmdGrpOverrides) { + sm_trie_clear(m_pCmdGrpOverrides); + } +} + +GroupId AdminCache::AddGroup(const char *group_name) +{ + if (sm_trie_retrieve(m_pGroups, group_name, NULL)) + { + return INVALID_GROUP_ID; + } + + GroupId id; + AdminGroup *pGroup; + if (m_FreeGroupList != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(m_FreeGroupList); + assert(pGroup->magic == GRP_MAGIC_UNSET); + id = m_FreeGroupList; + m_FreeGroupList = pGroup->next_grp; + } else { + id = m_pMemory->CreateMem(sizeof(AdminGroup), (void **)&pGroup); + } + + pGroup->immune_default = false; + pGroup->immune_global = false; + pGroup->immune_table = -1; + pGroup->magic = GRP_MAGIC_SET; + pGroup->next_grp = INVALID_GROUP_ID; + pGroup->pCmdGrpTable = NULL; + pGroup->pCmdTable = NULL; + pGroup->nameidx = m_pStrings->AddString(group_name); + memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL); + + if (m_FirstGroup == INVALID_GROUP_ID) + { + m_FirstGroup = id; + m_LastGroup = id; + pGroup->prev_grp = INVALID_GROUP_ID; + } else { + AdminGroup *pPrev = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + assert(pPrev->magic == GRP_MAGIC_SET); + pPrev->next_grp = id; + pGroup->prev_grp = m_LastGroup; + m_LastGroup = id; + } + + sm_trie_insert(m_pGroups, group_name, (void *)id); + + return id; +} + +GroupId AdminCache::FindGroupByName(const char *group_name) +{ + void *object; + + if (!sm_trie_retrieve(m_pGroups, group_name, &object)) + { + return INVALID_GROUP_ID; + } + + GroupId id = (GroupId)object; + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return INVALID_GROUP_ID; + } + + return id; +} + +void AdminCache::SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + if (flag < Admin_None || flag >= AdminFlags_TOTAL) + { + return; + } + + pGroup->addflags[flag] = enabled; +} + +bool AdminCache::GetGroupAddFlag(GroupId id, AdminFlag flag) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (flag < Admin_None || flag >= AdminFlags_TOTAL) + { + return false; + } + + return pGroup->addflags[flag]; +} + +unsigned int AdminCache::GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + unsigned int r = 0; + + for (unsigned int i = Admin_None + 1; + i < AdminFlags_TOTAL && r < total; + i++) + { + if (pGroup->addflags[i]) + { + flags[r++] = (AdminFlag)i; + } + } + + return r; +} + +void AdminCache::SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + if (type == Immunity_Default) + { + pGroup->immune_default = enabled; + } else if (type == Immunity_Global) { + pGroup->immune_global = enabled; + } +} + +bool AdminCache::GetGroupGenericImmunity(GroupId id, ImmunityType type) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + if (type == Immunity_Default) + { + return pGroup->immune_default; + } else if (type == Immunity_Global) { + return pGroup->immune_global; + } + + return false; +} + +void AdminCache::AddGroupImmunity(GroupId id, GroupId other_id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + AdminGroup *pOther = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pOther || pOther->magic != GRP_MAGIC_SET) + { + return; + } + + /* We always need to resize the immunity table */ + int *table, tblidx; + if (pOther->immune_table == -1) + { + tblidx = m_pMemory->CreateMem(sizeof(int) * 2, (void **)&table); + table[0] = 0; + } else { + int *old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); + tblidx = m_pMemory->CreateMem(sizeof(int) * (old_table[0] + 2), (void **)&table); + /* Get the old address again in caes of resize */ + old_table = (int *)m_pMemory->GetAddress(pOther->immune_table); + table[0] = old_table[0]; + for (unsigned int i=1; i<=(unsigned int)old_table[0]; i++) + { + table[i] = old_table[i]; + } + } + + /* Assign */ + pOther->immune_table = tblidx; + + /* Add to the array */ + table[0]++; + table[table[0]] = other_id; +} + +unsigned int AdminCache::GetGroupImmunityCount(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return 0; + } + + if (pGroup->immune_table == -1) + { + return 0; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + + return table[0]; +} + +GroupId AdminCache::GetGroupImmunity(GroupId id, unsigned int number) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return INVALID_GROUP_ID; + } + + if (pGroup->immune_table == -1) + { + return INVALID_GROUP_ID; + } + + int *table = (int *)m_pMemory->GetAddress(pGroup->immune_table); + if (number >= (unsigned int)table[0]) + { + return INVALID_GROUP_ID; + } + + return table[1 + number]; +} + +void AdminCache::AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + Trie *pTrie = NULL; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + { + pGroup->pCmdTable = sm_trie_create(); + } + pTrie = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + { + pGroup->pCmdGrpTable = sm_trie_create(); + } + pTrie = pGroup->pCmdGrpTable; + } else { + return; + } + + sm_trie_insert(pTrie, name, (void *)(int)rule); +} + +bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return false; + } + + Trie *pTrie = NULL; + if (type == Override_Command) + { + if (pGroup->pCmdTable == NULL) + { + return false; + } + pTrie = pGroup->pCmdTable; + } else if (type == Override_CommandGroup) { + if (pGroup->pCmdGrpTable == NULL) + { + return false; + } + pTrie = pGroup->pCmdGrpTable; + } else { + return false; + } + + void *object; + if (!sm_trie_retrieve(pTrie, name, &object)) + { + return false; + } + + if (pRule) + { + *pRule = (OverrideRule)(int)object; + } + + return true; +} + +void AdminCache::InvalidateGroup(GroupId id) +{ + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); + AdminGroup *pOther; + + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return; + } + + const char *str = m_pStrings->GetString(pGroup->nameidx); + sm_trie_delete(m_pGroups, str); + + /* Unlink from the live dbllink list */ + if (id == m_FirstGroup && id == m_LastGroup) + { + m_LastGroup = INVALID_GROUP_ID; + m_FirstGroup = INVALID_GROUP_ID; + } else if (id == m_FirstGroup) { + m_FirstGroup = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_FirstGroup); + pOther->prev_grp = INVALID_GROUP_ID; + } else if (id == m_LastGroup) { + m_LastGroup = pGroup->prev_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(m_LastGroup); + pOther->next_grp = INVALID_GROUP_ID; + } else { + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->prev_grp); + pOther->next_grp = pGroup->next_grp; + pOther = (AdminGroup *)m_pMemory->GetAddress(pGroup->next_grp); + pOther->prev_grp = pGroup->prev_grp; + } + + /* Free any used memory to be safe */ + if (pGroup->pCmdGrpTable) + { + sm_trie_destroy(pGroup->pCmdGrpTable); + pGroup->pCmdGrpTable = NULL; + } + if (pGroup->pCmdTable) + { + sm_trie_destroy(pGroup->pCmdTable); + pGroup->pCmdTable = NULL; + } + + /* Link into the free list */ + pGroup->magic = GRP_MAGIC_UNSET; + pGroup->next_grp = m_FreeGroupList; + m_FreeGroupList = id; + + /* :TODO: remove this group from any users */ +} + +void AdminCache::InvalidateGroupCache() +{ + /* Nuke the free list */ + m_FreeGroupList = -1; + + /* Nuke reverse lookups */ + sm_trie_clear(m_pGroups); + + /* Free memory on groups */ + GroupId cur = m_FirstGroup; + AdminGroup *pGroup; + while (cur != INVALID_GROUP_ID) + { + pGroup = (AdminGroup *)m_pMemory->GetAddress(cur); + assert(pGroup->magic == GRP_MAGIC_SET); + if (pGroup->pCmdGrpTable) + { + sm_trie_destroy(pGroup->pCmdGrpTable); + } + if (pGroup->pCmdTable) + { + sm_trie_destroy(pGroup->pCmdTable); + } + cur = pGroup->next_grp; + } + + m_FirstGroup = INVALID_GROUP_ID; + m_LastGroup = INVALID_GROUP_ID; + + /* :TODO: dump the admin cache */ + + /* Reset the memory table */ + m_pMemory->Reset(); +} diff --git a/core/AdminCache.h b/core/AdminCache.h new file mode 100644 index 00000000..b551d6e2 --- /dev/null +++ b/core/AdminCache.h @@ -0,0 +1,80 @@ +#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_ +#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ + +#include "sm_memtable.h" +#include +#include +#include "sm_globals.h" + +#define GRP_MAGIC_SET 0xDEADFADE +#define GRP_MAGIC_UNSET 0xFACEFACE + +struct AdminGroup +{ + uint32_t magic; /* Magic flag, for memory validation (ugh) */ + bool immune_global; /* Global immunity? */ + bool immune_default; /* Default immunity? */ + /* Immune from target table (-1 = nonexistant) + * [0] = number of entries + * [1...N] = immune targets + */ + int immune_table; + Trie *pCmdTable; /* Command override table (can be NULL) */ + Trie *pCmdGrpTable; /* Command group override table (can be NULL) */ + int next_grp; /* Next group in the chain */ + int prev_grp; /* Previous group in the chain */ + int nameidx; /* Name */ + bool addflags[AdminFlags_TOTAL]; /* Additive flags */ +}; + +class AdminCache : + public IAdminSystem, + public SMGlobalClass +{ +public: + AdminCache(); + ~AdminCache(); +public: //SMGlobalClass + void OnSourceModAllInitialized(); +public: //IAdminSystem + /** Command cache stuff */ + void AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag); + bool GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag); + void UnsetCommandOverride(const char *cmd, OverrideType type); + void DumpCommandOverrideCache(OverrideType type); + /** Group cache stuff */ + GroupId AddGroup(const char *group_name); + GroupId FindGroupByName(const char *group_name); + void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled); + bool GetGroupAddFlag(GroupId id, AdminFlag flag); + unsigned int GetGroupAddFlags(GroupId Id, AdminFlag flags[], unsigned int total); + void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled); + bool GetGroupGenericImmunity(GroupId id, ImmunityType type); + void InvalidateGroup(GroupId id); + void InvalidateGroupCache(); + void AddGroupImmunity(GroupId id, GroupId other_id); + unsigned int GetGroupImmunityCount(GroupId id); + GroupId GetGroupImmunity(GroupId id, unsigned int number); + void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule); + bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule); +private: + void _AddCommandOverride(const char *cmd, AdminFlag flag); + void _AddCommandGroupOverride(const char *group, AdminFlag flag); + bool _GetCommandOverride(const char *cmd, AdminFlag *pFlag); + bool _GetCommandGroupOverride(const char *group, AdminFlag *pFlag); + void _UnsetCommandOverride(const char *cmd); + void _UnsetCommandGroupOverride(const char *group); +public: + BaseStringTable *m_pStrings; + BaseMemTable *m_pMemory; + Trie *m_pCmdOverrides; + Trie *m_pCmdGrpOverrides; + int m_FirstGroup; + int m_LastGroup; + int m_FreeGroupList; + Trie *m_pGroups; +}; + +extern AdminCache g_Admins; + +#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_ diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index a1f60a33..dd3ee7a3 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -179,6 +179,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -257,6 +261,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -325,6 +333,10 @@ + + diff --git a/core/sm_trie.cpp b/core/sm_trie.cpp index c450d079..eaad3485 100644 --- a/core/sm_trie.cpp +++ b/core/sm_trie.cpp @@ -246,19 +246,25 @@ Trie *sm_trie_create() t->stringtab = (char *)malloc(sizeof(char) * 256); t->baseSize = 256; t->stSize = 256; - t->tail = 0; - memset(t->base, 0, sizeof(TrieNode) * (256 + 1)); - memset(t->stringtab, 0, sizeof(char) * 256); - - /* Sentinel root node */ - t->base[1].idx = 1; - t->base[1].mode = Node_Arc; - t->base[1].parent = 1; + sm_trie_clear(t); return t; } +void sm_trie_clear(Trie *trie) +{ + trie->tail = 0; + + memset(trie->base, 0, sizeof(TrieNode) * (trie->baseSize + 1)); + memset(trie->stringtab, 0, sizeof(char) * trie->stSize); + + /* Sentinel root node */ + trie->base[1].idx = 1; + trie->base[1].mode = Node_Arc; + trie->base[1].parent = 1; +} + void sm_trie_destroy(Trie *trie) { free(trie->base); diff --git a/core/sm_trie.h b/core/sm_trie.h index a6e0c0fe..9c008081 100644 --- a/core/sm_trie.h +++ b/core/sm_trie.h @@ -8,5 +8,6 @@ void sm_trie_destroy(Trie *trie); bool sm_trie_insert(Trie *trie, const char *key, void *value); bool sm_trie_retrieve(Trie *trie, const char *key, void **value); bool sm_trie_delete(Trie *trie, const char *key); +void sm_trie_clear(Trie *trie); #endif //_INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ diff --git a/public/IAdminSystem.h b/public/IAdminSystem.h new file mode 100644 index 00000000..b1a43f7e --- /dev/null +++ b/public/IAdminSystem.h @@ -0,0 +1,254 @@ +#ifndef _INCLUDE_SOURCEMOD_ADMINISTRATION_SYSTEM_H_ +#define _INCLUDE_SOURCEMOD_ADMINISTRATION_SYSTEM_H_ + +#include + +#define SMINTERFACE_ADMINSYS_NAME "IAdminSys" +#define SMINTERFACE_ADMINSYS_VERSION 1 + +/** + * Detailed notes: + * --------------- + * The administration system is more of a volatile cache than a system. It is designed to be + * temporary rather than permanent, in order to compensate for more storage methods. For example, + * a flat file might be read into the cache all at once. But a MySQL-based system might only cache + * admin permissions when that specific admin connects. + * + * The override cache is the simplest to explain. Any time an override is added, any existing + * and all future commands will gain a new access level set by the override. If unset, the default + * access level is restored. This cache is dynamically changeable. + * + * The group cache contains, for each group: + * 1] A set of inherent flags - fully readable/writable. + * 2] An immunity table - insertion and retrieval only. + * 3] An override table - insertion and retrieval only. + * Individual groups can be invalidated entirely. It should be considered an expensive + * operation, since each admin needs to be patched up to not reference the group. + */ + +namespace SourceMod +{ + enum AdminFlag + { + Admin_None = 0, + Admin_Reservation, /* Reserved slot */ + Admin_Kick, /* Kick another user */ + Admin_Ban, /* Ban another user */ + Admin_Unban, /* Unban another user */ + Admin_Slay, /* Slay/kill/damage another user */ + Admin_Changemap, /* Change the map */ + Admin_Convars, /* Change basic convars */ + Admin_Configs, /* Change configs */ + Admin_Chat, /* Special chat privileges */ + Admin_Vote, /* Special vote privileges */ + Admin_Password, /* Set a server password */ + Admin_RCON, /* Use RCON */ + Admin_Cheats, /* Change sv_cheats and use its commands */ + /* --- */ + AdminFlags_TOTAL, + }; + + enum OverrideType + { + Override_Command = 1, /* Command */ + Override_CommandGroup, /* Command group */ + }; + + enum OverrideRule + { + Command_Deny = 0, + Command_Allow = 1, + }; + + enum ImmunityType + { + Immunity_Default = 1, /* Immune from everyone with no immunity */ + Immunity_Global, /* Immune from everyone (except root admins) */ + }; + + typedef int GroupId; + + #define INVALID_GROUP_ID -1 + + /** + * @brief This is the administration options cache. + */ + class IAdminSystem : public SMInterface + { + public: + const char *GetInterfaceName() + { + return SMINTERFACE_ADMINSYS_NAME; + } + unsigned int GetInterfaceVersion() + { + return SMINTERFACE_ADMINSYS_VERSION; + } + public: + /** + * @brief Adds a global command flag override. Any command registered with this name + * will assume the new flag. This is applied retroactively as well. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param flag New admin flag. + */ + virtual void AddCommandOverride(const char *cmd, OverrideType type, AdminFlag flag) =0; + + /** + * @brief Returns a command override. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param pFlag Optional pointer to the set flag. + * @return True if there is an override, false otherwise. + */ + virtual bool GetCommandOverride(const char *cmd, OverrideType type, AdminFlag *pFlag) =0; + + /** + * @brief Unsets a command override. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + */ + virtual void UnsetCommandOverride(const char *cmd, OverrideType type) =0; + + /** + * @brief Dumps the global command override cache (unset all). + * + * @param type Override type (specific command or group). + */ + virtual void DumpCommandOverrideCache(OverrideType type) =0; + + /** + * @brief Adds a new group. Name must be unique. + * + * @param group_name String containing the group name. + * @return A new group id, INVALID_GROUP_ID if it already exists. + */ + virtual GroupId AddGroup(const char *group_name) =0; + + /** + * @brief Finds a group by name. + * + * @param group_name String containing the group name. + * @return A group id, or INVALID_GROUP_ID if not found. + */ + virtual GroupId FindGroupByName(const char *group_name) =0; + + /** + * @brief Adds or removes a flag from a group's flag set. + * Note: These are called "add flags" because they add to a user's flags. + * + * @param id Group id. + * @param flag Admin flag to toggle. + * @param enabled True to set the flag, false to unset/disable. + */ + virtual void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled) =0; + + /** + * @brief Gets the set value of an add flag on a group's flag set. + * + * @param id Group id. + * @param flag Admin flag to retrieve. + * @return True if enabled, false otherwise, + */ + virtual bool GetGroupAddFlag(GroupId id, AdminFlag flag) =0; + + /** + * @brief Returns the flag set that is added to a user from their group. + * Note: These are called "add flags" because they add to a user's flags. + * + * @param id GroupId of the group. + * @param flags Array to store flags in. + * @param total Total number of flags that can be stored in the array. + * @return Number of flags that were written to the array. + */ + virtual unsigned int GetGroupAddFlags(GroupId id, AdminFlag flags[], unsigned int total) =0; + + /** + * @brief Toggles a generic immunity type. + * + * @param id Group id. + * @param type Generic immunity type. + * @param enabled True to enable, false otherwise. + */ + virtual void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled) =0; + + /** + * @brief Returns whether or not a group has global immunity. + * + * @param id Group id. + * @param type Generic immunity type. + * @return True if the group has this immunity, false otherwise. + */ + virtual bool GetGroupGenericImmunity(GroupId id, ImmunityType type) =0; + + /** + * @brief Adds immunity to a specific group. + * + * @param id Group id. + * @param other_id Group id to receive immunity to. + */ + virtual void AddGroupImmunity(GroupId id, GroupId other_id) =0; + + /** + * @brief Returns the number of specific group immunities. + * + * @param id Group id. + * @return Number of group immunities. + */ + virtual unsigned int GetGroupImmunityCount(GroupId id) =0; + + /** + * @brief Returns a group that this group is immune to given an index. + * + * @param id Group id. + * @param number Index from 0 to N-1, from GetGroupImmunities(). + * @return GroupId that this group is immune to. + */ + virtual GroupId GetGroupImmunity(GroupId id, unsigned int number) =0; + + /** + * @brief Adds a group-specific override type. + * + * @param id Group id. + * @param name String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param rule Override allow/deny setting. + */ + virtual void AddGroupCommandOverride(GroupId id, + const char *name, + OverrideType type, + OverrideRule rule) =0; + + /** + * @brief Retrieves a group-specific command override. + * + * @param id Group id. + * @param name String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param rule Optional pointer to store allow/deny setting. + * @return True if an override exists, false otherwise. + */ + virtual bool GetGroupCommandOverride(GroupId id, + const char *name, + OverrideType type, + OverrideRule *pRule) =0; + + /** + * @brief Invalidates and removes a group from the group cache. + * + * @param id Group id. + */ + virtual void InvalidateGroup(GroupId id) =0; + + /** + * @brief Invalidates the entire group cache. WARNING: This will trigger + * an admin cache dump as well! + */ + virtual void InvalidateGroupCache() =0; + }; +}; + +#endif //_INCLUDE_SOURCEMOD_ADMINISTRATION_SYSTEM_H_ diff --git a/public/IExtensionSys.h b/public/IExtensionSys.h index c96ba405..b5531dd0 100644 --- a/public/IExtensionSys.h +++ b/public/IExtensionSys.h @@ -194,7 +194,7 @@ namespace SourceMod * @brief Loads a extension into the extension system. * * @param path Path to extension file, relative to the extensions folder. - * @param lifetime Lifetime of the extension. + * @param lifetime Lifetime of the extension (currently ignored). * @param error Error buffer. * @param err_max Maximum error buffer length. * @return New IExtension on success, NULL on failure. diff --git a/public/IHandleSys.h b/public/IHandleSys.h index ea5b6958..ba56bb43 100644 --- a/public/IHandleSys.h +++ b/public/IHandleSys.h @@ -242,7 +242,7 @@ namespace SourceMod * * @param pTypeAccess Optional TypeAccess buffer to initialize with the default values. * @param pHandleAccess Optional HandleAccess buffer to initialize with the default values. - * @return True on success, false if version is unsupported. + * @return True on success, false if version is unsupported. */ virtual bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess) =0; };