Database saving update (#104)

* implemented saving BatteryN and BatteryW

* implemented saving mentor

* moved int64->blob parsing to a separate function

* moved parsing blob->int64 to a separate function

* added functions for parsing int32->blob and vice versa

* added functions for parsing int16->blob and vice versa

* WIP saving quest items and active tasks

* Quest items are stored in inventory table instead of blob

* added sanity check for missionId

* saving active missions works

* removed unneccesary include

* implemented saving warplocationflag, skywaylocationflag and currentmissionid in database

* INFO DB message now shows how many accounts and player characters are in the database

* fixed dbsaveinterval being in [login] instead of [shard]

* fixed mission quit:
- fixed wrong json name, causing qitems not deleting properly
- quitting mission now resets npc kill count

* adjusted saving active missions

* removed blob parsing functions that ended up being unused

* removed accidentaly added include

* removed sending PCStyle2 on Player Enter

* added a sanity check in itemMoveHandler

* removed MapNum from PCLoad, as client doesn't even read it

* set BuddyWarpCooldown to 60s on PCLoad

* fixed a bug causing EXIT DUPLICATE not working

* added creation and last login timestamps to accounts and players

* added a sanity check for P_CL2LS_REQ_PC_EXIT_DUPLICATE

* implemented web api support, toggled by new setting (off by default)

* add usewebapi to config

Co-authored-by: Gent <gentsemaj@live.com>
This commit is contained in:
kamilprzyb
2020-09-21 21:43:53 +02:00
committed by GitHub
parent 321dca3f79
commit 5e0948ea93
11 changed files with 332 additions and 58 deletions

View File

@@ -53,17 +53,27 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
else
{
std::unique_ptr<Database::Account> findUser = Database::findAccount(userLogin);
// if account not found, create it
// if account not found
if (findUser == nullptr)
{
loginSessions[sock] = CNLoginData();
loginSessions[sock].userID = Database::addAccount(userLogin, userPassword);
loginSessions[sock].slot = 1;
success = true;
//web api takes care of registration
if (settings::USEWEBAPI)
errorCode = (int)LoginError::ID_DOESNT_EXIST;
//without web api, create new account
else
{
loginSessions[sock] = CNLoginData();
loginSessions[sock].userID = Database::addAccount(userLogin, userPassword);
loginSessions[sock].slot = 1;
success = true;
}
}
// if user exists, check if password is correct
else if (CNLoginServer::isPasswordCorrect(findUser->Password, userPassword))
{
/*calling this here to timestamp login attempt,
* in order to make duplicate exit sanity check work*/
Database::updateSelected(findUser->AccountID, findUser->Selected);
// check if account isn't currently in use
if (CNLoginServer::isAccountInUse(findUser->AccountID) ||
PlayerManager::isAccountInUse(findUser->AccountID))
@@ -100,7 +110,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
resp.iPaymentFlag = 1;
resp.iOpenBetaFlag = 0;
resp.uiSvrTime = getTime();
// send the resp in with original key
sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_SUCC, sizeof(sP_LS2CL_REP_LOGIN_SUCC));
@@ -144,10 +154,8 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
// Failure
else {
INITSTRUCT(sP_LS2CL_REP_LOGIN_FAIL, resp);
memcpy(resp.szID, login->szID, sizeof(char16_t) * 33);
U8toU16(userLogin, resp.szID);
resp.iErrorCode = errorCode;
sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_FAIL, sizeof(sP_LS2CL_REP_LOGIN_FAIL));
}
@@ -348,8 +356,22 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
sP_CL2LS_REQ_PC_EXIT_DUPLICATE* exit = (sP_CL2LS_REQ_PC_EXIT_DUPLICATE*)data->buf;
auto account = Database::findAccount(U16toU8(exit->szID));
//sanity check
if (account == nullptr)
{
std::cout << "[WARN] P_CL2LS_REQ_PC_EXIT_DUPLICATE submitted unknown username: " << exit->szID << std::endl;
break;
}
/* sanity check
* client is supposed to send us user password for verification,
* however it never sends it (>_<)
* therefore, we check if the account made a login attempt within last 30s
*/
if (account->LastLogin + 30000 < getTime())
{
std::cout << "[WARN] P_CL2LS_REQ_PC_EXIT_DUPLICATE submitted without a login attempt on: " << exit->szID << std::endl;
break;
}
int accountId = account->AccountID;
if (!exitDuplicate(accountId))
@@ -407,11 +429,19 @@ bool CNLoginServer::exitDuplicate(int accountId) {
bool CNLoginServer::isLoginDataGood(std::string login, std::string password) {
std::regex loginRegex("[a-zA-Z0-9_-]{4,32}");
//web api sends password hashed, so we don't check it
if (settings::USEWEBAPI)
return (std::regex_match(login, loginRegex));
//without web api
std::regex passwordRegex("[a-zA-Z0-9!@#$%^&*()_+]{8,32}");
return (std::regex_match(login, loginRegex) && std::regex_match(password, passwordRegex));
}
bool CNLoginServer::isPasswordCorrect(std::string actualPassword, std::string tryPassword) {
//web api sends password already hashed
if (settings::USEWEBAPI)
return actualPassword == tryPassword;
//without web api
return BCrypt::validatePassword(tryPassword, actualPassword);
}