Account level changes

tied account levels to accounts instead of players. implemented account banning logic in db
This commit is contained in:
Kamil 2020-12-06 00:03:52 +01:00 committed by Gent S
parent 4dc48198ab
commit a12faac0e2
3 changed files with 42 additions and 12 deletions

View File

@ -131,6 +131,10 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
if (!CNLoginServer::isPasswordCorrect(findUser.Password, userPassword)) if (!CNLoginServer::isPasswordCorrect(findUser.Password, userPassword))
return loginFail(LoginError::ID_AND_PASSWORD_DO_NOT_MATCH, userLogin, sock); return loginFail(LoginError::ID_AND_PASSWORD_DO_NOT_MATCH, userLogin, sock);
// is the account banned
if (findUser.BannedUntil > getTimestamp())
return loginFail(LoginError::LOGIN_ERROR, userLogin, sock);
/* /*
* calling this here to timestamp login attempt, * calling this here to timestamp login attempt,
* in order to make duplicate exit sanity check work * in order to make duplicate exit sanity check work
@ -166,7 +170,7 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
DEBUGLOG( DEBUGLOG(
std::cout << "Login Server: Login success. Welcome " << userLogin << " [" << loginSessions[sock].userID << "]" << std::endl; std::cout << "Login Server: Login success. Welcome " << userLogin << " [" << loginSessions[sock].userID << "]" << std::endl;
) )
if (resp.iCharCount == 0) if (resp.iCharCount == 0)
return; return;

View File

@ -64,8 +64,11 @@ void Database::createTables() {
"Login" TEXT NOT NULL UNIQUE, "Login" TEXT NOT NULL UNIQUE,
"Password" TEXT NOT NULL, "Password" TEXT NOT NULL,
"Selected" INTEGER DEFAULT 1 NOT NULL, "Selected" INTEGER DEFAULT 1 NOT NULL,
"AccountLevel" INTEGER NOT NULL,
"Created" INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, "Created" INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
"LastLogin" INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, "LastLogin" INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
"BannedUntil" INTEGER DEFAULT 0 NOT NULL,
"BannedSince" INTEGER DEFAULT 0 NOT NULL,
PRIMARY KEY("AccountID" AUTOINCREMENT) PRIMARY KEY("AccountID" AUTOINCREMENT)
); );
@ -90,7 +93,6 @@ void Database::createTables() {
"Angle" INTEGER NOT NULL, "Angle" INTEGER NOT NULL,
"HP" INTEGER NOT NULL, "HP" INTEGER NOT NULL,
"NameCheck" INTEGER NOT NULL, "NameCheck" INTEGER NOT NULL,
"AccountLevel" INTEGER NOT NULL,
"FusionMatter" INTEGER DEFAULT 0 NOT NULL, "FusionMatter" INTEGER DEFAULT 0 NOT NULL,
"Taros" INTEGER DEFAULT 0 NOT NULL, "Taros" INTEGER DEFAULT 0 NOT NULL,
"Quests" BLOB NOT NULL, "Quests" BLOB NOT NULL,
@ -196,6 +198,7 @@ void Database::createTables() {
"Type" INTEGER NOT NULL, "Type" INTEGER NOT NULL,
"Opt" INTEGER NOT NULL, "Opt" INTEGER NOT NULL,
"TimeLimit" INTEGER NOT NULL, "TimeLimit" INTEGER NOT NULL,
FOREIGN KEY("PlayerID") REFERENCES "Players"("PlayerID") ON DELETE CASCADE,
UNIQUE ("MsgIndex", "Slot") UNIQUE ("MsgIndex", "Slot")
); );
@ -232,7 +235,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" SELECT "AccountID", "Password", "Selected", "BannedUntil"
FROM "Accounts" FROM "Accounts"
WHERE "Login" = ? WHERE "Login" = ?
LIMIT 1; LIMIT 1;
@ -247,6 +250,7 @@ void Database::findAccount(Account* account, std::string login) {
account->AccountID = sqlite3_column_int(stmt, 0); account->AccountID = sqlite3_column_int(stmt, 0);
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);
} }
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
} }
@ -256,8 +260,8 @@ int Database::addAccount(std::string login, std::string password) {
const char* sql = R"( const char* sql = R"(
INSERT INTO "Accounts" INSERT INTO "Accounts"
("Login", "Password") ("Login", "Password", "AccountLevel")
VALUES (?, ?); VALUES (?, ?, ?);
)"; )";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
@ -265,16 +269,36 @@ int Database::addAccount(std::string login, std::string password) {
sqlite3_bind_text(stmt, 1, login.c_str(), -1, 0); sqlite3_bind_text(stmt, 1, login.c_str(), -1, 0);
std::string hashedPassword = BCrypt::generateHash(password); std::string hashedPassword = BCrypt::generateHash(password);
sqlite3_bind_text(stmt, 2, hashedPassword.c_str(), -1, 0); sqlite3_bind_text(stmt, 2, hashedPassword.c_str(), -1, 0);
sqlite3_bind_int(stmt, 3, settings::ACCLEVEL);
int rc = sqlite3_step(stmt); int rc = sqlite3_step(stmt);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
if (rc != SQLITE_DONE) { if (rc != SQLITE_DONE) {
std::cout << "[WARN] Database: failed to add new character" << std::endl; std::cout << "[WARN] Database: failed to add new account" << std::endl;
return 0; return 0;
} }
return sqlite3_last_insert_rowid(db); return sqlite3_last_insert_rowid(db);
} }
void Database::banAccount(int accountId, int days) {
std::lock_guard<std::mutex> lock(dbCrit);
const char* sql = R"(
UPDATE "Accounts"
SET "BannedSince" = (strftime('%s', 'now')),
"BannedUntil" = (strftime('%s', 'now')) + ?
WHERE "AccountID" = ?;
)";
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, days * 86400); // convert days to seconds
sqlite3_bind_int(stmt, 2, accountId);
if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cout << "[WARN] Database: failed to ban player" << std::endl;
}
}
void Database::updateSelected(int accountId, int slot) { void Database::updateSelected(int accountId, int slot) {
std::lock_guard<std::mutex> lock(dbCrit); std::lock_guard<std::mutex> lock(dbCrit);
@ -377,9 +401,9 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
const char* sql = R"( const char* sql = R"(
INSERT INTO "Players" INSERT INTO "Players"
("AccountID", "Slot", "Firstname", "LastName", "XCoordinates" , "YCoordinates", "ZCoordinates", "Angle", ("AccountID", "Slot", "Firstname", "LastName", "XCoordinates" , "YCoordinates", "ZCoordinates", "Angle",
"HP", "NameCheck", "AccountLevel", "Quests") "HP", "NameCheck", "Quests")
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
)"; )";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
std::string firstName = U16toU8(save->szFirstName); std::string firstName = U16toU8(save->szFirstName);
std::string lastName = U16toU8(save->szLastName); std::string lastName = U16toU8(save->szLastName);
@ -398,11 +422,10 @@ int Database::createCharacter(sP_CL2LS_REQ_SAVE_CHAR_NAME* save, int AccountID)
// if FNCode isn't 0, it's a wheel name // if FNCode isn't 0, it's a wheel name
int nameCheck = (settings::APPROVEALLNAMES || save->iFNCode) ? 1 : 0; int nameCheck = (settings::APPROVEALLNAMES || save->iFNCode) ? 1 : 0;
sqlite3_bind_int(stmt, 10, nameCheck); sqlite3_bind_int(stmt, 10, nameCheck);
sqlite3_bind_int(stmt, 11, settings::ACCLEVEL);
// 128 byte blob for completed quests // 128 byte blob for completed quests
unsigned char blobBuffer[128] = { 0 }; unsigned char blobBuffer[128] = { 0 };
sqlite3_bind_blob(stmt, 12, blobBuffer, sizeof(blobBuffer), 0); sqlite3_bind_blob(stmt, 11, blobBuffer, sizeof(blobBuffer), 0);
int rc = sqlite3_step(stmt); int rc = sqlite3_step(stmt);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
@ -795,12 +818,13 @@ void Database::getPlayer(Player* plr, int id) {
p.Level, p.Nano1, p.Nano2, p.Nano3, p.Level, p.Nano1, p.Nano2, p.Nano3,
p.AppearanceFlag, p.TutorialFlag, p.PayZoneFlag, p.AppearanceFlag, p.TutorialFlag, p.PayZoneFlag,
p.XCoordinates, p.YCoordinates, p.ZCoordinates, p.NameCheck, p.XCoordinates, p.YCoordinates, p.ZCoordinates, p.NameCheck,
p.Angle, p.HP, p.AccountLevel, p.FusionMatter, p.Taros, p.Quests, p.Angle, p.HP, acc.AccountLevel, p.FusionMatter, p.Taros, p.Quests,
p.BatteryW, p.BatteryN, p.Mentor, p.WarpLocationFlag, p.BatteryW, p.BatteryN, p.Mentor, p.WarpLocationFlag,
p.SkywayLocationFlag1, p.SkywayLocationFlag2, p.CurrentMissionID, p.SkywayLocationFlag1, p.SkywayLocationFlag2, p.CurrentMissionID,
a.Body, a.EyeColor, a.FaceStyle, a.Gender, a.HairColor, a.HairStyle, a.Height, a.SkinColor a.Body, a.EyeColor, a.FaceStyle, a.Gender, a.HairColor, a.HairStyle, a.Height, a.SkinColor
FROM "Players" as p FROM "Players" as p
INNER JOIN "Appearances" as a ON p.PlayerID = a.PlayerID INNER JOIN "Appearances" as a ON p.PlayerID = a.PlayerID
INNER JOIN "Accounts" as acc ON p.AccountID = acc.AccountID
WHERE p.PlayerID = ? WHERE p.PlayerID = ?
)"; )";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;

View File

@ -11,6 +11,7 @@ namespace Database {
int AccountID; int AccountID;
std::string Password; std::string Password;
int Selected; int Selected;
time_t BannedUntil;
}; };
struct Buddyship { struct Buddyship {
int PlayerAId; int PlayerAId;
@ -52,6 +53,7 @@ namespace Database {
void findAccount(Account* account, std::string login); void findAccount(Account* account, std::string login);
/// returns ID, 0 if something failed /// returns ID, 0 if something failed
int addAccount(std::string login, std::string password); int addAccount(std::string login, std::string password);
void banAccount(int accountId, int days);
void updateSelected(int accountId, int playerId); void updateSelected(int accountId, int playerId);
bool validateCharacter(int characterID, int userID); bool validateCharacter(int characterID, int userID);