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