plugins/admin-sql-prefetch.sp
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
child 2289 44045ead61cd
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
     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-2008 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, immunity 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 immunity;
   140 	new AdminId:adm, id;
   141 	
   142 	while (SQL_FetchRow(hQuery))
   143 	{
   144 		id = SQL_FetchInt(hQuery, 0);
   145 		SQL_FetchString(hQuery, 1, authtype, sizeof(authtype));
   146 		SQL_FetchString(hQuery, 2, identity, sizeof(identity));
   147 		SQL_FetchString(hQuery, 3, password, sizeof(password));
   148 		SQL_FetchString(hQuery, 4, flags, sizeof(flags));
   149 		SQL_FetchString(hQuery, 5, name, sizeof(name));
   150 		immunity = SQL_FetchInt(hQuery, 6);
   151 		
   152 		/* Use a pre-existing admin if we can */
   153 		if ((adm = FindAdminByIdentity(authtype, identity)) == INVALID_ADMIN_ID)
   154 		{
   155 			adm = CreateAdmin(name);
   156 			if (!BindAdminIdentity(adm, authtype, identity))
   157 			{
   158 				LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
   159 				continue;
   160 			}
   161 		}
   162 		
   163 		#if defined _DEBUG
   164 		PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s,%d):%d", id, authtype, identity, password, flags, name, immunity, adm);
   165 		#endif
   166 		
   167 		/* See if this admin wants a password */
   168 		if (password[0] != '\0')
   169 		{
   170 			SetAdminPassword(adm, password);
   171 		}
   172 		
   173 		/* Apply each flag */
   174 		new len = strlen(flags);
   175 		new AdminFlag:flag;
   176 		for (new i=0; i<len; i++)
   177 		{
   178 			if (!FindFlagByChar(flags[i], flag))
   179 			{
   180 				continue;
   181 			}
   182 			SetAdminFlag(adm, flag, true);
   183 		}
   184 
   185 		SetAdminImmunityLevel(adm, immunity);
   186 		
   187 		/* Look up groups */
   188 		if (hGroupQuery != INVALID_HANDLE)
   189 		{
   190 			FetchUserGroups(hGroupQuery, adm, id);
   191 		}
   192 	}
   193 	
   194 	CloseHandle(hGroupQuery);
   195 	CloseHandle(hQuery);
   196 }
   197 
   198 FetchGroups(Handle:db)
   199 {
   200 	decl String:query[255];
   201 	new Handle:hQuery;
   202 	
   203 	Format(query, sizeof(query), "SELECT flags, name, immunity_level FROM sm_groups");
   204 
   205 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   206 	{
   207 		decl String:error[255];
   208 		SQL_GetError(db, error, sizeof(error));
   209 		LogError("FetchGroups() query failed: %s", query);
   210 		LogError("Query error: %s", error);
   211 		return;
   212 	}
   213 	
   214 	/* Now start fetching groups */
   215 	decl String:flags[32];
   216 	decl String:name[128];
   217 	new immunity;
   218 	while (SQL_FetchRow(hQuery))
   219 	{
   220 		SQL_FetchString(hQuery, 0, flags, sizeof(flags));
   221 		SQL_FetchString(hQuery, 1, name, sizeof(name));
   222 		immunity = SQL_FetchInt(hQuery, 2);
   223 		
   224 #if defined _DEBUG
   225 		PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name);
   226 #endif
   227 		
   228 		/* Find or create the group */
   229 		new GroupId:gid;
   230 		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
   231 		{
   232 			gid = CreateAdmGroup(name);
   233 		}
   234 		
   235 		/* Add flags from the database to the group */
   236 		new num_flag_chars = strlen(flags);
   237 		for (new i=0; i<num_flag_chars; i++)
   238 		{
   239 			decl AdminFlag:flag;
   240 			if (!FindFlagByChar(flags[i], flag))
   241 			{
   242 				continue;
   243 			}
   244 			SetAdmGroupAddFlag(gid, flag, true);
   245 		}
   246 		
   247 		/* Set the immunity level this group has */
   248 		SetAdmGroupImmunityLevel(gid, immunity);
   249 	}
   250 	
   251 	CloseHandle(hQuery);
   252 	
   253 	/** 
   254 	 * Get immunity in a big lump.  This is a nasty query but it gets the job done.
   255 	 */
   256 	new len = 0;
   257 	len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
   258 	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
   259 	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
   260 	
   261 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   262 	{
   263 		decl String:error[255];
   264 		SQL_GetError(db, error, sizeof(error));
   265 		LogError("FetchGroups() query failed: %s", query);
   266 		LogError("Query error: %s", error);
   267 		return;
   268 	}
   269 	
   270 	while (SQL_FetchRow(hQuery))
   271 	{
   272 		decl String:group1[80];
   273 		decl String:group2[80];
   274 		new GroupId:gid1, GroupId:gid2;
   275 		
   276 		SQL_FetchString(hQuery, 0, group1, sizeof(group1));
   277 		SQL_FetchString(hQuery, 1, group2, sizeof(group2));
   278 		
   279 		if (((gid1 = FindAdmGroup(group1)) == INVALID_GROUP_ID)
   280 			|| (gid2 = FindAdmGroup(group2)) == INVALID_GROUP_ID)
   281 		{
   282 			continue;
   283 		}
   284 		
   285 		SetAdmGroupImmuneFrom(gid1, gid2);
   286 #if defined _DEBUG
   287 		PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", gid1, gid2);
   288 #endif
   289 	}
   290 	
   291 	CloseHandle(hQuery);
   292 	
   293 	/**
   294 	 * Fetch overrides in a lump query.
   295 	 */
   296 	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");
   297 	
   298 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   299 	{
   300 		decl String:error[255];
   301 		SQL_GetError(db, error, sizeof(error));
   302 		LogError("FetchGroups() query failed: %s", query);
   303 		LogError("Query error: %s", error);
   304 		return;
   305 	}
   306 	
   307 	decl String:type[16];
   308 	decl String:cmd[64];
   309 	decl String:access[16];
   310 	while (SQL_FetchRow(hQuery))
   311 	{
   312 		SQL_FetchString(hQuery, 0, name, sizeof(name));
   313 		SQL_FetchString(hQuery, 1, type, sizeof(type));
   314 		SQL_FetchString(hQuery, 2, cmd, sizeof(cmd));
   315 		SQL_FetchString(hQuery, 3, access, sizeof(access));
   316 		
   317 		new GroupId:gid;
   318 		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
   319 		{
   320 			continue;
   321 		}
   322 				
   323 		new OverrideType:o_type = Override_Command;
   324 		if (StrEqual(type, "group"))
   325 		{
   326 			o_type = Override_CommandGroup;
   327 		}
   328 		
   329 		new OverrideRule:o_rule = Command_Deny;
   330 		if (StrEqual(access, "allow"))
   331 		{
   332 			o_rule = Command_Allow;
   333 		}
   334 				
   335 		#if defined _DEBUG
   336 		PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", gid, cmd, o_type, o_rule);
   337 		#endif
   338 		
   339 		AddAdmGroupCmdOverride(gid, cmd, o_type, o_rule);
   340 	}
   341 	
   342 	CloseHandle(hQuery);
   343 }
   344 
   345 FetchOverrides(Handle:db)
   346 {
   347 	decl String:query[255];
   348 	new Handle:hQuery;
   349 	
   350 	Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
   351 
   352 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   353 	{
   354 		decl String:error[255];
   355 		SQL_GetError(db, error, sizeof(error));
   356 		LogError("FetchOverrides() query failed: %s", query);
   357 		LogError("Query error: %s", error);
   358 		return;
   359 	}
   360 	
   361 	decl String:type[64];
   362 	decl String:name[64];
   363 	decl String:flags[32];
   364 	new flag_bits;
   365 	while (SQL_FetchRow(hQuery))
   366 	{
   367 		SQL_FetchString(hQuery, 0, type, sizeof(type));
   368 		SQL_FetchString(hQuery, 1, name, sizeof(name));
   369 		SQL_FetchString(hQuery, 2, flags, sizeof(flags));
   370 		
   371 #if defined _DEBUG
   372 		PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
   373 #endif
   374 		
   375 		flag_bits = ReadFlagString(flags);
   376 		if (StrEqual(type, "command"))
   377 		{
   378 			AddCommandOverride(name, Override_Command, flag_bits);
   379 		} else if (StrEqual(type, "group")) {
   380 			AddCommandOverride(name, Override_CommandGroup, flag_bits);
   381 		}
   382 	}
   383 	
   384 	CloseHandle(hQuery);
   385 }
   386