plugins/sql-admin-manager.sp
author David Anderson <dvander@alliedmods.net>
Sun Aug 26 19:51:24 2007 +0000 (2007-08-26)
changeset 1375 b7acfca8070d
parent 1330 ab94316bb52b
child 1403 ecb9c66fd4bb
permissions -rw-r--r--
fixed amb830 - basefunvotes.sp was named wrong
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SQL Admin Manager Plugin
     5  * Adds/managers admins and groups in an SQL database.
     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 Admin Manager",
    42 	author = "AlliedModders LLC",
    43 	description = "Manages SQL admins",
    44 	version = SOURCEMOD_VERSION,
    45 	url = "http://www.sourcemod.net/"
    46 };
    47 
    48 public OnPluginStart()
    49 {
    50 	LoadTranslations("common.phrases");
    51 	LoadTranslations("sqladmins.phrases");
    52 
    53 	RegAdminCmd("sm_sql_addadmin", Command_AddAdmin, ADMFLAG_ROOT, "Adds an admin to the SQL database");
    54 	RegAdminCmd("sm_sql_deladmin", Command_DelAdmin, ADMFLAG_ROOT, "Removes an admin from the SQL database");
    55 	RegAdminCmd("sm_sql_addgroup", Command_AddGroup, ADMFLAG_ROOT, "Adds a group to the SQL database");
    56 	RegAdminCmd("sm_sql_delgroup", Command_DelGroup, ADMFLAG_ROOT, "Removes a group from the SQL database");
    57 	RegAdminCmd("sm_sql_setadmingroups", Command_SetAdminGroups, ADMFLAG_ROOT, "Sets an admin's groups in the SQL database");
    58 }
    59 
    60 Handle:Connect()
    61 {
    62 	decl String:error[255];
    63 	new Handle:db;
    64 	
    65 	if (SQL_CheckConfig("admins"))
    66 	{
    67 		db = SQL_Connect("admins", true, error, sizeof(error));
    68 	} else {
    69 		db = SQL_Connect("default", true, error, sizeof(error));
    70 	}
    71 	
    72 	if (db == INVALID_HANDLE)
    73 	{
    74 		LogError("Could not connect to database: %s", error);
    75 	}
    76 	
    77 	return db;
    78 }
    79 
    80 public Action:Command_SetAdminGroups(client, args)
    81 {
    82 	if (args < 2)
    83 	{
    84 		ReplyToCommand(client, "[SM] Usage: sm_sql_setadmingroups <authtype> <identity> [group1] ... [group N]");
    85 		return Plugin_Handled;
    86 	}
    87 	
    88 	decl String:authtype[16];
    89 	GetCmdArg(1, authtype, sizeof(authtype));
    90 	
    91 	if (!StrEqual(authtype, "steam")
    92 		&& !StrEqual(authtype, "ip")
    93 		&& !StrEqual(authtype, "name"))
    94 	{
    95 		ReplyToCommand(client, "[SM] %t", "Invalid authtype");
    96 		return Plugin_Handled;
    97 	}
    98 	
    99 	new Handle:db = Connect();
   100 	if (db == INVALID_HANDLE)
   101 	{
   102 		ReplyToCommand(client, "[SM] %t", "Could not connect to database");
   103 		return Plugin_Handled;
   104 	}
   105 	
   106 	decl String:identity[65];
   107 	decl String:safe_identity[140];
   108 	GetCmdArg(2, identity, sizeof(identity));
   109 	SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
   110 	
   111 	decl String:query[255];
   112 	Format(query, 
   113 		sizeof(query),
   114 		"SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'",
   115 		authtype,
   116 		safe_identity);
   117 		
   118 	new Handle:hQuery;
   119 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   120 	{
   121 		return DoError(client, db, query, "Admin lookup query failed");
   122 	}
   123 	
   124 	if (!SQL_FetchRow(hQuery))
   125 	{
   126 		ReplyToCommand(client, "[SM] %t", "SQL Admin not found");
   127 		CloseHandle(hQuery);
   128 		CloseHandle(db);
   129 		return Plugin_Handled;
   130 	}
   131 	
   132 	new id = SQL_FetchInt(hQuery, 0);
   133 	
   134 	CloseHandle(hQuery);
   135 	
   136 	/**
   137 	 * First delete all of the user's existing groups.
   138 	 */
   139 	Format(query, sizeof(query), "DELETE FROM sm_admins_groups WHERE admin_id = %d", id);
   140 	if (!SQL_FastQuery(db, query))
   141 	{
   142 		return DoError(client, db, query, "Admin group deletion query failed");
   143 	}
   144 	
   145 	if (args < 3)
   146 	{
   147 		ReplyToCommand(client, "[SM] %t", "SQL Admin groups reset");
   148 		CloseHandle(db);
   149 		return Plugin_Handled;
   150 	}
   151 	
   152 	decl String:error[256];
   153 	new Handle:hAddQuery, Handle:hFindQuery;
   154 	
   155 	Format(query, sizeof(query), "SELECT id FROM sm_groups WHERE name = ?");
   156 	if ((hFindQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
   157 	{
   158 		return DoStmtError(client, db, query, error, "Group search prepare failed");
   159 	}
   160 	
   161 	Format(query, 
   162 		sizeof(query), 
   163 		"INSERT INTO sm_admins_groups (admin_id, group_id, inherit_order) VALUES (%d, ?, ?)",
   164 		id);
   165 	if ((hAddQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
   166 	{
   167 		CloseHandle(hFindQuery);
   168 		return DoStmtError(client, db, query, error, "Add admin group prepare failed");
   169 	}
   170 	
   171 	decl String:name[80];
   172 	new inherit_order = 0;
   173 	for (new i=3; i<=args; i++)
   174 	{
   175 		GetCmdArg(i, name, sizeof(name));
   176 		
   177 		SQL_BindParamString(hFindQuery, 0, name, false);
   178 		if (!SQL_Execute(hFindQuery) || !SQL_FetchRow(hFindQuery))
   179 		{
   180 			ReplyToCommand(client, "[SM] %t", "SQL Group X not found", name);
   181 		} else {
   182 			new gid = SQL_FetchInt(hFindQuery, 0);
   183 			
   184 			SQL_BindParamInt(hAddQuery, 0, gid);
   185 			SQL_BindParamInt(hAddQuery, 1, ++inherit_order);
   186 			if (!SQL_Execute(hAddQuery))
   187 			{
   188 				ReplyToCommand(client, "[SM] %t", "SQL Group X failed to bind", name);
   189 				inherit_order--;
   190 			}
   191 		}
   192 	}
   193 	
   194 	CloseHandle(hAddQuery);
   195 	CloseHandle(hFindQuery);
   196 	CloseHandle(db);
   197 	
   198 	if (inherit_order == 1)
   199 	{
   200 		ReplyToCommand(client, "[SM] %t", "Added group to user");
   201 	} else if (inherit_order > 1) {
   202 		ReplyToCommand(client, "[SM] %t", "Added groups to user", inherit_order);
   203 	}
   204 	
   205 	return Plugin_Handled;
   206 }
   207 
   208 public Action:Command_DelGroup(client, args)
   209 {
   210 	if (args < 1)
   211 	{
   212 		ReplyToCommand(client, "[SM] Usage: sm_sql_delgroup <name>");
   213 		return Plugin_Handled;
   214 	}
   215 
   216 	new Handle:db = Connect();
   217 	if (db == INVALID_HANDLE)
   218 	{
   219 		ReplyToCommand(client, "[SM] %t", "Could not connect to database");
   220 		return Plugin_Handled;
   221 	}
   222 	
   223 	new len;
   224 	decl String:name[80];
   225 	decl String:safe_name[180];
   226 	GetCmdArgString(name, sizeof(name));
   227 	
   228 	/* Strip quotes in case the user tries to use them */
   229 	len = strlen(name);
   230 	if (len > 1 && (name[0] == '"' && name[len-1] == '"'))
   231 	{
   232 		name[--len] = '\0';
   233 		SQL_QuoteString(db, name[1], safe_name, sizeof(safe_name));
   234 	} else {
   235 		SQL_QuoteString(db, name, safe_name, sizeof(safe_name));
   236 	}
   237 	
   238 	decl String:query[256];
   239 	
   240 	new Handle:hQuery;
   241 	Format(query, sizeof(query), "SELECT id FROM sm_groups WHERE name = '%s'", safe_name);
   242 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   243 	{
   244 		return DoError(client, db, query, "Group retrieval query failed");
   245 	}
   246 	
   247 	if (!SQL_FetchRow(hQuery))
   248 	{
   249 		ReplyToCommand(client, "[SM] %t", "SQL Group not found");
   250 		CloseHandle(hQuery);
   251 		CloseHandle(db);
   252 		return Plugin_Handled;
   253 	}
   254 	
   255 	new id = SQL_FetchInt(hQuery, 0);
   256 	
   257 	CloseHandle(hQuery);
   258 	
   259 	/* Delete admin inheritance for this group */
   260 	Format(query, sizeof(query), "DELETE FROM sm_admins_groups WHERE group_id = %d", id);
   261 	if (!SQL_FastQuery(db, query))
   262 	{
   263 		return DoError(client, db, query, "Admin group deletion query failed");
   264 	}
   265 	
   266 	/* Delete group overrides */
   267 	Format(query, sizeof(query), "DELETE FROM sm_group_overrides WHERE group_id = %d", id);
   268 	if (!SQL_FastQuery(db, query))
   269 	{
   270 		return DoError(client, db, query, "Group override deletion query failed");
   271 	}
   272 	
   273 	/* Delete immunity */
   274 	Format(query, sizeof(query), "DELETE FROM sm_group_immunity WHERE group_id = %d OR other_id = %d", id, id);
   275 	if (!SQL_FastQuery(db, query))
   276 	{
   277 		return DoError(client, db, query, "Group immunity deletion query failed");
   278 	}
   279 	
   280 	/* Finally delete the group */
   281 	Format(query, sizeof(query), "DELETE FROM sm_groups WHERE id = %d", id);
   282 	if (!SQL_FastQuery(db, query))
   283 	{
   284 		return DoError(client, db, query, "Group deletion query failed");
   285 	}
   286 	
   287 	ReplyToCommand(client, "[SM] %t", "SQL Group deleted");
   288 	
   289 	CloseHandle(db);
   290 	
   291 	return Plugin_Handled;
   292 }
   293 
   294 public Action:Command_AddGroup(client, args)
   295 {
   296 	if (args < 2)
   297 	{
   298 		ReplyToCommand(client, "[SM] Usage: sm_sql_addgroup <name> <flags> [immunity]");
   299 		ReplyToCommand(client, "[SM] %t", "Invalid immunity");
   300 		return Plugin_Handled;
   301 	}
   302 
   303 	new String:immunity[32] = "none";
   304 	if (args >= 3)
   305 	{
   306 		GetCmdArg(3, immunity, sizeof(immunity));
   307 		if (!StrEqual(immunity, "none")
   308 			&& !StrEqual(immunity, "global")
   309 			&& !StrEqual(immunity, "default"))
   310 		{
   311 			ReplyToCommand(client, "[SM] %t", "Invalid immunity");
   312 			return Plugin_Handled;
   313 		}
   314 	}
   315 	
   316 	new Handle:db = Connect();
   317 	if (db == INVALID_HANDLE)
   318 	{
   319 		ReplyToCommand(client, "[SM] %t", "Could not connect to database");
   320 		return Plugin_Handled;
   321 	}
   322 	
   323 	decl String:name[64];
   324 	decl String:safe_name[64];
   325 	GetCmdArg(1, name, sizeof(name));
   326 	SQL_QuoteString(db, name, safe_name, sizeof(safe_name));
   327 	
   328 	new Handle:hQuery;
   329 	decl String:query[256];
   330 	Format(query, sizeof(query), "SELECT id FROM sm_groups WHERE name = '%s'", safe_name);
   331 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   332 	{
   333 		return DoError(client, db, query, "Group retrieval query failed");
   334 	}
   335 	
   336 	if (SQL_GetRowCount(hQuery) > 0)
   337 	{
   338 		ReplyToCommand(client, "[SM] %t", "SQL Group already exists");
   339 		CloseHandle(hQuery);
   340 		CloseHandle(db);
   341 		return Plugin_Handled;
   342 	}
   343 	
   344 	CloseHandle(hQuery);
   345 	
   346 	decl String:flags[30];
   347 	decl String:safe_flags[64];
   348 	GetCmdArg(2, flags, sizeof(safe_flags));
   349 	SQL_QuoteString(db, flags, safe_flags, sizeof(safe_flags));
   350 	
   351 	Format(query, 
   352 		sizeof(query),
   353 		"INSERT INTO sm_groups (immunity, flags, name) VALUES ('%s', '%s', '%s')",
   354 		immunity,
   355 		safe_flags,
   356 		safe_name);
   357 	
   358 	if (!SQL_FastQuery(db, query))
   359 	{
   360 		return DoError(client, db, query, "Group insertion query failed");
   361 	}
   362 	
   363 	ReplyToCommand(client, "[SM] %t", "SQL Group added");
   364 	
   365 	CloseHandle(db);
   366 		
   367 	return Plugin_Handled;
   368 }	
   369 
   370 public Action:Command_DelAdmin(client, args)
   371 {
   372 	if (args < 2)
   373 	{
   374 		ReplyToCommand(client, "[SM] Usage: sm_sql_deladmin <authtype> <identity>");
   375 		ReplyToCommand(client, "[SM] %t", "Invalid authtype");
   376 		return Plugin_Handled;
   377 	}
   378 	
   379 	decl String:authtype[16];
   380 	GetCmdArg(1, authtype, sizeof(authtype));
   381 	
   382 	if (!StrEqual(authtype, "steam")
   383 		&& !StrEqual(authtype, "ip")
   384 		&& !StrEqual(authtype, "name"))
   385 	{
   386 		ReplyToCommand(client, "[SM] %t", "Invalid authtype");
   387 		return Plugin_Handled;
   388 	}
   389 	
   390 	new Handle:db = Connect();
   391 	if (db == INVALID_HANDLE)
   392 	{
   393 		ReplyToCommand(client, "[SM] %t", "Could not connect to database");
   394 		return Plugin_Handled;
   395 	}
   396 	
   397 	decl String:identity[65];
   398 	decl String:safe_identity[140];
   399 	GetCmdArg(2, identity, sizeof(identity));
   400 	SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
   401 	
   402 	decl String:query[255];
   403 	Format(query, 
   404 		sizeof(query),
   405 		"SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'",
   406 		authtype,
   407 		safe_identity);
   408 		
   409 	new Handle:hQuery;
   410 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   411 	{
   412 		return DoError(client, db, query, "Admin lookup query failed");
   413 	}
   414 	
   415 	if (!SQL_FetchRow(hQuery))
   416 	{
   417 		ReplyToCommand(client, "[SM] %t", "SQL Admin not found");
   418 		CloseHandle(hQuery);
   419 		CloseHandle(db);
   420 		return Plugin_Handled;
   421 	}
   422 	
   423 	new id = SQL_FetchInt(hQuery, 0);
   424 	
   425 	CloseHandle(hQuery);
   426 	
   427 	/* Delete group bindings */
   428 	Format(query, sizeof(query), "DELETE FROM sm_admins_groups WHERE admin_id = %d", id);
   429 	if (!SQL_FastQuery(db, query))
   430 	{
   431 		return DoError(client, db, query, "Admin group deletion query failed");
   432 	}
   433 	
   434 	Format(query, sizeof(query), "DELETE FROM sm_admins WHERE id = %d", id);
   435 	if (!SQL_FastQuery(db, query))
   436 	{
   437 		return DoError(client, db, query, "Admin deletion query failed");
   438 	}
   439 	
   440 	CloseHandle(db);
   441 	
   442 	ReplyToCommand(client, "[SM] %t", "SQL Admin deleted");
   443 	
   444 	return Plugin_Handled;
   445 }
   446 
   447 public Action:Command_AddAdmin(client, args)
   448 {
   449 	if (args < 4)
   450 	{
   451 		ReplyToCommand(client, "[SM] Usage: sm_sql_addadmin <alias> <authtype> <identity> <flags> [password]");
   452 		ReplyToCommand(client, "[SM] %t", "Invalid authtype");
   453 		return Plugin_Handled;
   454 	}
   455 	
   456 	decl String:authtype[16];
   457 	GetCmdArg(2, authtype, sizeof(authtype));
   458 	
   459 	if (!StrEqual(authtype, "steam")
   460 		&& !StrEqual(authtype, "ip")
   461 		&& !StrEqual(authtype, "name"))
   462 	{
   463 		ReplyToCommand(client, "[SM] %t", "Invalid authtype");
   464 		return Plugin_Handled;
   465 	}
   466 	
   467 	decl String:identity[65];
   468 	decl String:safe_identity[140];
   469 	GetCmdArg(3, identity, sizeof(identity));
   470 	
   471 	decl String:query[256];
   472 	new Handle:hQuery;
   473 	new Handle:db = Connect();
   474 	if (db == INVALID_HANDLE)
   475 	{
   476 		ReplyToCommand(client, "[SM] %t", "Could not connect to database");
   477 		return Plugin_Handled;
   478 	}
   479 	
   480 	SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
   481 	
   482 	Format(query, sizeof(query), "SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'", authtype, identity);
   483 	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
   484 	{
   485 		return DoError(client, db, query, "Admin retrieval query failed");
   486 	}
   487 	
   488 	if (SQL_GetRowCount(hQuery) > 0)
   489 	{
   490 		ReplyToCommand(client, "[SM] %t", "SQL Admin already exists");
   491 		CloseHandle(hQuery);
   492 		CloseHandle(db);
   493 		return Plugin_Handled;
   494 	}
   495 	
   496 	CloseHandle(hQuery);
   497 	
   498 	decl String:alias[64];
   499 	decl String:safe_alias[140];
   500 	GetCmdArg(1, alias, sizeof(alias));
   501 	SQL_QuoteString(db, alias, safe_alias, sizeof(safe_alias));
   502 	
   503 	decl String:flags[30];
   504 	decl String:safe_flags[64];
   505 	GetCmdArg(4, flags, sizeof(flags));
   506 	SQL_QuoteString(db, flags, safe_flags, sizeof(safe_flags));
   507 	
   508 	decl String:password[32];
   509 	decl String:safe_password[80];
   510 	if (args > 4)
   511 	{
   512 		GetCmdArg(5, password, sizeof(password));
   513 		SQL_QuoteString(db, password, safe_password, sizeof(safe_password));
   514 	} else {
   515 		safe_password[0] = '\0';
   516 	}
   517 	
   518 	new len = 0;
   519 	len += Format(query[len], sizeof(query)-len, "INSERT INTO sm_admins (authtype, identity, password, flags, name) VALUES");
   520 	if (safe_password[0] == '\0')
   521 	{
   522 		len += Format(query[len], sizeof(query)-len, " ('%s', '%s', NULL, '%s', '%s')", authtype, safe_identity, safe_flags, safe_alias);
   523 	} else {
   524 		len += Format(query[len], sizeof(query)-len, " ('%s', '%s', '%s', '%s', '%s')", authtype, safe_identity, safe_password, safe_flags, safe_alias);
   525 	}
   526 	
   527 	if (!SQL_FastQuery(db, query))
   528 	{
   529 		return DoError(client, db, query, "Admin insertion query failed");
   530 	}
   531 	
   532 	ReplyToCommand(client, "[SM] %t", "SQL Admin added");
   533 	
   534 	CloseHandle(db);
   535 		
   536 	return Plugin_Handled;
   537 }
   538 
   539 stock Action:DoError(client, Handle:db, const String:query[], const String:msg[])
   540 {
   541 		decl String:error[255];
   542 		SQL_GetError(db, error, sizeof(error));
   543 		LogError("%s: %s", msg, error);
   544 		LogError("Query dump: %s", query);
   545 		CloseHandle(db);
   546 		ReplyToCommand(client, "[SM] %t", "Failed to query database");
   547 		return Plugin_Handled;
   548 }
   549 
   550 stock Action:DoStmtError(client, Handle:db, const String:query[], const String:error[], const String:msg[])
   551 {
   552 		LogError("%s: %s", msg, error);
   553 		LogError("Query dump: %s", query);
   554 		CloseHandle(db);
   555 		ReplyToCommand(client, "[SM] %t", "Failed to query database");
   556 		return Plugin_Handled;
   557 }
   558