Added command extension system (#12)
* Added command extension system Resolve #10 * Added akashi definitions * Updated headers to comply to the standard * Added full definition to argument * Clang-format pass * Missing header for GCC * Missing header for GCC * Move method implementation to source file
This commit is contained in:
parent
ec44039816
commit
f307f728c9
12
bin/config_sample/acl_roles.ini
Normal file
12
bin/config_sample/acl_roles.ini
Normal file
@ -0,0 +1,12 @@
|
||||
[moderator]
|
||||
ban = true
|
||||
kick = true
|
||||
mute = true
|
||||
chat_moderator = true
|
||||
|
||||
[supervisor]
|
||||
ban = true
|
||||
kick = true
|
||||
mute = true
|
||||
chat_moderator = true
|
||||
modify_users = true
|
80
bin/config_sample/command_extensions.ini
Normal file
80
bin/config_sample/command_extensions.ini
Normal file
@ -0,0 +1,80 @@
|
||||
[getarea]
|
||||
aliases = ga
|
||||
|
||||
[getareas]
|
||||
aliases = gas
|
||||
|
||||
[area_lock]
|
||||
aliases = lock_area lock
|
||||
|
||||
[area_spectate]
|
||||
aliases = spectatable
|
||||
|
||||
[area_unlock]
|
||||
aliases = unlock_area unlock
|
||||
|
||||
[area_kick]
|
||||
aliases = kick_area areakick
|
||||
|
||||
[background]
|
||||
aliases = bg
|
||||
|
||||
[lock_background]
|
||||
aliases = lock_bg lockbg bglock
|
||||
|
||||
[unlock_background]
|
||||
aliases = unlock_bg unlockbg bgunlock
|
||||
|
||||
[roll]
|
||||
aliases = r
|
||||
|
||||
[set_motd]
|
||||
aliases = setmotd
|
||||
|
||||
[force_charselect]
|
||||
aliases = forcecharselect
|
||||
|
||||
[notecard_reveal]
|
||||
aliases = reveal_notecard notecardreveal
|
||||
|
||||
[notecard_clear]
|
||||
aliases = clear_notecard notecardclear
|
||||
|
||||
[allow_blankposting]
|
||||
aliases = allowblankposting
|
||||
|
||||
[forceimmediate]
|
||||
aliases = force_noint_pres
|
||||
|
||||
[allow_iniswap]
|
||||
aliases = allowiniswap
|
||||
|
||||
[ooc_mute]
|
||||
aliases = mute_ooc oocmute
|
||||
|
||||
[ooc_unmute]
|
||||
aliases = unmute_ooc oocunmute
|
||||
|
||||
[block_wtce]
|
||||
aliases = blockwtce
|
||||
|
||||
[unblock_wtce]
|
||||
aliases = unblockwtce
|
||||
|
||||
[block_dj]
|
||||
aliases = blockdj
|
||||
|
||||
[unblock_dj]
|
||||
aliases = unblockdj
|
||||
|
||||
[kick_uid]
|
||||
aliases = kickuid
|
||||
|
||||
[update_ban]
|
||||
aliases = updateban
|
||||
|
||||
[ignore_bglist]
|
||||
aliases = ignorebglist
|
||||
|
||||
[ignore_bglist]
|
||||
aliases = ignorebglist
|
@ -29,6 +29,7 @@ SOURCES += \
|
||||
src/aoclient.cpp \
|
||||
src/aopacket.cpp \
|
||||
src/area_data.cpp \
|
||||
src/command_extension.cpp \
|
||||
src/commands/area.cpp \
|
||||
src/commands/authentication.cpp \
|
||||
src/commands/casing.cpp \
|
||||
@ -53,8 +54,10 @@ SOURCES += \
|
||||
|
||||
HEADERS += include/aoclient.h \
|
||||
include/acl_roles_handler.h \
|
||||
include/akashidefs.h \
|
||||
include/aopacket.h \
|
||||
include/area_data.h \
|
||||
include/command_extension.h \
|
||||
include/config_manager.h \
|
||||
include/data_types.h \
|
||||
include/db_manager.h \
|
||||
|
@ -41,7 +41,7 @@ class ACLRole
|
||||
*
|
||||
* @see ACLRoleHandler#loadFile and ACLRoleHandler#saveFile
|
||||
*/
|
||||
static const QHash<ACLRole::Permission, QString> permission_captions;
|
||||
static const QHash<ACLRole::Permission, QString> PERMISSION_CAPTIONS;
|
||||
|
||||
/**
|
||||
* @brief Constructs a role without any permissions.
|
||||
@ -98,6 +98,7 @@ class ACLRole
|
||||
*/
|
||||
ACLRole::Permissions m_permissions;
|
||||
};
|
||||
Q_DECLARE_METATYPE(ACLRole::Permission)
|
||||
|
||||
class ACLRolesHandler : public QObject
|
||||
{
|
||||
|
17
core/include/akashidefs.h
Normal file
17
core/include/akashidefs.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef AKASHIDEFS_H
|
||||
#define AKASHIDEFS_H
|
||||
|
||||
#include <QString>
|
||||
#include <qnamespace.h>
|
||||
|
||||
namespace akashi {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
using SplitBehavior = QString::SplitBehavior;
|
||||
#else
|
||||
using SplitBehavior = Qt::SplitBehaviorFlags;
|
||||
#endif
|
||||
const SplitBehavior KeepEmptyParts = SplitBehavior::KeepEmptyParts;
|
||||
const SplitBehavior SkipEmptyParts = SplitBehavior::SkipEmptyParts;
|
||||
}
|
||||
|
||||
#endif // AKASHIDEFS_H
|
@ -46,6 +46,37 @@ class AOClient : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Describes a command's details.
|
||||
*/
|
||||
struct CommandInfo
|
||||
{
|
||||
QVector<ACLRole::Permission> acl_permissions; //!< The permissions necessary to be able to run the command. @see ACLRole::Permission.
|
||||
int minArgs; //!< The minimum mandatory arguments needed for the command to function.
|
||||
void (AOClient::*action)(int, QStringList);
|
||||
};
|
||||
|
||||
/**
|
||||
* @property CommandInfo::action
|
||||
*
|
||||
* @brief A function reference that contains what the command actually does.
|
||||
*
|
||||
* @param int When called, this parameter will be filled with the argument count. @anchor commandArgc
|
||||
* @param QStringList When called, this parameter will be filled the list of arguments. @anchor commandArgv
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The list of commands available on the server.
|
||||
*
|
||||
* @details Generally called with the format of `/command parameters` in the out-of-character chat.
|
||||
* @showinitializer
|
||||
*
|
||||
* @tparam QString The name of the command, without the leading slash.
|
||||
* @tparam CommandInfo The details of the command.
|
||||
* See @ref CommandInfo "the type's documentation" for more details.
|
||||
*/
|
||||
static const QMap<QString, CommandInfo> COMMANDS;
|
||||
|
||||
/**
|
||||
* @brief Creates an instance of the AOClient class.
|
||||
*
|
||||
@ -1032,16 +1063,19 @@ class AOClient : public QObject
|
||||
void cmdHelp(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Gets or sets the server's Message Of The Day.
|
||||
*
|
||||
* @details If called without arguments, gets the MOTD.
|
||||
*
|
||||
* If it has any number of arguments, it is set as the **MOTD**.
|
||||
* @brief Gets the server's Message Of The Day.
|
||||
*
|
||||
* @iscommand
|
||||
*/
|
||||
void cmdMOTD(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Sets the server's Message Of The Day.
|
||||
*
|
||||
* @iscommand
|
||||
*/
|
||||
void cmdSetMOTD(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Gives a very brief description of Akashi.
|
||||
*
|
||||
@ -1635,13 +1669,20 @@ class AOClient : public QObject
|
||||
void cmdUnCharCurse(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Forces a client into the charselect screen.
|
||||
* @brief Forces the caller's client into the charselect screen.
|
||||
*
|
||||
* @iscommand
|
||||
*/
|
||||
void cmdCharSelect(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Forces the target's client into the charselect screen.
|
||||
*
|
||||
* @details The only argument is the **target's ID** whom the client wants to force into charselect.
|
||||
*
|
||||
* @iscommand
|
||||
*/
|
||||
void cmdCharSelect(int argc, QStringList argv);
|
||||
void cmdForceCharSelect(int argc, QStringList argv);
|
||||
|
||||
/**
|
||||
* @brief Sends a message to an area that you a CM in.
|
||||
@ -2042,176 +2083,6 @@ class AOClient : public QObject
|
||||
*/
|
||||
bool change_auth_started = false;
|
||||
|
||||
/**
|
||||
* @brief Describes a command's details.
|
||||
*/
|
||||
struct CommandInfo
|
||||
{
|
||||
ACLRole::Permission acl_permission; //!< The permissions necessary to be able to run the command. @see ACLRole::Permission.
|
||||
int minArgs; //!< The minimum mandatory arguments needed for the command to function.
|
||||
void (AOClient::*action)(int, QStringList);
|
||||
};
|
||||
|
||||
/**
|
||||
* @property CommandInfo::action
|
||||
*
|
||||
* @brief A function reference that contains what the command actually does.
|
||||
*
|
||||
* @param int When called, this parameter will be filled with the argument count. @anchor commandArgc
|
||||
* @param QStringList When called, this parameter will be filled the list of arguments. @anchor commandArgv
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The list of commands available on the server.
|
||||
*
|
||||
* @details Generally called with the format of `/command parameters` in the out-of-character chat.
|
||||
* @showinitializer
|
||||
*
|
||||
* @tparam QString The name of the command, without the leading slash.
|
||||
* @tparam CommandInfo The details of the command.
|
||||
* See @ref CommandInfo "the type's documentation" for more details.
|
||||
*/
|
||||
const QMap<QString, CommandInfo> commands{
|
||||
{"login", {ACLRole::NONE, 0, &AOClient::cmdLogin}},
|
||||
{"getareas", {ACLRole::NONE, 0, &AOClient::cmdGetAreas}},
|
||||
{"gas", {ACLRole::NONE, 0, &AOClient::cmdGetAreas}},
|
||||
{"getarea", {ACLRole::NONE, 0, &AOClient::cmdGetArea}},
|
||||
{"ga", {ACLRole::NONE, 0, &AOClient::cmdGetArea}},
|
||||
{"ban", {ACLRole::BAN, 3, &AOClient::cmdBan}},
|
||||
{"kick", {ACLRole::KICK, 2, &AOClient::cmdKick}},
|
||||
{"changeauth", {ACLRole::SUPER, 0, &AOClient::cmdChangeAuth}},
|
||||
{"rootpass", {ACLRole::SUPER, 1, &AOClient::cmdSetRootPass}},
|
||||
{"background", {ACLRole::NONE, 1, &AOClient::cmdSetBackground}},
|
||||
{"bg", {ACLRole::NONE, 1, &AOClient::cmdSetBackground}},
|
||||
{"bglock", {ACLRole::BGLOCK, 0, &AOClient::cmdBgLock}},
|
||||
{"bgunlock", {ACLRole::BGLOCK, 0, &AOClient::cmdBgUnlock}},
|
||||
{"adduser", {ACLRole::MODIFY_USERS, 2, &AOClient::cmdAddUser}},
|
||||
{"removeuser", {ACLRole::MODIFY_USERS, 1, &AOClient::cmdRemoveUser}},
|
||||
{"listusers", {ACLRole::MODIFY_USERS, 0, &AOClient::cmdListUsers}},
|
||||
{"setperms", {ACLRole::MODIFY_USERS, 2, &AOClient::cmdSetPerms}},
|
||||
{"removeperms", {ACLRole::MODIFY_USERS, 1, &AOClient::cmdRemovePerms}},
|
||||
{"listperms", {ACLRole::NONE, 0, &AOClient::cmdListPerms}},
|
||||
{"logout", {ACLRole::NONE, 0, &AOClient::cmdLogout}},
|
||||
{"pos", {ACLRole::NONE, 1, &AOClient::cmdPos}},
|
||||
{"g", {ACLRole::NONE, 1, &AOClient::cmdG}},
|
||||
{"need", {ACLRole::NONE, 1, &AOClient::cmdNeed}},
|
||||
{"coinflip", {ACLRole::NONE, 0, &AOClient::cmdFlip}},
|
||||
{"roll", {ACLRole::NONE, 0, &AOClient::cmdRoll}},
|
||||
{"r", {ACLRole::NONE, 0, &AOClient::cmdRoll}},
|
||||
{"rollp", {ACLRole::NONE, 0, &AOClient::cmdRollP}},
|
||||
{"doc", {ACLRole::NONE, 0, &AOClient::cmdDoc}},
|
||||
{"cleardoc", {ACLRole::NONE, 0, &AOClient::cmdClearDoc}},
|
||||
{"cm", {ACLRole::NONE, 0, &AOClient::cmdCM}},
|
||||
{"uncm", {ACLRole::CM, 0, &AOClient::cmdUnCM}},
|
||||
{"invite", {ACLRole::CM, 1, &AOClient::cmdInvite}},
|
||||
{"uninvite", {ACLRole::CM, 1, &AOClient::cmdUnInvite}},
|
||||
{"lock", {ACLRole::CM, 0, &AOClient::cmdLock}},
|
||||
{"area_lock", {ACLRole::CM, 0, &AOClient::cmdLock}},
|
||||
{"spectatable", {ACLRole::CM, 0, &AOClient::cmdSpectatable}},
|
||||
{"area_spectate", {ACLRole::CM, 0, &AOClient::cmdSpectatable}},
|
||||
{"unlock", {ACLRole::CM, 0, &AOClient::cmdUnLock}},
|
||||
{"area_unlock", {ACLRole::CM, 0, &AOClient::cmdUnLock}},
|
||||
{"timer", {ACLRole::CM, 0, &AOClient::cmdTimer}},
|
||||
{"area", {ACLRole::NONE, 1, &AOClient::cmdArea}},
|
||||
{"play", {ACLRole::CM, 1, &AOClient::cmdPlay}},
|
||||
{"areakick", {ACLRole::CM, 1, &AOClient::cmdAreaKick}},
|
||||
{"area_kick", {ACLRole::CM, 1, &AOClient::cmdAreaKick}},
|
||||
{"randomchar", {ACLRole::NONE, 0, &AOClient::cmdRandomChar}},
|
||||
{"switch", {ACLRole::NONE, 1, &AOClient::cmdSwitch}},
|
||||
{"toggleglobal", {ACLRole::NONE, 0, &AOClient::cmdToggleGlobal}},
|
||||
{"mods", {ACLRole::NONE, 0, &AOClient::cmdMods}},
|
||||
{"commands", {ACLRole::NONE, 0, &AOClient::cmdCommands}},
|
||||
{"status", {ACLRole::NONE, 1, &AOClient::cmdStatus}},
|
||||
{"forcepos", {ACLRole::CM, 2, &AOClient::cmdForcePos}},
|
||||
{"currentmusic", {ACLRole::NONE, 0, &AOClient::cmdCurrentMusic}},
|
||||
{"pm", {ACLRole::NONE, 2, &AOClient::cmdPM}},
|
||||
{"evidence_mod", {ACLRole::EVI_MOD, 1, &AOClient::cmdEvidenceMod}},
|
||||
{"motd", {ACLRole::NONE, 0, &AOClient::cmdMOTD}},
|
||||
{"announce", {ACLRole::ANNOUNCE, 1, &AOClient::cmdAnnounce}},
|
||||
{"m", {ACLRole::MODCHAT, 1, &AOClient::cmdM}},
|
||||
{"gm", {ACLRole::MODCHAT, 1, &AOClient::cmdGM}},
|
||||
{"mute", {ACLRole::MUTE, 1, &AOClient::cmdMute}},
|
||||
{"unmute", {ACLRole::MUTE, 1, &AOClient::cmdUnMute}},
|
||||
{"bans", {ACLRole::BAN, 0, &AOClient::cmdBans}},
|
||||
{"unban", {ACLRole::BAN, 1, &AOClient::cmdUnBan}},
|
||||
{"subtheme", {ACLRole::CM, 1, &AOClient::cmdSubTheme}},
|
||||
{"about", {ACLRole::NONE, 0, &AOClient::cmdAbout}},
|
||||
{"evidence_swap", {ACLRole::CM, 2, &AOClient::cmdEvidence_Swap}},
|
||||
{"notecard", {ACLRole::NONE, 1, &AOClient::cmdNoteCard}},
|
||||
{"notecardreveal", {ACLRole::CM, 0, &AOClient::cmdNoteCardReveal}},
|
||||
{"notecard_reveal", {ACLRole::CM, 0, &AOClient::cmdNoteCardReveal}},
|
||||
{"notecardclear", {ACLRole::NONE, 0, &AOClient::cmdNoteCardClear}},
|
||||
{"notecard_clear", {ACLRole::NONE, 0, &AOClient::cmdNoteCardClear}},
|
||||
{"8ball", {ACLRole::NONE, 1, &AOClient::cmd8Ball}},
|
||||
{"lm", {ACLRole::MODCHAT, 1, &AOClient::cmdLM}},
|
||||
{"judgelog", {ACLRole::CM, 0, &AOClient::cmdJudgeLog}},
|
||||
{"allowblankposting", {ACLRole::MODCHAT, 0, &AOClient::cmdAllowBlankposting}},
|
||||
{"allow_blankposting", {ACLRole::MODCHAT, 0, &AOClient::cmdAllowBlankposting}},
|
||||
{"gimp", {ACLRole::MUTE, 1, &AOClient::cmdGimp}},
|
||||
{"ungimp", {ACLRole::MUTE, 1, &AOClient::cmdUnGimp}},
|
||||
{"baninfo", {ACLRole::BAN, 1, &AOClient::cmdBanInfo}},
|
||||
{"testify", {ACLRole::CM, 0, &AOClient::cmdTestify}},
|
||||
{"testimony", {ACLRole::NONE, 0, &AOClient::cmdTestimony}},
|
||||
{"examine", {ACLRole::CM, 0, &AOClient::cmdExamine}},
|
||||
{"pause", {ACLRole::CM, 0, &AOClient::cmdPauseTestimony}},
|
||||
{"delete", {ACLRole::CM, 0, &AOClient::cmdDeleteStatement}},
|
||||
{"update", {ACLRole::CM, 0, &AOClient::cmdUpdateStatement}},
|
||||
{"add", {ACLRole::CM, 0, &AOClient::cmdAddStatement}},
|
||||
{"reload", {ACLRole::SUPER, 0, &AOClient::cmdReload}},
|
||||
{"disemvowel", {ACLRole::MUTE, 1, &AOClient::cmdDisemvowel}},
|
||||
{"undisemvowel", {ACLRole::MUTE, 1, &AOClient::cmdUnDisemvowel}},
|
||||
{"shake", {ACLRole::MUTE, 1, &AOClient::cmdShake}},
|
||||
{"unshake", {ACLRole::MUTE, 1, &AOClient::cmdUnShake}},
|
||||
{"forceimmediate", {ACLRole::CM, 0, &AOClient::cmdForceImmediate}},
|
||||
{"force_noint_pres", {ACLRole::CM, 0, &AOClient::cmdForceImmediate}},
|
||||
{"allowiniswap", {ACLRole::CM, 0, &AOClient::cmdAllowIniswap}},
|
||||
{"allow_iniswap", {ACLRole::CM, 0, &AOClient::cmdAllowIniswap}},
|
||||
{"afk", {ACLRole::NONE, 0, &AOClient::cmdAfk}},
|
||||
{"savetestimony", {ACLRole::NONE, 1, &AOClient::cmdSaveTestimony}},
|
||||
{"loadtestimony", {ACLRole::CM, 1, &AOClient::cmdLoadTestimony}},
|
||||
{"permitsaving", {ACLRole::MODCHAT, 1, &AOClient::cmdPermitSaving}},
|
||||
{"mutepm", {ACLRole::NONE, 0, &AOClient::cmdMutePM}},
|
||||
{"toggleadverts", {ACLRole::NONE, 0, &AOClient::cmdToggleAdverts}},
|
||||
{"oocmute", {ACLRole::MUTE, 1, &AOClient::cmdOocMute}},
|
||||
{"ooc_mute", {ACLRole::MUTE, 1, &AOClient::cmdOocMute}},
|
||||
{"oocunmute", {ACLRole::MUTE, 1, &AOClient::cmdOocUnMute}},
|
||||
{"ooc_unmute", {ACLRole::MUTE, 1, &AOClient::cmdOocUnMute}},
|
||||
{"blockwtce", {ACLRole::MUTE, 1, &AOClient::cmdBlockWtce}},
|
||||
{"block_wtce", {ACLRole::MUTE, 1, &AOClient::cmdBlockWtce}},
|
||||
{"unblockwtce", {ACLRole::MUTE, 1, &AOClient::cmdUnBlockWtce}},
|
||||
{"unblock_wtce", {ACLRole::MUTE, 1, &AOClient::cmdUnBlockWtce}},
|
||||
{"blockdj", {ACLRole::MUTE, 1, &AOClient::cmdBlockDj}},
|
||||
{"block_dj", {ACLRole::MUTE, 1, &AOClient::cmdBlockDj}},
|
||||
{"unblockdj", {ACLRole::MUTE, 1, &AOClient::cmdUnBlockDj}},
|
||||
{"unblock_dj", {ACLRole::MUTE, 1, &AOClient::cmdUnBlockDj}},
|
||||
{"charcurse", {ACLRole::MUTE, 1, &AOClient::cmdCharCurse}},
|
||||
{"uncharcurse", {ACLRole::MUTE, 1, &AOClient::cmdUnCharCurse}},
|
||||
{"charselect", {ACLRole::NONE, 0, &AOClient::cmdCharSelect}},
|
||||
{"togglemusic", {ACLRole::CM, 0, &AOClient::cmdToggleMusic}},
|
||||
{"a", {ACLRole::NONE, 2, &AOClient::cmdA}},
|
||||
{"s", {ACLRole::NONE, 0, &AOClient::cmdS}},
|
||||
{"kickuid", {ACLRole::KICK, 2, &AOClient::cmdKickUid}},
|
||||
{"kick_uid", {ACLRole::KICK, 2, &AOClient::cmdKickUid}},
|
||||
{"firstperson", {ACLRole::NONE, 0, &AOClient::cmdFirstPerson}},
|
||||
{"updateban", {ACLRole::BAN, 3, &AOClient::cmdUpdateBan}},
|
||||
{"update_ban", {ACLRole::BAN, 3, &AOClient::cmdUpdateBan}},
|
||||
{"changepass", {ACLRole::NONE, 1, &AOClient::cmdChangePassword}},
|
||||
{"ignorebglist", {ACLRole::IGNORE_BGLIST, 0, &AOClient::cmdIgnoreBgList}},
|
||||
{"ignore_bglist", {ACLRole::IGNORE_BGLIST, 0, &AOClient::cmdIgnoreBgList}},
|
||||
{"notice", {ACLRole::SEND_NOTICE, 1, &AOClient::cmdNotice}},
|
||||
{"noticeg", {ACLRole::SEND_NOTICE, 1, &AOClient::cmdNoticeGlobal}},
|
||||
{"togglejukebox", {ACLRole::NONE, 0, &AOClient::cmdToggleJukebox}},
|
||||
{"help", {ACLRole::NONE, 1, &AOClient::cmdHelp}},
|
||||
{"clearcm", {ACLRole::KICK, 0, &AOClient::cmdClearCM}},
|
||||
{"togglemessage", {ACLRole::CM, 0, &AOClient::cmdToggleAreaMessageOnJoin}},
|
||||
{"clearmessage", {ACLRole::CM, 0, &AOClient::cmdClearAreaMessage}},
|
||||
{"areamessage", {ACLRole::CM, 0, &AOClient::cmdAreaMessage}},
|
||||
{"addsong", {ACLRole::CM, 1, &AOClient::cmdAddSong}},
|
||||
{"addcategory", {ACLRole::CM, 1, &AOClient::cmdAddCategory}},
|
||||
{"removeentry", {ACLRole::CM, 1, &AOClient::cmdRemoveCategorySong}},
|
||||
{"toggleroot", {ACLRole::CM, 0, &AOClient::cmdToggleRootlist}},
|
||||
{"clearcustom", {ACLRole::CM, 0, &AOClient::cmdClearCustom}}};
|
||||
|
||||
/**
|
||||
* @brief Filled with part of a packet if said packet could not be read fully from the client's socket.
|
||||
*
|
||||
|
197
core/include/command_extension.h
Normal file
197
core/include/command_extension.h
Normal file
@ -0,0 +1,197 @@
|
||||
#ifndef COMMAND_EXTENSION_H
|
||||
#define COMMAND_EXTENSION_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "include/acl_roles_handler.h"
|
||||
|
||||
class CommandExtension
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a null command extension.
|
||||
*/
|
||||
CommandExtension();
|
||||
|
||||
/**
|
||||
* @brief Constructs a command extension with the given command name.
|
||||
*
|
||||
* @param f_command_name The command's name.
|
||||
*/
|
||||
CommandExtension(QString f_command_name);
|
||||
|
||||
/**
|
||||
* @brief Destroys the command extension.
|
||||
*/
|
||||
~CommandExtension();
|
||||
|
||||
/**
|
||||
* @brief Returns the command's name.
|
||||
*
|
||||
* @details The command's name act as a possible identifier to determine whatever the command extension matches a command or not.
|
||||
*/
|
||||
QString getCommandName() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the command name.
|
||||
*
|
||||
* @param f_command_name The command's name.
|
||||
*/
|
||||
void setCommandName(QString f_command_name);
|
||||
|
||||
/**
|
||||
* @brief Checks if the given alias matches any of the possible alias of the command extension, including the command's name itself.
|
||||
*
|
||||
* @param f_alias The alias to check.
|
||||
*
|
||||
* @return True if the alias matches, false otherwise.
|
||||
*/
|
||||
bool checkCommandNameAndAlias(QString f_alias) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the aliases of the command.
|
||||
*/
|
||||
QStringList getAliases() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the aliases of the command to the given aliases.
|
||||
*
|
||||
* @param f_aliases The command aliases.
|
||||
*/
|
||||
void setAliases(QStringList f_aliases);
|
||||
|
||||
/**
|
||||
* @brief Returns the list of permissions. If the permissions are not set or empty, returns f_defaultPermissions.
|
||||
*
|
||||
* @param f_defaultPermissions A list of permissions to return if the extensions's permissions are not set or empty.
|
||||
*/
|
||||
QVector<ACLRole::Permission> getPermissions(QVector<ACLRole::Permission> f_defaultPermissions) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the list of permissions.
|
||||
*/
|
||||
QVector<ACLRole::Permission> getPermissions() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the list of permissions to the given list of permissions.
|
||||
*
|
||||
* @param f_permissions A list of permissions.
|
||||
*/
|
||||
void setPermissions(QVector<ACLRole::Permission> f_permissions);
|
||||
|
||||
/**
|
||||
* @brief Sets the list of permissions based on their captions.
|
||||
*
|
||||
* @param f_captions
|
||||
*
|
||||
* @see ACLRole#PERMISSION_CAPTIONS
|
||||
*/
|
||||
void setPermissionsByCaption(QStringList f_captions);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The command name to which the extension is loosely associated to.
|
||||
*/
|
||||
QString m_command_name;
|
||||
|
||||
/**
|
||||
* @brief A list of aliases for the command.
|
||||
*/
|
||||
QStringList m_aliases;
|
||||
|
||||
/**
|
||||
* @brief A list containing both the command's name and the list of aliases.
|
||||
*/
|
||||
QStringList m_merged_aliases;
|
||||
|
||||
/**
|
||||
* @brief A list of permissions.
|
||||
*/
|
||||
QVector<ACLRole::Permission> m_permissions;
|
||||
|
||||
/**
|
||||
* @brief Updates #m_merged_aliases.
|
||||
*/
|
||||
void updateMergedAliases();
|
||||
};
|
||||
|
||||
class CommandExtensionCollection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a null command extension collection.
|
||||
*
|
||||
* @details The collection does load extensions automatically.
|
||||
*
|
||||
* @param parent Qt-based parent
|
||||
*/
|
||||
CommandExtensionCollection(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Destroys the collection.
|
||||
*/
|
||||
~CommandExtensionCollection();
|
||||
|
||||
/**
|
||||
* @brief Sets the command name whitelist to the given list.
|
||||
*
|
||||
* @param f_command_names A list of command name.
|
||||
*
|
||||
* @see #m_command_name_whitelist
|
||||
*/
|
||||
void setCommandNameWhitelist(QStringList f_command_names);
|
||||
|
||||
/**
|
||||
* @brief Returns the list of extensions.
|
||||
*
|
||||
* @see CommandExtension
|
||||
*/
|
||||
QList<CommandExtension> getExtensions() const;
|
||||
|
||||
/**
|
||||
* @brief Checks if a command extension associated to the given command name exists.
|
||||
*
|
||||
* @param f_command_name The target command name.
|
||||
*
|
||||
* @return True if the command extension exists, false otherwise.
|
||||
*/
|
||||
bool containsExtension(QString f_command_name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a command extension associated to the given command name. If no command extension is associated to the command name, returns a null command extension.
|
||||
*
|
||||
* @param f_command_name The target command name.
|
||||
*
|
||||
* @return Returns a command extension.
|
||||
*/
|
||||
CommandExtension getExtension(QString f_command_name) const;
|
||||
|
||||
/**
|
||||
* @brief Clear the current command extensions and load command extensions from the given file. The file must be of the INI format.
|
||||
*
|
||||
* @details If the command name whitelist is not empty, only command extensions pertaining may be registered.
|
||||
*
|
||||
* @param f_filename The path to the file.
|
||||
*/
|
||||
bool loadFile(QString f_filename);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief A list of command names to allow.
|
||||
*
|
||||
* @see #loadFile
|
||||
*/
|
||||
QStringList m_command_name_whitelist;
|
||||
|
||||
/**
|
||||
* @brief A map of extensions associated to a command name.
|
||||
*/
|
||||
QMap<QString, CommandExtension> m_extensions;
|
||||
};
|
||||
|
||||
#endif // COMMAND_EXTENSION_H
|
@ -35,6 +35,7 @@ class ACLRolesHandler;
|
||||
class Advertiser;
|
||||
class AOClient;
|
||||
class AreaData;
|
||||
class CommandExtensionCollection;
|
||||
class ConfigManager;
|
||||
class DBManager;
|
||||
class Discord;
|
||||
@ -282,12 +283,20 @@ class Server : public QObject
|
||||
/**
|
||||
* @brief Returns a pointer to a database manager.
|
||||
*
|
||||
* @return A pointer to database manager.
|
||||
* @return A pointer to a database manager.
|
||||
*/
|
||||
DBManager *getDatabaseManager();
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to ACL role handler.
|
||||
*/
|
||||
ACLRolesHandler *getACLRolesHandler();
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to a command extension collection.
|
||||
*/
|
||||
CommandExtensionCollection *getCommandExtensionCollection();
|
||||
|
||||
/**
|
||||
* @brief The server-wide global timer.
|
||||
*/
|
||||
@ -511,8 +520,16 @@ class Server : public QObject
|
||||
*/
|
||||
DBManager *db_manager;
|
||||
|
||||
/**
|
||||
* @see ACLRolesHandler
|
||||
*/
|
||||
ACLRolesHandler *acl_roles_handler;
|
||||
|
||||
/**
|
||||
* @see CommandExtensionCollection
|
||||
*/
|
||||
CommandExtensionCollection *command_extension_collection;
|
||||
|
||||
/**
|
||||
* @brief Connects new AOClient to logger and disconnect handling.
|
||||
**/
|
||||
|
@ -12,7 +12,11 @@ const QHash<QString, ACLRole> ACLRolesHandler::readonly_roles{
|
||||
{ACLRolesHandler::SUPER_ID, ACLRole(ACLRole::SUPER)},
|
||||
};
|
||||
|
||||
const QHash<ACLRole::Permission, QString> ACLRole::permission_captions{
|
||||
const QHash<ACLRole::Permission, QString> ACLRole::PERMISSION_CAPTIONS{
|
||||
{
|
||||
ACLRole::Permission::NONE,
|
||||
"none",
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::KICK,
|
||||
"kick",
|
||||
@ -31,11 +35,11 @@ const QHash<ACLRole::Permission, QString> ACLRole::permission_captions{
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::CM,
|
||||
"set_gamemaster",
|
||||
"gamemaster",
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::GLOBAL_TIMER,
|
||||
"use_global_timer",
|
||||
"global_timer",
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::EVI_MOD,
|
||||
@ -43,7 +47,7 @@ const QHash<ACLRole::Permission, QString> ACLRole::permission_captions{
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::MOTD,
|
||||
"set_motd",
|
||||
"motd",
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::ANNOUNCE,
|
||||
@ -75,7 +79,7 @@ const QHash<ACLRole::Permission, QString> ACLRole::permission_captions{
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::IGNORE_BGLIST,
|
||||
"ignore_bg_list",
|
||||
"ignore_background_list",
|
||||
},
|
||||
{
|
||||
ACLRole::Permission::SEND_NOTICE,
|
||||
@ -176,17 +180,17 @@ bool ACLRolesHandler::loadFile(QString f_file_name)
|
||||
if (l_settings.status() != QSettings::NoError) {
|
||||
switch (l_settings.status()) {
|
||||
case QSettings::AccessError:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: failed to open file; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
|
||||
case QSettings::FormatError:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: file is malformed; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
|
||||
default:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: unknown error; aborting; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
}
|
||||
@ -200,20 +204,23 @@ bool ACLRolesHandler::loadFile(QString f_file_name)
|
||||
for (const QString &i_group : l_group_list) {
|
||||
const QString l_upper_group = i_group.toUpper();
|
||||
if (readonly_roles.contains(l_upper_group)) {
|
||||
qWarning() << "ACLRolesHandler warning: cannot modify role;" << i_group << "is read-only";
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "warning: cannot modify role;" << i_group << "is read-only";
|
||||
continue;
|
||||
}
|
||||
|
||||
l_settings.beginGroup(i_group);
|
||||
if (l_role_records.contains(l_upper_group)) {
|
||||
qWarning() << "ACLRolesHandler warning: role" << l_upper_group << "already exist! Overwriting.";
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "warning: role" << l_upper_group << "already exist";
|
||||
continue;
|
||||
}
|
||||
l_role_records.append(l_upper_group);
|
||||
|
||||
ACLRole l_role;
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::permission_captions.keys();
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::PERMISSION_CAPTIONS.keys();
|
||||
for (const ACLRole::Permission &i_permission : l_permissions) {
|
||||
l_role.setPermission(i_permission, l_settings.value(ACLRole::permission_captions.value(i_permission), false).toBool());
|
||||
l_role.setPermission(i_permission, l_settings.value(ACLRole::PERMISSION_CAPTIONS.value(i_permission), false).toBool());
|
||||
}
|
||||
m_roles.insert(l_upper_group, std::move(l_role));
|
||||
|
||||
@ -230,17 +237,17 @@ bool ACLRolesHandler::saveFile(QString f_file_name)
|
||||
if (l_settings.status() != QSettings::NoError) {
|
||||
switch (l_settings.status()) {
|
||||
case QSettings::AccessError:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: failed to open file; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
|
||||
case QSettings::FormatError:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: file is malformed; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
|
||||
default:
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: unknown error; aborting; aborting (" << f_file_name << ")";
|
||||
break;
|
||||
}
|
||||
@ -259,22 +266,22 @@ bool ACLRolesHandler::saveFile(QString f_file_name)
|
||||
const ACLRole i_role = m_roles.value(l_upper_role_id);
|
||||
l_settings.beginGroup(l_upper_role_id);
|
||||
if (i_role.checkPermission(ACLRole::SUPER)) {
|
||||
l_settings.setValue(ACLRole::permission_captions.value(ACLRole::SUPER), true);
|
||||
l_settings.setValue(ACLRole::PERMISSION_CAPTIONS.value(ACLRole::SUPER), true);
|
||||
}
|
||||
else {
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::permission_captions.keys();
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::PERMISSION_CAPTIONS.keys();
|
||||
for (const ACLRole::Permission i_permission : l_permissions) {
|
||||
if (!i_role.checkPermission(i_permission)) {
|
||||
continue;
|
||||
}
|
||||
l_settings.setValue(ACLRole::permission_captions.value(i_permission), true);
|
||||
l_settings.setValue(ACLRole::PERMISSION_CAPTIONS.value(i_permission), true);
|
||||
}
|
||||
}
|
||||
l_settings.endGroup();
|
||||
}
|
||||
l_settings.sync();
|
||||
if (l_settings.status() != QSettings::NoError) {
|
||||
qWarning() << "ACLRolesHandler"
|
||||
qWarning() << "[ACL Role Handler]"
|
||||
<< "error: failed to write file; aborting (" << f_file_name << ")";
|
||||
return false;
|
||||
}
|
||||
|
@ -19,10 +19,133 @@
|
||||
|
||||
#include "include/aopacket.h"
|
||||
#include "include/area_data.h"
|
||||
#include "include/command_extension.h"
|
||||
#include "include/config_manager.h"
|
||||
#include "include/db_manager.h"
|
||||
#include "include/server.h"
|
||||
|
||||
const QMap<QString, AOClient::CommandInfo> AOClient::COMMANDS{
|
||||
{"login", {{ACLRole::NONE}, 0, &AOClient::cmdLogin}},
|
||||
{"getarea", {{ACLRole::NONE}, 0, &AOClient::cmdGetArea}},
|
||||
{"getareas", {{ACLRole::NONE}, 0, &AOClient::cmdGetAreas}},
|
||||
{"ban", {{ACLRole::BAN}, 3, &AOClient::cmdBan}},
|
||||
{"kick", {{ACLRole::KICK}, 2, &AOClient::cmdKick}},
|
||||
{"changeauth", {{ACLRole::SUPER}, 0, &AOClient::cmdChangeAuth}},
|
||||
{"rootpass", {{ACLRole::SUPER}, 1, &AOClient::cmdSetRootPass}},
|
||||
{"background", {{ACLRole::NONE}, 1, &AOClient::cmdSetBackground}},
|
||||
{"lock_background", {{ACLRole::BGLOCK}, 0, &AOClient::cmdBgLock}},
|
||||
{"unlock_background", {{ACLRole::BGLOCK}, 0, &AOClient::cmdBgUnlock}},
|
||||
{"adduser", {{ACLRole::MODIFY_USERS}, 2, &AOClient::cmdAddUser}},
|
||||
{"removeuser", {{ACLRole::MODIFY_USERS}, 1, &AOClient::cmdRemoveUser}},
|
||||
{"listusers", {{ACLRole::MODIFY_USERS}, 0, &AOClient::cmdListUsers}},
|
||||
{"setperms", {{ACLRole::MODIFY_USERS}, 2, &AOClient::cmdSetPerms}},
|
||||
{"removeperms", {{ACLRole::MODIFY_USERS}, 1, &AOClient::cmdRemovePerms}},
|
||||
{"listperms", {{ACLRole::NONE}, 0, &AOClient::cmdListPerms}},
|
||||
{"logout", {{ACLRole::NONE}, 0, &AOClient::cmdLogout}},
|
||||
{"pos", {{ACLRole::NONE}, 1, &AOClient::cmdPos}},
|
||||
{"g", {{ACLRole::NONE}, 1, &AOClient::cmdG}},
|
||||
{"need", {{ACLRole::NONE}, 1, &AOClient::cmdNeed}},
|
||||
{"coinflip", {{ACLRole::NONE}, 0, &AOClient::cmdFlip}},
|
||||
{"roll", {{ACLRole::NONE}, 0, &AOClient::cmdRoll}},
|
||||
{"rollp", {{ACLRole::NONE}, 0, &AOClient::cmdRollP}},
|
||||
{"doc", {{ACLRole::NONE}, 0, &AOClient::cmdDoc}},
|
||||
{"cleardoc", {{ACLRole::NONE}, 0, &AOClient::cmdClearDoc}},
|
||||
{"cm", {{ACLRole::NONE}, 0, &AOClient::cmdCM}},
|
||||
{"uncm", {{ACLRole::CM}, 0, &AOClient::cmdUnCM}},
|
||||
{"invite", {{ACLRole::CM}, 1, &AOClient::cmdInvite}},
|
||||
{"uninvite", {{ACLRole::CM}, 1, &AOClient::cmdUnInvite}},
|
||||
{"area_lock", {{ACLRole::CM}, 0, &AOClient::cmdLock}},
|
||||
{"area_spectate", {{ACLRole::CM}, 0, &AOClient::cmdSpectatable}},
|
||||
{"area_unlock", {{ACLRole::CM}, 0, &AOClient::cmdUnLock}},
|
||||
{"timer", {{ACLRole::CM}, 0, &AOClient::cmdTimer}},
|
||||
{"area", {{ACLRole::NONE}, 1, &AOClient::cmdArea}},
|
||||
{"play", {{ACLRole::CM}, 1, &AOClient::cmdPlay}},
|
||||
{"area_kick", {{ACLRole::CM}, 1, &AOClient::cmdAreaKick}},
|
||||
{"randomchar", {{ACLRole::NONE}, 0, &AOClient::cmdRandomChar}},
|
||||
{"switch", {{ACLRole::NONE}, 1, &AOClient::cmdSwitch}},
|
||||
{"toggleglobal", {{ACLRole::NONE}, 0, &AOClient::cmdToggleGlobal}},
|
||||
{"mods", {{ACLRole::NONE}, 0, &AOClient::cmdMods}},
|
||||
{"commands", {{ACLRole::NONE}, 0, &AOClient::cmdCommands}},
|
||||
{"status", {{ACLRole::NONE}, 1, &AOClient::cmdStatus}},
|
||||
{"forcepos", {{ACLRole::CM}, 2, &AOClient::cmdForcePos}},
|
||||
{"currentmusic", {{ACLRole::NONE}, 0, &AOClient::cmdCurrentMusic}},
|
||||
{"pm", {{ACLRole::NONE}, 2, &AOClient::cmdPM}},
|
||||
{"evidence_mod", {{ACLRole::EVI_MOD}, 1, &AOClient::cmdEvidenceMod}},
|
||||
{"motd", {{ACLRole::NONE}, 0, &AOClient::cmdMOTD}},
|
||||
{"set_motd", {{ACLRole::MOTD}, 1, &AOClient::cmdSetMOTD}},
|
||||
{"announce", {{ACLRole::ANNOUNCE}, 1, &AOClient::cmdAnnounce}},
|
||||
{"m", {{ACLRole::MODCHAT}, 1, &AOClient::cmdM}},
|
||||
{"gm", {{ACLRole::MODCHAT}, 1, &AOClient::cmdGM}},
|
||||
{"mute", {{ACLRole::MUTE}, 1, &AOClient::cmdMute}},
|
||||
{"unmute", {{ACLRole::MUTE}, 1, &AOClient::cmdUnMute}},
|
||||
{"bans", {{ACLRole::BAN}, 0, &AOClient::cmdBans}},
|
||||
{"unban", {{ACLRole::BAN}, 1, &AOClient::cmdUnBan}},
|
||||
{"subtheme", {{ACLRole::CM}, 1, &AOClient::cmdSubTheme}},
|
||||
{"about", {{ACLRole::NONE}, 0, &AOClient::cmdAbout}},
|
||||
{"evidence_swap", {{ACLRole::CM}, 2, &AOClient::cmdEvidence_Swap}},
|
||||
{"notecard", {{ACLRole::NONE}, 1, &AOClient::cmdNoteCard}},
|
||||
{"notecard_reveal", {{ACLRole::CM}, 0, &AOClient::cmdNoteCardReveal}},
|
||||
{"notecard_clear", {{ACLRole::NONE}, 0, &AOClient::cmdNoteCardClear}},
|
||||
{"8ball", {{ACLRole::NONE}, 1, &AOClient::cmd8Ball}},
|
||||
{"lm", {{ACLRole::MODCHAT}, 1, &AOClient::cmdLM}},
|
||||
{"judgelog", {{ACLRole::CM}, 0, &AOClient::cmdJudgeLog}},
|
||||
{"allow_blankposting", {{ACLRole::MODCHAT}, 0, &AOClient::cmdAllowBlankposting}},
|
||||
{"gimp", {{ACLRole::MUTE}, 1, &AOClient::cmdGimp}},
|
||||
{"ungimp", {{ACLRole::MUTE}, 1, &AOClient::cmdUnGimp}},
|
||||
{"baninfo", {{ACLRole::BAN}, 1, &AOClient::cmdBanInfo}},
|
||||
{"testify", {{ACLRole::CM}, 0, &AOClient::cmdTestify}},
|
||||
{"testimony", {{ACLRole::NONE}, 0, &AOClient::cmdTestimony}},
|
||||
{"examine", {{ACLRole::CM}, 0, &AOClient::cmdExamine}},
|
||||
{"pause", {{ACLRole::CM}, 0, &AOClient::cmdPauseTestimony}},
|
||||
{"delete", {{ACLRole::CM}, 0, &AOClient::cmdDeleteStatement}},
|
||||
{"update", {{ACLRole::CM}, 0, &AOClient::cmdUpdateStatement}},
|
||||
{"add", {{ACLRole::CM}, 0, &AOClient::cmdAddStatement}},
|
||||
{"reload", {{ACLRole::SUPER}, 0, &AOClient::cmdReload}},
|
||||
{"disemvowel", {{ACLRole::MUTE}, 1, &AOClient::cmdDisemvowel}},
|
||||
{"undisemvowel", {{ACLRole::MUTE}, 1, &AOClient::cmdUnDisemvowel}},
|
||||
{"shake", {{ACLRole::MUTE}, 1, &AOClient::cmdShake}},
|
||||
{"unshake", {{ACLRole::MUTE}, 1, &AOClient::cmdUnShake}},
|
||||
{"forceimmediate", {{ACLRole::CM}, 0, &AOClient::cmdForceImmediate}},
|
||||
{"allow_iniswap", {{ACLRole::CM}, 0, &AOClient::cmdAllowIniswap}},
|
||||
{"afk", {{ACLRole::NONE}, 0, &AOClient::cmdAfk}},
|
||||
{"savetestimony", {{ACLRole::NONE}, 1, &AOClient::cmdSaveTestimony}},
|
||||
{"loadtestimony", {{ACLRole::CM}, 1, &AOClient::cmdLoadTestimony}},
|
||||
{"permitsaving", {{ACLRole::MODCHAT}, 1, &AOClient::cmdPermitSaving}},
|
||||
{"mutepm", {{ACLRole::NONE}, 0, &AOClient::cmdMutePM}},
|
||||
{"toggleadverts", {{ACLRole::NONE}, 0, &AOClient::cmdToggleAdverts}},
|
||||
{"ooc_mute", {{ACLRole::MUTE}, 1, &AOClient::cmdOocMute}},
|
||||
{"ooc_unmute", {{ACLRole::MUTE}, 1, &AOClient::cmdOocUnMute}},
|
||||
{"block_wtce", {{ACLRole::MUTE}, 1, &AOClient::cmdBlockWtce}},
|
||||
{"unblock_wtce", {{ACLRole::MUTE}, 1, &AOClient::cmdUnBlockWtce}},
|
||||
{"block_dj", {{ACLRole::MUTE}, 1, &AOClient::cmdBlockDj}},
|
||||
{"unblock_dj", {{ACLRole::MUTE}, 1, &AOClient::cmdUnBlockDj}},
|
||||
{"charcurse", {{ACLRole::MUTE}, 1, &AOClient::cmdCharCurse}},
|
||||
{"uncharcurse", {{ACLRole::MUTE}, 1, &AOClient::cmdUnCharCurse}},
|
||||
{"charselect", {{ACLRole::NONE}, 0, &AOClient::cmdCharSelect}},
|
||||
{"force_charselect", {{ACLRole::FORCE_CHARSELECT}, 1, &AOClient::cmdForceCharSelect}},
|
||||
{"togglemusic", {{ACLRole::CM}, 0, &AOClient::cmdToggleMusic}},
|
||||
{"a", {{ACLRole::NONE}, 2, &AOClient::cmdA}},
|
||||
{"s", {{ACLRole::NONE}, 0, &AOClient::cmdS}},
|
||||
{"kick_uid", {{ACLRole::KICK}, 2, &AOClient::cmdKickUid}},
|
||||
{"firstperson", {{ACLRole::NONE}, 0, &AOClient::cmdFirstPerson}},
|
||||
{"update_ban", {{ACLRole::BAN}, 3, &AOClient::cmdUpdateBan}},
|
||||
{"changepass", {{ACLRole::NONE}, 1, &AOClient::cmdChangePassword}},
|
||||
{"ignore_bglist", {{ACLRole::IGNORE_BGLIST}, 0, &AOClient::cmdIgnoreBgList}},
|
||||
{"notice", {{ACLRole::SEND_NOTICE}, 1, &AOClient::cmdNotice}},
|
||||
{"noticeg", {{ACLRole::SEND_NOTICE}, 1, &AOClient::cmdNoticeGlobal}},
|
||||
{"togglejukebox", {{ACLRole::CM, ACLRole::JUKEBOX}, 0, &AOClient::cmdToggleJukebox}},
|
||||
{"help", {{ACLRole::NONE}, 1, &AOClient::cmdHelp}},
|
||||
{"clearcm", {{ACLRole::KICK}, 0, &AOClient::cmdClearCM}},
|
||||
{"togglemessage", {{ACLRole::CM}, 0, &AOClient::cmdToggleAreaMessageOnJoin}},
|
||||
{"clearmessage", {{ACLRole::CM}, 0, &AOClient::cmdClearAreaMessage}},
|
||||
{"areamessage", {{ACLRole::CM}, 0, &AOClient::cmdAreaMessage}},
|
||||
{"addsong", {{ACLRole::CM}, 1, &AOClient::cmdAddSong}},
|
||||
{"addcategory", {{ACLRole::CM}, 1, &AOClient::cmdAddCategory}},
|
||||
{"removeentry", {{ACLRole::CM}, 1, &AOClient::cmdRemoveCategorySong}},
|
||||
{"toggleroot", {{ACLRole::CM}, 0, &AOClient::cmdToggleRootlist}},
|
||||
{"clearcustom", {{ACLRole::CM}, 0, &AOClient::cmdClearCustom}},
|
||||
};
|
||||
|
||||
void AOClient::clientData()
|
||||
{
|
||||
if (last_read + m_socket->bytesAvailable() > 30720) { // Client can send a max of 30KB to the server over two sequential reads
|
||||
@ -202,20 +325,44 @@ void AOClient::changePosition(QString new_pos)
|
||||
|
||||
void AOClient::handleCommand(QString command, int argc, QStringList argv)
|
||||
{
|
||||
CommandInfo l_info = commands.value(command, {ACLRole::NONE, -1, &AOClient::cmdDefault});
|
||||
command = command.toLower();
|
||||
QString l_target_command = command;
|
||||
QVector<ACLRole::Permission> l_permissions;
|
||||
|
||||
if (!checkPermission(l_info.acl_permission)) {
|
||||
// check for aliases
|
||||
const QList<CommandExtension> l_extensions = server->getCommandExtensionCollection()->getExtensions();
|
||||
for (const CommandExtension &i_extension : l_extensions) {
|
||||
if (i_extension.checkCommandNameAndAlias(command)) {
|
||||
l_target_command = i_extension.getCommandName();
|
||||
l_permissions = i_extension.getPermissions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CommandInfo l_command = COMMANDS.value(l_target_command, {{ACLRole::NONE}, -1, &AOClient::cmdDefault});
|
||||
if (l_permissions.isEmpty()) {
|
||||
l_permissions.append(l_command.acl_permissions);
|
||||
}
|
||||
|
||||
bool l_has_permissions = false;
|
||||
for (const ACLRole::Permission i_permission : qAsConst(l_permissions)) {
|
||||
if (checkPermission(i_permission)) {
|
||||
l_has_permissions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!l_has_permissions) {
|
||||
sendServerMessage("You do not have permission to use that command.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc < l_info.minArgs) {
|
||||
if (argc < l_command.minArgs) {
|
||||
sendServerMessage("Invalid command syntax.");
|
||||
sendServerMessage("The expected syntax for this command is: \n" + ConfigManager::commandHelp(command).usage);
|
||||
return;
|
||||
}
|
||||
|
||||
(this->*(l_info.action))(argc, argv);
|
||||
(this->*(l_command.action))(argc, argv);
|
||||
}
|
||||
|
||||
void AOClient::arup(ARUPType type, bool broadcast)
|
||||
|
166
core/src/command_extension.cpp
Normal file
166
core/src/command_extension.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include "include/command_extension.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
|
||||
#include "include/akashidefs.h"
|
||||
|
||||
CommandExtension::CommandExtension() {}
|
||||
|
||||
CommandExtension::CommandExtension(QString f_command_name)
|
||||
{
|
||||
setCommandName(f_command_name);
|
||||
}
|
||||
|
||||
CommandExtension::~CommandExtension() {}
|
||||
|
||||
QString CommandExtension::getCommandName() const
|
||||
{
|
||||
return m_command_name;
|
||||
}
|
||||
|
||||
void CommandExtension::setCommandName(QString f_command_name)
|
||||
{
|
||||
m_command_name = f_command_name;
|
||||
updateMergedAliases();
|
||||
}
|
||||
|
||||
bool CommandExtension::checkCommandNameAndAlias(QString f_alias) const
|
||||
{
|
||||
return m_merged_aliases.contains(f_alias, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QStringList CommandExtension::getAliases() const
|
||||
{
|
||||
return m_aliases;
|
||||
}
|
||||
|
||||
void CommandExtension::setAliases(QStringList f_aliases)
|
||||
{
|
||||
m_aliases = f_aliases;
|
||||
for (QString &i_alias : m_aliases) {
|
||||
i_alias = i_alias.toLower();
|
||||
}
|
||||
updateMergedAliases();
|
||||
}
|
||||
|
||||
QVector<ACLRole::Permission> CommandExtension::getPermissions(QVector<ACLRole::Permission> f_defaultPermissions) const
|
||||
{
|
||||
return m_permissions.isEmpty() ? f_defaultPermissions : m_permissions;
|
||||
}
|
||||
|
||||
QVector<ACLRole::Permission> CommandExtension::getPermissions() const
|
||||
{
|
||||
return getPermissions(QVector<ACLRole::Permission>{});
|
||||
}
|
||||
|
||||
void CommandExtension::setPermissions(QVector<ACLRole::Permission> f_permissions)
|
||||
{
|
||||
m_permissions = f_permissions;
|
||||
}
|
||||
|
||||
void CommandExtension::setPermissionsByCaption(QStringList f_captions)
|
||||
{
|
||||
QVector<ACLRole::Permission> l_permissions;
|
||||
const QStringList l_permission_captions = ACLRole::PERMISSION_CAPTIONS.values();
|
||||
for (const QString &i_caption : qAsConst(f_captions)) {
|
||||
const QString l_lower_caption = i_caption.toLower();
|
||||
if (!l_permission_captions.contains(l_lower_caption)) {
|
||||
qWarning() << "[Command Extension]"
|
||||
<< "error: permission" << i_caption << "does not exist";
|
||||
continue;
|
||||
}
|
||||
l_permissions.append(ACLRole::PERMISSION_CAPTIONS.key(l_lower_caption));
|
||||
}
|
||||
setPermissions(l_permissions);
|
||||
}
|
||||
|
||||
void CommandExtension::updateMergedAliases()
|
||||
{
|
||||
m_merged_aliases = QStringList{m_command_name} + m_aliases;
|
||||
}
|
||||
|
||||
CommandExtensionCollection::CommandExtensionCollection(QObject *parent) :
|
||||
QObject(parent)
|
||||
{}
|
||||
|
||||
CommandExtensionCollection::~CommandExtensionCollection() {}
|
||||
|
||||
void CommandExtensionCollection::setCommandNameWhitelist(QStringList f_command_names)
|
||||
{
|
||||
m_command_name_whitelist = f_command_names;
|
||||
for (QString &i_alias : m_command_name_whitelist) {
|
||||
i_alias = i_alias.toLower();
|
||||
}
|
||||
}
|
||||
|
||||
QList<CommandExtension> CommandExtensionCollection::getExtensions() const
|
||||
{
|
||||
return m_extensions.values();
|
||||
}
|
||||
|
||||
bool CommandExtensionCollection::containsExtension(QString f_command_name) const
|
||||
{
|
||||
return m_extensions.contains(f_command_name);
|
||||
}
|
||||
|
||||
CommandExtension CommandExtensionCollection::getExtension(QString f_command_name) const
|
||||
{
|
||||
return m_extensions.value(f_command_name);
|
||||
}
|
||||
|
||||
bool CommandExtensionCollection::loadFile(QString f_filename)
|
||||
{
|
||||
QSettings l_settings(f_filename, QSettings::IniFormat);
|
||||
l_settings.setIniCodec("UTF-8");
|
||||
if (l_settings.status() != QSettings::NoError) {
|
||||
qWarning() << "[Command Extension Collection]"
|
||||
<< "error: failed to load file" << f_filename << "; aborting";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_extensions.clear();
|
||||
QStringList l_alias_records;
|
||||
QStringList l_command_records;
|
||||
const QStringList l_group_list = l_settings.childGroups();
|
||||
for (const QString &i_group : l_group_list) {
|
||||
const QString l_command_name = i_group.toLower();
|
||||
if (!m_command_name_whitelist.isEmpty() && !m_command_name_whitelist.contains(l_command_name)) {
|
||||
qWarning() << "[Command Extension Collection]"
|
||||
<< "error: command" << l_command_name << "cannot be extended; does not exist";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l_command_records.contains(l_command_name)) {
|
||||
qWarning() << "[Command Extension Collection]"
|
||||
<< "warning: command extension" << l_command_name << "already exist";
|
||||
continue;
|
||||
}
|
||||
l_command_records.append(l_command_name);
|
||||
|
||||
l_settings.beginGroup(i_group);
|
||||
|
||||
QStringList l_aliases = l_settings.value("aliases").toString().split(" ", akashi::SkipEmptyParts);
|
||||
for (QString &i_alias : l_aliases) {
|
||||
i_alias = i_alias.toLower();
|
||||
}
|
||||
|
||||
for (const QString &i_recorded_alias : l_alias_records) {
|
||||
if (l_aliases.contains(i_recorded_alias)) {
|
||||
qWarning() << "[Command Extension Collection]"
|
||||
<< "warning: command alias" << i_recorded_alias << "was already defined";
|
||||
l_aliases.removeAll(i_recorded_alias);
|
||||
}
|
||||
}
|
||||
l_alias_records.append(l_aliases);
|
||||
|
||||
CommandExtension l_extension(l_command_name);
|
||||
l_extension.setAliases(l_aliases);
|
||||
l_extension.setPermissionsByCaption(l_settings.value("permissions").toString().split(" ", akashi::SkipEmptyParts));
|
||||
m_extensions.insert(l_command_name, std::move(l_extension));
|
||||
|
||||
l_settings.endGroup();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -153,10 +153,10 @@ void AOClient::cmdListPerms(int argc, QStringList argv)
|
||||
l_message.append("SUPER (Be careful! This grants the user all permissions.)");
|
||||
}
|
||||
else {
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::permission_captions.keys();
|
||||
const QList<ACLRole::Permission> l_permissions = ACLRole::PERMISSION_CAPTIONS.keys();
|
||||
for (const ACLRole::Permission i_permission : l_permissions) {
|
||||
if (l_target_role.checkPermission(i_permission)) {
|
||||
l_message.append(ACLRole::permission_captions.value(i_permission));
|
||||
l_message.append(ACLRole::PERMISSION_CAPTIONS.value(i_permission));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -474,34 +474,34 @@ void AOClient::cmdUnCharCurse(int argc, QStringList argv)
|
||||
|
||||
void AOClient::cmdCharSelect(int argc, QStringList argv)
|
||||
{
|
||||
if (argc == 0) {
|
||||
changeCharacter(-1);
|
||||
sendPacket("DONE");
|
||||
Q_UNUSED(argc);
|
||||
Q_UNUSED(argv);
|
||||
|
||||
changeCharacter(-1);
|
||||
sendPacket("DONE");
|
||||
}
|
||||
|
||||
void AOClient::cmdForceCharSelect(int argc, QStringList argv)
|
||||
{
|
||||
Q_UNUSED(argc);
|
||||
|
||||
bool ok = false;
|
||||
int l_target_id = argv[0].toInt(&ok);
|
||||
if (!ok) {
|
||||
sendServerMessage("This ID does not look valid. Please use the client ID.");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!checkPermission(ACLRole::FORCE_CHARSELECT)) {
|
||||
sendServerMessage("You do not have permission to force another player to character select!");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
int l_target_id = argv[0].toInt(&ok);
|
||||
if (!ok) {
|
||||
sendServerMessage("This ID does not look valid. Please use the client ID.");
|
||||
return;
|
||||
}
|
||||
AOClient *l_target = server->getClientByID(l_target_id);
|
||||
|
||||
AOClient *l_target = server->getClientByID(l_target_id);
|
||||
|
||||
if (l_target == nullptr) {
|
||||
sendServerMessage("Unable to locate client with ID " + QString::number(l_target_id) + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
l_target->changeCharacter(-1);
|
||||
l_target->sendPacket("DONE");
|
||||
sendServerMessage("Client has been forced into character select!");
|
||||
if (l_target == nullptr) {
|
||||
sendServerMessage("Unable to locate client with ID " + QString::number(l_target_id) + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
l_target->changeCharacter(-1);
|
||||
l_target->sendPacket("DONE");
|
||||
sendServerMessage("Client has been forced into character select!");
|
||||
}
|
||||
|
||||
void AOClient::cmdA(int argc, QStringList argv)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "include/aoclient.h"
|
||||
|
||||
#include "include/area_data.h"
|
||||
#include "include/command_extension.h"
|
||||
#include "include/config_manager.h"
|
||||
#include "include/db_manager.h"
|
||||
#include "include/server.h"
|
||||
@ -165,11 +166,27 @@ void AOClient::cmdCommands(int argc, QStringList argv)
|
||||
QStringList l_entries;
|
||||
l_entries << "Allowed commands:";
|
||||
QMap<QString, CommandInfo>::const_iterator i;
|
||||
for (i = commands.constBegin(); i != commands.constEnd(); ++i) {
|
||||
CommandInfo info = i.value();
|
||||
if (checkPermission(info.acl_permission)) { // if we are allowed to use this command
|
||||
l_entries << "/" + i.key();
|
||||
for (i = COMMANDS.constBegin(); i != COMMANDS.constEnd(); ++i) {
|
||||
const CommandInfo l_command = i.value();
|
||||
const CommandExtension l_extension = server->getCommandExtensionCollection()->getExtension(i.key());
|
||||
const QVector<ACLRole::Permission> l_permissions = l_extension.getPermissions(l_command.acl_permissions);
|
||||
bool l_has_permission = false;
|
||||
for (const ACLRole::Permission i_permission : qAsConst(l_permissions)) {
|
||||
if (checkPermission(i_permission)) {
|
||||
l_has_permission = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!l_has_permission) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString l_info = "/" + i.key();
|
||||
const QStringList l_aliases = l_extension.getAliases();
|
||||
if (!l_aliases.isEmpty()) {
|
||||
l_info += " [aka: " + l_aliases.join(", ") + "]";
|
||||
}
|
||||
l_entries << l_info;
|
||||
}
|
||||
sendServerMessage(l_entries.join("\n"));
|
||||
}
|
||||
@ -191,19 +208,19 @@ void AOClient::cmdHelp(int argc, QStringList argv)
|
||||
|
||||
void AOClient::cmdMOTD(int argc, QStringList argv)
|
||||
{
|
||||
if (argc == 0) {
|
||||
sendServerMessage("=== MOTD ===\r\n" + ConfigManager::motd() + "\r\n=============");
|
||||
}
|
||||
else if (argc > 0) {
|
||||
if (checkPermission(ACLRole::MOTD)) {
|
||||
QString l_MOTD = argv.join(" ");
|
||||
ConfigManager::setMotd(l_MOTD);
|
||||
sendServerMessage("MOTD has been changed.");
|
||||
}
|
||||
else {
|
||||
sendServerMessage("You do not have permission to change the MOTD");
|
||||
}
|
||||
}
|
||||
Q_UNUSED(argc)
|
||||
Q_UNUSED(argv)
|
||||
|
||||
sendServerMessage("=== MOTD ===\r\n" + ConfigManager::motd() + "\r\n=============");
|
||||
}
|
||||
|
||||
void AOClient::cmdSetMOTD(int argc, QStringList argv)
|
||||
{
|
||||
Q_UNUSED(argc)
|
||||
|
||||
QString l_MOTD = argv.join(" ");
|
||||
ConfigManager::setMotd(l_MOTD);
|
||||
sendServerMessage("MOTD has been changed.");
|
||||
}
|
||||
|
||||
void AOClient::cmdBans(int argc, QStringList argv)
|
||||
|
@ -127,15 +127,10 @@ void AOClient::cmdToggleJukebox(int argc, QStringList argv)
|
||||
Q_UNUSED(argc);
|
||||
Q_UNUSED(argv);
|
||||
|
||||
if (checkPermission(ACLRole::CM) | checkPermission(ACLRole::JUKEBOX)) {
|
||||
AreaData *l_area = server->getAreaById(m_current_area);
|
||||
l_area->toggleJukebox();
|
||||
QString l_state = l_area->isjukeboxEnabled() ? "enabled." : "disabled.";
|
||||
sendServerMessageArea("The jukebox in this area has been " + l_state);
|
||||
}
|
||||
else {
|
||||
sendServerMessage("You do not have permission to change the jukebox status.");
|
||||
}
|
||||
AreaData *l_area = server->getAreaById(m_current_area);
|
||||
l_area->toggleJukebox();
|
||||
QString l_state = l_area->isjukeboxEnabled() ? "enabled." : "disabled.";
|
||||
sendServerMessageArea("The jukebox in this area has been " + l_state);
|
||||
}
|
||||
|
||||
void AOClient::cmdAddSong(int argc, QStringList argv)
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <QQueue>
|
||||
|
||||
#include "include/akashidefs.h"
|
||||
#include "include/aopacket.h"
|
||||
#include "include/area_data.h"
|
||||
#include "include/config_manager.h"
|
||||
@ -258,11 +259,7 @@ void AOClient::pktOocChat(AreaData *area, int argc, QStringList argv, AOPacket p
|
||||
return;
|
||||
AOPacket final_packet("CT", {m_ooc_name, l_message, "0"});
|
||||
if (l_message.at(0) == '/') {
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QStringList l_cmd_argv = l_message.split(" ", QString::SplitBehavior::SkipEmptyParts);
|
||||
#else
|
||||
QStringList l_cmd_argv = l_message.split(" ", Qt::SkipEmptyParts);
|
||||
#endif
|
||||
QStringList l_cmd_argv = l_message.split(" ", akashi::SkipEmptyParts);
|
||||
QString l_command = l_cmd_argv[0].trimmed().toLower();
|
||||
l_command = l_command.right(l_command.length() - 1);
|
||||
l_cmd_argv.removeFirst();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "include/aoclient.h"
|
||||
#include "include/aopacket.h"
|
||||
#include "include/area_data.h"
|
||||
#include "include/command_extension.h"
|
||||
#include "include/config_manager.h"
|
||||
#include "include/db_manager.h"
|
||||
#include "include/discord.h"
|
||||
@ -48,6 +49,10 @@ Server::Server(int p_port, int p_ws_port, QObject *parent) :
|
||||
acl_roles_handler = new ACLRolesHandler;
|
||||
acl_roles_handler->loadFile("config/acl_roles.ini");
|
||||
|
||||
command_extension_collection = new CommandExtensionCollection;
|
||||
command_extension_collection->setCommandNameWhitelist(AOClient::COMMANDS.keys());
|
||||
command_extension_collection->loadFile("config/command_extensions.ini");
|
||||
|
||||
// We create it, even if its not used later on.
|
||||
discord = new Discord(this);
|
||||
|
||||
@ -286,6 +291,8 @@ void Server::reloadSettings()
|
||||
handleDiscordIntegration();
|
||||
logger->loadLogtext();
|
||||
m_ipban_list = ConfigManager::iprangeBans();
|
||||
acl_roles_handler->loadFile("config/acl_roles.ini");
|
||||
command_extension_collection->loadFile("config/command_extensions.ini");
|
||||
}
|
||||
|
||||
void Server::broadcast(AOPacket packet, int area_index)
|
||||
@ -463,6 +470,11 @@ ACLRolesHandler *Server::getACLRolesHandler()
|
||||
return acl_roles_handler;
|
||||
}
|
||||
|
||||
CommandExtensionCollection *Server::getCommandExtensionCollection()
|
||||
{
|
||||
return command_extension_collection;
|
||||
}
|
||||
|
||||
void Server::allowMessage()
|
||||
{
|
||||
m_can_send_ic_messages = true;
|
||||
|
@ -3,4 +3,5 @@ TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
unittest_area \
|
||||
unittest_music_manager \
|
||||
unittest_acl_roles_handler
|
||||
unittest_acl_roles_handler \
|
||||
unittest_command_extension
|
||||
|
@ -0,0 +1,237 @@
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include <QTest>
|
||||
|
||||
#include <include/command_extension.h>
|
||||
|
||||
namespace tests {
|
||||
namespace unittests {
|
||||
|
||||
/**
|
||||
* @brief Unit Tester class for ACL roles-related functions.
|
||||
*/
|
||||
class tst_CommandExtension : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef QVector<ACLRole::Permission> PermVector;
|
||||
|
||||
CommandExtension m_extension;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Initialises every tests
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* @brief The data function of checkCommandName
|
||||
*/
|
||||
void checkCommandName_data();
|
||||
|
||||
/**
|
||||
* @brief Tests various command names
|
||||
*/
|
||||
void checkCommandName();
|
||||
|
||||
/**
|
||||
* @brief The data function of checkAliases
|
||||
*/
|
||||
void checkAliases_data();
|
||||
|
||||
/**
|
||||
* @brief Tests various aliases
|
||||
*/
|
||||
void checkAliases();
|
||||
|
||||
/**
|
||||
* @brief The data function of checkAlias
|
||||
*/
|
||||
void checkAlias_data();
|
||||
|
||||
/**
|
||||
* @brief checkAlias
|
||||
*/
|
||||
void checkAlias();
|
||||
|
||||
/**
|
||||
* @brief The data function of checkPermission
|
||||
*/
|
||||
void checkPermission_data();
|
||||
|
||||
/**
|
||||
* @brief Tests various permission scenarios
|
||||
*/
|
||||
void checkPermission();
|
||||
|
||||
/**
|
||||
* @brief The data function of setPermissionsByCaption
|
||||
*/
|
||||
void setPermissionsByCaption_data();
|
||||
|
||||
/**
|
||||
* @brief Tests the role caption conversion
|
||||
*/
|
||||
void setPermissionsByCaption();
|
||||
};
|
||||
|
||||
void tst_CommandExtension::init()
|
||||
{
|
||||
m_extension = CommandExtension();
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkCommandName_data()
|
||||
{
|
||||
QTest::addColumn<QString>("name");
|
||||
QTest::addColumn<QString>("expected_name");
|
||||
QTest::addColumn<bool>("expected_result");
|
||||
|
||||
QTest::newRow("Identical name") << "extension"
|
||||
<< "extension" << true;
|
||||
QTest::newRow("Different name") << "different"
|
||||
<< "extension" << false;
|
||||
QTest::newRow("No name") << QString{}
|
||||
<< "extension" << false;
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkCommandName()
|
||||
{
|
||||
QFETCH(QString, name);
|
||||
QFETCH(QString, expected_name);
|
||||
QFETCH(bool, expected_result);
|
||||
|
||||
{
|
||||
CommandExtension l_extension(name);
|
||||
QCOMPARE(l_extension.getCommandName() == expected_name, expected_result);
|
||||
}
|
||||
|
||||
{
|
||||
CommandExtension l_extension;
|
||||
l_extension.setCommandName(name);
|
||||
QCOMPARE(l_extension.getCommandName() == expected_name, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkAliases_data()
|
||||
{
|
||||
QTest::addColumn<QString>("name");
|
||||
QTest::addColumn<QStringList>("aliases");
|
||||
QTest::addColumn<QStringList>("expected_aliases");
|
||||
QTest::addColumn<bool>("expected_result");
|
||||
|
||||
QTest::newRow("Identical aliases") << "extension" << QStringList{"ext", "extended"} << QStringList{"ext", "extended"} << true;
|
||||
QTest::newRow("Different aliases") << "extension" << QStringList{"ext", "extended"} << QStringList{"will", "not", "be", "valid"} << false;
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkAliases()
|
||||
{
|
||||
QFETCH(QString, name);
|
||||
QFETCH(QStringList, aliases);
|
||||
QFETCH(QStringList, expected_aliases);
|
||||
QFETCH(bool, expected_result);
|
||||
|
||||
{
|
||||
CommandExtension l_extension;
|
||||
l_extension.setAliases(aliases);
|
||||
QCOMPARE(l_extension.getAliases() == expected_aliases, expected_result);
|
||||
}
|
||||
|
||||
{
|
||||
CommandExtension l_extension(name);
|
||||
l_extension.setAliases(aliases);
|
||||
QCOMPARE(l_extension.getAliases() == expected_aliases, expected_result);
|
||||
}
|
||||
|
||||
{
|
||||
CommandExtension l_extension;
|
||||
l_extension.setCommandName(name);
|
||||
l_extension.setAliases(aliases);
|
||||
QCOMPARE(l_extension.getAliases() == expected_aliases, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkAlias_data()
|
||||
{
|
||||
QTest::addColumn<QString>("name");
|
||||
QTest::addColumn<QStringList>("aliases");
|
||||
QTest::addColumn<QString>("target");
|
||||
QTest::addColumn<bool>("expected_result");
|
||||
|
||||
QTest::newRow("Target found: name") << "extension" << QStringList{"ext", "extended"} << "extension" << true;
|
||||
QTest::newRow("Target found: alias") << "extension" << QStringList{"ext", "extended"} << "ext" << true;
|
||||
QTest::newRow("Target not found") << "extension" << QStringList{"ext", "extended"} << "wont_find_me" << false;
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkAlias()
|
||||
{
|
||||
QFETCH(QString, name);
|
||||
QFETCH(QStringList, aliases);
|
||||
QFETCH(QString, target);
|
||||
QFETCH(bool, expected_result);
|
||||
|
||||
{
|
||||
m_extension.setCommandName(name);
|
||||
m_extension.setAliases(aliases);
|
||||
QCOMPARE(m_extension.checkCommandNameAndAlias(target), expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_CommandExtension::setPermissionsByCaption_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("permission_captions");
|
||||
QTest::addColumn<PermVector>("expected_permissions");
|
||||
QTest::addColumn<bool>("message_required");
|
||||
QTest::addColumn<bool>("expected_result");
|
||||
|
||||
QTest::addRow("Valid captions") << QStringList{"none", "super"} << PermVector{ACLRole::NONE, ACLRole::SUPER} << false << true;
|
||||
QTest::addRow("Invalid captions") << QStringList{"none", "not_none"} << PermVector{ACLRole::NONE, ACLRole::SUPER} << true << false;
|
||||
QTest::addRow("Valid and invalid captions") << QStringList{"none", "not_super"} << PermVector{ACLRole::NONE} << true << true;
|
||||
}
|
||||
|
||||
void tst_CommandExtension::setPermissionsByCaption()
|
||||
{
|
||||
QFETCH(QStringList, permission_captions);
|
||||
QFETCH(PermVector, expected_permissions);
|
||||
QFETCH(bool, message_required);
|
||||
QFETCH(bool, expected_result);
|
||||
|
||||
{
|
||||
if (message_required) {
|
||||
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("\\[Command Extension\\] error: permission \".*?\" does not exist"));
|
||||
}
|
||||
m_extension.setPermissionsByCaption(permission_captions);
|
||||
QCOMPARE(m_extension.getPermissions() == expected_permissions, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkPermission_data()
|
||||
{
|
||||
QTest::addColumn<PermVector>("permissions");
|
||||
QTest::addColumn<PermVector>("default_permissions");
|
||||
QTest::addColumn<PermVector>("expected_permissions");
|
||||
QTest::addColumn<bool>("expected_result");
|
||||
|
||||
QTest::addRow("Matches permissions") << PermVector{ACLRole::SUPER} << PermVector{} << PermVector{ACLRole::SUPER} << true;
|
||||
QTest::addRow("Matches default permissions") << PermVector{} << PermVector{ACLRole::NONE} << PermVector{ACLRole::NONE} << true;
|
||||
}
|
||||
|
||||
void tst_CommandExtension::checkPermission()
|
||||
{
|
||||
QFETCH(PermVector, permissions);
|
||||
QFETCH(PermVector, default_permissions);
|
||||
QFETCH(PermVector, expected_permissions);
|
||||
QFETCH(bool, expected_result);
|
||||
|
||||
{
|
||||
m_extension.setPermissions(permissions);
|
||||
QCOMPARE(m_extension.getPermissions(default_permissions) == expected_permissions, expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tests::unittests::tst_CommandExtension)
|
||||
|
||||
#include "tst_unittest_command_extension.moc"
|
@ -0,0 +1,6 @@
|
||||
QT -= gui
|
||||
|
||||
include(../tests_common.pri)
|
||||
|
||||
SOURCES += \
|
||||
tst_unittest_command_extension.cpp
|
Loading…
Reference in New Issue
Block a user