Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new account events: onAccountCreate/onAccountRemove & new function getAccountType #3019

Merged
merged 16 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Server/mods/deathmatch/logic/CAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class CAccount
const SString& GetName() { return m_strName; }
void SetName(const std::string& strName);

EAccountType GetType() { return m_AccountType; }
TracerDS marked this conversation as resolved.
Show resolved Hide resolved

void SetPassword(const SString& strPassword);
bool IsPassword(const SString& strPassword, bool* pbUsedHttpPassAppend = nullptr);
SString GetPasswordHash();
Expand Down
156 changes: 78 additions & 78 deletions Server/mods/deathmatch/logic/CAccountManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "CIdArray.h"
#include "CAccessControlListManager.h"
#include "Utils.h"
#include "CMapManager.h"

CAccountManager::CAccountManager(const SString& strDbPathFilename)
: m_AccountProtect(6, 30000, 60000 * 1) // Max of 6 attempts per 30 seconds, then 1 minute ignore
Expand Down Expand Up @@ -862,7 +863,7 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua)
if (iter->second.GetType() == LUA_TBOOLEAN)
{
lua_pushstring(pLua, iter->second.GetKey().c_str());
lua_pushboolean(pLua, iter->second.GetStrValue() == "true" ? true : false);
lua_pushboolean(pLua, iter->second.GetStrValue() == "true");
lua_settable(pLua, -3);
}
if (iter->second.GetType() == LUA_TNUMBER)
Expand Down Expand Up @@ -891,46 +892,44 @@ bool CAccountManager::GetAllAccountData(CAccount* pAccount, lua_State* pLua)
m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT key,value,type from userdata where userid=?", SQLITE_INTEGER, iUserID);

// Do we have any results?
if (result->nRows > 0)
if (result->nRows <= 0)
return false;

// Loop through until i is the same as the number of rows
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
// Loop through until i is the same as the number of rows
for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
// Get our key
strKey = reinterpret_cast<const char*>(row[0].pVal);
// Get our type
int iType = static_cast<int>(row[2].nVal);
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
// Account data is stored as text so we don't need to check what type it is just return it
if (iType == LUA_TNIL)
{
const CRegistryResultRow& row = *iter;
// Get our key
strKey = (const char*)row[0].pVal;
// Get our type
int iType = static_cast<int>(row[2].nVal);
// Account data is stored as text so we don't need to check what type it is just return it
if (iType == LUA_TNIL)
{
lua_pushstring(pLua, strKey);
lua_pushnil(pLua);
lua_settable(pLua, -3);
}
if (iType == LUA_TBOOLEAN)
{
SString strResult = (const char*)row[1].pVal;
lua_pushstring(pLua, strKey);
lua_pushboolean(pLua, strResult == "true" ? true : false);
lua_settable(pLua, -3);
}
if (iType == LUA_TNUMBER)
{
lua_pushstring(pLua, strKey);
lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL));
lua_settable(pLua, -3);
}
else
{
lua_pushstring(pLua, strKey);
lua_pushstring(pLua, ((const char*)row[1].pVal));
lua_settable(pLua, -3);
}
lua_pushstring(pLua, strKey);
lua_pushnil(pLua);
lua_settable(pLua, -3);
}
if (iType == LUA_TBOOLEAN)
{
SString strResult = (const char*)row[1].pVal;
lua_pushstring(pLua, strKey);
lua_pushboolean(pLua, strResult == "true");
lua_settable(pLua, -3);
}
if (iType == LUA_TNUMBER)
{
lua_pushstring(pLua, strKey);
lua_pushnumber(pLua, strtod((const char*)row[1].pVal, NULL));
lua_settable(pLua, -3);
}
else
{
lua_pushstring(pLua, strKey);
lua_pushstring(pLua, ((const char*)row[1].pVal));
lua_settable(pLua, -3);
}
return true;
}
return false;
return true;
}

void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector<CAccount*>& outAccounts)
Expand All @@ -939,10 +938,8 @@ void CAccountManager::GetAccountsBySerial(const SString& strSerial, std::vector<
CRegistryResult result;
m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE serial = ?", SQLITE_TEXT, strSerial.c_str());

for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
const CRegistryResultRow& row = *iter;

CAccount* pAccount = Get((const char*)row[0].pVal);
if (pAccount)
outAccounts.push_back(pAccount);
Expand All @@ -955,10 +952,8 @@ void CAccountManager::GetAccountsByIP(const SString& strIP, std::vector<CAccount
CRegistryResult result;
m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE ip = ?", SQLITE_TEXT, strIP.c_str());

for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
const CRegistryResultRow& row = *iter;

CAccount* pAccount = Get((const char*)row[0].pVal);
if (pAccount)
outAccounts.push_back(pAccount);
Expand All @@ -970,10 +965,8 @@ CAccount* CAccountManager::GetAccountByID(int ID)
CRegistryResult result;
m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "SELECT name FROM accounts WHERE id = ?", SQLITE_INTEGER, ID);

for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
const auto& row = *iter;

return Get(reinterpret_cast<const char*>(row[0].pVal));
}

Expand All @@ -988,39 +981,53 @@ void CAccountManager::GetAccountsByData(const SString& dataName, const SString&
"SELECT acc.name FROM accounts acc, userdata dat WHERE dat.key = ? AND dat.value = ? AND dat.userid = acc.id",
SQLITE_TEXT, dataName.c_str(), SQLITE_TEXT, value.c_str());

for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
const CRegistryResultRow& row = *iter;

CAccount* pAccount = Get((const char*)row[0].pVal);
if (pAccount)
outAccounts.push_back(pAccount);
}
}

// Fires for all joining players
CAccount* CAccountManager::AddGuestAccount(const SString& strName)
{
CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName);
CAccount* pAccount = new CAccount(this, EAccountType::Guest, strName);
CLuaArguments Arguments;
Arguments.PushAccount(pAccount);
g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments);
return pAccount;
}

// Fires only when console is created
CAccount* CAccountManager::AddConsoleAccount(const SString& strName)
{
CAccount* pAccount = new CAccount(this, EAccountType::Console, strName);
CAccount* pAccount = new CAccount(this, EAccountType::Console, strName);
CLuaArguments Arguments;
Arguments.PushAccount(pAccount);
g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments);
return pAccount;
}

// Fires for all created player accounts
CAccount* CAccountManager::AddPlayerAccount(const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial,
const SString& strHttpPassAppend)
{
CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, iUserID, strIP, strSerial, strHttpPassAppend);
CLuaArguments Arguments;
Arguments.PushAccount(pAccount);
g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments);
return pAccount;
}

// Fires whenever "addaccount" or "addAccount" was executed
CAccount* CAccountManager::AddNewPlayerAccount(const SString& strName, const SString& strPassword)
{
CAccount* pAccount = new CAccount(this, EAccountType::Player, strName, strPassword, ++m_iAccounts);
Save(pAccount);
CLuaArguments Arguments;
Arguments.PushAccount(pAccount);
g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountCreate", Arguments);
return pAccount;
}

Expand All @@ -1035,6 +1042,9 @@ bool CAccountManager::RemoveAccount(CAccount* pAccount)
m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM userdata WHERE userid=?", SQLITE_INTEGER, iUserID);
m_pDatabaseManager->Execf(m_hDbConnection, "DELETE FROM serialusage WHERE userid=?", SQLITE_INTEGER, iUserID);
}
CLuaArguments Arguments;
Arguments.PushAccount(pAccount);
g_pGame->GetMapManager()->GetRootElement()->CallEvent("onAccountRemove", Arguments);
delete pAccount;
return true;
}
Expand All @@ -1055,22 +1065,21 @@ void CAccountManager::StaticDbCallback(CDbJobData* pJobData, void* pContext)

void CAccountManager::DbCallback(CDbJobData* pJobData)
{
if (m_pDatabaseManager->QueryPoll(pJobData, 0))
if (!m_pDatabaseManager->QueryPoll(pJobData, 0))
{
if (pJobData->result.status == EJobResult::FAIL)
{
CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason);
if (pJobData->result.strReason.ContainsI("missing database"))
{
// Try reconnection
CLogger::LogPrintf("INFO: Reconnecting to accounts database\n");
ReconnectToDatabase();
}
}
CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason);
return;
}
else

if (pJobData->result.status != EJobResult::FAIL)
return;

CLogger::LogPrintf("ERROR: While updating account with '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason);
if (pJobData->result.strReason.ContainsI("missing database"))
{
CLogger::LogPrintf("ERROR: Something worrying happened in DbCallback '%s': %s.\n", *pJobData->GetCommandStringForLog(), *pJobData->result.strReason);
// Try reconnection
CLogger::LogPrintf("INFO: Reconnecting to accounts database\n");
ReconnectToDatabase();
}
}

Expand All @@ -1079,19 +1088,15 @@ void CAccountManager::DbCallback(CDbJobData* pJobData)
//
bool CAccountManager::IsValidAccountName(const SString& strName)
{
if (strName.length() < MIN_USERNAME_LENGTH)
return false;
return true;
return strName.length() >= MIN_USERNAME_LENGTH;
}

//
// Check password is legal for an existing account
//
bool CAccountManager::IsValidPassword(const SString& strPassword)
{
if (strPassword.length() < MIN_PASSWORD_LENGTH)
return false;
return true;
return strPassword.length() >= MIN_PASSWORD_LENGTH;
}

//
Expand Down Expand Up @@ -1142,12 +1147,8 @@ bool CAccountManager::IsAuthorizedSerialRequired(CAccount* pAccount)
//
bool CAccountManager::IsHttpLoginAllowed(CAccount* pAccount, const SString& strIp)
{
if (!g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) ||
!IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp))
{
return true;
}
return false;
return !g_pGame->GetConfig()->GetAuthSerialHttpEnabled() || g_pGame->GetConfig()->IsAuthSerialHttpIpException(strIp) ||
!IsAuthorizedSerialRequired(pAccount) || pAccount->IsIpAuthorized(strIp);
}

//
Expand All @@ -1173,9 +1174,8 @@ void CAccountManager::LoadAccountSerialUsage(CAccount* pAccount)
" WHERE userid=?",
SQLITE_INTEGER, pAccount->GetID());

for (CRegistryResultIterator iter = result->begin(); iter != result->end(); ++iter)
for (const auto& row : *result.operator->())
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
const CRegistryResultRow& row = *iter;
outSerialUsageList.push_back(CAccount::SSerialUsage());
CAccount::SSerialUsage& info = outSerialUsageList.back();
info.strSerial = (const char*)row[0].pVal;
Expand Down
3 changes: 3 additions & 0 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,9 @@ void CGame::AddBuiltInEvents()
// Account events
m_Events.AddEvent("onAccountDataChange", "account, key, value", NULL, false);

m_Events.AddEvent("onAccountCreate", "account", NULL, false);
m_Events.AddEvent("onAccountRemove", "account", NULL, false);

// Other events
m_Events.AddEvent("onSettingChange", "setting, oldValue, newValue", NULL, false);
m_Events.AddEvent("onChatMessage", "message, element", NULL, false);
Expand Down
16 changes: 16 additions & 0 deletions Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void CLuaAccountDefs::LoadFunctions()

// Account get functions
{"getAccountName", GetAccountName},
{"getAccountType", ArgumentParser<GetAccountType>},
{"getAccountPlayer", GetAccountPlayer},
{"isGuestAccount", IsGuestAccount},
{"getAccountData", GetAccountData},
Expand Down Expand Up @@ -77,6 +78,7 @@ void CLuaAccountDefs::AddClass(lua_State* luaVM)
lua_classfunction(luaVM, "getData", "getAccountData");
lua_classfunction(luaVM, "getAllData", "getAllAccountData");
lua_classfunction(luaVM, "getName", "getAccountName");
lua_classfunction(luaVM, "getType", "getAccountType");
lua_classfunction(luaVM, "getPlayer", "getAccountPlayer");
lua_classfunction(luaVM, "isGuest", "isGuestAccount");

Expand Down Expand Up @@ -116,6 +118,20 @@ int CLuaAccountDefs::GetAccountName(lua_State* luaVM)
return 1;
}

std::optional<std::string> CLuaAccountDefs::GetAccountType(CAccount* pAccount)
{
switch (pAccount->GetType())
{
case EAccountType::Guest:
return "guest";
case EAccountType::Console:
return "console";
case EAccountType::Player:
return "player";
}
return {};
}

int CLuaAccountDefs::GetAccountPlayer(lua_State* luaVM)
{
// player getAccountPlayer ( account theAccount )
Expand Down
3 changes: 3 additions & 0 deletions Server/mods/deathmatch/logic/luadefs/CLuaAccountDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class CLuaAccountDefs : public CLuaDefs
LUA_DECLARE(GetAccount);
LUA_DECLARE(GetAccounts);
LUA_DECLARE(GetAccountName);

static std::optional<std::string> GetAccountType(CAccount* pAccount);

LUA_DECLARE(GetAccountPlayer);
LUA_DECLARE(IsGuestAccount);
LUA_DECLARE(GetAccountData);
Expand Down