core/AdminCache.cpp
changeset 404 673ccd0935ba
parent 370 d3a484f98f6d
child 405 3e5727a37caa
     1.1 --- a/core/AdminCache.cpp	Sun Jan 28 04:19:46 2007 +0000
     1.2 +++ b/core/AdminCache.cpp	Mon Jan 29 04:19:14 2007 +0000
     1.3 @@ -26,8 +26,10 @@
     1.4  	m_pStrings = new BaseStringTable(1024);
     1.5  	m_pMemory = m_pStrings->GetMemTable();
     1.6  	m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
     1.7 +	m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID;
     1.8  	m_pGroups = sm_trie_create();
     1.9  	m_pCacheFwd = NULL;
    1.10 +	m_FirstGroup = -1;
    1.11  }
    1.12  
    1.13  AdminCache::~AdminCache()
    1.14 @@ -52,6 +54,13 @@
    1.15  	delete m_pStrings;
    1.16  }
    1.17  
    1.18 +void AdminCache::OnSourceModStartup(bool late)
    1.19 +{
    1.20 +	RegisterAuthIdentType("steam");
    1.21 +	RegisterAuthIdentType("name");
    1.22 +	RegisterAuthIdentType("ip");
    1.23 +}
    1.24 +
    1.25  void AdminCache::OnSourceModAllInitialized()
    1.26  {
    1.27  	m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
    1.28 @@ -196,6 +205,51 @@
    1.29  	}
    1.30  }
    1.31  
    1.32 +AdminId AdminCache::CreateAdmin(const char *name)
    1.33 +{
    1.34 +	AdminId id;
    1.35 +	AdminUser *pUser;
    1.36 +
    1.37 +	if (m_FreeUserList != INVALID_ADMIN_ID)
    1.38 +	{
    1.39 +		pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
    1.40 +		assert(pUser->magic == USR_MAGIC_UNSET);
    1.41 +		id = m_FreeUserList;
    1.42 +		m_FreeUserList = pUser->next_user;
    1.43 +	} else {
    1.44 +		id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
    1.45 +		pUser->grp_size = 0;
    1.46 +		pUser->grp_table = -1;
    1.47 +		pUser->auth_size = 0;
    1.48 +		pUser->auth_table = -1;
    1.49 +	}
    1.50 +
    1.51 +	memset(pUser->flags, 0, sizeof(pUser->flags));
    1.52 +	memset(pUser->eflags, 0, sizeof(pUser->flags));
    1.53 +	pUser->grp_count = 0;
    1.54 +	pUser->auth_count = 0;
    1.55 +	pUser->password = -1;
    1.56 +	pUser->magic = USR_MAGIC_SET;
    1.57 +
    1.58 +	if (m_FirstUser == INVALID_ADMIN_ID)
    1.59 +	{
    1.60 +		m_FirstUser = id;
    1.61 +		m_LastUser = id;
    1.62 +	} else {
    1.63 +		AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
    1.64 +		pPrev->next_user = id;
    1.65 +		pUser->prev_user = m_LastUser;
    1.66 +		m_LastUser = id;
    1.67 +	}
    1.68 +
    1.69 +	if (name && name[0] != '\0')
    1.70 +	{
    1.71 +		pUser->nameidx = m_pStrings->AddString(name);
    1.72 +	}
    1.73 +
    1.74 +	return id;
    1.75 +}
    1.76 +
    1.77  GroupId AdminCache::AddGroup(const char *group_name)
    1.78  {
    1.79  	if (sm_trie_retrieve(m_pGroups, group_name, NULL))
    1.80 @@ -222,7 +276,6 @@
    1.81  	pGroup->next_grp = INVALID_GROUP_ID;
    1.82  	pGroup->pCmdGrpTable = NULL;
    1.83  	pGroup->pCmdTable = NULL;
    1.84 -	pGroup->nameidx = m_pStrings->AddString(group_name);
    1.85  	memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
    1.86  
    1.87  	if (m_FirstGroup == INVALID_GROUP_ID)
    1.88 @@ -238,6 +291,8 @@
    1.89  		m_LastGroup = id;
    1.90  	}
    1.91  
    1.92 +	pGroup->nameidx = m_pStrings->AddString(group_name);
    1.93 +
    1.94  	sm_trie_insert(m_pGroups, group_name, (void *)id);
    1.95  
    1.96  	return id;
    1.97 @@ -498,6 +553,80 @@
    1.98  	return true;
    1.99  }
   1.100  
   1.101 +Trie *AdminCache::GetMethodByIndex(unsigned int index)
   1.102 +{
   1.103 +	List<AuthMethod>::iterator iter;
   1.104 +	for (iter=m_AuthMethods.begin();
   1.105 +		 iter!=m_AuthMethods.end();
   1.106 +		 iter++)
   1.107 +	{
   1.108 +		if (index-- == 0)
   1.109 +		{
   1.110 +			return (*iter).table;
   1.111 +		}
   1.112 +	}
   1.113 +
   1.114 +	return NULL;
   1.115 +}
   1.116 +
   1.117 +bool AdminCache::InvalidateAdmin(AdminId id)
   1.118 +{
   1.119 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.120 +	AdminUser *pOther;
   1.121 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.122 +	{
   1.123 +		return false;
   1.124 +	}
   1.125 +
   1.126 +	/* Unlink from the dbl link list */
   1.127 +	if (id == m_FirstUser && id == m_LastUser)
   1.128 +	{
   1.129 +		m_FirstUser = INVALID_ADMIN_ID;
   1.130 +		m_LastUser = INVALID_ADMIN_ID;
   1.131 +	} else if (id == m_FirstUser) {
   1.132 +		m_FirstUser = pUser->next_user;
   1.133 +		pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
   1.134 +		pOther->prev_user = INVALID_ADMIN_ID;
   1.135 +	} else if (id == m_LastUser) {
   1.136 +		m_LastUser = pUser->prev_user;
   1.137 +		pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
   1.138 +		pOther->next_user = INVALID_ADMIN_ID;
   1.139 +	} else {
   1.140 +		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
   1.141 +		pOther->next_user = pUser->next_user;
   1.142 +		pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
   1.143 +		pOther->prev_user = pUser->prev_user;
   1.144 +	}
   1.145 +
   1.146 +	/* Unlink from auth tables */
   1.147 +	if (pUser->auth_count > 0)
   1.148 +	{
   1.149 +		UserAuth *pAuth = (UserAuth *)m_pMemory->GetAddress(pUser->auth_table);
   1.150 +		Trie *pTrie;
   1.151 +		for (unsigned int i=0; i<pUser->auth_count; i++)
   1.152 +		{
   1.153 +			pTrie = GetMethodByIndex(pAuth[i].index);
   1.154 +			if (!pTrie)
   1.155 +			{
   1.156 +				continue;
   1.157 +			}
   1.158 +			sm_trie_delete(pTrie, m_pStrings->GetString(pAuth->identidx));
   1.159 +		}
   1.160 +	}
   1.161 +
   1.162 +	/* Clear table counts */
   1.163 +	pUser->grp_count = 0;
   1.164 +	pUser->auth_count = 0;
   1.165 +
   1.166 +	/* Link into free list */
   1.167 +	pUser->magic = USR_MAGIC_UNSET;
   1.168 +	pUser->next_user = m_FreeUserList;
   1.169 +	m_FreeUserList = id;
   1.170 +
   1.171 +	return true;
   1.172 +}
   1.173 +
   1.174 +
   1.175  void AdminCache::InvalidateGroup(GroupId id)
   1.176  {
   1.177  	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
   1.178 @@ -548,7 +677,44 @@
   1.179  	pGroup->next_grp = m_FreeGroupList;
   1.180  	m_FreeGroupList = id;
   1.181  
   1.182 -	/* :TODO: remove this group from any users */
   1.183 +	int idx = m_FirstUser;
   1.184 +	AdminUser *pUser;
   1.185 +	int *table;
   1.186 +	while (idx != INVALID_ADMIN_ID)
   1.187 +	{
   1.188 +		pUser = (AdminUser *)m_pMemory->GetAddress(idx);
   1.189 +		if (pUser->grp_count > 0)
   1.190 +		{
   1.191 +			table = (int *)m_pMemory->GetAddress(pUser->grp_table);
   1.192 +			for (unsigned int i=0; i<pUser->grp_count; i++)
   1.193 +			{
   1.194 +				if (table[i] == id)
   1.195 +				{
   1.196 +					/* We have to remove this entry */
   1.197 +					for (unsigned int j=i+1; j<pUser->grp_count; j++)
   1.198 +					{
   1.199 +						/* Move everything down by one */
   1.200 +						table[j-1] = table[j];
   1.201 +					}
   1.202 +					/* Decrease count */
   1.203 +					pUser->grp_count--;
   1.204 +					/* Recalculate effective flags */
   1.205 +					memset(pUser->eflags, 0, sizeof(pUser->eflags));
   1.206 +					for (unsigned int j=0; j<pUser->grp_count; j++)
   1.207 +					{
   1.208 +						pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
   1.209 +						for (unsigned int k=0; k<AdminFlags_TOTAL; k++)
   1.210 +						{
   1.211 +							pUser->eflags[k] = (pUser->flags[k] || pOther->addflags[k]);
   1.212 +						}
   1.213 +					}
   1.214 +					/* Break now, duplicates aren't allowed */
   1.215 +					break;
   1.216 +				}
   1.217 +			}
   1.218 +		}
   1.219 +		idx = pUser->next_user;
   1.220 +	}
   1.221  }
   1.222  
   1.223  void AdminCache::InvalidateGroupCache()
   1.224 @@ -580,7 +746,7 @@
   1.225  	m_FirstGroup = INVALID_GROUP_ID;
   1.226  	m_LastGroup = INVALID_GROUP_ID;
   1.227  
   1.228 -	/* :TODO: dump the admin cache */
   1.229 +	InvalidateAdminCache(false);
   1.230  
   1.231  	/* Reset the memory table */
   1.232  	m_pMemory->Reset();
   1.233 @@ -596,6 +762,41 @@
   1.234  	m_hooks.remove(pListener);
   1.235  }
   1.236  
   1.237 +void AdminCache::RegisterAuthIdentType(const char *name)
   1.238 +{
   1.239 +	if (sm_trie_retrieve(m_pAuthTables, name, NULL))
   1.240 +	{
   1.241 +		return;
   1.242 +	}
   1.243 +
   1.244 +	Trie *pAuth = sm_trie_create();
   1.245 +
   1.246 +	AuthMethod method;
   1.247 +	method.name.assign(name);
   1.248 +	method.table = pAuth;
   1.249 +
   1.250 +	m_AuthMethods.push_back(method);
   1.251 +
   1.252 +	sm_trie_insert(m_pAuthTables, name, pAuth);
   1.253 +}
   1.254 +
   1.255 +void AdminCache::InvalidateAdminCache(bool unlink_admins)
   1.256 +{
   1.257 +	/* Wipe the identity cache first */
   1.258 +	List<AuthMethod>::iterator iter;
   1.259 +	for (iter=m_AuthMethods.begin();
   1.260 +		 iter!=m_AuthMethods.end();
   1.261 +		 iter++)
   1.262 +	{
   1.263 +		sm_trie_clear((*iter).table);
   1.264 +	}
   1.265 +	
   1.266 +	while (m_FirstUser != INVALID_ADMIN_ID)
   1.267 +	{
   1.268 +		InvalidateAdmin(m_FirstUser);
   1.269 +	}
   1.270 +}
   1.271 +
   1.272  void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
   1.273  {
   1.274  	if (cache_flags & ADMIN_CACHE_OVERRIDES)
   1.275 @@ -604,19 +805,19 @@
   1.276  		DumpCommandOverrideCache(Override_CommandGroup);
   1.277  	}
   1.278  
   1.279 -	if ((cache_flags & ADMIN_CACHE_ADMINS) ||
   1.280 -		(cache_flags & ADMIN_CACHE_GROUPS))
   1.281 -	{
   1.282 -		/* Make sure the flag is set */
   1.283 -		cache_flags |= ADMIN_CACHE_ADMINS;
   1.284 -		/* :TODO: Dump admin cache */
   1.285 -	}
   1.286 -
   1.287 +	/* This will auto-invalidate the admin cache */
   1.288  	if (cache_flags & ADMIN_CACHE_GROUPS)
   1.289  	{
   1.290  		InvalidateGroupCache();
   1.291  	}
   1.292  
   1.293 +	/* If we only requested an admin rebuild, re-use the internal memory */
   1.294 +	if ((cache_flags & ADMIN_CACHE_ADMINS) &&
   1.295 +		!(cache_flags & ADMIN_CACHE_GROUPS))
   1.296 +	{
   1.297 +		InvalidateAdminCache(true);
   1.298 +	}
   1.299 +
   1.300  	if (rebuild)
   1.301  	{
   1.302  		List<IAdminListener *>::iterator iter;
   1.303 @@ -631,3 +832,236 @@
   1.304  		m_pCacheFwd->Execute(&result);
   1.305  	}
   1.306  }
   1.307 +
   1.308 +const char *AdminCache::GetAdminName(AdminId id)
   1.309 +{
   1.310 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.311 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.312 +	{
   1.313 +		return NULL;
   1.314 +	}
   1.315 +
   1.316 +	return m_pStrings->GetString(pUser->nameidx);
   1.317 +}
   1.318 +
   1.319 +bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
   1.320 +{
   1.321 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.322 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.323 +	{
   1.324 +		return false;
   1.325 +	}
   1.326 +
   1.327 +	Trie *pTable;
   1.328 +	if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
   1.329 +	{
   1.330 +		return false;
   1.331 +	}
   1.332 +
   1.333 +	if (sm_trie_retrieve(pTable, ident, NULL))
   1.334 +	{
   1.335 +		return false;
   1.336 +	}
   1.337 +
   1.338 +	return sm_trie_insert(pTable, ident, (void **)id);
   1.339 +}
   1.340 +
   1.341 +AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
   1.342 +{
   1.343 +	Trie *pTable;
   1.344 +	if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
   1.345 +	{
   1.346 +		return INVALID_ADMIN_ID;
   1.347 +	}
   1.348 +
   1.349 +	void *object;
   1.350 +	if (!sm_trie_retrieve(pTable, identity, &object))
   1.351 +	{
   1.352 +		return INVALID_ADMIN_ID;
   1.353 +	}
   1.354 +
   1.355 +	return (AdminId)object;
   1.356 +}
   1.357 +
   1.358 +void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
   1.359 +{
   1.360 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.361 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.362 +	{
   1.363 +		return;
   1.364 +	}
   1.365 +
   1.366 +	if (flag < Admin_None
   1.367 +		|| flag >= AdminFlags_TOTAL)
   1.368 +	{
   1.369 +		return;
   1.370 +	}
   1.371 +
   1.372 +	pUser->flags[enabled] = false;
   1.373 +}
   1.374 +
   1.375 +bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
   1.376 +{
   1.377 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.378 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.379 +	{
   1.380 +		return false;
   1.381 +	}
   1.382 +
   1.383 +	if (flag < Admin_None
   1.384 +		|| flag >= AdminFlags_TOTAL)
   1.385 +	{
   1.386 +		return false;
   1.387 +	}
   1.388 +
   1.389 +	if (mode == Access_Real)
   1.390 +	{
   1.391 +		return pUser->flags[flag];
   1.392 +	} else if (mode == Access_Effective) {
   1.393 +		return (pUser->flags[flag] || pUser->eflags[flag]);
   1.394 +	}
   1.395 +
   1.396 +	return false;
   1.397 +}
   1.398 +
   1.399 +unsigned int AdminCache::GetAdminFlags(AdminId id, bool flags[], unsigned int total, AccessMode mode)
   1.400 +{
   1.401 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.402 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.403 +	{
   1.404 +		return 0;
   1.405 +	}
   1.406 +
   1.407 +	unsigned int i = 0;
   1.408 +	if (mode == Access_Real)
   1.409 +	{
   1.410 +		for (i=0; i<AdminFlags_TOTAL && i<total; i++)
   1.411 +		{
   1.412 +			flags[i] = pUser->flags[i];
   1.413 +		}
   1.414 +	} else if (mode == Access_Effective) {
   1.415 +		for (i=0; i<AdminFlags_TOTAL && i<total; i++)
   1.416 +		{
   1.417 +			flags[i] = (pUser->flags[i] || pUser->eflags[i]);
   1.418 +		}
   1.419 +	}
   1.420 +
   1.421 +	return i;
   1.422 +}
   1.423 +
   1.424 +bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
   1.425 +{
   1.426 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.427 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.428 +	{
   1.429 +		return false;
   1.430 +	}
   1.431 +
   1.432 +	AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
   1.433 +	if (!pGroup || pGroup->magic != USR_MAGIC_SET)
   1.434 +	{
   1.435 +		return false;
   1.436 +	}
   1.437 +
   1.438 +	int *table;
   1.439 +	if (pUser->grp_count + 1 > pUser->grp_size)
   1.440 +	{
   1.441 +		int new_size = 0;
   1.442 +		int tblidx;
   1.443 +		
   1.444 +		if (pUser->grp_size == 0)
   1.445 +		{
   1.446 +			new_size = 2;
   1.447 +		} else {
   1.448 +			new_size = pUser->grp_size * 2;
   1.449 +		}
   1.450 +		
   1.451 +		/* Create and refresh pointers */
   1.452 +		tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
   1.453 +		pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.454 +		pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
   1.455 +
   1.456 +		/* Copy old data if necessary */
   1.457 +		if (pUser->grp_table != -1)
   1.458 +		{
   1.459 +			int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
   1.460 +			memcpy(table, old_table, sizeof(int) * pUser->grp_count);
   1.461 +		}
   1.462 +		pUser->grp_table = tblidx;
   1.463 +		pUser->grp_size = new_size;
   1.464 +	} else {
   1.465 +		table = (int *)m_pMemory->GetAddress(pUser->grp_table);
   1.466 +	}
   1.467 +
   1.468 +	for (unsigned int i=0; i<pUser->grp_count; i++)
   1.469 +	{
   1.470 +		if (table[i] == gid)
   1.471 +		{
   1.472 +			return false;
   1.473 +		}
   1.474 +	}
   1.475 +
   1.476 +	table[pUser->grp_count] = gid;
   1.477 +	pUser->grp_count++;
   1.478 +
   1.479 +	/* Compute new effective flags */
   1.480 +	for (unsigned int i=Admin_None;
   1.481 +		 i<AdminFlags_TOTAL;
   1.482 +		 i++)
   1.483 +	{
   1.484 +		/* Only inherit flags additive flags we don't have */
   1.485 +		if (!pUser->eflags[i])
   1.486 +		{
   1.487 +			pUser->eflags[i] = pGroup->addflags[i];
   1.488 +		}
   1.489 +	}
   1.490 +
   1.491 +	return true;
   1.492 +}
   1.493 +
   1.494 +unsigned int AdminCache::GetAdminGroupCount(AdminId id)
   1.495 +{
   1.496 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.497 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.498 +	{
   1.499 +		return 0;
   1.500 +	}
   1.501 +
   1.502 +	return pUser->grp_count;
   1.503 +}
   1.504 +
   1.505 +GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
   1.506 +{
   1.507 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.508 +	if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
   1.509 +	{
   1.510 +		return INVALID_GROUP_ID;
   1.511 +	}
   1.512 +
   1.513 +	int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
   1.514 +
   1.515 +	return table[index];
   1.516 +}
   1.517 +
   1.518 +const char *AdminCache::GetAdminPassword(AdminId id)
   1.519 +{
   1.520 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.521 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.522 +	{
   1.523 +		return NULL;
   1.524 +	}
   1.525 +
   1.526 +	return m_pStrings->GetString(pUser->password);
   1.527 +}
   1.528 +
   1.529 +void AdminCache::SetAdminPassword(AdminId id, const char *password)
   1.530 +{	
   1.531 +	AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
   1.532 +	if (!pUser || pUser->magic != USR_MAGIC_SET)
   1.533 +	{
   1.534 +		return;
   1.535 +	}
   1.536 +
   1.537 +	pUser->password = m_pStrings->AddString(password);
   1.538 +}
   1.539 +