added some access helper functions

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40440
This commit is contained in:
David Anderson 2007-02-05 10:34:58 +00:00
parent b018cd9d3a
commit 6858d12ad9
3 changed files with 145 additions and 11 deletions

View File

@ -35,15 +35,8 @@ AdminCache::AdminCache()
AdminCache::~AdminCache()
{
if (m_pCmdGrpOverrides)
{
sm_trie_destroy(m_pCmdGrpOverrides);
}
if (m_pCmdOverrides)
{
sm_trie_destroy(m_pCmdOverrides);
}
sm_trie_destroy(m_pCmdGrpOverrides);
sm_trie_destroy(m_pCmdOverrides);
DumpAdminCache(0xFFFFFFFF, false);
@ -193,6 +186,8 @@ AdminId AdminCache::CreateAdmin(const char *name)
pUser->magic = USR_MAGIC_SET;
pUser->auth.identidx = -1;
pUser->auth.index = 0;
pUser->immune_default = false;
pUser->immune_global = false;
if (m_FirstUser == INVALID_ADMIN_ID)
{
@ -986,9 +981,18 @@ bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
table[pUser->grp_count] = gid;
pUser->grp_count++;
/* Compute new effective flags */
/* Compute new effective permissions */
pUser->eflags |= pGroup->addflags;
if (pGroup->immune_default)
{
pUser->immune_default = true;
}
if (pGroup->immune_global)
{
pUser->immune_global = true;
}
return true;
}
@ -1087,3 +1091,100 @@ unsigned int AdminCache::FlagBitsToArray(FlagBits bits, AdminFlag array[], unsig
return num;
}
bool AdminCache::CheckAdminFlags(AdminId id, FlagBits bits)
{
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
return ((pUser->eflags & bits) == bits);
}
bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
{
/**
* Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
* First, if the targetted AdminId is INVALID_ADMIN_ID, targeting succeeds.
*/
if (id == INVALID_ADMIN_ID)
{
return false;
}
if (target == INVALID_ADMIN_ID)
{
return true;
}
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
if (!pUser || pUser->magic != USR_MAGIC_SET)
{
return false;
}
AdminUser *pTarget = (AdminUser *)m_pMemory->GetAddress(target);
if (!pTarget || pTarget->magic != USR_MAGIC_SET)
{
return false;
}
/**
* Second, if the targeting admin is root, targeting suceeds.
*/
if (pUser->eflags & ADMFLAG_ROOT)
{
return true;
}
/** Fourth, if the targetted admin has global immunity, targeting fails. */
if (pTarget->immune_global)
{
return false;
}
/**
* Fifth, if the targetted admin has default immunity
* and the admin belongs to no groups, targeting fails.
*/
if (pTarget->immune_default && pUser->grp_count < 1)
{
return false;
}
/**
* Sixth, if the targetted admin has specific immunity from the
* targeting admin via group immunities, targeting fails.
*/
//:TODO: speed this up... maybe with trie hacks.
//idea is to insert %d.%d in the trie after computing this and use it as a cache lookup.
//problem is the trie cannot delete prefixes, so we'd have a problem with invalidations.
if (pTarget->grp_count > 0 && pUser->grp_count > 0)
{
int *grp_table = (int *)m_pMemory->GetAddress(pTarget->grp_table);
int *src_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
GroupId id, other;
unsigned int num;
for (unsigned int i=0; i<pTarget->grp_count; i++)
{
id = grp_table[i];
num = GetGroupImmunityCount(id);
for (unsigned int j=0; j<num; i++)
{
other = GetGroupImmunity(id, j);
for (unsigned int k=0; k<pUser->grp_count; k++)
{
if (other == src_table[k])
{
return false;
}
}
}
}
}
return true;
}

View File

@ -73,6 +73,8 @@ struct AdminUser
int next_user; /* Next user in ze list */
int prev_user; /* Prev user in the list */
UserAuth auth; /* Auth method for this user */
bool immune_global; /* Whether globally immune */
bool immune_default; /* Whether defaultly immune */
};
class AdminCache :
@ -127,6 +129,8 @@ public: //IAdminSystem
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
bool CheckAdminFlags(AdminId id, FlagBits bits);
bool CanAdminTarget(AdminId id, AdminId target);
private:
void _UnsetCommandOverride(const char *cmd);
void _UnsetCommandGroupOverride(const char *group);

View File

@ -416,7 +416,7 @@ namespace SourceMod
virtual bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode) =0;
/**
* @brief Returns a bitarray of flags enabled on an admin.
* @brief Returns the bitstring of access flags on an admin.
*
* @param id AdminId index of the admin.
* @param mode Access mode to use.
@ -524,6 +524,35 @@ namespace SourceMod
* @return Number of flags written.
*/
virtual unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize) =0;
/**
* @brief Checks whether a user has access to a given set of flag bits.
* Note: This is a wrapper around GetAdminFlags().
*
* @param id AdminId index of admin.
* @param flags Bitstring containing the permissions to check.
* @return True if user has permission, false otherwise.
*/
virtual bool CheckAdminFlags(AdminId id, FlagBits bits) =0;
/**
* @brief Checks whether an AdminId can target another AdminId.
*
* Zeroth, if the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
* First, if the targetted AdminId is INVALID_ADMIN_ID, targeting succeeds.
* Second, if the targeting admin is root, targeting suceeds.
* Third, if the targetted admin has global immunity, targeting fails.
* Fourth, if the targetted admin has default immunity,
* and the admin belongs to no groups, targeting fails.
* Fifth, if the targetted admin has specific immunity from the
* targeting admin via group immunities, targeting fails.
* Sixth, targeting succeeds if it passes these tests.
*
* @param id AdminId index of admin doing the targeting. Can be INVALID_ADMIN_ID.
* @param target AdminId index of the target admin. Can be INVALID_ADMIN_ID.
* @return True if this admin has permission to target the other admin.
*/
virtual bool CanAdminTarget(AdminId id, AdminId target) =0;
};
}