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