add permissions (only everyone is checked yet)

This commit is contained in:
Green Sky 2023-12-04 16:53:38 +01:00
parent f83abab0a0
commit 51c5d9b06c
No known key found for this signature in database
3 changed files with 118 additions and 21 deletions

View File

@ -253,7 +253,8 @@ int main(int argc, char** argv) {
return true; 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( mcd.registerCommand(

View File

@ -2,12 +2,15 @@
#include <solanaceae/util/config_model.hpp> #include <solanaceae/util/config_model.hpp>
#include <solanaceae/message3/components.hpp> #include <solanaceae/message3/components.hpp>
#include <solanaceae/contact/components.hpp>
#include <solanaceae/toxcore/utils.hpp>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <cassert>
//MessageCommandDispatcher::Command::Command(Command&& other) : //MessageCommandDispatcher::Command::Command(Command&& other) :
//m(std::move(other.m)), //m(std::move(other.m)),
@ -26,6 +29,9 @@ MessageCommandDispatcher::MessageCommandDispatcher(
) : ) :
_cr(cr), _rmm(rmm), _conf(conf) _cr(cr), _rmm(rmm), _conf(conf)
{ {
// overwrite default admin to false
_conf.set("MessageCommandDispatcher", "admin", false);
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct); _rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
{ // setup basic commands for bot { // setup basic commands for bot
@ -35,7 +41,8 @@ MessageCommandDispatcher::MessageCommandDispatcher(
[this](std::string_view params, Message3Handle m) -> bool { [this](std::string_view params, Message3Handle m) -> bool {
return helpCommand(params, m); 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 m_prefix, // module prefix (if any)
std::string_view command, // command std::string_view command, // command
std::function<bool(std::string_view params, Message3Handle m)>&& fn, std::function<bool(std::string_view params, Message3Handle m)>&& 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}; 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"; 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{ _command_map[full_command_string] = Command{
std::string{m}, std::string{m},
std::string{m_prefix}, std::string{m_prefix},
std::string{command}, std::string{command},
std::move(fn), 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 + " ===" "=== " + module_name + " ==="
}); });
bool module_empty = true;
for (const auto& it : command_list) { for (const auto& it : command_list) {
if (!hasPermission(it->second, contact_from)) {
continue;
}
module_empty = false;
std::string help_line {" !"}; std::string help_line {" !"};
if (!it->second.m_prefix.empty()) { if (!it->second.m_prefix.empty()) {
help_line += it->second.m_prefix + " "; help_line += it->second.m_prefix + " ";
@ -138,15 +171,44 @@ bool MessageCommandDispatcher::helpCommand(std::string_view params, Message3Hand
help_line help_line
}); });
} }
if (module_empty) {
// unsend module cat title
_message_queue.pop_back();
}
} }
return true; return true;
} }
bool MessageCommandDispatcher::hasPermission(const Command& cmd, const Contact3 contact) {
if (!_cr.all_of<Contact::Components::ID>(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::Components::ID>(contact).data);
//_conf.get_bool
//_conf.set("MessageCommandDispatcher", "admin", false);
return false;
}
bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& e) { bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct& e) {
if (!e.e.all_of<Message::Components::MessageText, Message::Components::TagUnread>()) { if (!e.e.all_of<Message::Components::ContactFrom, Message::Components::MessageText, Message::Components::TagUnread>()) {
std::cout << "MCD: got message that is not"; std::cout << "MCD: got message that is not";
if (!e.e.all_of<Message::Components::ContactFrom>()) {
std::cout << " contact_from";
}
if (!e.e.all_of<Message::Components::MessageText>()) { if (!e.e.all_of<Message::Components::MessageText>()) {
std::cout << " text"; std::cout << " text";
} }
@ -180,7 +242,6 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
// TODO: has the permissions // TODO: has the permissions
if (false) { // is private if (false) { // is private
} else { } else {
// check for command prefix // check for command prefix
@ -237,6 +298,8 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
std::cout << "------- params:'" << params << "'\n"; std::cout << "------- params:'" << params << "'\n";
} }
const auto contact_from = e.e.get<Message::Components::ContactFrom>().c;
// first search first + space + second word // first search first + space + second word
if (!second_word.empty()) { if (!second_word.empty()) {
std::string query {first_word}; std::string query {first_word};
@ -245,6 +308,10 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
const auto command_it = _command_map.find(query); const auto command_it = _command_map.find(query);
if (command_it != _command_map.cend()) { if (command_it != _command_map.cend()) {
if (!hasPermission(command_it->second, contact_from)) {
return false;
}
command_it->second.fn(params, e.e); command_it->second.fn(params, e.e);
return true; return true;
} }
@ -253,6 +320,10 @@ bool MessageCommandDispatcher::onEvent(const Message::Events::MessageConstruct&
// then seach first word only // then seach first word only
const auto command_it = _command_map.find(std::string{first_word}); const auto command_it = _command_map.find(std::string{first_word});
if (command_it != _command_map.cend()) { if (command_it != _command_map.cend()) {
if (!hasPermission(command_it->second, contact_from)) {
return false;
}
params = std::string{second_word} + " " + params; params = std::string{second_word} + " " + params;
command_it->second.fn(params, e.e); command_it->second.fn(params, e.e);
return true; return true;

View File

@ -1,8 +1,13 @@
#pragma once #pragma once
#include <solanaceae/message3/registry_message_model.hpp> #include <solanaceae/message3/registry_message_model.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <deque> #include <deque>
#include <string>
#include <string_view>
#include <functional>
#include <unordered_map>
// fwd // fwd
struct ConfigModelI; struct ConfigModelI;
@ -12,22 +17,39 @@ class MessageCommandDispatcher : public RegistryMessageModelEventI {
RegistryMessageModel& _rmm; RegistryMessageModel& _rmm;
ConfigModelI& _conf; ConfigModelI& _conf;
struct Command { public:
std::string m; // module enum Perms {
std::string m_prefix; // module prefix (if any) BLACKLIST = 1 << 0,
std::string command; // command WHITELIST = 1 << 1,
std::function<bool(std::string_view params, Message3Handle m)> fn;
std::string help_text;
//Command(const Command&) = delete; // can only be trumped by blacklist
}; EVERYONE = 1 << 2,
std::unordered_map<std::string, Command> _command_map;
struct QueuedMessage { // can only be trumped by blacklist
Contact3 to; // TODO: replace with groups?
std::string message; ADMIN = 1 << 3,
}; MODERATOR = 1 << 4,
std::deque<QueuedMessage> _message_queue; };
private:
struct Command {
std::string m; // module
std::string m_prefix; // module prefix (if any)
std::string command; // command
std::function<bool(std::string_view params, Message3Handle m)> fn;
std::string help_text;
Perms perms = Perms::ADMIN; // default to highest
//Command(const Command&) = delete;
};
std::unordered_map<std::string, Command> _command_map;
struct QueuedMessage {
Contact3 to;
std::string message;
};
std::deque<QueuedMessage> _message_queue;
public: public:
MessageCommandDispatcher(Contact3Registry& cr, RegistryMessageModel& rmm, ConfigModelI& conf); 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 m_prefix, // module prefix (if any)
std::string_view command, // command std::string_view command, // command
std::function<bool(std::string_view params, Message3Handle m)>&& fn, std::function<bool(std::string_view params, Message3Handle m)>&& fn,
std::string_view help_text std::string_view help_text,
Perms perms = Perms::ADMIN
); );
// generates a help // generates a help
bool helpCommand(std::string_view params, Message3Handle m); bool helpCommand(std::string_view params, Message3Handle m);
bool hasPermission(const Command& cmd, const Contact3 contact);
protected: // mm protected: // mm
bool onEvent(const Message::Events::MessageConstruct& e) override; bool onEvent(const Message::Events::MessageConstruct& e) override;
bool onEvent(const Message::Events::MessageUpdated& e) override; bool onEvent(const Message::Events::MessageUpdated& e) override;