plugins/admin-sql-prefetch.sp
author Scott Ehlert <ds@alliedmods.net>
Wed Feb 18 02:30:21 2009 -0600 (2009-02-18)
changeset 2584 6972eb067f48
parent 2289 44045ead61cd
child 2641 f56dd4215df6
permissions -rw-r--r--
Merge.
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@1947
     7
 * SourceMod (C)2004-2008 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