plugins/admin-sql-prefetch.sp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1326 d24c8f8a2e07
child 1403 ecb9c66fd4bb
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

(This day shall henceforth be known as the Eighty Column Massacre of '07)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SQL Admins Plugin (Prefetch)
     5  * Prefetches admins from an SQL database without threading.
     6  *
     7  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     8  * =============================================================================
     9  *
    10  * This program is free software; you can redistribute it and/or modify it under
    11  * the terms of the GNU General Public License, version 3.0, as published by the
    12  * Free Software Foundation.
    13  * 
    14  * This program is distributed in the hope that it will be useful, but WITHOUT
    15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    17  * details.
    18  *
    19  * You should have received a copy of the GNU General Public License along with
    20  * this program.  If not, see <http://www.gnu.org/licenses/>.
    21  *
    22  * As a special exception, AlliedModders LLC gives you permission to link the
    23  * code of this program (as well as its derivative works) to "Half-Life 2," the
    24  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    25  * by the Valve Corporation.  You must obey the GNU General Public License in
    26  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    27  * this exception to all derivative works.  AlliedModders LLC defines further
    28  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    29  * or <http://www.sourcemod.net/license.php>.
    30  *
    31  * Version: $Id$
    32  */
    33 
    34 /* We like semicolons */
    35 #pragma semicolon 1
    36 
    37 #include <sourcemod>
    38 
    39 public Plugin:myinfo = 
    40 {
    41 	name = "SQL Admins (Prefetch)",
    42 	author = "AlliedModders LLC",
    43 	description = "Reads all admins from SQL",
    44 	version = SOURCEMOD_VERSION,
    45 	url = "http://www.sourcemod.net/"
    46 };
    47 
    48 public OnRebuildAdminCache(AdminCachePart:part)
    49 {
    50 	/* First try to get a database connection */
    51 	decl String:error[255];
    52 	new Handle:db;
    53 	
    54 	if (SQL_CheckConfig("admins"))
    55 	{
    56 		db = SQL_Connect("admins", true, error, sizeof(error));
    57 	} else {
    58 		db = SQL_Connect("default", true, error, sizeof(error));
    59 	}
    60 	
    61 	if (db == INVALID_HANDLE)
    62 	{
    63 		LogError("Could not connect to database \"default\": %s", error);
    64 		return;
    65 	}
    66 	
    67 	if (part == AdminCache_Overrides)
    68 	{
    69 		FetchOverrides(db);
    70 	} else if (part == AdminCache_Groups) {
    71 		FetchGroups(db);
    72 	} else if (part == AdminCache_Admins) {
    73 		FetchUsers(db);
    74 	}
    75 	
    76 	CloseHandle(db);
    77 }
    78 
    79 FetchUserGroups(Handle:hQuery, AdminId:adm, id)
    80 {
    81 	SQL_BindParamInt(hQuery, 0, id);
    82 	if (!SQL_Execute(hQuery))
    83 	{
    84 		decl String:error[255];
    85 		SQL_GetError(hQuery, error, sizeof(error));
    86 		LogError("FetchUserGroups() statement execute failed: %s", error);
    87 		return;
    88 	}
    89 	
    90 	decl String:name[80];
    91 	new GroupId:gid;
    92 	while (SQL_FetchRow(hQuery))
    93 	{
    94 		SQL_FetchString(hQuery, 0, name, sizeof(name));
    95 		
    96 		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
    97 		{
    98 			/* Group wasn't found, don't bother with it.  */
    99 			continue;
   100 		}
   101 		
   102 		#if defined _DEBUG
   103 		PrintToServer("Found admin group (%d, %d, %d)", id, gid, adm);
   104 		#endif
   105 		
   106 		AdminInheritGroup(adm, gid);
   107 	}
   108 }
   109 
   110 FetchUsers(Handle:db)
   111 {
   112 	decl String:query[255], String:error[255];
   113 	new Handle:hQuery, Handle:hGroupQuery;
   114 	
   115 	Format(query, sizeof(query), "SELECT id, authtype, identity, password, flags, name FROM sm_admins");
   116 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   117 	{
   118 		SQL_GetError(db, error, sizeof(error));
   119 		LogError("FetchUsers() query failed: %s", query);
   120 		LogError("Query error: %s", error);
   121 		return;
   122 	}
   123 	
   124 	/* If this fails it's non-fatal */
   125 	Format(query,
   126 		sizeof(query), 
   127 		"SELECT g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id WHERE ag.admin_id = ? ORDER BY inherit_order ASC");
   128 	if ((hGroupQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
   129 	{
   130 		LogError("FetchUsers() group query preparation failed: %s", query);
   131 		LogError("Query error: %s", error);
   132 	}
   133 	
   134 	decl String:authtype[16];
   135 	decl String:identity[80];
   136 	decl String:password[80];
   137 	decl String:flags[32];
   138 	decl String:name[80];
   139 	new AdminId:adm, id;
   140 	
   141 	while (SQL_FetchRow(hQuery))
   142 	{
   143 		id = SQL_FetchInt(hQuery, 0);
   144 		SQL_FetchString(hQuery, 1, authtype, sizeof(authtype));
   145 		SQL_FetchString(hQuery, 2, identity, sizeof(identity));
   146 		SQL_FetchString(hQuery, 3, password, sizeof(password));
   147 		SQL_FetchString(hQuery, 4, flags, sizeof(flags));
   148 		SQL_FetchString(hQuery, 5, name, sizeof(name));
   149 		
   150 		/* Use a pre-existing admin if we can */
   151 		if ((adm = FindAdminByIdentity(authtype, identity)) == INVALID_ADMIN_ID)
   152 		{
   153 			adm = CreateAdmin(name);
   154 			if (!BindAdminIdentity(adm, authtype, identity))
   155 			{
   156 				LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
   157 				continue;
   158 			}
   159 		}
   160 		
   161 		#if defined _DEBUG
   162 		PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s):%d", id, authtype, identity, password, flags, name, adm);
   163 		#endif
   164 		
   165 		/* See if this admin wants a password */
   166 		if (password[0] != '\0')
   167 		{
   168 			SetAdminPassword(adm, password);
   169 		}
   170 		
   171 		/* Apply each flag */
   172 		new len = strlen(flags);
   173 		new AdminFlag:flag;
   174 		for (new i=0; i<len; i++)
   175 		{
   176 			if (!FindFlagByChar(flags[i], flag))
   177 			{
   178 				continue;
   179 			}
   180 			SetAdminFlag(adm, flag, true);
   181 		}
   182 		
   183 		/* Look up groups */
   184 		if (hGroupQuery != INVALID_HANDLE)
   185 		{
   186 			FetchUserGroups(hGroupQuery, adm, id);
   187 		}
   188 	}
   189 	
   190 	CloseHandle(hGroupQuery);
   191 	CloseHandle(hQuery);
   192 }
   193 
   194 FetchGroups(Handle:db)
   195 {
   196 	decl String:query[255];
   197 	new Handle:hQuery;
   198 	
   199 	Format(query, sizeof(query), "SELECT immunity, flags, name FROM sm_groups");
   200 
   201 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   202 	{
   203 		decl String:error[255];
   204 		SQL_GetError(db, error, sizeof(error));
   205 		LogError("FetchGroups() query failed: %s", query);
   206 		LogError("Query error: %s", error);
   207 		return;
   208 	}
   209 	
   210 	/* Now start fetching groups */
   211 	decl String:immunity[16];
   212 	decl String:flags[32];
   213 	decl String:name[128];
   214 	while (SQL_FetchRow(hQuery))
   215 	{
   216 		SQL_FetchString(hQuery, 0, immunity, sizeof(immunity));
   217 		SQL_FetchString(hQuery, 1, flags, sizeof(flags));
   218 		SQL_FetchString(hQuery, 2, name, sizeof(name));
   219 		
   220 #if defined _DEBUG
   221 		PrintToServer("Adding group (%s, %s, %s)", immunity, flags, name);
   222 #endif
   223 		
   224 		/* Find or create the group */
   225 		new GroupId:gid;
   226 		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
   227 		{
   228 			gid = CreateAdmGroup(name);
   229 		}
   230 		
   231 		/* Add flags from the database to the group */
   232 		new num_flag_chars = strlen(flags);
   233 		for (new i=0; i<num_flag_chars; i++)
   234 		{
   235 			decl AdminFlag:flag;
   236 			if (!FindFlagByChar(flags[i], flag))
   237 			{
   238 				continue;
   239 			}
   240 			SetAdmGroupAddFlag(gid, flag, true);
   241 		}
   242 		
   243 		/* Set the immunity level this group has */
   244 		if (StrEqual(immunity, "all"))
   245 		{
   246 			SetAdmGroupImmunity(gid, Immunity_Default, true);
   247 			SetAdmGroupImmunity(gid, Immunity_Global, true);
   248 		} else if (StrEqual(immunity, "default")) {
   249 			SetAdmGroupImmunity(gid, Immunity_Default, true);
   250 		} else if (StrEqual(immunity, "global")) {
   251 			SetAdmGroupImmunity(gid, Immunity_Global, true);
   252 		}
   253 	}
   254 	
   255 	CloseHandle(hQuery);
   256 	
   257 	/** 
   258 	 * Get immunity in a big lump.  This is a nasty query but it gets the job done.
   259 	 */
   260 	new len = 0;
   261 	len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
   262 	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
   263 	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
   264 	
   265 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   266 	{
   267 		decl String:error[255];
   268 		SQL_GetError(db, error, sizeof(error));
   269 		LogError("FetchGroups() query failed: %s", query);
   270 		LogError("Query error: %s", error);
   271 		return;
   272 	}
   273 	
   274 	while (SQL_FetchRow(hQuery))
   275 	{
   276 		decl String:group1[80];
   277 		decl String:group2[80];
   278 		new GroupId:gid1, GroupId:gid2;
   279 		
   280 		SQL_FetchString(hQuery, 0, group1, sizeof(group1));
   281 		SQL_FetchString(hQuery, 1, group2, sizeof(group2));
   282 		
   283 		if (((gid1 = FindAdmGroup(group1)) == INVALID_GROUP_ID)
   284 			|| (gid2 = FindAdmGroup(group2)) == INVALID_GROUP_ID)
   285 		{
   286 			continue;
   287 		}
   288 		
   289 		SetAdmGroupImmuneFrom(gid1, gid2);
   290 #if defined _DEBUG
   291 		PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", gid1, gid2);
   292 #endif
   293 	}
   294 	
   295 	CloseHandle(hQuery);
   296 	
   297 	/**
   298 	 * Fetch overrides in a lump query.
   299 	 */
   300 	Format(query, sizeof(query), "SELECT g.name, go.type, go.name, go.access FROM sm_group_overrides go LEFT JOIN sm_groups g ON go.group_id = g.id");
   301 	
   302 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   303 	{
   304 		decl String:error[255];
   305 		SQL_GetError(db, error, sizeof(error));
   306 		LogError("FetchGroups() query failed: %s", query);
   307 		LogError("Query error: %s", error);
   308 		return;
   309 	}
   310 	
   311 	decl String:type[16];
   312 	decl String:cmd[64];
   313 	decl String:access[16];
   314 	while (SQL_FetchRow(hQuery))
   315 	{
   316 		SQL_FetchString(hQuery, 0, name, sizeof(name));
   317 		SQL_FetchString(hQuery, 1, type, sizeof(type));
   318 		SQL_FetchString(hQuery, 2, cmd, sizeof(cmd));
   319 		SQL_FetchString(hQuery, 3, access, sizeof(access));
   320 		
   321 		new GroupId:gid;
   322 		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
   323 		{
   324 			continue;
   325 		}
   326 				
   327 		new OverrideType:o_type = Override_Command;
   328 		if (StrEqual(type, "group"))
   329 		{
   330 			o_type = Override_CommandGroup;
   331 		}
   332 		
   333 		new OverrideRule:o_rule = Command_Deny;
   334 		if (StrEqual(access, "allow"))
   335 		{
   336 			o_rule = Command_Allow;
   337 		}
   338 				
   339 		#if defined _DEBUG
   340 		PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", gid, cmd, o_type, o_rule);
   341 		#endif
   342 		
   343 		AddAdmGroupCmdOverride(gid, cmd, o_type, o_rule);
   344 	}
   345 	
   346 	CloseHandle(hQuery);
   347 }
   348 
   349 FetchOverrides(Handle:db)
   350 {
   351 	decl String:query[255];
   352 	new Handle:hQuery;
   353 	
   354 	Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
   355 
   356 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   357 	{
   358 		decl String:error[255];
   359 		SQL_GetError(db, error, sizeof(error));
   360 		LogError("FetchOverrides() query failed: %s", query);
   361 		LogError("Query error: %s", error);
   362 		return;
   363 	}
   364 	
   365 	decl String:type[64];
   366 	decl String:name[64];
   367 	decl String:flags[32];
   368 	new flag_bits;
   369 	while (SQL_FetchRow(hQuery))
   370 	{
   371 		SQL_FetchString(hQuery, 0, type, sizeof(type));
   372 		SQL_FetchString(hQuery, 1, name, sizeof(name));
   373 		SQL_FetchString(hQuery, 2, flags, sizeof(flags));
   374 		
   375 #if defined _DEBUG
   376 		PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
   377 #endif
   378 		
   379 		flag_bits = ReadFlagString(flags);
   380 		if (StrEqual(type, "command"))
   381 		{
   382 			AddCommandOverride(name, Override_Command, flag_bits);
   383 		} else if (StrEqual(type, "group")) {
   384 			AddCommandOverride(name, Override_CommandGroup, flag_bits);
   385 		}
   386 	}
   387 	
   388 	CloseHandle(hQuery);
   389 }