From ecb173738acbf5b22de264b44bfd6f8143d01327 Mon Sep 17 00:00:00 2001 From: ShahanaFarooqui Date: Fri, 31 Mar 2023 11:54:46 +1030 Subject: [PATCH] commando: add restrictions information in listrune command --- plugins/commando.c | 128 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/plugins/commando.c b/plugins/commando.c index 02ab22933..5df9032f7 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -77,6 +77,76 @@ static bool usage_eq_id(const struct usage *u, u64 id) HTABLE_DEFINE_TYPE(struct usage, usage_id, id_hash, usage_eq_id, usage_table); static struct usage_table *usage_table; +/* The unique id is embedded with a special restriction with an empty field name */ +static bool is_unique_id(struct rune_restr **restrs, unsigned int index) +{ + /* must be the first restriction */ + if (index != 0) + return false; + + /* Must be the only alternative */ + if (tal_count(restrs[index]->alterns) != 1) + return false; + + /* Must have an empty field name */ + return streq(restrs[index]->alterns[0]->fieldname, ""); +} + +static char *rune_altern_to_english(const tal_t *ctx, const struct rune_altern *alt) +{ + const char *cond_str; + switch (alt->condition) { + case RUNE_COND_IF_MISSING: + return tal_strcat(ctx, alt->fieldname, " is missing"); + case RUNE_COND_EQUAL: + cond_str = "equal to"; + break; + case RUNE_COND_NOT_EQUAL: + cond_str = "unequal to"; + break; + case RUNE_COND_BEGINS: + cond_str = "starts with"; + break; + case RUNE_COND_ENDS: + cond_str = "ends with"; + break; + case RUNE_COND_CONTAINS: + cond_str = "contains"; + break; + case RUNE_COND_INT_LESS: + cond_str = "<"; + break; + case RUNE_COND_INT_GREATER: + cond_str = ">"; + break; + case RUNE_COND_LEXO_BEFORE: + cond_str = "sorts before"; + break; + case RUNE_COND_LEXO_AFTER: + cond_str = "sorts after"; + break; + case RUNE_COND_COMMENT: + return tal_fmt(ctx, "comment: %s %s", alt->fieldname, alt->value); + } + return tal_fmt(ctx, "%s %s %s", alt->fieldname, cond_str, alt->value); +} + +static char *json_add_alternative(const tal_t *ctx, + struct json_stream *js, + const char *fieldname, + struct rune_altern *alternative) +{ + char *altern_english; + altern_english = rune_altern_to_english(ctx, alternative); + json_object_start(js, fieldname); + json_add_string(js, "fieldname", alternative->fieldname); + json_add_string(js, "value", alternative->value); + json_add_stringn(js, "condition", (char *)&alternative->condition, 1); + json_add_string(js, "english", altern_english); + json_object_end(js); + return altern_english; +} + static bool is_rune_blacklisted(const struct rune *rune) { u64 uid; @@ -1037,16 +1107,56 @@ static struct command_result *json_commando_rune(struct command *cmd, return send_outreq(plugin, req); } -static struct command_result *json_add_runestr(struct json_stream *js, +static void join_strings(char **base, const char *connector, char *append) +{ + if (streq(*base, "")) { + *base = append; + } else { + tal_append_fmt(base, " %s %s", connector, append); + } +} + +static struct command_result *json_add_rune(struct json_stream *js, + const struct rune *rune, const char *rune_str, size_t rune_strlen, bool stored) { + char *rune_english; + rune_english = ""; json_object_start(js, NULL); json_add_stringn(js, "rune", rune_str, rune_strlen); if (!stored) { json_add_bool(js, "stored", false); } + if (is_rune_blacklisted(rune)) { + json_add_bool(js, "blacklisted", true); + } + if (rune_is_derived(master_rune, rune)) { + json_add_bool(js, "our_rune", false); + } + json_add_string(js, "unique_id", rune->unique_id); + json_array_start(js, "restrictions"); + for (size_t i = 0; i < tal_count(rune->restrs); i++) { + char *restr_english; + restr_english = ""; + /* Already printed out the unique id */ + if (is_unique_id(rune->restrs, i)) { + continue; + } + json_object_start(js, NULL); + json_array_start(js, "alternatives"); + for (size_t j = 0; j < tal_count(rune->restrs[i]->alterns); j++) { + join_strings(&restr_english, "OR", + json_add_alternative(tmpctx, js, NULL, rune->restrs[i]->alterns[j])); + } + json_array_end(js); + json_add_string(js, "english", restr_english); + json_object_end(js); + join_strings(&rune_english, "AND", restr_english); + } + json_array_end(js); + json_add_string(js, "restrictions_as_english", rune_english); json_object_end(js); return NULL; } @@ -1072,14 +1182,26 @@ static struct command_result *listdatastore_done(struct command *cmd, json_array_start(js, "runes"); json_for_each_arr(i, t, d) { + const struct rune *this_rune; const jsmntok_t *s = json_get_member(buf, t, "string"); if (runestr != NULL && !json_tok_streq(buf, s, runestr)) continue; - json_add_runestr(js, buf + s->start, s->end - s->start, true); + if (rune) { + this_rune = rune; + } else { + this_rune = rune_from_base64n(tmpctx, buf + s->start, s->end - s->start); + if (this_rune == NULL) { + plugin_log(plugin, LOG_BROKEN, + "Invalid rune in datastore %.*s", + s->end - s->start, buf + s->start); + continue; + } + } + json_add_rune(js, this_rune, buf + s->start, s->end - s->start, true); printed = true; } if (rune && !printed) { - json_add_runestr(js, runestr, strlen(runestr), false); + json_add_rune(js, rune, runestr, strlen(runestr), false); } json_array_end(js); return command_finished(cmd, js);