diff --git a/sql/updates/auth/2024_09_14_auth_00.sql b/sql/updates/auth/2024_09_14_auth_00.sql deleted file mode 100644 index 9d25cf5a6c..0000000000 --- a/sql/updates/auth/2024_09_14_auth_00.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE `account_access`; diff --git a/sql/updates/auth/2024_10_2_auth_00.sql b/sql/updates/auth/2024_10_2_auth_00.sql deleted file mode 100644 index 5fb87971f7..0000000000 --- a/sql/updates/auth/2024_10_2_auth_00.sql +++ /dev/null @@ -1,2 +0,0 @@ -DELETE FROM `rbac_permissions` WHERE `id`=228; -DELETE FROM `rbac_permissions` WHERE `id`=375; \ No newline at end of file diff --git a/sql/updates/auth/2026-01-23_auth_00.sql b/sql/updates/auth/2026-01-23_auth_00.sql new file mode 100644 index 0000000000..8bcf687578 --- /dev/null +++ b/sql/updates/auth/2026-01-23_auth_00.sql @@ -0,0 +1,13 @@ +DROP TABLE `account_access`; +CREATE TABLE `account_access` ( + `id` int unsigned NOT NULL, + `gmlevel` tinyint unsigned NOT NULL, + `RealmID` int NOT NULL DEFAULT '-1', + PRIMARY KEY (`id`,`RealmID`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +DELETE FROM `rbac_permissions` WHERE `id`=228; +INSERT INTO `rbac_permissions` (`id`, `name`) VALUES (228, 'Command: account set gmlevel'); + +DELETE FROM `rbac_permissions` WHERE `id`=375; +INSERT INTO `rbac_permissions` (`id`, `name`) VALUES (375, 'Command: gm list'); diff --git a/sql/updates/world/2024_09_14_world_00.sql b/sql/updates/world/2024_09_14_world_00.sql deleted file mode 100644 index e901b3b274..0000000000 --- a/sql/updates/world/2024_09_14_world_00.sql +++ /dev/null @@ -1,6 +0,0 @@ -DELETE FROM `skyfire_string` WHERE `entry`=401; -DELETE FROM `skyfire_string` WHERE `entry`=402; -DELETE FROM `skyfire_string` WHERE `entry`=403; -DELETE FROM `skyfire_string` WHERE `entry`=597; -DELETE FROM `skyfire_string` WHERE `entry`=598; -DELETE FROM `skyfire_string` WHERE `entry`=599; diff --git a/sql/updates/world/2024_09_14_world_01.sql b/sql/updates/world/2024_09_14_world_01.sql deleted file mode 100644 index 1cfc4c951e..0000000000 --- a/sql/updates/world/2024_09_14_world_01.sql +++ /dev/null @@ -1,2 +0,0 @@ -DELETE FROM `command` WHERE `name`='account set gmlevel'; -DELETE FROM `command` WHERE `name`='gm list'; \ No newline at end of file diff --git a/sql/updates/world/2026-01-23_world_00.sql b/sql/updates/world/2026-01-23_world_00.sql new file mode 100644 index 0000000000..5b00a0804a --- /dev/null +++ b/sql/updates/world/2026-01-23_world_00.sql @@ -0,0 +1,18 @@ +DELETE FROM `skyfire_string` WHERE `entry`=401; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (401, 'You change security level of account %s to %i.'); +DELETE FROM `skyfire_string` WHERE `entry`=402; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (402, '%s changed your security level to %i.'); +DELETE FROM `skyfire_string` WHERE `entry`=403; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (403, 'You have low security level for this.'); +DELETE FROM `skyfire_string` WHERE `entry`=597; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (597, 'Current gamemasters:'); +DELETE FROM `skyfire_string` WHERE `entry`=598; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (598, '| Account | GM |'); +DELETE FROM `skyfire_string` WHERE `entry`=599; +INSERT INTO `skyfire_string` (`entry`, `content_default`) VALUES (599, 'No gamemasters.'); + +DELETE FROM `command` WHERE `name`='account set gmlevel'; +INSERT INTO `command` (`name`, `permission`, `help`) VALUES ('account set gmlevel', 228, 'Syntax: .account set gmlevel [$account] #level [#realmid] Set the security level for targeted player (can\'t be used at self) or for account $name to a level of #level on the realm #realmID. #level may range from 0 to 3. #reamID may be -1 for all realms.'); +DELETE FROM `command` WHERE `name`='gm list'; +INSERT INTO `command` (`name`, `permission`, `help`) VALUES ('gm list', 375, 'Syntax: .gm list Display a list of all Game Masters accounts and security levels.'); + diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 2bba0609b2..f377a068a2 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -409,7 +409,7 @@ bool AuthSocket::_HandleLogonChallenge() } else { - _srp6.emplace(_login, fields[4].GetBinary(), fields[5].GetBinary()); + _srp6.emplace(_login, fields[5].GetBinary(), fields[6].GetBinary()); BigNumber unk3; unk3.SetRand(16 * 8); @@ -431,7 +431,7 @@ bool AuthSocket::_HandleLogonChallenge() uint8 securityFlags = 0; // Check if token is used - _tokenKey = fields[6].GetString(); + _tokenKey = fields[7].GetString(); if (!_tokenKey.empty()) securityFlags = 4; @@ -455,6 +455,9 @@ bool AuthSocket::_HandleLogonChallenge() if (securityFlags & 0x04) // Security token input pkt << uint8(1); + AccountTypes secLevel = AccountTypes(fields[4].GetUInt8()); + _accountSecurityLevel = secLevel <= AccountTypes::SEC_ADMINISTRATOR ? AccountTypes(secLevel) : AccountTypes::SEC_ADMINISTRATOR; + _localizationName.resize(4); for (int i = 0; i < 4; ++i) _localizationName[i] = ch->country[4 - i - 1]; @@ -667,7 +670,9 @@ bool AuthSocket::_HandleReconnectChallenge() std::reverse(_os.begin(), _os.end()); Field* fields = result->Fetch(); - _accountSecurityLevel = AccountTypes::SEC_PLAYER; + AccountTypes secLevel = AccountTypes(fields[2].GetUInt8()); + _accountSecurityLevel = secLevel <= AccountTypes::SEC_ADMINISTRATOR ? AccountTypes(secLevel) : AccountTypes::SEC_ADMINISTRATOR; + _sessionKey = fields[0].GetBinary(); SkyFire::Crypto::GetRandomBytes(_reconnectProof); diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 3e8afd67fb..57cd44c072 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -113,6 +113,10 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId) stmt->setUInt32(0, accountId); trans->Append(stmt); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); + stmt->setUInt32(0, accountId); + trans->Append(stmt); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS); stmt->setUInt32(0, accountId); trans->Append(stmt); @@ -244,12 +248,21 @@ uint32 AccountMgr::GetId(std::string const& username) AccountTypes AccountMgr::GetSecurity(uint32 accountId) { - return AccountTypes::SEC_PLAYER; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL); + stmt->setUInt32(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + return (result) ? AccountTypes((*result)[0].GetUInt8()) : AccountTypes::SEC_PLAYER; } AccountTypes AccountMgr::GetSecurity(uint32 accountId, int32 realmId) { - return AccountTypes::SEC_PLAYER; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); + stmt->setUInt32(0, accountId); + stmt->setInt32(1, realmId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + return (result) ? AccountTypes((*result)[0].GetUInt8()) : AccountTypes::SEC_PLAYER; } bool AccountMgr::GetName(uint32 accountId, std::string& name) @@ -454,6 +467,30 @@ void AccountMgr::UpdateAccountAccess(rbac::RBACData* rbac, uint32 accountId, uin if (rbac && securityLevel == rbac->GetSecurityLevel()) rbac->SetSecurityLevel(securityLevel); + // Delete old security level from DB + if (realmId == -1) + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); + stmt->setUInt32(0, accountId); + LoginDatabase.Execute(stmt); + } + else + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); + stmt->setUInt32(0, accountId); + stmt->setUInt32(1, realmId); + LoginDatabase.Execute(stmt); + } + + // Add new security level + if (securityLevel) + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); + stmt->setUInt32(0, accountId); + stmt->setUInt8(1, securityLevel); + stmt->setInt32(2, realmId); + LoginDatabase.Execute(stmt); + } } rbac::RBACPermission const* AccountMgr::GetRBACPermission(uint32 permissionId) const diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 4ef9b8a7b1..ce35f945f8 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -119,7 +119,7 @@ namespace rbac RBAC_PERM_COMMAND_ACCOUNT_PASSWORD = 225, RBAC_PERM_COMMAND_ACCOUNT_SET = 226, RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON = 227, - // 228, + RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL = 228, RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD = 229, RBAC_PERM_COMMAND_ACHIEVEMENT = 230, RBAC_PERM_COMMAND_ACHIEVEMENT_ADD = 231, @@ -260,7 +260,7 @@ namespace rbac RBAC_PERM_COMMAND_GM_CHAT = 372, RBAC_PERM_COMMAND_GM_FLY = 373, RBAC_PERM_COMMAND_GM_INGAME = 374, - // 375 + RBAC_PERM_COMMAND_GM_LIST = 375, RBAC_PERM_COMMAND_GM_VISIBLE = 376, RBAC_PERM_COMMAND_GO = 377, RBAC_PERM_COMMAND_GO_CREATURE = 378, diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 876eea14aa..519d9353f9 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -114,6 +114,14 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac else return true; // caller must report error for (target == NULL && target_account == 0) + AccountTypes target_ac_sec = target_sec; + if (m_session->GetSecurity() < target_ac_sec || (strong && m_session->GetSecurity() <= target_ac_sec)) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return true; + } + return false; } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 07ce298a14..2bbbfa2a5e 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -372,6 +372,9 @@ enum SkyFireStrings // level 3 chat LANG_SCRIPTS_RELOADED = 400, + LANG_YOU_CHANGE_SECURITY = 401, + LANG_YOURS_SECURITY_CHANGED = 402, + LANG_YOURS_SECURITY_IS_LOW = 403, LANG_CREATURE_MOVE_DISABLED = 404, LANG_CREATURE_MOVE_ENABLED = 405, LANG_NO_WEATHER = 406, @@ -598,6 +601,9 @@ enum SkyFireStrings LANG_BANLIST_ACCOUNTS_HEADER = 594, LANG_BANLIST_IPS = 595, LANG_BANLIST_IPS_HEADER = 596, + LANG_GMLIST = 597, + LANG_GMLIST_HEADER = 598, + LANG_GMLIST_EMPTY = 599, // End Level 3 list, continued at 1100 diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index f86651367e..47f6239e93 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -859,6 +859,7 @@ int WorldSocket::HandleSendAuthSession() int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) { + uint8 security; uint16 clientBuild; uint32 id; uint32 addonSize; @@ -984,6 +985,22 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) return -1; } + // Checks gmlevel per Realm + stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID); + + stmt->setUInt32(0, id); + stmt->setInt32(1, int32(VirtualRealmID)); + + result = LoginDatabase.Query(stmt); + + if (!result) + security = 0; + else + { + fields = result->Fetch(); + security = fields[0].GetUInt8(); + } + // Re-check account ban (same check as in realmd) stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BANS); @@ -999,6 +1016,16 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) return -1; } + // Check locked state for server + AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit(); + SF_LOG_DEBUG("network", "Allowed Level: %u Player Level %u", uint8(allowedAccountType), security); + if (allowedAccountType > AccountTypes::SEC_PLAYER && AccountTypes(security) < allowedAccountType) + { + SendAuthResponseError(ResponseCodes::AUTH_UNAVAILABLE); + SF_LOG_INFO("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough"); + return -1; + } + // Check that Key and account name are the same on client and server uint8 t[4] = { 0x00, 0x00, 0x00, 0x00 }; @@ -1044,7 +1071,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) LoginDatabase.Execute(stmt); // NOTE ATM the socket is single-threaded, have this in mind ... - ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes::SEC_PLAYER, expansion, mutetime, locale, recruiter, isRecruiter, hasBoost), -1); + ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter, hasBoost), -1); m_Crypt.Init(sessionKey); diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 941bce1f0a..9c68be252a 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -32,6 +32,7 @@ public: { { "addon", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, true, &HandleAccountSetAddonCommand, "", }, { "sec", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC, true, NULL, "", accountSetSecTable }, + { "gmlevel", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL, true, &HandleAccountSetGmLevelCommand, "", }, { "password", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD, true, &HandleAccountSetPasswordCommand, "", }, }; static std::vector accountLockCommandTable = @@ -609,6 +610,108 @@ public: return true; } + static bool HandleAccountSetGmLevelCommand(ChatHandler* handler, char const* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string targetAccountName; + uint32 targetAccountId = 0; + AccountTypes targetSecurity = AccountTypes::SEC_PLAYER; + AccountTypes gm = AccountTypes::SEC_PLAYER; + char* arg1 = strtok((char*)args, " "); + char* arg2 = strtok(NULL, " "); + char* arg3 = strtok(NULL, " "); + bool isAccountNameGiven = true; + + if (!arg3) + { + if (!handler->getSelectedPlayer()) + return false; + isAccountNameGiven = false; + } + + // Check for second parameter + if (!isAccountNameGiven && !arg2) + return false; + + // Check for account + if (isAccountNameGiven) + { + targetAccountName = arg1; + if (!AccountMgr::normalizeString(targetAccountName)) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + } + + // Check for invalid specified GM level. + gm = AccountTypes((isAccountNameGiven) ? atoi(arg2) : atoi(arg1)); + if (gm > AccountTypes::SEC_CONSOLE) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + // handler->getSession() == NULL only for console + targetAccountId = (isAccountNameGiven) ? AccountMgr::GetId(targetAccountName) : handler->getSelectedPlayer()->GetSession()->GetAccountId(); + int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); + AccountTypes playerSecurity; + if (handler->GetSession()) + playerSecurity = AccountMgr::GetSecurity(handler->GetSession()->GetAccountId(), gmRealmID); + else + playerSecurity = AccountTypes::SEC_CONSOLE; + + // can set security level only for target with less security and to less security that we have + // This also restricts setting handler's own security. + targetSecurity = AccountMgr::GetSecurity(targetAccountId, gmRealmID); + if (targetSecurity >= playerSecurity || gm >= playerSecurity) + { + handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + handler->SetSentErrorMessage(true); + return false; + } + + // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 + if (gmRealmID == -1 && !AccountMgr::IsConsoleAccount(playerSecurity)) + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST); + + stmt->setUInt32(0, targetAccountId); + stmt->setUInt8(1, uint8(gm)); + + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (result) + { + handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + handler->SetSentErrorMessage(true); + return false; + } + } + + // Check if provided realmID has a negative value other than -1 + if (gmRealmID < -1) + { + handler->SendSysMessage(LANG_INVALID_REALMID); + handler->SetSentErrorMessage(true); + return false; + } + + rbac::RBACData* rbac = isAccountNameGiven ? NULL : handler->getSelectedPlayer()->GetSession()->GetRBACData(); + sAccountMgr->UpdateAccountAccess(rbac, targetAccountId, uint8(gm), gmRealmID); + + handler->PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); + return true; + } + /// Set password for account static bool HandleAccountSetPasswordCommand(ChatHandler* handler, char const* args) { diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 60938a7e1e..c3c0b0d107 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -31,6 +31,7 @@ public: { "chat", rbac::RBAC_PERM_COMMAND_GM_CHAT, false, &HandleGMChatCommand, "", }, { "fly", rbac::RBAC_PERM_COMMAND_GM_FLY, false, &HandleGMFlyCommand, "", }, { "ingame", rbac::RBAC_PERM_COMMAND_GM_INGAME, true, &HandleGMListIngameCommand, "", }, + { "list", rbac::RBAC_PERM_COMMAND_GM_LIST, true, &HandleGMListFullCommand, "", }, { "visible", rbac::RBAC_PERM_COMMAND_GM_VISIBLE, false, &HandleGMVisibleCommand, "", }, { "", rbac::RBAC_PERM_COMMAND_GM, false, &HandleGMCommand, "", }, }; @@ -143,6 +144,41 @@ public: return true; } + /// Display the list of GMs + static bool HandleGMListFullCommand(ChatHandler* handler, char const* /*args*/) + { + ///- Get the accounts with GM Level >0 + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_GM_ACCOUNTS); + stmt->setUInt8(0, uint8(AccountTypes::SEC_MODERATOR)); + stmt->setInt32(1, int32(realmID)); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (result) + { + handler->SendSysMessage(LANG_GMLIST); + handler->SendSysMessage("========================"); + ///- Cycle through them. Display username and GM level + do + { + Field* fields = result->Fetch(); + char const* name = fields[0].GetCString(); + uint8 security = fields[1].GetUInt8(); + uint8 max = (16 - strlen(name)) / 2; + uint8 max2 = max; + if ((max + max2 + strlen(name)) == 16) + max2 = max - 1; + if (handler->GetSession()) + handler->PSendSysMessage("| %s GMLevel %u", name, security); + else + handler->PSendSysMessage("|%*s%s%*s| %u |", max, " ", name, max2, " ", security); + } while (result->NextRow()); + handler->SendSysMessage("========================"); + } + else + handler->PSendSysMessage(LANG_GMLIST_EMPTY); + return true; + } + //Enable\Disable Invisible mode static bool HandleGMVisibleCommand(ChatHandler* handler, char const* args) { diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index fa8cebdd46..00f5ac6ae9 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -24,10 +24,10 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username LIKE CONCAT('%%', ?, '%%') GROUP BY account.id", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Skyfire realmd', 'Failed login autoban', 1)", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT session_key, id FROM account WHERE username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.session_key, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET session_key = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT id, locked, lock_country, last_ip, salt, verifier, token_key FROM account WHERE username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.id, a.locked, a.lock_country, a.last_ip, aa.gmlevel, a.salt, a.verifier, a.token_key FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_FAILEDLOGINS, "SELECT id, failed_logins FROM account WHERE username = ?", CONNECTION_SYNCH); @@ -62,14 +62,21 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = 1 WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS, "DELETE FROM account_access WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, "DELETE FROM account_access WHERE id = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_ASYNC); + PrepareStatement(LOGIN_INS_ACCOUNT_ACCESS, "INSERT INTO account_access (id,gmlevel,RealmID) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, "SELECT gmlevel FROM account_access WHERE id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT gmlevel FROM account_access WHERE id = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_SYNCH); PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.permissionId, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN rbac_account_permissions aa ON (a.id = aa.accountId AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT username, last_ip, expansion FROM account WHERE id = ?", CONNECTION_SYNCH); - //PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS, "SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST, "SELECT 1 FROM account_access WHERE id = ? AND gmlevel > ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS, "SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_RECRUITER, "SELECT 1 FROM account WHERE recruiter = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_BANS, "SELECT 1 FROM account_banned WHERE id = ? AND active = 1 UNION SELECT 1 FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH); @@ -79,6 +86,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH); PrepareStatement(LOGIN_GET_EMAIL_BY_ID, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION, "INSERT INTO rbac_account_permissions (accountId, permissionId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION, "DELETE FROM rbac_account_permissions WHERE accountId = ? AND permissionId = ? AND (realmId = ? OR realmId = -1)", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h index 0fdad12fa9..9045c55208 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/shared/Database/Implementation/LoginDatabase.h @@ -82,13 +82,20 @@ enum LoginDatabaseStatements LOGIN_UPD_ACCOUNT_ONLINE, LOGIN_UPD_UPTIME_PLAYERS, LOGIN_DEL_OLD_LOGS, + LOGIN_DEL_ACCOUNT_ACCESS, + LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, + LOGIN_INS_ACCOUNT_ACCESS, LOGIN_GET_ACCOUNT_ID_BY_USERNAME, + LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, + LOGIN_GET_GMLEVEL_BY_REALMID, LOGIN_GET_USERNAME_BY_ID, LOGIN_SEL_CHECK_PASSWORD, LOGIN_SEL_CHECK_PASSWORD_BY_NAME, LOGIN_SEL_PINFO, LOGIN_SEL_PINFO_BANS, + LOGIN_SEL_GM_ACCOUNTS, LOGIN_SEL_ACCOUNT_INFO, + LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST, LOGIN_SEL_ACCOUNT_ACCESS, LOGIN_SEL_ACCOUNT_RECRUITER, LOGIN_SEL_BANS, @@ -99,6 +106,7 @@ enum LoginDatabaseStatements LOGIN_SEL_AUTOBROADCAST, LOGIN_GET_EMAIL_BY_ID, + LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, LOGIN_INS_RBAC_ACCOUNT_PERMISSION, LOGIN_DEL_RBAC_ACCOUNT_PERMISSION,