changeset 643:eff84e503c26

Irccd: implement rule_util, #771
author David Demelier <markand@malikania.fr>
date Wed, 21 Mar 2018 19:45:55 +0100
parents d3ea56d7a126
children aae6d5a2b28d
files libirccd/CMakeLists.txt libirccd/irccd/daemon/command/rule_add_command.cpp libirccd/irccd/daemon/command/rule_edit_command.cpp libirccd/irccd/daemon/command/rule_info_command.cpp libirccd/irccd/daemon/command/rule_list_command.cpp libirccd/irccd/daemon/command/rule_move_command.cpp libirccd/irccd/daemon/command/rule_remove_command.cpp libirccd/irccd/daemon/rule_util.cpp libirccd/irccd/daemon/rule_util.hpp libirccd/irccd/daemon/service/rule_service.cpp libirccd/irccd/daemon/service/rule_service.hpp
diffstat 11 files changed, 275 insertions(+), 167 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd/CMakeLists.txt	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/CMakeLists.txt	Wed Mar 21 19:45:55 2018 +0100
@@ -61,6 +61,7 @@
     ${libirccd_SOURCE_DIR}/irccd/daemon/logger.hpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/plugin.hpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/rule.hpp
+    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.hpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/server.hpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/server_util.hpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/service/plugin_service.hpp
@@ -108,6 +109,7 @@
     ${libirccd_SOURCE_DIR}/irccd/daemon/logger.cpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/plugin.cpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/rule.cpp
+    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.cpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/server.cpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/server_util.cpp
     ${libirccd_SOURCE_DIR}/irccd/daemon/service/plugin_service.cpp
--- a/libirccd/irccd/daemon/command/rule_add_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_add_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -20,6 +20,7 @@
 
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/transport_client.hpp>
+#include <irccd/daemon/rule_util.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
 
@@ -41,7 +42,7 @@
     if (index > irccd.rules().length())
         throw rule_error(rule_error::error::invalid_index);
 
-    irccd.rules().insert(rule_service::from_json(args), *index);
+    irccd.rules().insert(rule_util::from_json(args), *index);
     client.success("rule-add");
 }
 
--- a/libirccd/irccd/daemon/command/rule_edit_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_edit_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -16,7 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <irccd/json_util.hpp>
+
 #include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/rule_util.hpp>
 #include <irccd/daemon/transport_client.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
@@ -46,8 +49,12 @@
     };
 
     // Create a copy to avoid incomplete edition in case of errors.
-    auto index = irccd.rules().get_index(args);
-    auto rule = irccd.rules().require(index);
+    const auto index = json_util::get_uint(args, "/index"_json_pointer);
+
+    if (!index)
+        throw rule_error(rule_error::invalid_index);
+
+    auto rule = irccd.rules().require(*index);
 
     updateset(rule.get_channels(), args, "channels");
     updateset(rule.get_events(), args, "events");
@@ -69,7 +76,7 @@
     }
 
     // All done, sync the rule.
-    irccd.rules().require(index) = rule;
+    irccd.rules().require(*index) = rule;
     client.success("rule-edit");
 }
 
--- a/libirccd/irccd/daemon/command/rule_info_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_info_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -16,7 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <irccd/json_util.hpp>
+
 #include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/rule_util.hpp>
 #include <irccd/daemon/transport_client.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
@@ -32,7 +35,12 @@
 
 void rule_info_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args)
 {
-    auto json = rule_service::to_json(irccd.rules().require(irccd.rules().get_index(args)));
+    const auto index = json_util::get_uint(args, "/index"_json_pointer);
+
+    if (!index)
+        throw rule_error(rule_error::invalid_index);
+
+    auto json = rule_util::to_json(irccd.rules().require(*index));
 
     json.push_back({"command", "rule-info"});
     client.send(std::move(json));
--- a/libirccd/irccd/daemon/command/rule_list_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_list_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -17,6 +17,7 @@
  */
 
 #include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/rule_util.hpp>
 #include <irccd/daemon/transport_client.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
@@ -35,7 +36,7 @@
     auto array = nlohmann::json::array();
 
     for (const auto& rule : irccd.rules().list())
-        array.push_back(rule_service::to_json(rule));
+        array.push_back(rule_util::to_json(rule));
 
     client.send({
         { "command",    "rule-list"         },
--- a/libirccd/irccd/daemon/command/rule_move_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_move_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -16,7 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <irccd/json_util.hpp>
+
 #include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/rule_util.hpp>
 #include <irccd/daemon/transport_client.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
@@ -32,8 +35,11 @@
 
 void rule_move_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args)
 {
-    auto from = rule_service::get_index(args, "from");
-    auto to = rule_service::get_index(args, "to");
+    const auto from = json_util::get_uint(args, "/from"_json_pointer);
+    const auto to = json_util::get_uint(args, "/to"_json_pointer);
+
+    if (!from || !to)
+        throw rule_error(rule_error::invalid_index);
 
     /*
      * Examples of moves
@@ -66,18 +72,18 @@
      */
 
     // Ignore dumb input.
-    if (from == to) {
+    if (*from == *to) {
         client.success("rule-move");
         return;
     }
 
-    if (from >= irccd.rules().length())
+    if (*from >= irccd.rules().length())
         throw rule_error(rule_error::error::invalid_index);
 
-    auto save = irccd.rules().list()[from];
+    const auto save = irccd.rules().list()[*from];
 
-    irccd.rules().remove(from);
-    irccd.rules().insert(save, to > irccd.rules().length() ? irccd.rules().length() : to);
+    irccd.rules().remove(*from);
+    irccd.rules().insert(save, *to > irccd.rules().length() ? irccd.rules().length() : *to);
     client.success("rule-move");
 }
 
--- a/libirccd/irccd/daemon/command/rule_remove_command.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/command/rule_remove_command.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <irccd/json_util.hpp>
+
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/transport_client.hpp>
 
@@ -32,12 +34,12 @@
 
 void rule_remove_command::exec(irccd& irccd, transport_client& client, const nlohmann::json& args)
 {
-    auto index = rule_service::get_index(args);
+    const auto index = json_util::get_uint(args, "/index"_json_pointer);
 
-    if (index >= irccd.rules().length())
+    if (!index || *index >= irccd.rules().length())
         throw rule_error(rule_error::invalid_index);
 
-    irccd.rules().remove(index);
+    irccd.rules().remove(*index);
     client.success("rule-remove");
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd/irccd/daemon/rule_util.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -0,0 +1,152 @@
+/*
+ * rule_util.cpp -- rule utilities
+ *
+ * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <unordered_set>
+
+#include <irccd/ini.hpp>
+
+#include <irccd/daemon/rule.hpp>
+
+#include "rule_util.hpp"
+
+namespace irccd {
+
+namespace rule_util {
+
+rule from_config(const ini::section& sc)
+{
+    // Simple converter from std::vector to std::unordered_set.
+    const auto toset = [] (const auto& v) {
+        return std::unordered_set<std::string>(v.begin(), v.end());
+    };
+
+    rule::set servers, channels, origins, plugins, events;
+    rule::action action = rule::action::accept;
+
+    // Get the sets.
+    ini::section::const_iterator it;
+
+    if ((it = sc.find("servers")) != sc.end())
+        servers = toset(*it);
+    if ((it = sc.find("channels")) != sc.end())
+        channels = toset(*it);
+    if ((it = sc.find("origins")) != sc.end())
+        origins = toset(*it);
+    if ((it = sc.find("plugins")) != sc.end())
+        plugins = toset(*it);
+    if ((it = sc.find("channels")) != sc.end())
+        channels = toset(*it);
+
+    // Get the action.
+    auto actionstr = sc.get("action").value();
+
+    if (actionstr == "drop")
+        action = rule::action::drop;
+    else if (actionstr == "accept")
+        action = rule::action::accept;
+    else
+        throw rule_error(rule_error::invalid_action);
+
+    return {
+        std::move(servers),
+        std::move(channels),
+        std::move(origins),
+        std::move(plugins),
+        std::move(events),
+        action
+    };
+}
+
+rule from_json(const nlohmann::json& json)
+{
+    const auto toset = [] (auto object, auto name) {
+        rule::set result;
+
+        for (const auto& s : object[name])
+            if (s.is_string())
+                result.insert(s.template get<std::string>());
+
+        return result;
+    };
+    const auto toaction = [] (const auto& object, const auto& name) {
+        const auto v = object.find(name);
+
+        if (v == object.end() || !v->is_string())
+            throw rule_error(rule_error::invalid_action);
+
+        const auto s = v->template get<std::string>();
+
+        if (s == "accept")
+            return rule::action::accept;
+        if (s == "drop")
+            return rule::action::drop;
+
+        throw rule_error(rule_error::invalid_action);
+    };
+
+    return {
+        toset(json, "servers"),
+        toset(json, "channels"),
+        toset(json, "origins"),
+        toset(json, "plugins"),
+        toset(json, "events"),
+        toaction(json, "action")
+    };
+}
+
+unsigned get_index(const nlohmann::json& json, const std::string& key)
+{
+    const auto index = json.find(key);
+
+    if (index == json.end() || !index->is_number_integer() || index->get<int>() < 0)
+        throw rule_error(rule_error::invalid_index);
+
+    return index->get<int>();
+}
+
+nlohmann::json to_json(const rule& rule)
+{
+    const auto join = [] (const auto& set) {
+        auto array = nlohmann::json::array();
+
+        for (const auto& entry : set)
+            array.push_back(entry);
+
+        return array;
+    };
+    const auto str = [] (auto action) {
+        switch (action) {
+        case rule::action::accept:
+            return "accept";
+        default:
+            return "drop";
+        }
+    };
+
+    return {
+        { "servers",    join(rule.get_servers())    },
+        { "channels",   join(rule.get_channels())   },
+        { "plugins",    join(rule.get_plugins())    },
+        { "events",     join(rule.get_events())     },
+        { "action",     str(rule.get_action())      }
+    };
+}
+
+} // !rule_util
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd/irccd/daemon/rule_util.hpp	Wed Mar 21 19:45:55 2018 +0100
@@ -0,0 +1,78 @@
+/*
+ * rule_util.hpp -- rule utilities
+ *
+ * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_DAEMON_RULE_UTIL_HPP
+#define IRCCD_DAEMON_RULE_UTIL_HPP
+
+/**
+ * \file rule_util.hpp
+ * \brief Rule utilities.
+ */
+
+#include <json.hpp>
+
+namespace irccd {
+
+namespace ini {
+
+class section;
+
+} // !ini
+
+class config;
+class rule;
+
+/**
+ * \brief Rule utilities.
+ */
+namespace rule_util {
+
+/**
+ * Load a rule from a JSON object.
+ *
+ * For possible use in transport commands or Javascript API.
+ *
+ * \pre json.is_object()
+ * \param json the JSON object
+ * \return the new rule
+ * \throw rule_error on errors
+ */
+rule from_json(const nlohmann::json& json);
+
+/**
+ * Load a rule from a INI section.
+ *
+ * \param sc the ini section
+ * \return the rule
+ * \throw rule_error on errors
+ */
+rule from_config(const ini::section& sc);
+
+/**
+ * Convert a rule into a JSON object.
+ *
+ * \param rule the rule
+ * \throw the JSON representation
+ */
+nlohmann::json to_json(const rule& rule);
+
+} // !rule_util
+
+} // !irccd
+
+#endif // !IRCCD_DAEMON_RULE_UTIL_HPP
--- a/libirccd/irccd/daemon/service/rule_service.cpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/service/rule_service.cpp	Wed Mar 21 19:45:55 2018 +0100
@@ -23,6 +23,7 @@
 
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/logger.hpp>
+#include <irccd/daemon/rule_util.hpp>
 
 #include <irccd/daemon/service/rule_service.hpp>
 
@@ -30,128 +31,9 @@
 
 namespace {
 
-rule load_rule(const ini::section& sc)
-{
-    assert(sc.key() == "rule");
-
-    // Simple converter from std::vector to std::unordered_set.
-    auto toset = [] (const auto& v) {
-        return std::unordered_set<std::string>(v.begin(), v.end());
-    };
-
-    rule::set servers, channels, origins, plugins, events;
-    rule::action action = rule::action::accept;
-
-    // Get the sets.
-    ini::section::const_iterator it;
-
-    if ((it = sc.find("servers")) != sc.end())
-        servers = toset(*it);
-    if ((it = sc.find("channels")) != sc.end())
-        channels = toset(*it);
-    if ((it = sc.find("origins")) != sc.end())
-        origins = toset(*it);
-    if ((it = sc.find("plugins")) != sc.end())
-        plugins = toset(*it);
-    if ((it = sc.find("channels")) != sc.end())
-        channels = toset(*it);
-
-    // Get the action.
-    auto actionstr = sc.get("action").value();
-
-    if (actionstr == "drop")
-        action = rule::action::drop;
-    else if (actionstr == "accept")
-        action = rule::action::accept;
-    else
-        throw rule_error(rule_error::invalid_action);
-
-    return {
-        std::move(servers),
-        std::move(channels),
-        std::move(origins),
-        std::move(plugins),
-        std::move(events),
-        action
-    };
-}
 
 } // !namespace
 
-rule rule_service::from_json(const nlohmann::json& json)
-{
-    auto toset = [] (auto object, auto name) {
-        rule::set result;
-
-        for (const auto& s : object[name])
-            if (s.is_string())
-                result.insert(s.template get<std::string>());
-
-        return result;
-    };
-    auto toaction = [] (auto object, auto name) {
-        auto v = object[name];
-
-        if (!v.is_string())
-            throw rule_error(rule_error::invalid_action);
-
-        auto s = v.template get<std::string>();
-        if (s == "accept")
-            return rule::action::accept;
-        if (s == "drop")
-            return rule::action::drop;
-
-        throw rule_error(rule_error::invalid_action);
-    };
-
-    return {
-        toset(json, "servers"),
-        toset(json, "channels"),
-        toset(json, "origins"),
-        toset(json, "plugins"),
-        toset(json, "events"),
-        toaction(json, "action")
-    };
-}
-
-unsigned rule_service::get_index(const nlohmann::json& json, const std::string& key)
-{
-    auto index = json.find(key);
-
-    if (index == json.end() || !index->is_number_integer() || index->get<int>() < 0)
-        throw rule_error(rule_error::invalid_index);
-
-    return index->get<int>();
-}
-
-nlohmann::json rule_service::to_json(const rule& rule)
-{
-    auto join = [] (const auto& set) {
-        auto array = nlohmann::json::array();
-
-        for (const auto& entry : set)
-            array.push_back(entry);
-
-        return array;
-    };
-    auto str = [] (auto action) {
-        switch (action) {
-        case rule::action::accept:
-            return "accept";
-        default:
-            return "drop";
-        }
-    };
-
-    return {
-        { "servers",    join(rule.get_servers())    },
-        { "channels",   join(rule.get_channels())   },
-        { "plugins",    join(rule.get_plugins())    },
-        { "events",     join(rule.get_events())     },
-        { "action",     str(rule.get_action())      }
-    };
-}
-
 rule_service::rule_service(irccd &irccd)
     : irccd_(irccd)
 {
@@ -231,7 +113,7 @@
             continue;
 
         try {
-            rules_.push_back(load_rule(section));
+            rules_.push_back(rule_util::from_config(section));
         } catch (const std::exception& ex) {
             irccd_.log().warning() << "rule: " << ex.what() << std::endl;
         }
--- a/libirccd/irccd/daemon/service/rule_service.hpp	Wed Mar 21 12:51:25 2018 +0100
+++ b/libirccd/irccd/daemon/service/rule_service.hpp	Wed Mar 21 19:45:55 2018 +0100
@@ -46,37 +46,6 @@
 
 public:
     /**
-     * Load a rule from a JSON object.
-     *
-     * For possible use in transport commands or Javascript API.
-     *
-     * \pre json.is_object()
-     * \param json the JSON object
-     * \return the new rule
-     * \throw rule_error on errors
-     */
-    static rule from_json(const nlohmann::json& json);
-
-    /**
-     * Helper to get rule index in a JSON object.
-     *
-     * \pre json.is_object()
-     * \param json the JSON object
-     * \param key the index property
-     * \return the index
-     * \throw rule_error on errors
-     */
-    static unsigned get_index(const nlohmann::json& json, const std::string& key = "index");
-
-    /**
-     * Convert a rule into a JSON object.
-     *
-     * \param rule the rule
-     * \throw the JSON representation
-     */
-    static nlohmann::json to_json(const rule& rule);
-
-    /**
      * Create the rule service.
      */
     rule_service(irccd& instance);