1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/plugins/sql-admin-manager.sp Tue Aug 14 04:46:21 2007 +0000
1.3 @@ -0,0 +1,533 @@
1.4 +/**
1.5 + * sql-admin-manager.sp
1.6 + * Adds/managers admins and groups in an SQL database.
1.7 + *
1.8 + * This file is part of SourceMod, Copyright (C) 2004-2007 AlliedModders LLC
1.9 + *
1.10 + * This program is free software; you can redistribute it and/or
1.11 + * modify it under the terms of the GNU General Public License
1.12 + * as published by the Free Software Foundation; either version 2
1.13 + * of the License, or (at your option) any later version.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License
1.21 + * along with this program; if not, write to the Free Software
1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1.23 + *
1.24 + * Version: $Id$
1.25 + */
1.26 +
1.27 +/* We like semicolons */
1.28 +#pragma semicolon 1
1.29 +
1.30 +#include <sourcemod>
1.31 +
1.32 +public Plugin:myinfo =
1.33 +{
1.34 + name = "SQL Admin Manager",
1.35 + author = "AlliedModders LLC",
1.36 + description = "Manages SQL admins",
1.37 + version = SOURCEMOD_VERSION,
1.38 + url = "http://www.sourcemod.net/"
1.39 +};
1.40 +
1.41 +public OnPluginStart()
1.42 +{
1.43 + LoadTranslations("common.phrases");
1.44 + LoadTranslations("sqladmins.phrases");
1.45 +
1.46 + RegAdminCmd("sm_sql_addadmin", Command_AddAdmin, ADMFLAG_ROOT, "Adds an admin to the SQL database");
1.47 + RegAdminCmd("sm_sql_deladmin", Command_DelAdmin, ADMFLAG_ROOT, "Removes an admin from the SQL database");
1.48 + RegAdminCmd("sm_sql_addgroup", Command_AddGroup, ADMFLAG_ROOT, "Adds a group to the SQL database");
1.49 + RegAdminCmd("sm_sql_delgroup", Command_DelGroup, ADMFLAG_ROOT, "Removes a group from the SQL database");
1.50 + RegAdminCmd("sm_sql_setadmingroups", Command_SetAdminGroups, ADMFLAG_ROOT, "Sets an admin's groups in the SQL database");
1.51 +}
1.52 +
1.53 +Handle:Connect()
1.54 +{
1.55 + decl String:error[255];
1.56 + new Handle:db;
1.57 +
1.58 + if (SQL_CheckConfig("admins"))
1.59 + {
1.60 + db = SQL_Connect("admins", true, error, sizeof(error));
1.61 + } else {
1.62 + db = SQL_Connect("default", true, error, sizeof(error));
1.63 + }
1.64 +
1.65 + if (db == INVALID_HANDLE)
1.66 + {
1.67 + LogError("Could not connect to database: %s", error);
1.68 + }
1.69 +
1.70 + return db;
1.71 +}
1.72 +
1.73 +public Action:Command_SetAdminGroups(client, args)
1.74 +{
1.75 + if (args < 2)
1.76 + {
1.77 + ReplyToCommand(client, "[SM] Usage: sm_sql_setadmingroups <authtype> <identity> [group1] ... [group N]");
1.78 + return Plugin_Handled;
1.79 + }
1.80 +
1.81 + decl String:authtype[16];
1.82 + GetCmdArg(1, authtype, sizeof(authtype));
1.83 +
1.84 + if (!StrEqual(authtype, "steam")
1.85 + && !StrEqual(authtype, "ip")
1.86 + && !StrEqual(authtype, "name"))
1.87 + {
1.88 + ReplyToCommand(client, "[SM] %t", "Invalid authtype");
1.89 + return Plugin_Handled;
1.90 + }
1.91 +
1.92 + new Handle:db = Connect();
1.93 + if (db == INVALID_HANDLE)
1.94 + {
1.95 + ReplyToCommand(client, "[SM] %t", "Could not connect to database");
1.96 + return Plugin_Handled;
1.97 + }
1.98 +
1.99 + decl String:identity[65];
1.100 + decl String:safe_identity[140];
1.101 + GetCmdArg(2, identity, sizeof(identity));
1.102 + SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
1.103 +
1.104 + decl String:query[255];
1.105 + Format(query,
1.106 + sizeof(query),
1.107 + "SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'",
1.108 + authtype,
1.109 + safe_identity);
1.110 +
1.111 + new Handle:hQuery;
1.112 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
1.113 + {
1.114 + return DoError(client, db, query, "Admin lookup query failed");
1.115 + }
1.116 +
1.117 + if (!SQL_FetchRow(hQuery))
1.118 + {
1.119 + ReplyToCommand(client, "[SM] %t", "SQL Admin not found");
1.120 + CloseHandle(hQuery);
1.121 + CloseHandle(db);
1.122 + return Plugin_Handled;
1.123 + }
1.124 +
1.125 + new id = SQL_FetchInt(hQuery, 0);
1.126 +
1.127 + CloseHandle(hQuery);
1.128 +
1.129 + /**
1.130 + * First delete all of the user's existing groups.
1.131 + */
1.132 + Format(query, sizeof(query), "DELETE FROM sm_admins_groups WHERE admin_id = %d", id);
1.133 + if (!SQL_FastQuery(db, query))
1.134 + {
1.135 + return DoError(client, db, query, "Admin group deletion query failed");
1.136 + }
1.137 +
1.138 + if (args < 3)
1.139 + {
1.140 + ReplyToCommand(client, "[SM] %t", "SQL Admin groups reset");
1.141 + CloseHandle(db);
1.142 + return Plugin_Handled;
1.143 + }
1.144 +
1.145 + decl String:error[256];
1.146 + new Handle:hAddQuery, Handle:hFindQuery;
1.147 +
1.148 + Format(query, sizeof(query), "SELECT id FROM sm_groups WHERE name = ?");
1.149 + if ((hFindQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
1.150 + {
1.151 + return DoStmtError(client, db, query, error, "Group search prepare failed");
1.152 + }
1.153 +
1.154 + Format(query,
1.155 + sizeof(query),
1.156 + "INSERT INTO sm_admins_groups (admin_id, group_id, inherit_order) VALUES (%d, ?, ?)",
1.157 + id);
1.158 + if ((hAddQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
1.159 + {
1.160 + CloseHandle(hFindQuery);
1.161 + return DoStmtError(client, db, query, error, "Add admin group prepare failed");
1.162 + }
1.163 +
1.164 + decl String:name[80];
1.165 + new inherit_order = 0;
1.166 + for (new i=3; i<=args; i++)
1.167 + {
1.168 + GetCmdArg(i, name, sizeof(name));
1.169 +
1.170 + SQL_BindParamString(hFindQuery, 0, name, false);
1.171 + if (!SQL_Execute(hFindQuery) || !SQL_FetchRow(hFindQuery))
1.172 + {
1.173 + ReplyToCommand(client, "[SM] %t", "SQL Group X not found", name);
1.174 + } else {
1.175 + new gid = SQL_FetchInt(hFindQuery, 0);
1.176 +
1.177 + SQL_BindParamInt(hAddQuery, 0, gid);
1.178 + SQL_BindParamInt(hAddQuery, 1, ++inherit_order);
1.179 + if (!SQL_Execute(hAddQuery))
1.180 + {
1.181 + ReplyToCommand(client, "[SM] %t", "SQL Group X failed to bind", name);
1.182 + inherit_order--;
1.183 + }
1.184 + }
1.185 + }
1.186 +
1.187 + CloseHandle(hAddQuery);
1.188 + CloseHandle(hFindQuery);
1.189 + CloseHandle(db);
1.190 +
1.191 + if (inherit_order == 1)
1.192 + {
1.193 + ReplyToCommand(client, "[SM] %t", "Added group to user");
1.194 + } else if (inherit_order > 1) {
1.195 + ReplyToCommand(client, "[SM] %t", "Added groups to user", inherit_order);
1.196 + }
1.197 +
1.198 + return Plugin_Handled;
1.199 +}
1.200 +
1.201 +public Action:Command_DelGroup(client, args)
1.202 +{
1.203 + if (args < 1)
1.204 + {
1.205 + ReplyToCommand(client, "[SM] Usage: sm_sql_addgroup <name>");
1.206 + return Plugin_Handled;
1.207 + }
1.208 +
1.209 + new Handle:db = Connect();
1.210 + if (db == INVALID_HANDLE)
1.211 + {
1.212 + ReplyToCommand(client, "[SM] %t", "Could not connect to database");
1.213 + return Plugin_Handled;
1.214 + }
1.215 +
1.216 + new len;
1.217 + decl String:name[80];
1.218 + decl String:safe_name[180];
1.219 + GetCmdArgString(name, sizeof(name));
1.220 +
1.221 + /* Strip quotes in case the user tries to use them */
1.222 + len = strlen(name);
1.223 + if (len > 1 && (name[0] == '"' && name[len-1] == '"'))
1.224 + {
1.225 + name[--len] = '\0';
1.226 + SQL_QuoteString(db, name[1], safe_name, sizeof(safe_name));
1.227 + } else {
1.228 + SQL_QuoteString(db, name, safe_name, sizeof(safe_name));
1.229 + }
1.230 +
1.231 + decl String:query[256];
1.232 +
1.233 + /* Delete admin inheritance for this group */
1.234 + Format(query,
1.235 + sizeof(query),
1.236 + "DELETE FROM sm_admins_groups WHERE group_id IN (SELECT id FROM sm_groups WHERE name = '%s')",
1.237 + safe_name);
1.238 + if (!SQL_FastQuery(db, query))
1.239 + {
1.240 + return DoError(client, db, query, "Admin group deletion query failed");
1.241 + }
1.242 +
1.243 + /* Delete group overrides */
1.244 + Format(query,
1.245 + sizeof(query),
1.246 + "DELETE FROM sm_group_overrides WHERE group_id IN (SELECT id FROM sm_groups WHERE name = '%s')",
1.247 + safe_name);
1.248 + if (!SQL_FastQuery(db, query))
1.249 + {
1.250 + return DoError(client, db, query, "Group override deletion query failed");
1.251 + }
1.252 +
1.253 + /* Finally delete the group */
1.254 + Format(query, sizeof(query), "DELETE FROM sm_groups WHERE name = '%s'", safe_name);
1.255 + if (!SQL_FastQuery(db, query))
1.256 + {
1.257 + return DoError(client, db, query, "Group deletion query failed");
1.258 + }
1.259 +
1.260 + if (SQL_GetAffectedRows(db))
1.261 + {
1.262 + ReplyToCommand(client, "[SM] %t", "SQL Group deleted");
1.263 + } else {
1.264 + ReplyToCommand(client, "[SM] %t", "SQL Group not found");
1.265 + }
1.266 +
1.267 + CloseHandle(db);
1.268 +
1.269 + return Plugin_Handled;
1.270 +}
1.271 +
1.272 +public Action:Command_AddGroup(client, args)
1.273 +{
1.274 + if (args < 2)
1.275 + {
1.276 + ReplyToCommand(client, "[SM] Usage: sm_sql_addgroup <name> <flags> [immunity]");
1.277 + ReplyToCommand(client, "[SM] %t", "Invalid immunity");
1.278 + return Plugin_Handled;
1.279 + }
1.280 +
1.281 + new String:immunity[32] = "none";
1.282 + if (args >= 3)
1.283 + {
1.284 + GetCmdArg(3, immunity, sizeof(immunity));
1.285 + if (!StrEqual(immunity, "none")
1.286 + && !StrEqual(immunity, "global")
1.287 + && !StrEqual(immunity, "default"))
1.288 + {
1.289 + ReplyToCommand(client, "[SM] %t", "Invalid immunity");
1.290 + return Plugin_Handled;
1.291 + }
1.292 + }
1.293 +
1.294 + new Handle:db = Connect();
1.295 + if (db == INVALID_HANDLE)
1.296 + {
1.297 + ReplyToCommand(client, "[SM] %t", "Could not connect to database");
1.298 + return Plugin_Handled;
1.299 + }
1.300 +
1.301 + decl String:name[64];
1.302 + decl String:safe_name[64];
1.303 + GetCmdArg(1, name, sizeof(name));
1.304 + SQL_QuoteString(db, name, safe_name, sizeof(safe_name));
1.305 +
1.306 + new Handle:hQuery;
1.307 + decl String:query[256];
1.308 + Format(query, sizeof(query), "SELECT id FROM sm_groups WHERE name = '%s'", safe_name);
1.309 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
1.310 + {
1.311 + return DoError(client, db, query, "Group retrieval query failed");
1.312 + }
1.313 +
1.314 + if (SQL_GetRowCount(hQuery) > 0)
1.315 + {
1.316 + ReplyToCommand(client, "[SM] %t", "SQL Group already exists");
1.317 + CloseHandle(hQuery);
1.318 + CloseHandle(db);
1.319 + return Plugin_Handled;
1.320 + }
1.321 +
1.322 + CloseHandle(hQuery);
1.323 +
1.324 + decl String:flags[30];
1.325 + decl String:safe_flags[64];
1.326 + GetCmdArg(2, flags, sizeof(safe_flags));
1.327 + SQL_QuoteString(db, flags, safe_flags, sizeof(safe_flags));
1.328 +
1.329 + Format(query,
1.330 + sizeof(query),
1.331 + "INSERT INTO sm_groups (immunity, flags, name) VALUES ('%s', '%s', '%s')",
1.332 + immunity,
1.333 + safe_flags,
1.334 + safe_name);
1.335 +
1.336 + if (!SQL_FastQuery(db, query))
1.337 + {
1.338 + return DoError(client, db, query, "Group insertion query failed");
1.339 + }
1.340 +
1.341 + ReplyToCommand(client, "[SM] %t", "SQL Group added");
1.342 +
1.343 + CloseHandle(db);
1.344 +
1.345 + return Plugin_Handled;
1.346 +}
1.347 +
1.348 +public Action:Command_DelAdmin(client, args)
1.349 +{
1.350 + if (args < 2)
1.351 + {
1.352 + ReplyToCommand(client, "[SM] Usage: sm_sql_deladmin <authtype> <identity>");
1.353 + ReplyToCommand(client, "[SM] %t", "Invalid authtype");
1.354 + return Plugin_Handled;
1.355 + }
1.356 +
1.357 + decl String:authtype[16];
1.358 + GetCmdArg(1, authtype, sizeof(authtype));
1.359 +
1.360 + if (!StrEqual(authtype, "steam")
1.361 + && !StrEqual(authtype, "ip")
1.362 + && !StrEqual(authtype, "name"))
1.363 + {
1.364 + ReplyToCommand(client, "[SM] %t", "Invalid authtype");
1.365 + return Plugin_Handled;
1.366 + }
1.367 +
1.368 + new Handle:db = Connect();
1.369 + if (db == INVALID_HANDLE)
1.370 + {
1.371 + ReplyToCommand(client, "[SM] %t", "Could not connect to database");
1.372 + return Plugin_Handled;
1.373 + }
1.374 +
1.375 + decl String:identity[65];
1.376 + decl String:safe_identity[140];
1.377 + GetCmdArg(2, identity, sizeof(identity));
1.378 + SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
1.379 +
1.380 + decl String:query[255];
1.381 + Format(query,
1.382 + sizeof(query),
1.383 + "SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'",
1.384 + authtype,
1.385 + safe_identity);
1.386 +
1.387 + new Handle:hQuery;
1.388 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
1.389 + {
1.390 + return DoError(client, db, query, "Admin lookup query failed");
1.391 + }
1.392 +
1.393 + if (!SQL_FetchRow(hQuery))
1.394 + {
1.395 + ReplyToCommand(client, "[SM] %t", "SQL Admin not found");
1.396 + CloseHandle(hQuery);
1.397 + CloseHandle(db);
1.398 + return Plugin_Handled;
1.399 + }
1.400 +
1.401 + new id = SQL_FetchInt(hQuery, 0);
1.402 +
1.403 + CloseHandle(hQuery);
1.404 +
1.405 + /* Delete group bindings */
1.406 + Format(query, sizeof(query), "DELETE FROM sm_admins_groups WHERE admin_id = %d", id);
1.407 + if (!SQL_FastQuery(db, query))
1.408 + {
1.409 + return DoError(client, db, query, "Admin group deletion query failed");
1.410 + }
1.411 +
1.412 + Format(query, sizeof(query), "DELETE FROM sm_admins WHERE id = %d", id);
1.413 + if (!SQL_FastQuery(db, query))
1.414 + {
1.415 + return DoError(client, db, query, "Admin deletion query failed");
1.416 + }
1.417 +
1.418 + CloseHandle(db);
1.419 +
1.420 + ReplyToCommand(client, "[SM] %t", "SQL Admin deleted");
1.421 +
1.422 + return Plugin_Handled;
1.423 +}
1.424 +
1.425 +public Action:Command_AddAdmin(client, args)
1.426 +{
1.427 + if (args < 4)
1.428 + {
1.429 + ReplyToCommand(client, "[SM] Usage: sm_sql_addadmin <alias> <authtype> <identity> <flags> [password]");
1.430 + ReplyToCommand(client, "[SM] %t", "Invalid authtype");
1.431 + return Plugin_Handled;
1.432 + }
1.433 +
1.434 + decl String:authtype[16];
1.435 + GetCmdArg(2, authtype, sizeof(authtype));
1.436 +
1.437 + if (!StrEqual(authtype, "steam")
1.438 + && !StrEqual(authtype, "ip")
1.439 + && !StrEqual(authtype, "name"))
1.440 + {
1.441 + ReplyToCommand(client, "[SM] %t", "Invalid authtype");
1.442 + return Plugin_Handled;
1.443 + }
1.444 +
1.445 + decl String:identity[65];
1.446 + decl String:safe_identity[140];
1.447 + GetCmdArg(3, identity, sizeof(identity));
1.448 +
1.449 + decl String:query[256];
1.450 + new Handle:hQuery;
1.451 + new Handle:db = Connect();
1.452 + if (db == INVALID_HANDLE)
1.453 + {
1.454 + ReplyToCommand(client, "[SM] %t", "Could not connect to database");
1.455 + return Plugin_Handled;
1.456 + }
1.457 +
1.458 + SQL_QuoteString(db, identity, safe_identity, sizeof(safe_identity));
1.459 +
1.460 + Format(query, sizeof(query), "SELECT id FROM sm_admins WHERE authtype = '%s' AND identity = '%s'", authtype, identity);
1.461 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
1.462 + {
1.463 + return DoError(client, db, query, "Admin retrieval query failed");
1.464 + }
1.465 +
1.466 + if (SQL_GetRowCount(hQuery) > 0)
1.467 + {
1.468 + ReplyToCommand(client, "[SM] %t", "SQL Admin already exists");
1.469 + CloseHandle(hQuery);
1.470 + CloseHandle(db);
1.471 + return Plugin_Handled;
1.472 + }
1.473 +
1.474 + CloseHandle(hQuery);
1.475 +
1.476 + decl String:alias[64];
1.477 + decl String:safe_alias[140];
1.478 + GetCmdArg(1, alias, sizeof(alias));
1.479 + SQL_QuoteString(db, alias, safe_alias, sizeof(safe_alias));
1.480 +
1.481 + decl String:flags[30];
1.482 + decl String:safe_flags[64];
1.483 + GetCmdArg(4, flags, sizeof(flags));
1.484 + SQL_QuoteString(db, flags, safe_flags, sizeof(safe_flags));
1.485 +
1.486 + decl String:password[32];
1.487 + decl String:safe_password[80];
1.488 + if (args > 4)
1.489 + {
1.490 + GetCmdArg(5, password, sizeof(password));
1.491 + SQL_QuoteString(db, password, safe_password, sizeof(safe_password));
1.492 + } else {
1.493 + safe_password[0] = '\0';
1.494 + }
1.495 +
1.496 + new len = 0;
1.497 + len += Format(query[len], sizeof(query)-len, "INSERT INTO sm_admins (authtype, identity, password, flags, name) VALUES");
1.498 + if (safe_password[0] == '\0')
1.499 + {
1.500 + len += Format(query[len], sizeof(query)-len, " ('%s', '%s', NULL, '%s', '%s')", authtype, safe_identity, safe_flags, safe_alias);
1.501 + } else {
1.502 + len += Format(query[len], sizeof(query)-len, " ('%s', '%s', '%s', '%s', '%s')", authtype, safe_identity, safe_password, safe_flags, safe_alias);
1.503 + }
1.504 +
1.505 + if (!SQL_FastQuery(db, query))
1.506 + {
1.507 + return DoError(client, db, query, "Admin insertion query failed");
1.508 + }
1.509 +
1.510 + ReplyToCommand(client, "[SM] %t", "SQL Admin added");
1.511 +
1.512 + CloseHandle(db);
1.513 +
1.514 + return Plugin_Handled;
1.515 +}
1.516 +
1.517 +stock Action:DoError(client, Handle:db, const String:query[], const String:msg[])
1.518 +{
1.519 + decl String:error[255];
1.520 + SQL_GetError(db, error, sizeof(error));
1.521 + LogError("%s: %s", msg, error);
1.522 + LogError("Query dump: %s", query);
1.523 + CloseHandle(db);
1.524 + ReplyToCommand(client, "[SM] %t", "Failed to query database");
1.525 + return Plugin_Handled;
1.526 +}
1.527 +
1.528 +stock Action:DoStmtError(client, Handle:db, const String:query[], const String:error[], const String:msg[])
1.529 +{
1.530 + LogError("%s: %s", msg, error);
1.531 + LogError("Query dump: %s", query);
1.532 + CloseHandle(db);
1.533 + ReplyToCommand(client, "[SM] %t", "Failed to query database");
1.534 + return Plugin_Handled;
1.535 +}
1.536 +