From 95aaa0dbc97b0d16178f59c6685ecea974a50000 Mon Sep 17 00:00:00 2001 From: LDA Date: Sat, 6 Jul 2024 02:16:52 +0200 Subject: [PATCH] [MOD/ADD] Use glob-like system for admins. --- src/Commands/Admin.c | 49 ++++++++++++++++++++++++++++++++++++++ src/Glob.c | 51 ++++++++++++++++++++++++++++++++++++++++ src/Main.c | 1 + src/MatrixEventHandler.c | 4 ++-- src/Parsee/Config.c | 6 ----- src/Parsee/User.c | 31 ++++++++++++++++++++++++ src/include/Bot.h | 1 + src/include/Glob.h | 10 ++++++++ src/include/Parsee.h | 8 +++---- src/include/Routes.h | 6 ++++- 10 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 src/Commands/Admin.c create mode 100644 src/Glob.c create mode 100644 src/include/Glob.h diff --git a/src/Commands/Admin.c b/src/Commands/Admin.c new file mode 100644 index 0000000..65e85e8 --- /dev/null +++ b/src/Commands/Admin.c @@ -0,0 +1,49 @@ +#include + +#include +#include +#include + +#include +#include +#include + +CommandHead(CmdAdmin, cmd, argp) +{ + ParseeCmdArg *args = argp; + ParseeData *data = args->data; + HashMap *event = args->event; + char *glob; + BotInitialise(); + BotRequired(glob); + { + DbRef *admins = DbLock(data->db, 1, "admins"); + HashMap *json; + Array *list; + bool init = false; + + if (!admins) + { + admins = DbCreate(data->db, 1, "admins"); + } + json = DbJson(admins); + + if (!(list = GrabArray(json, 1, "admins"))) + { + list = ArrayCreate(); + init = true; + } + + ArrayAdd(list, JsonValueString(glob)); + + if (init) + { + HashMapSet(json, "admins", JsonValueArray(list)); + } + + DbUnlock(data->db, admins); + } + ReplySprintf("Added glob '%s'", glob); +end: + BotDestroy(); +} diff --git a/src/Glob.c b/src/Glob.c new file mode 100644 index 0000000..805f5a6 --- /dev/null +++ b/src/Glob.c @@ -0,0 +1,51 @@ +#include + +#include +#include + +bool +GlobMatches(char *rule, char *string) +{ + char c1, c2; + if (!rule || !string) + { + return false; + } + + while ((c1 = *rule)) + { + char next = *(rule + 1); + c2 = *string; + switch (c1) + { + case '*': + /* TODO */ + while ((c2 = *string) && (c2 != next)) + { + string++; + } + if (next && !c2) + { + return false; + } + break; + case '?': + if (!c2) + { + return false; + } + string++; + break; + default: + if (c1 != c2) + { + return false; + } + string++; + break; + } + rule++; + } + + return !*string; +} diff --git a/src/Main.c b/src/Main.c index 4f09923..0c6e9fe 100644 --- a/src/Main.c +++ b/src/Main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/src/MatrixEventHandler.c b/src/MatrixEventHandler.c index 9289436..4bdd23c 100644 --- a/src/MatrixEventHandler.c +++ b/src/MatrixEventHandler.c @@ -96,12 +96,12 @@ ParseeBotHandler(ParseeData *data, HashMap *event) } /* TODO: Make an improvment. This is the bare minimum */ - if (!StrEquals(sender, data->config->matrix_admin)) + if (!ParseeIsAdmin(data, sender)) { Free(ASSend( data->config, id, profile, "m.room.message", - MatrixCreateNotice("You are not the admin") + MatrixCreateNotice("You are not authorised to do this.") )); Free(profile); return; diff --git a/src/Parsee/Config.c b/src/Parsee/Config.c index ed333db..8f6bb3d 100644 --- a/src/Parsee/Config.c +++ b/src/Parsee/Config.c @@ -79,9 +79,6 @@ ParseeConfigLoad(char *conf) CopyToStr(db_path, "db"); - CopyToStr(jabber_admin, "jabber_admin"); - CopyToStr(matrix_admin, "matrix_admin"); - JsonFree(json); StreamClose(stream); } @@ -126,9 +123,6 @@ ParseeConfigFree(void) Free(config->db_path); Free(config->homeserver_host); - Free(config->jabber_admin); - Free(config->matrix_admin); - Free(config->as_token); Free(config->hs_token); Free(config->sender_localpart); diff --git a/src/Parsee/User.c b/src/Parsee/User.c index 9c44acf..08fd32d 100644 --- a/src/Parsee/User.c +++ b/src/Parsee/User.c @@ -716,3 +716,34 @@ ParseeToUnauth(ParseeData *data, char *mxc) UriFree(url); return ret; } + +#include +bool +ParseeIsAdmin(ParseeData *data, char *user) +{ + DbRef *admins; + HashMap *json; + Array *values; + size_t i; + bool ret = false; + if (!data || !user) + { + return false; + } + + admins = DbLock(data->db, 1, "admins"); + json = DbJson(admins); + + values = GrabArray(json, 1, "admins"); + for (i = 0; i < ArraySize(values); i++) + { + char *glob = JsonValueAsString(ArrayGet(values, i)); + if ((ret = GlobMatches(glob, user))) + { + break; + } + } + + DbUnlock(data->db, admins); + return ret; +} diff --git a/src/include/Bot.h b/src/include/Bot.h index 12575a2..96ded6d 100644 --- a/src/include/Bot.h +++ b/src/include/Bot.h @@ -19,6 +19,7 @@ if (!prop) \ { \ ReplyBasic("Field `" #prop "` REQUIRED."); \ + goto end; \ } #define BotDestroy() Free(profile) diff --git a/src/include/Glob.h b/src/include/Glob.h new file mode 100644 index 0000000..a2dfdd1 --- /dev/null +++ b/src/include/Glob.h @@ -0,0 +1,10 @@ +#ifndef PARSEE_GLOB_H +#define PARSEE_GLOB_H + +#include + +/* Verifies if a string matches a rule, as specified in + * https://spec.matrix.org/v1.11/appendices/#glob-style-matching. */ +extern bool GlobMatches(char *rule, char *string); + +#endif diff --git a/src/include/Parsee.h b/src/include/Parsee.h index 7deba6d..ac4f295 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -35,10 +35,6 @@ typedef struct ParseeConfig { /* ------- DB -------- */ char *db_path; - - /* ------- ADMIN ------- */ - char *jabber_admin; - char *matrix_admin; } ParseeConfig; typedef struct ParseeData { @@ -217,4 +213,8 @@ extern bool ParseeManageBan(ParseeData *, char *user, char *room); /* Same as ParseeVerifyStanza, but DMs */ extern bool ParseeVerifyDMStanza(ParseeData *data, char *room_id, char *id); + + +/* Checks if any user is an admin */ +extern bool ParseeIsAdmin(ParseeData *data, char *user); #endif diff --git a/src/include/Routes.h b/src/include/Routes.h index 98e5122..4b99234 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -42,7 +42,7 @@ typedef struct ParseeCmdArg { ) \ X_COMMAND( \ "plumb-muc", CmdPlumb, \ - "Plumbs an existing Matrix room to a MUC." \ + "Plumbs an existing Matrix room to a MUC. " \ "You'll need to give the Parsee bot enough " \ "privileges, however. " \ ) \ @@ -50,6 +50,10 @@ typedef struct ParseeCmdArg { "help", CmdHelp, \ "Shows the command list" \ ) \ + X_COMMAND( \ + "adminify", CmdAdmin, \ + "Adminifies a Matrix glob pattern." \ + ) \ X_COMMAND( \ "stats", CmdStats, \ "Shows some Parsee statistics." \