From b5779b1aa5b60459dd2d8ff3366fe2eacf591106 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 14 Mar 2021 13:13:26 -0500 Subject: [PATCH 1/4] add /bans --- include/aoclient.h | 4 +++- include/db_manager.h | 10 ++++++++++ src/commands.cpp | 16 ++++++++++++++++ src/db_manager.cpp | 21 +++++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/include/aoclient.h b/include/aoclient.h index 1d663fe..48e9606 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -224,6 +224,7 @@ class AOClient : public QObject { void cmdGM(int argc, QStringList argv); void cmdMute(int argc, QStringList argv); void cmdUnmute(int argc, QStringList argv); + void cmdBans(int argc, QStringList argv); // Casing/RP void cmdPlay(int argc, QStringList argv); void cmdNeed(int argc, QStringList argv); @@ -315,7 +316,8 @@ class AOClient : public QObject { {"m", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdM}}, {"gm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdGM}}, {"mute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdMute}}, - {"unmute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnmute}} + {"unmute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnmute}}, + {"bans", {ACLFlags.value("BAN"), 0, &AOClient::cmdBans}} }; QString partial_packet; diff --git a/include/db_manager.h b/include/db_manager.h index d18b87a..a93b7a4 100644 --- a/include/db_manager.h +++ b/include/db_manager.h @@ -41,6 +41,16 @@ public: long long getBanDuration(QString hdid); long long getBanDuration(QHostAddress hdid); + struct BanInfo { + QString ipid; + QHostAddress ip; + QString hdid; + unsigned long time; + QString reason; + long long duration; + }; + QList getRecentBans(); + void addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration); bool createUser(QString username, QString salt, QString password, unsigned long long acl); diff --git a/src/commands.cpp b/src/commands.cpp index 033050b..3325a20 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -971,6 +971,22 @@ void AOClient::cmdUnmute(int argc, QStringList argv) server->getClientByID(uid)->is_muted = false; } +void AOClient::cmdBans(int argc, QStringList argv) +{ + QStringList recent_bans; + recent_bans << "Last 5 bans:"; + recent_bans << "-----"; + for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) { + recent_bans << "Affected IPID: " + ban.ipid; + recent_bans << "Affected HDID: " + ban.hdid; + recent_bans << "Reason for ban: " + ban.reason; + recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm"); + recent_bans << "Ban lasts until: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm"); + recent_bans << "-----"; + } + sendServerMessage(recent_bans.join("\n")); +} + QStringList AOClient::buildAreaList(int area_idx) { QStringList entries; diff --git a/src/db_manager.cpp b/src/db_manager.cpp index 6a0c0b7..e203fcc 100644 --- a/src/db_manager.cpp +++ b/src/db_manager.cpp @@ -122,6 +122,27 @@ long long DBManager::getBanDuration(QHostAddress ip) } } +QList DBManager::getRecentBans() +{ + QList return_list; + QSqlQuery query; + query.prepare("SELECT TOP(5) * FROM BANS ORDER BY TIME DESC"); + query.setForwardOnly(true); + query.exec(); + while (query.next()) { + BanInfo ban; + ban.ipid = query.value(0).toString(); + ban.hdid = query.value(1).toString(); + ban.ip = QHostAddress(query.value(2).toString()); + ban.time = static_cast(query.value(3).toULongLong()); + ban.reason = query.value(4).toString(); + ban.duration = query.value(5).toLongLong(); + return_list.append(ban); + } + std::reverse(return_list.begin(), return_list.end()); + return return_list; +} + void DBManager::addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration) { QSqlQuery query; From b562b77be9fb9cc232eb79cacaa3b907d7586c7e Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 14 Mar 2021 13:28:59 -0500 Subject: [PATCH 2/4] use BanInfo for inserting bans, send ban id and duration with KB packet --- include/db_manager.h | 6 ++++-- src/commands.cpp | 29 +++++++++++++++-------------- src/db_manager.cpp | 44 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/include/db_manager.h b/include/db_manager.h index a93b7a4..e99ca76 100644 --- a/include/db_manager.h +++ b/include/db_manager.h @@ -39,7 +39,9 @@ public: QString getBanReason(QHostAddress ip); QString getBanReason(QString hdid); long long getBanDuration(QString hdid); - long long getBanDuration(QHostAddress hdid); + long long getBanDuration(QHostAddress ip); + int getBanID(QString hdid); + int getBanID(QHostAddress ip); struct BanInfo { QString ipid; @@ -51,7 +53,7 @@ public: }; QList getRecentBans(); - void addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration); + void addBan(BanInfo ban); bool createUser(QString username, QString salt, QString password, unsigned long long acl); unsigned long long getACL(QString moderator_name); diff --git a/src/commands.cpp b/src/commands.cpp index 3325a20..605f224 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -95,6 +95,8 @@ void AOClient::cmdBan(int argc, QStringList argv) args_str += " " + argv[i]; } + DBManager::BanInfo ban; + QRegularExpression quoteMatcher("['\"](.+?)[\"']"); QRegularExpressionMatchIterator matches = quoteMatcher.globalMatch(args_str); QList unquoted_args; @@ -103,7 +105,6 @@ void AOClient::cmdBan(int argc, QStringList argv) unquoted_args.append(match.captured(1)); } - QString reason; QString duration = "perma"; if (unquoted_args.length() < 1) { @@ -111,7 +112,7 @@ void AOClient::cmdBan(int argc, QStringList argv) return; } - reason = unquoted_args.at(0); + ban.reason = unquoted_args.at(0); if (unquoted_args.length() > 1) duration = unquoted_args.at(1); @@ -126,34 +127,34 @@ void AOClient::cmdBan(int argc, QStringList argv) return; } - QString target_ipid = argv[0]; - QHostAddress ip; - QString hdid; - unsigned long time = QDateTime::currentDateTime().toSecsSinceEpoch(); + ban.duration = duration_seconds; + + ban.ipid = argv[0]; + ban.time = QDateTime::currentDateTime().toSecsSinceEpoch(); bool ban_logged = false; int kick_counter = 0; if (argc > 2) { for (int i = 2; i < argv.length(); i++) { - reason += " " + argv[i]; + ban.reason += " " + argv[i]; } } - for (AOClient* client : server->getClientsByIpid(target_ipid)) { + for (AOClient* client : server->getClientsByIpid(ban.ipid)) { if (!ban_logged) { - ip = client->remote_ip; - hdid = client->hwid; - server->db_manager->addBan(target_ipid, ip, hdid, time, reason, duration_seconds); - sendServerMessage("Banned user with ipid " + target_ipid + " for reason: " + reason); + ban.ip = client->remote_ip; + ban.hdid = client->hwid; + server->db_manager->addBan(ban); + sendServerMessage("Banned user with ipid " + ban.ipid + " for reason: " + ban.reason); ban_logged = true; } - client->sendPacket("KB", {reason}); + client->sendPacket("KB", {ban.reason + "\nID: " + QString::number(server->db_manager->getBanID(ban.ip)) + "\nUntil: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm")}); client->socket->close(); kick_counter++; } if (kick_counter > 1) - sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids"); + sendServerMessage("Kicked " + QString::number(kick_counter) + " clients with matching ipids."); if (!ban_logged) sendServerMessage("User with ipid not found!"); } diff --git a/src/db_manager.cpp b/src/db_manager.cpp index e203fcc..335e10b 100644 --- a/src/db_manager.cpp +++ b/src/db_manager.cpp @@ -122,6 +122,36 @@ long long DBManager::getBanDuration(QHostAddress ip) } } + +int DBManager::getBanID(QString hdid) +{ + QSqlQuery query; + query.prepare("SELECT ID FROM BANS WHERE HDID = ?"); + query.addBindValue(hdid); + query.exec(); + if (query.first()) { + return query.value(0).toInt(); + } + else { + return -1; + } +} + + +int DBManager::getBanID(QHostAddress ip) +{ + QSqlQuery query; + query.prepare("SELECT ID FROM BANS WHERE IP = ?"); + query.addBindValue(ip.toString()); + query.exec(); + if (query.first()) { + return query.value(0).toInt(); + } + else { + return -1; + } +} + QList DBManager::getRecentBans() { QList return_list; @@ -143,16 +173,16 @@ QList DBManager::getRecentBans() return return_list; } -void DBManager::addBan(QString ipid, QHostAddress ip, QString hdid, unsigned long time, QString reason, long long duration) +void DBManager::addBan(BanInfo ban) { QSqlQuery query; query.prepare("INSERT INTO BANS(IPID, HDID, IP, TIME, REASON, DURATION) VALUES(?, ?, ?, ?, ?, ?)"); - query.addBindValue(ipid); - query.addBindValue(hdid); - query.addBindValue(ip.toString()); - query.addBindValue(QString::number(time)); - query.addBindValue(reason); - query.addBindValue(duration); + query.addBindValue(ban.ipid); + query.addBindValue(ban.hdid); + query.addBindValue(ban.ip.toString()); + query.addBindValue(QString::number(ban.time)); + query.addBindValue(ban.reason); + query.addBindValue(ban.duration); if (!query.exec()) qDebug() << "SQL Error:" << query.lastError().text(); } From 9b32188cc6d93fdde631d2af4b65c19d27167ac0 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 14 Mar 2021 13:44:12 -0500 Subject: [PATCH 3/4] add /unban and /removeuser --- include/aoclient.h | 7 ++++++- include/db_manager.h | 2 ++ src/commands.cpp | 22 ++++++++++++++++++++++ src/db_manager.cpp | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/include/aoclient.h b/include/aoclient.h index 48e9606..8370489 100644 --- a/include/aoclient.h +++ b/include/aoclient.h @@ -193,6 +193,7 @@ class AOClient : public QObject { void cmdChangeAuth(int argc, QStringList argv); void cmdSetRootPass(int argc, QStringList argv); void cmdAddUser(int argc, QStringList argv); + void cmdRemoveUser(int argc, QStringList argv); void cmdListPerms(int argc, QStringList argv); void cmdAddPerms(int argc, QStringList argv); void cmdRemovePerms(int argc, QStringList argv); @@ -218,6 +219,7 @@ class AOClient : public QObject { // Moderation void cmdMods(int argc, QStringList argv); void cmdBan(int argc, QStringList argv); + void cmdUnBan(int argc, QStringList argv); void cmdKick(int argc, QStringList argv); void cmdAnnounce(int argc, QStringList argv); void cmdM(int argc, QStringList argv); @@ -317,7 +319,10 @@ class AOClient : public QObject { {"gm", {ACLFlags.value("MODCHAT"), 1, &AOClient::cmdGM}}, {"mute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdMute}}, {"unmute", {ACLFlags.value("MUTE"), 1, &AOClient::cmdUnmute}}, - {"bans", {ACLFlags.value("BAN"), 0, &AOClient::cmdBans}} + {"bans", {ACLFlags.value("BAN"), 0, &AOClient::cmdBans}}, + {"unban", {ACLFlags.value("BAN"), 1, &AOClient::cmdUnBan}}, + {"removeuser", {ACLFlags.value("MODIFY_USERS"), 1, &AOClient::cmdRemoveUser}}, + }; QString partial_packet; diff --git a/include/db_manager.h b/include/db_manager.h index e99ca76..636f3f1 100644 --- a/include/db_manager.h +++ b/include/db_manager.h @@ -54,8 +54,10 @@ public: QList getRecentBans(); void addBan(BanInfo ban); + bool invalidateBan(int id); bool createUser(QString username, QString salt, QString password, unsigned long long acl); + bool deleteUser(QString username); unsigned long long getACL(QString moderator_name); bool authenticate(QString username, QString password); bool updateACL(QString username, unsigned long long acl, bool mode); diff --git a/src/commands.cpp b/src/commands.cpp index 605f224..8789554 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -269,6 +269,14 @@ void AOClient::cmdAddUser(int argc, QStringList argv) sendServerMessage("Unable to create user " + argv[0] + ".\nDoes a user with that name already exist?"); } +void AOClient::cmdRemoveUser(int argc, QStringList argv) +{ + if (server->db_manager->deleteUser(argv[0])) + sendServerMessage("Successfully removed user " + argv[0] + "."); + else + sendServerMessage("Unable to remove user " + argv[0] + ".\nDoes it exist?"); +} + void AOClient::cmdListPerms(int argc, QStringList argv) { unsigned long long user_acl = server->db_manager->getACL(moderator_name); @@ -988,6 +996,20 @@ void AOClient::cmdBans(int argc, QStringList argv) sendServerMessage(recent_bans.join("\n")); } +void AOClient::cmdUnBan(int argc, QStringList argv) +{ + bool ok; + int target_ban = argv[0].toInt(&ok); + if (!ok) { + sendServerMessage("Invalid ban ID."); + return; + } + else if (server->db_manager->invalidateBan(target_ban)) + sendServerMessage("Successfully invalidated ban " + argv[0] + "."); + else + sendServerMessage("Couldn't invalidate ban " + argv[0] + ", are you sure it exists?"); +} + QStringList AOClient::buildAreaList(int area_idx) { QStringList entries; diff --git a/src/db_manager.cpp b/src/db_manager.cpp index 335e10b..bd2ba32 100644 --- a/src/db_manager.cpp +++ b/src/db_manager.cpp @@ -187,6 +187,23 @@ void DBManager::addBan(BanInfo ban) qDebug() << "SQL Error:" << query.lastError().text(); } +bool DBManager::invalidateBan(int id) +{ + QSqlQuery ban_exists; + ban_exists.prepare("SELECT DURATION FROM bans WHERE ID = ?"); + ban_exists.addBindValue(id); + ban_exists.exec(); + + if (ban_exists.first()) + return false; + + QSqlQuery query; + query.prepare("UPDATE bans SET DURATION = 0 WHERE ID = ?"); + query.addBindValue(id); + query.exec(); + return true; +} + bool DBManager::createUser(QString username, QString salt, QString password, unsigned long long acl) { QSqlQuery username_exists; @@ -215,6 +232,23 @@ bool DBManager::createUser(QString username, QString salt, QString password, uns return true; } +bool DBManager::deleteUser(QString username) +{ + QSqlQuery username_exists; + username_exists.prepare("SELECT ACL FROM users WHERE USERNAME = ?"); + username_exists.addBindValue(username); + username_exists.exec(); + + if (username_exists.first()) + return false; + + QSqlQuery query; + query.prepare("DELETE FROM users WHERE USERNAME = ?"); + username_exists.addBindValue(username); + username_exists.exec(); + return true; +} + unsigned long long DBManager::getACL(QString moderator_name) { if (moderator_name == "") From 6b3bfb2fdac0090525c2e23e55db4a662336387e Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 14 Mar 2021 13:49:55 -0500 Subject: [PATCH 4/4] add some cute flavor text for permanent bans --- src/commands.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/commands.cpp b/src/commands.cpp index 8789554..63e7a39 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -986,11 +986,16 @@ void AOClient::cmdBans(int argc, QStringList argv) recent_bans << "Last 5 bans:"; recent_bans << "-----"; for (DBManager::BanInfo ban : server->db_manager->getRecentBans()) { + QString banned_until; + if (ban.duration == -2) + banned_until = "The heat death of the universe"; + else + banned_until = QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm"); recent_bans << "Affected IPID: " + ban.ipid; recent_bans << "Affected HDID: " + ban.hdid; recent_bans << "Reason for ban: " + ban.reason; recent_bans << "Date of ban: " + QDateTime::fromSecsSinceEpoch(ban.time).toString("dd.MM.yyyy, hh:mm"); - recent_bans << "Ban lasts until: " + QDateTime::fromSecsSinceEpoch(ban.time).addSecs(ban.duration).toString("dd.MM.yyyy, hh:mm"); + recent_bans << "Ban lasts until: " + banned_until; recent_bans << "-----"; } sendServerMessage(recent_bans.join("\n"));