From 51c5d9b06cf2b3e8f45baffe70166c78dff278de Mon Sep 17 00:00:00 2001 From: Green Sky Date: Mon, 4 Dec 2023 16:53:38 +0100 Subject: [PATCH] add permissions (only everyone is checked yet) --- src/main.cpp | 3 +- src/message_command_dispatcher.cpp | 81 ++++++++++++++++++++++++++++-- src/message_command_dispatcher.hpp | 55 ++++++++++++++------ 3 files changed, 118 insertions(+), 21 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 884a6d4..6ced6a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -253,7 +253,8 @@ int main(int argc, char** argv) { return true; }, - "Query the tox status of dht and to you." + "Query the tox status of dht and to you.", + MessageCommandDispatcher::Perms::EVERYONE ); mcd.registerCommand( diff --git a/src/message_command_dispatcher.cpp b/src/message_command_dispatcher.cpp index 64f11dd..14d303a 100644 --- a/src/message_command_dispatcher.cpp +++ b/src/message_command_dispatcher.cpp @@ -2,12 +2,15 @@ #include #include +#include +#include #include #include #include #include #include +#include //MessageCommandDispatcher::Command::Command(Command&& other) : //m(std::move(other.m)), @@ -26,6 +29,9 @@ MessageCommandDispatcher::MessageCommandDispatcher( ) : _cr(cr), _rmm(rmm), _conf(conf) { + // overwrite default admin to false + _conf.set("MessageCommandDispatcher", "admin", false); + _rmm.subscribe(this, RegistryMessageModel_Event::message_construct); { // setup basic commands for bot @@ -35,7 +41,8 @@ MessageCommandDispatcher::MessageCommandDispatcher( [this](std::string_view params, Message3Handle m) -> bool { return helpCommand(params, m); }, - "Get help" + "Get help", + Perms::EVERYONE ); } } @@ -87,7 +94,8 @@ void MessageCommandDispatcher::registerCommand( std::string_view m_prefix, // module prefix (if any) std::string_view command, // command std::function&& fn, - std::string_view help_text + std::string_view help_text, + Perms perms ) { std::string full_command_string = (m_prefix.empty() ? "" : std::string{m_prefix} + " ") + std::string{command}; @@ -95,12 +103,30 @@ void MessageCommandDispatcher::registerCommand( std::cout << "MCD warning: overwriting existing '" << full_command_string << "'\n"; } + assert( + // needs atleast one "group" + (perms & ( + Perms::EVERYONE | + Perms::ADMIN | + Perms::MODERATOR + )) != 0u + ); + + assert( + // at most one "group" + (((perms & Perms::EVERYONE) != 0) + + ((perms & Perms::ADMIN) != 0) + + ((perms & Perms::MODERATOR) != 0)) + == 1 + ); + _command_map[full_command_string] = Command{ std::string{m}, std::string{m_prefix}, std::string{command}, std::move(fn), - std::string{help_text} + std::string{help_text}, + perms }; } @@ -122,7 +148,14 @@ bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Hand "=== " + module_name + " ===" }); + bool module_empty = true; for (const auto& it : command_list) { + if (!hasPermission(it->second, contact_from)) { + continue; + } + + module_empty = false; + std::string help_line {" !"}; if (!it->second.m_prefix.empty()) { help_line += it->second.m_prefix + " "; @@ -138,15 +171,44 @@ bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Hand help_line }); } + + if (module_empty) { + // unsend module cat title + _message_queue.pop_back(); + } } return true; } +bool MessageCommandDispatcher::hasPermission(const Command& cmd, const Contact3 contact) { + if (!_cr.all_of(contact)) { + std::cerr << "MCD error: contact without ID\n"; + return false; // default to false + } + + if ((cmd.perms & Perms::EVERYONE) != 0) { + // TODO: blacklist here + return true; + } + + // TODO: blacklist here + + const auto id_str = bin2hex(_cr.get(contact).data); + + //_conf.get_bool + //_conf.set("MessageCommandDispatcher", "admin", false); + + return false; +} + bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& e) { - if (!e.e.all_of()) { + if (!e.e.all_of()) { std::cout << "MCD: got message that is not"; + if (!e.e.all_of()) { + std::cout << " contact_from"; + } if (!e.e.all_of()) { std::cout << " text"; } @@ -180,7 +242,6 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& // TODO: has the permissions - if (false) { // is private } else { // check for command prefix @@ -237,6 +298,8 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& std::cout << "------- params:'" << params << "'\n"; } + const auto contact_from = e.e.get().c; + // first search first + space + second word if (!second_word.empty()) { std::string query {first_word}; @@ -245,6 +308,10 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& const auto command_it = _command_map.find(query); if (command_it != _command_map.cend()) { + if (!hasPermission(command_it->second, contact_from)) { + return false; + } + command_it->second.fn(params, e.e); return true; } @@ -253,6 +320,10 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& // then seach first word only const auto command_it = _command_map.find(std::string{first_word}); if (command_it != _command_map.cend()) { + if (!hasPermission(command_it->second, contact_from)) { + return false; + } + params = std::string{second_word} + " " + params; command_it->second.fn(params, e.e); return true; diff --git a/src/message_command_dispatcher.hpp b/src/message_command_dispatcher.hpp index 0988280..1437c33 100644 --- a/src/message_command_dispatcher.hpp +++ b/src/message_command_dispatcher.hpp @@ -1,8 +1,13 @@ #pragma once #include +#include #include +#include +#include +#include +#include // fwd struct ConfigModelI; @@ -12,22 +17,39 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI { RegistryMessageModel& _rmm; ConfigModelI& _conf; - struct Command { - std::string m; // module - std::string m_prefix; // module prefix (if any) - std::string command; // command - std::function fn; - std::string help_text; + public: + enum Perms { + BLACKLIST = 1 << 0, + WHITELIST = 1 << 1, - //Command(const Command&) = delete; - }; - std::unordered_map _command_map; + // can only be trumped by blacklist + EVERYONE = 1 << 2, - struct QueuedMessage { - Contact3 to; - std::string message; - }; - std::deque _message_queue; + // can only be trumped by blacklist + // TODO: replace with groups? + ADMIN = 1 << 3, + MODERATOR = 1 << 4, + }; + + private: + struct Command { + std::string m; // module + std::string m_prefix; // module prefix (if any) + std::string command; // command + std::function fn; + std::string help_text; + + Perms perms = Perms::ADMIN; // default to highest + + //Command(const Command&) = delete; + }; + std::unordered_map _command_map; + + struct QueuedMessage { + Contact3 to; + std::string message; + }; + std::deque _message_queue; public: MessageCommandDispatcher(Contact3Registry& cr, RegistryMessageModel& rmm, ConfigModelI& conf); @@ -49,12 +71,15 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI { std::string_view m_prefix, // module prefix (if any) std::string_view command, // command std::function&& fn, - std::string_view help_text + std::string_view help_text, + Perms perms = Perms::ADMIN ); // generates a help bool helpCommand(std::string_view params, Message3Handle m); + bool hasPermission(const Command& cmd, const Contact3 contact); + protected: // mm bool onEvent(const Message::Events::MessageConstruct& e) override; bool onEvent(const Message::Events::MessageUpdated& e) override;