initial import of finished admin api

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40410
This commit is contained in:
David Anderson
2007-01-29 04:19:14 +00:00
parent 7a8d164b25
commit c66632776f
4 changed files with 657 additions and 11 deletions
+445 -11
View File
@@ -26,8 +26,10 @@ AdminCache::AdminCache()
m_pStrings = new BaseStringTable(1024);
m_pMemory = m_pStrings->GetMemTable();
m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID;
m_pGroups = sm_trie_create();
m_pCacheFwd = NULL;
m_FirstGroup = -1;
}
AdminCache::~AdminCache()
@@ -52,6 +54,13 @@ AdminCache::~AdminCache()
delete m_pStrings;
}
void AdminCache::OnSourceModStartup(bool late)
{
RegisterAuthIdentType("steam");
RegisterAuthIdentType("name");
RegisterAuthIdentType("ip");
}
void AdminCache::OnSourceModAllInitialized()
{
m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
@@ -196,6 +205,51 @@ void AdminCache::DumpCommandOverrideCache(OverrideType type)
}
}
AdminId AdminCache::CreateAdmin(const char *name)
{
AdminId id;
AdminUser *pUser;
if (m_FreeUserList != INVALID_ADMIN_ID)
{
pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
assert(pUser->magic == USR_MAGIC_UNSET);
id = m_FreeUserList;
m_FreeUserList = pUser->next_user;
} else {
id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
pUser->grp_size = 0;
pUser->grp_table = -1;
pUser->auth_size = 0;
pUser->auth_table = -1;
}
memset(pUser->flags, 0, sizeof(pUser->flags));
memset(pUser->eflags, 0, sizeof(pUser->flags));
pUser->grp_count = 0;
pUser->auth_count = 0;
pUser->password = -1;
pUser->magic = USR_MAGIC_SET;
if (m_FirstUser == INVALID_ADMIN_ID)
{
m_FirstUser = id;
m_LastUser = id;
} else {
AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
pPrev->next_user = id;
pUser->prev_user = m_LastUser;
m_LastUser = id;
}
if (name && name[0] != '\0')
{
pUser->nameidx = m_pStrings->AddString(name);
}
return id;
}
GroupId AdminCache::AddGroup(const char *group_name)
{
if (sm_trie_retrieve(m_pGroups, group_name, NULL))
@@ -222,7 +276,6 @@ GroupId AdminCache::AddGroup(const char *group_name)
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)
@@ -238,6 +291,8 @@ GroupId AdminCache::AddGroup(const char *group_name)
m_LastGroup = id;
}
pGroup->nameidx = m_pStrings->AddString(group_name);
sm_trie_insert(m_pGroups, group_name, (void *)id);
return id;
@@ -498,6 +553,80 @@ bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideT
return true;
}
Trie *AdminCache::GetMethodByIndex(unsigned int index)
{
List<AuthMethod>::iterator iter;
for (iter=m_AuthMethods.begin();
iter!=m_AuthMethods.end();
iter++)
{
if (index-- == 0)
{
return (*iter).table;
}
}
return NULL;
}
bool AdminCache::InvalidateAdmin(AdminId id)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
AdminUser *pOther;
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
/* Unlink from the dbl link list */
if (id == m_FirstUser && id == m_LastUser)
{
m_FirstUser = INVALID_ADMIN_ID;
m_LastUser = INVALID_ADMIN_ID;
} else if (id == m_FirstUser) {
m_FirstUser = pUser->next_user;
pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
pOther->prev_user = INVALID_ADMIN_ID;
} else if (id == m_LastUser) {
m_LastUser = pUser->prev_user;
pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
pOther->next_user = INVALID_ADMIN_ID;
} else {
pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
pOther->next_user = pUser->next_user;
pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
pOther->prev_user = pUser->prev_user;
}
/* Unlink from auth tables */
if (pUser->auth_count > 0)
{
UserAuth *pAuth = (UserAuth *)m_pMemory->GetAddress(pUser->auth_table);
Trie *pTrie;
for (unsigned int i=0; i<pUser->auth_count; i++)
{
pTrie = GetMethodByIndex(pAuth[i].index);
if (!pTrie)
{
continue;
}
sm_trie_delete(pTrie, m_pStrings->GetString(pAuth->identidx));
}
}
/* Clear table counts */
pUser->grp_count = 0;
pUser->auth_count = 0;
/* Link into free list */
pUser->magic = USR_MAGIC_UNSET;
pUser->next_user = m_FreeUserList;
m_FreeUserList = id;
return true;
}
void AdminCache::InvalidateGroup(GroupId id)
{
AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
@@ -548,7 +677,44 @@ void AdminCache::InvalidateGroup(GroupId id)
pGroup->next_grp = m_FreeGroupList;
m_FreeGroupList = id;
/* :TODO: remove this group from any users */
int idx = m_FirstUser;
AdminUser *pUser;
int *table;
while (idx != INVALID_ADMIN_ID)
{
pUser = (AdminUser *)m_pMemory->GetAddress(idx);
if (pUser->grp_count > 0)
{
table = (int *)m_pMemory->GetAddress(pUser->grp_table);
for (unsigned int i=0; i<pUser->grp_count; i++)
{
if (table[i] == id)
{
/* We have to remove this entry */
for (unsigned int j=i+1; j<pUser->grp_count; j++)
{
/* Move everything down by one */
table[j-1] = table[j];
}
/* Decrease count */
pUser->grp_count--;
/* Recalculate effective flags */
memset(pUser->eflags, 0, sizeof(pUser->eflags));
for (unsigned int j=0; j<pUser->grp_count; j++)
{
pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
for (unsigned int k=0; k<AdminFlags_TOTAL; k++)
{
pUser->eflags[k] = (pUser->flags[k] || pOther->addflags[k]);
}
}
/* Break now, duplicates aren't allowed */
break;
}
}
}
idx = pUser->next_user;
}
}
void AdminCache::InvalidateGroupCache()
@@ -580,7 +746,7 @@ void AdminCache::InvalidateGroupCache()
m_FirstGroup = INVALID_GROUP_ID;
m_LastGroup = INVALID_GROUP_ID;
/* :TODO: dump the admin cache */
InvalidateAdminCache(false);
/* Reset the memory table */
m_pMemory->Reset();
@@ -596,6 +762,41 @@ void AdminCache::RemoveAdminListener(IAdminListener *pListener)
m_hooks.remove(pListener);
}
void AdminCache::RegisterAuthIdentType(const char *name)
{
if (sm_trie_retrieve(m_pAuthTables, name, NULL))
{
return;
}
Trie *pAuth = sm_trie_create();
AuthMethod method;
method.name.assign(name);
method.table = pAuth;
m_AuthMethods.push_back(method);
sm_trie_insert(m_pAuthTables, name, pAuth);
}
void AdminCache::InvalidateAdminCache(bool unlink_admins)
{
/* Wipe the identity cache first */
List<AuthMethod>::iterator iter;
for (iter=m_AuthMethods.begin();
iter!=m_AuthMethods.end();
iter++)
{
sm_trie_clear((*iter).table);
}
while (m_FirstUser != INVALID_ADMIN_ID)
{
InvalidateAdmin(m_FirstUser);
}
}
void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
{
if (cache_flags & ADMIN_CACHE_OVERRIDES)
@@ -604,19 +805,19 @@ void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
DumpCommandOverrideCache(Override_CommandGroup);
}
if ((cache_flags & ADMIN_CACHE_ADMINS) ||
(cache_flags & ADMIN_CACHE_GROUPS))
{
/* Make sure the flag is set */
cache_flags |= ADMIN_CACHE_ADMINS;
/* :TODO: Dump admin cache */
}
/* This will auto-invalidate the admin cache */
if (cache_flags & ADMIN_CACHE_GROUPS)
{
InvalidateGroupCache();
}
/* If we only requested an admin rebuild, re-use the internal memory */
if ((cache_flags & ADMIN_CACHE_ADMINS) &&
!(cache_flags & ADMIN_CACHE_GROUPS))
{
InvalidateAdminCache(true);
}
if (rebuild)
{
List<IAdminListener *>::iterator iter;
@@ -631,3 +832,236 @@ void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
m_pCacheFwd->Execute(&result);
}
}
const char *AdminCache::GetAdminName(AdminId id)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return NULL;
}
return m_pStrings->GetString(pUser->nameidx);
}
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
Trie *pTable;
if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
{
return false;
}
if (sm_trie_retrieve(pTable, ident, NULL))
{
return false;
}
return sm_trie_insert(pTable, ident, (void **)id);
}
AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
{
Trie *pTable;
if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
{
return INVALID_ADMIN_ID;
}
void *object;
if (!sm_trie_retrieve(pTable, identity, &object))
{
return INVALID_ADMIN_ID;
}
return (AdminId)object;
}
void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return;
}
if (flag < Admin_None
|| flag >= AdminFlags_TOTAL)
{
return;
}
pUser->flags[enabled] = false;
}
bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
if (flag < Admin_None
|| flag >= AdminFlags_TOTAL)
{
return false;
}
if (mode == Access_Real)
{
return pUser->flags[flag];
} else if (mode == Access_Effective) {
return (pUser->flags[flag] || pUser->eflags[flag]);
}
return false;
}
unsigned int AdminCache::GetAdminFlags(AdminId id, bool flags[], unsigned int total, AccessMode mode)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return 0;
}
unsigned int i = 0;
if (mode == Access_Real)
{
for (i=0; i<AdminFlags_TOTAL && i<total; i++)
{
flags[i] = pUser->flags[i];
}
} else if (mode == Access_Effective) {
for (i=0; i<AdminFlags_TOTAL && i<total; i++)
{
flags[i] = (pUser->flags[i] || pUser->eflags[i]);
}
}
return i;
}
bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
if (!pGroup || pGroup->magic != USR_MAGIC_SET)
{
return false;
}
int *table;
if (pUser->grp_count + 1 > pUser->grp_size)
{
int new_size = 0;
int tblidx;
if (pUser->grp_size == 0)
{
new_size = 2;
} else {
new_size = pUser->grp_size * 2;
}
/* Create and refresh pointers */
tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
pUser = (AdminUser *)m_pMemory->GetAddress(id);
pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
/* Copy old data if necessary */
if (pUser->grp_table != -1)
{
int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
memcpy(table, old_table, sizeof(int) * pUser->grp_count);
}
pUser->grp_table = tblidx;
pUser->grp_size = new_size;
} else {
table = (int *)m_pMemory->GetAddress(pUser->grp_table);
}
for (unsigned int i=0; i<pUser->grp_count; i++)
{
if (table[i] == gid)
{
return false;
}
}
table[pUser->grp_count] = gid;
pUser->grp_count++;
/* Compute new effective flags */
for (unsigned int i=Admin_None;
i<AdminFlags_TOTAL;
i++)
{
/* Only inherit flags additive flags we don't have */
if (!pUser->eflags[i])
{
pUser->eflags[i] = pGroup->addflags[i];
}
}
return true;
}
unsigned int AdminCache::GetAdminGroupCount(AdminId id)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return 0;
}
return pUser->grp_count;
}
GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
{
return INVALID_GROUP_ID;
}
int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
return table[index];
}
const char *AdminCache::GetAdminPassword(AdminId id)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return NULL;
}
return m_pStrings->GetString(pUser->password);
}
void AdminCache::SetAdminPassword(AdminId id, const char *password)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return;
}
pUser->password = m_pStrings->AddString(password);
}
+55
View File
@@ -17,6 +17,7 @@
#include "sm_memtable.h"
#include <sm_trie.h>
#include <sh_list.h>
#include <sh_string.h>
#include <IAdminSystem.h>
#include "sm_globals.h"
#include <IForwardSys.h>
@@ -25,6 +26,8 @@ using namespace SourceHook;
#define GRP_MAGIC_SET 0xDEADFADE
#define GRP_MAGIC_UNSET 0xFACEFACE
#define USR_MAGIC_SET 0xDEADFACE
#define USR_MAGIC_UNSET 0xFADEDEAD
struct AdminGroup
{
@@ -44,6 +47,35 @@ struct AdminGroup
bool addflags[AdminFlags_TOTAL]; /* Additive flags */
};
struct AuthMethod
{
String name;
Trie *table;
};
struct UserAuth
{
unsigned int index; /* Index into auth table */
int identidx; /* Index into the string table */
};
struct AdminUser
{
int magic; /* Magic flag, for memory validation */
bool flags[AdminFlags_TOTAL]; /* Base flags */
bool eflags[AdminFlags_TOTAL]; /* Effective flags */
int nameidx; /* Name index */
int password; /* Password index */
unsigned int grp_count; /* Number of groups */
unsigned int grp_size; /* Size of groups table */
int grp_table; /* Group table itself */
int next_user; /* Next user in ze list */
int prev_user; /* Prev user in the list */
unsigned int auth_count; /* Number of auth methods */
unsigned int auth_size; /* Size of auth table */
int auth_table; /* Auth table itself */
};
class AdminCache :
public IAdminSystem,
public SMGlobalClass
@@ -52,6 +84,7 @@ public:
AdminCache();
~AdminCache();
public: //SMGlobalClass
void OnSourceModStartup(bool late);
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: //IAdminSystem
@@ -76,6 +109,21 @@ public: //IAdminSystem
void DumpAdminCache(int cache_flags, bool rebuild);
void AddAdminListener(IAdminListener *pListener);
void RemoveAdminListener(IAdminListener *pListener);
/** User stuff */
void RegisterAuthIdentType(const char *name);
AdminId CreateAdmin(const char *name);
const char *GetAdminName(AdminId id);
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
unsigned int GetAdminFlags(AdminId id, bool flags[], unsigned int total, AccessMode mode);
bool AdminInheritGroup(AdminId id, GroupId gid);
unsigned int GetAdminGroupCount(AdminId id);
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
void SetAdminPassword(AdminId id, const char *password);
const char *GetAdminPassword(AdminId id);
AdminId FindAdminByIdentity(const char *auth, const char *identity);
bool InvalidateAdmin(AdminId id);
private:
void _AddCommandOverride(const char *cmd, AdminFlag flag);
void _AddCommandGroupOverride(const char *group, AdminFlag flag);
@@ -84,7 +132,9 @@ private:
void _UnsetCommandOverride(const char *cmd);
void _UnsetCommandGroupOverride(const char *group);
void InvalidateGroupCache();
void InvalidateAdminCache(bool unlink_admins);
void DumpCommandOverrideCache(OverrideType type);
Trie *GetMethodByIndex(unsigned int index);
public:
BaseStringTable *m_pStrings;
BaseMemTable *m_pMemory;
@@ -95,7 +145,12 @@ public:
int m_FreeGroupList;
Trie *m_pGroups;
List<IAdminListener *> m_hooks;
List<AuthMethod> m_AuthMethods;
Trie *m_pAuthTables;
IForward *m_pCacheFwd;
int m_FirstUser;
int m_LastUser;
int m_FreeUserList;
};
extern AdminCache g_Admins;
+2
View File
@@ -39,6 +39,8 @@ public:
* begin at the first index again.
*/
void Reset();
private:
unsigned char *membase;
unsigned int size;