add some user management command

This commit is contained in:
scatterflower 2020-09-29 06:11:04 -05:00
parent 7c6b892fb9
commit 2cc415e42b
5 changed files with 150 additions and 38 deletions

View File

@ -53,12 +53,13 @@ class AOClient : public QObject {
QString moderator_name = "";
QString ooc_name = "";
enum ACLFlags {
NONE = 0ULL,
KICK = 1ULL << 0,
BAN = 1ULL << 1,
BGLOCK = 1ULL << 2,
SUPER = ~0ULL
QMap<QString, unsigned long long> ACLFlags {
{"NONE", 0ULL},
{"KICK", 1ULL << 0},
{"BAN", 1ULL << 1},
{"BGLOCK", 1ULL << 2},
{"MODIFY_USERS", 1ULL << 3},
{"SUPER", ~0ULL}
};
public slots:
@ -112,21 +113,21 @@ class AOClient : public QObject {
};
const QMap<QString, PacketInfo> packets {
{"HI", {ACLFlags::NONE, 1, &AOClient::pktHardwareId}},
{"ID", {ACLFlags::NONE, 2, &AOClient::pktSoftwareId}},
{"askchaa", {ACLFlags::NONE, 0, &AOClient::pktBeginLoad}},
{"RC", {ACLFlags::NONE, 0, &AOClient::pktRequestChars}},
{"RM", {ACLFlags::NONE, 0, &AOClient::pktRequestMusic}},
{"RD", {ACLFlags::NONE, 0, &AOClient::pktLoadingDone}},
{"PW", {ACLFlags::NONE, 1, &AOClient::pktCharPassword}},
{"CC", {ACLFlags::NONE, 3, &AOClient::pktSelectChar}},
{"MS", {ACLFlags::NONE, 1, &AOClient::pktIcChat}}, // TODO: doublecheck
{"CT", {ACLFlags::NONE, 2, &AOClient::pktOocChat}},
{"CH", {ACLFlags::NONE, 1, &AOClient::pktPing}},
{"MC", {ACLFlags::NONE, 2, &AOClient::pktChangeMusic}},
{"RT", {ACLFlags::NONE, 1, &AOClient::pktWtCe}},
{"HP", {ACLFlags::NONE, 2, &AOClient::pktHpBar}},
{"WSIP", {ACLFlags::NONE, 1, &AOClient::pktWebSocketIp}}
{"HI", {ACLFlags.value("NONE"), 1, &AOClient::pktHardwareId}},
{"ID", {ACLFlags.value("NONE"), 2, &AOClient::pktSoftwareId}},
{"askchaa", {ACLFlags.value("NONE"), 0, &AOClient::pktBeginLoad}},
{"RC", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestChars}},
{"RM", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestMusic}},
{"RD", {ACLFlags.value("NONE"), 0, &AOClient::pktLoadingDone}},
{"PW", {ACLFlags.value("NONE"), 1, &AOClient::pktCharPassword}},
{"CC", {ACLFlags.value("NONE"), 3, &AOClient::pktSelectChar}},
{"MS", {ACLFlags.value("NONE"), 1, &AOClient::pktIcChat}}, // TODO: doublecheck
{"CT", {ACLFlags.value("NONE"), 2, &AOClient::pktOocChat}},
{"CH", {ACLFlags.value("NONE"), 1, &AOClient::pktPing}},
{"MC", {ACLFlags.value("NONE"), 2, &AOClient::pktChangeMusic}},
{"RT", {ACLFlags.value("NONE"), 1, &AOClient::pktWtCe}},
{"HP", {ACLFlags.value("NONE"), 2, &AOClient::pktHpBar}},
{"WSIP", {ACLFlags.value("NONE"), 1, &AOClient::pktWebSocketIp}}
};
// Commands
@ -141,6 +142,9 @@ class AOClient : public QObject {
void cmdSetBackground(int argc, QStringList argv);
void cmdBgLock(int argc, QStringList argv);
void cmdBgUnlock(int argc, QStringList argv);
void cmdAddUser(int argc, QStringList argv);
void cmdListPerms(int argc, QStringList argv);
void cmdAddPerms(int argc, QStringList argv);
// Command helper functions
QStringList buildAreaList(int area_idx);
@ -155,17 +159,20 @@ class AOClient : public QObject {
};
const QMap<QString, CommandInfo> commands {
{"login", {ACLFlags::NONE, 1, &AOClient::cmdLogin}},
{"getareas", {ACLFlags::NONE, 0 , &AOClient::cmdGetAreas}},
{"getarea", {ACLFlags::NONE, 0, &AOClient::cmdGetArea}},
{"ban", {ACLFlags::BAN, 2, &AOClient::cmdBan}},
{"kick", {ACLFlags::KICK, 2, &AOClient::cmdKick}},
{"changeauth", {ACLFlags::SUPER, 0, &AOClient::cmdChangeAuth}},
{"rootpass", {ACLFlags::SUPER, 1, &AOClient::cmdSetRootPass}},
{"background", {ACLFlags::NONE, 1, &AOClient::cmdSetBackground}},
{"bg", {ACLFlags::NONE, 1, &AOClient::cmdSetBackground}},
{"bglock", {ACLFlags::BGLOCK, 0, &AOClient::cmdBgLock}},
{"bgunlock", {ACLFlags::BGLOCK, 0, &AOClient::cmdBgUnlock}}
{"login", {ACLFlags.value("NONE"), 1, &AOClient::cmdLogin}},
{"getareas", {ACLFlags.value("NONE"), 0 , &AOClient::cmdGetAreas}},
{"getarea", {ACLFlags.value("NONE"), 0, &AOClient::cmdGetArea}},
{"ban", {ACLFlags.value("BAN"), 2, &AOClient::cmdBan}},
{"kick", {ACLFlags.value("KICK"), 2, &AOClient::cmdKick}},
{"changeauth", {ACLFlags.value("SUPER"), 0, &AOClient::cmdChangeAuth}},
{"rootpass", {ACLFlags.value("SUPER"), 1, &AOClient::cmdSetRootPass}},
{"background", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground}},
{"bg", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground}},
{"bglock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgLock}},
{"bgunlock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgUnlock}},
{"adduser", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddUser}},
{"listperms", {ACLFlags.value("MODIFY_USERS"), 0, &AOClient::cmdListPerms}},
{"addperm", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddPerms}}
};
QString partial_packet;

View File

@ -18,8 +18,6 @@
#ifndef BAN_MANAGER_H
#define BAN_MANAGER_H
#include "include/aoclient.h"
#include <QDebug>
#include <QHostAddress>
#include <QMessageAuthenticationCode>
@ -45,6 +43,7 @@ public:
void createUser(QString username, QString salt, QString password, unsigned long long acl);
unsigned long long getACL(QString moderator_name);
bool authenticate(QString username, QString password);
bool updateACL(QString username, unsigned long long acl);
private:
const QString DRIVER;

View File

@ -218,7 +218,7 @@ void AOClient::sendServerMessage(QString message)
bool AOClient::checkAuth(unsigned long long acl_mask)
{
if (acl_mask != ACLFlags::NONE) {
if (acl_mask != ACLFlags.value("NONE")) {
if (!authenticated) {
return false;
}

View File

@ -32,6 +32,11 @@ void AOClient::cmdLogin(int argc, QStringList argv)
QString modpass = config.value("modpass", "default").toString();
QString auth_type = config.value("auth", "simple").toString();
if (authenticated) {
sendServerMessage("You are already logged in!");
return;
}
// TODO: tell the user if no modpass is set
if (auth_type == "simple") {
if(argv[0] == modpass) {
@ -162,7 +167,7 @@ void AOClient::cmdSetRootPass(int argc, QStringList argv)
quint64 salt_number = QRandomGenerator::system()->generate64();
QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
server->db_manager->createUser("root", salt, argv[0], ACLFlags::SUPER);
server->db_manager->createUser("root", salt, argv[0], ACLFlags.value("SUPER"));
}
void AOClient::cmdSetBackground(int argc, QStringList argv)
@ -199,6 +204,84 @@ void AOClient::cmdBgUnlock(int argc, QStringList argv)
server->broadcast(AOPacket("CT", {"Server", current_char + " unlocked the background.", "1"}), current_area);
}
void AOClient::cmdAddUser(int argc, QStringList argv)
{
quint64 salt_number = QRandomGenerator::system()->generate64();
QString salt = QStringLiteral("%1").arg(salt_number, 16, 16, QLatin1Char('0'));
server->db_manager->createUser(argv[0], salt, argv[1], ACLFlags.value("NONE"));
sendServerMessage("Created user " + argv[0] + ".\nUse /addperm to modify their permissions.");
}
void AOClient::cmdListPerms(int argc, QStringList argv)
{
unsigned long long user_acl = server->db_manager->getACL(moderator_name);
QStringList message;
if (argc == 0) {
// Just print out all permissions available to the user.
message.append("You can add the following permissions to users:");
for (QString perm : ACLFlags.keys()) {
if (perm == "NONE"); // don't need to list this one
else if (perm == "SUPER") {
if (user_acl == ACLFlags.value("SUPER")) // This has to be checked separately, because SUPER & anything will always be truthy
message.append("SUPER (Be careful! This grants the user all permissions.)");
}
else if ((ACLFlags.value(perm) & user_acl) == 0); // user doesn't have this permission, don't print it
else
message.append(perm);
}
}
else {
message.append("User " + argv[0] + " has the following permissions:");
unsigned long long acl = server->db_manager->getACL(argv[0]);
if (acl == 0) {
sendServerMessage("This user either doesn't exist, or has no permissions set.");
return;
}
for (QString perm : ACLFlags.keys()) {
if ((ACLFlags.value(perm) & acl) != 0 && perm != "SUPER") {
message.append(perm);
}
}
}
sendServerMessage(message.join("\n"));
}
void AOClient::cmdAddPerms(int argc, QStringList argv)
{
unsigned long long user_acl = server->db_manager->getACL(moderator_name);
argv[1] = argv[1].toUpper();
if (!ACLFlags.keys().contains(argv[1])) {
sendServerMessage("That permission doesn't exist!");
return;
}
if (argv[1] == "SUPER") {
if (user_acl != ACLFlags.value("SUPER")) {
// This has to be checked separately, because SUPER & anything will always be truthy
sendServerMessage("You aren't allowed to add that permission!");
return;
}
}
if (argv[1] == "NONE") {
sendServerMessage("Added no permissions!");
return;
}
unsigned long long newperm = ACLFlags.value(argv[1]);
if ((newperm & user_acl) != 0) {
if (server->db_manager->updateACL(argv[0], newperm))
sendServerMessage("Successfully added permission " + argv[1] + " to user " + argv[0]);
else
sendServerMessage(argv[0] + " wasn't found!");
return;
}
sendServerMessage("You aren't allowed to add that permission!");
}
QStringList AOClient::buildAreaList(int area_idx)
{
QStringList entries;

View File

@ -110,12 +110,12 @@ void DBManager::createUser(QString username, QString salt, QString password, uns
unsigned long long DBManager::getACL(QString moderator_name)
{
if (moderator_name == "")
return AOClient::ACLFlags::NONE;
return 0;
QSqlQuery query("SELECT ACL FROM users WHERE USERNAME = ?");
query.addBindValue(moderator_name);
query.exec();
if (!query.first())
return AOClient::ACLFlags::NONE;
return 0;
return query.value(0).toULongLong();
}
@ -146,6 +146,29 @@ bool DBManager::authenticate(QString username, QString password)
return salted_password == stored_pass;
}
bool DBManager::updateACL(QString username, unsigned long long acl)
{
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;
unsigned long long old_acl = username_exists.value(0).toULongLong();
unsigned long long new_acl = acl | old_acl;
if (acl == 0) // Allow clearing all perms via adding perm "NONE"
new_acl = 0;
QSqlQuery update_acl;
update_acl.prepare("UPDATE users SET ACL = ? WHERE USERNAME = ?");
update_acl.addBindValue(new_acl);
update_acl.addBindValue(username);
update_acl.exec();
return true;
}
DBManager::~DBManager()
{
db.close();