implemented custom error messages in login screen for regex fail or banned account

This commit is contained in:
Kamil 2020-12-17 12:18:04 +01:00 committed by Gent S
parent 26d0623d07
commit 140227406c
3 changed files with 63 additions and 8 deletions

View File

@ -118,8 +118,20 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
userPassword.erase(userPassword.find("\n"), 1); userPassword.erase(userPassword.find("\n"), 1);
// check regex // check regex
if (!CNLoginServer::isLoginDataGood(userLogin, userPassword)) if (!CNLoginServer::isLoginDataGood(userLogin, userPassword)) {
// send a custom error message
INITSTRUCT(sP_FE2CL_GM_REP_PC_ANNOUNCE, msg);
std::string text = "Invalid login or password\n";
text += "Login has to be 4 - 32 characters long and can't contain special characters other than dash and underscore\n";
text += "Password has to be 8 - 32 characters long";
U8toU16(text, msg.szAnnounceMsg, sizeof(msg.szAnnounceMsg));
msg.iDuringTime = 15;
sock->sendPacket((void*)&msg, P_FE2CL_GM_REP_PC_ANNOUNCE, sizeof(sP_FE2CL_GM_REP_PC_ANNOUNCE));
// we still have to send login fail to prevent softlock
return loginFail(LoginError::LOGIN_ERROR, userLogin, sock); return loginFail(LoginError::LOGIN_ERROR, userLogin, sock);
}
Database::Account findUser = {}; Database::Account findUser = {};
Database::findAccount(&findUser, userLogin); Database::findAccount(&findUser, userLogin);
@ -133,7 +145,25 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
// is the account banned // is the account banned
if (findUser.BannedUntil > getTimestamp()) if (findUser.BannedUntil > getTimestamp())
return loginFail(LoginError::LOGIN_ERROR, userLogin, sock); {
// send a custom error message
INITSTRUCT(sP_FE2CL_GM_REP_PC_ANNOUNCE, msg);
// ceiling devision
int64_t remainingDays = (findUser.BannedUntil-getTimestamp()) / 86400 + ((findUser.BannedUntil - getTimestamp()) % 86400 != 0);
std::string text = "Your account has been banned by game master\nReason: ";
text += findUser.BanReason;
text += "\nBan expires in " + std::to_string(remainingDays) + " day";
if (remainingDays > 1)
text += "s";
U8toU16(text, msg.szAnnounceMsg, sizeof(msg.szAnnounceMsg));
msg.iDuringTime = 99999999;
sock->sendPacket((void*)&msg, P_FE2CL_GM_REP_PC_ANNOUNCE, sizeof(sP_FE2CL_GM_REP_PC_ANNOUNCE));
// don't send fail packet to softlock sucker's client
return;
}
/* /*
* calling this here to timestamp login attempt, * calling this here to timestamp login attempt,
@ -180,7 +210,10 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
sock->sendPacket((void*)&*it, P_LS2CL_REP_CHAR_INFO, sizeof(sP_LS2CL_REP_CHAR_INFO)); sock->sendPacket((void*)&*it, P_LS2CL_REP_CHAR_INFO, sizeof(sP_LS2CL_REP_CHAR_INFO));
DEBUGLOG( DEBUGLOG(
std::cout << "Login Server: Loaded " << (int)resp.iCharCount << " characters" << std::endl; std::string message = "Login Server: Loaded " + std::to_string(resp.iCharCount) + "character";
if ((int)resp.iCharCount > 1)
message += "s";
std::cout << message << std::endl;
) )
} }

View File

@ -128,10 +128,29 @@ void Database::checkMetaTable() {
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
if (dbVersion != DATABASE_VERSION) { if (dbVersion != DATABASE_VERSION) {
// we should be handling migrations here in the future // migrations
std::cout << "[FATAL] DB Version doesn't match Server Build" << std::endl; if (dbVersion == 1) {
// Version 1 - > 2
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
int rc = sqlite3_exec(db, "ALTER TABLE Accounts ADD BanReason TEXT", NULL, NULL, NULL);
if (rc != SQLITE_OK) {
std::cout << "[FATAL] Failed to apply Database migration" << std::endl;
exit(1); exit(1);
} }
rc = sqlite3_exec(db, "UPDATE Meta SET Value = 2 WHERE Key = 'DatabaseVersion';", NULL, NULL, NULL);
if (rc != SQLITE_OK) {
std::cout << "[FATAL] Failed to apply Database migration" << std::endl;
exit(1);
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
}
else {
std::cout << "[FATAL] Invalid DB Version" << std::endl;
exit(1);
}
}
} }
void Database::createMetaTable() { void Database::createMetaTable() {
@ -203,6 +222,7 @@ void Database::createTables() {
LastLogin INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, LastLogin INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
BannedUntil INTEGER DEFAULT 0 NOT NULL, BannedUntil INTEGER DEFAULT 0 NOT NULL,
BannedSince INTEGER DEFAULT 0 NOT NULL, BannedSince INTEGER DEFAULT 0 NOT NULL,
BanReason TEXT,
PRIMARY KEY(AccountID AUTOINCREMENT) PRIMARY KEY(AccountID AUTOINCREMENT)
); );
@ -370,7 +390,7 @@ void Database::findAccount(Account* account, std::string login) {
std::lock_guard<std::mutex> lock(dbCrit); std::lock_guard<std::mutex> lock(dbCrit);
const char* sql = R"( const char* sql = R"(
SELECT AccountID, Password, Selected, BannedUntil SELECT AccountID, Password, Selected, BannedUntil, BanReason
FROM Accounts FROM Accounts
WHERE Login = ? WHERE Login = ?
LIMIT 1; LIMIT 1;
@ -386,6 +406,7 @@ void Database::findAccount(Account* account, std::string login) {
account->Password = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))); account->Password = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
account->Selected = sqlite3_column_int(stmt, 2); account->Selected = sqlite3_column_int(stmt, 2);
account->BannedUntil = sqlite3_column_int64(stmt, 3); account->BannedUntil = sqlite3_column_int64(stmt, 3);
account->BanReason = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4));
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
} }

View File

@ -4,7 +4,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define DATABASE_VERSION 1 #define DATABASE_VERSION 2
namespace Database { namespace Database {
@ -13,6 +13,7 @@ namespace Database {
std::string Password; std::string Password;
int Selected; int Selected;
time_t BannedUntil; time_t BannedUntil;
std::string BanReason;
}; };
struct EmailData { struct EmailData {
int PlayerId; int PlayerId;