From cf0f5c84ea9d898c1034324fcaba9d26d96f37c9 Mon Sep 17 00:00:00 2001 From: Jan Kolarik Date: Fri, 2 Feb 2024 11:10:48 +0100 Subject: [PATCH] dnf5daemon: Introduce enabling repositories in Repo interface Move the existing functionality of enabling and disabling of repositories from the RepoConf interface. Drop the RepoConf interface as the remaining list functionality that is required by clients is already provided by the Repo::list. Change the logic of commands to be strict against invalid arguments. --- dnf5daemon-server/dbus.hpp | 6 +- .../interfaces/org.rpm.dnf.v0.rpm.Repo.xml | 20 +++ .../polkit/org.rpm.dnf.v0.policy | 2 +- .../{repoconf => repo}/configuration.cpp | 0 .../{repoconf => repo}/configuration.hpp | 4 +- dnf5daemon-server/services/repo/repo.cpp | 59 +++++++ dnf5daemon-server/services/repo/repo.hpp | 5 + .../services/repoconf/repo_conf.cpp | 146 ------------------ .../services/repoconf/repo_conf.hpp | 49 ------ dnf5daemon-server/session.cpp | 2 - 10 files changed, 90 insertions(+), 203 deletions(-) rename dnf5daemon-server/services/{repoconf => repo}/configuration.cpp (100%) rename dnf5daemon-server/services/{repoconf => repo}/configuration.hpp (93%) delete mode 100644 dnf5daemon-server/services/repoconf/repo_conf.cpp delete mode 100644 dnf5daemon-server/services/repoconf/repo_conf.hpp diff --git a/dnf5daemon-server/dbus.hpp b/dnf5daemon-server/dbus.hpp index 4c514b6e19..06c12dcac8 100644 --- a/dnf5daemon-server/dbus.hpp +++ b/dnf5daemon-server/dbus.hpp @@ -55,7 +55,6 @@ const char * const DBUS_OBJECT_PATH = "/org/rpm/dnf/v0"; // interfaces const char * const INTERFACE_BASE = "org.rpm.dnf.v0.Base"; const char * const INTERFACE_REPO = "org.rpm.dnf.v0.rpm.Repo"; -const char * const INTERFACE_REPOCONF = "org.rpm.dnf.v0.rpm.RepoConf"; const char * const INTERFACE_RPM = "org.rpm.dnf.v0.rpm.Rpm"; const char * const INTERFACE_GOAL = "org.rpm.dnf.v0.Goal"; const char * const INTERFACE_GROUP = "org.rpm.dnf.v0.comps.Group"; @@ -87,13 +86,14 @@ const char * const SIGNAL_TRANSACTION_ELEM_PROGRESS = "transaction_elem_progress const char * const SIGNAL_TRANSACTION_FINISHED = "transaction_finished"; // polkit actions -const char * const POLKIT_REPOCONF_WRITE = "org.rpm.dnf.v0.rpm.RepoConf.write"; const char * const POLKIT_EXECUTE_RPM_TRANSACTION = "org.rpm.dnf.v0.rpm.execute_transaction"; const char * const POLKIT_CONFIRM_KEY_IMPORT = "org.rpm.dnf.v0.rpm.Repo.confirm_key"; +const char * const POLKIT_REPOCONF_WRITE = "org.rpm.dnf.v0.rpm.Repo.conf_write"; // errors const char * const ERROR = "org.rpm.dnf.v0.Error"; -const char * const ERROR_REPOCONF = "org.rpm.dnf.v0.rpm.RepoConf.Error"; +const char * const ERROR_REPOCONF = "org.rpm.dnf.v0.rpm.Repo.ConfError"; +const char * const ERROR_REPO_ID_UNKNOWN = "org.rpm.dnf.v0.rpm.Repo.NoMatchingIdError"; const char * const ERROR_RESOLVE = "org.rpm.dnf.v0.rpm.Rpm.ResolveError"; const char * const ERROR_TRANSACTION = "org.rpm.dnf.v0.rpm.Rpm.TransactionError"; diff --git a/dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.rpm.Repo.xml b/dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.rpm.Repo.xml index b5ffa8ea14..5d3113d841 100644 --- a/dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.rpm.Repo.xml +++ b/dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.rpm.Repo.xml @@ -60,6 +60,26 @@ along with libdnf. If not, see . + + + + + + + + + + diff --git a/dnf5daemon-server/polkit/org.rpm.dnf.v0.policy b/dnf5daemon-server/polkit/org.rpm.dnf.v0.policy index 1dc2d4c9c1..41a8070f19 100644 --- a/dnf5daemon-server/polkit/org.rpm.dnf.v0.policy +++ b/dnf5daemon-server/polkit/org.rpm.dnf.v0.policy @@ -6,7 +6,7 @@ Dnf https://github.com/rpm-software-management/libdnf/ - + Write repository configuration file Writing changes to repository configuration file requires authentication. diff --git a/dnf5daemon-server/services/repoconf/configuration.cpp b/dnf5daemon-server/services/repo/configuration.cpp similarity index 100% rename from dnf5daemon-server/services/repoconf/configuration.cpp rename to dnf5daemon-server/services/repo/configuration.cpp diff --git a/dnf5daemon-server/services/repoconf/configuration.hpp b/dnf5daemon-server/services/repo/configuration.hpp similarity index 93% rename from dnf5daemon-server/services/repoconf/configuration.hpp rename to dnf5daemon-server/services/repo/configuration.hpp index 4cd28fe3dc..f519f38738 100644 --- a/dnf5daemon-server/services/repoconf/configuration.hpp +++ b/dnf5daemon-server/services/repo/configuration.hpp @@ -18,8 +18,8 @@ along with libdnf. If not, see . */ -#ifndef DNF5DAEMON_SERVER_SERVICES_REPOCONF_CONFIGURATION_HPP -#define DNF5DAEMON_SERVER_SERVICES_REPOCONF_CONFIGURATION_HPP +#ifndef DNF5DAEMON_SERVER_SERVICES_REPO_CONFIGURATION_HPP +#define DNF5DAEMON_SERVER_SERVICES_REPO_CONFIGURATION_HPP #include "session.hpp" diff --git a/dnf5daemon-server/services/repo/repo.cpp b/dnf5daemon-server/services/repo/repo.cpp index db299133c5..c23f6dd790 100644 --- a/dnf5daemon-server/services/repo/repo.cpp +++ b/dnf5daemon-server/services/repo/repo.cpp @@ -19,8 +19,10 @@ along with libdnf. If not, see . #include "repo.hpp" +#include "configuration.hpp" #include "dbus.hpp" #include "utils.hpp" +#include "utils/string.hpp" #include #include @@ -28,8 +30,10 @@ along with libdnf. If not, see . #include #include +#include #include #include +#include #include namespace { @@ -264,6 +268,12 @@ void Repo::dbus_register() { dnfdaemon::INTERFACE_REPO, "confirm_key", "sb", "", [this](sdbus::MethodCall call) -> void { session.get_threads_manager().handle_method(*this, &Repo::confirm_key, call); }); + dbus_object->registerMethod(dnfdaemon::INTERFACE_REPO, "enable", "as", "", [this](sdbus::MethodCall call) -> void { + session.get_threads_manager().handle_method(*this, &Repo::enable, call, session.session_locale); + }); + dbus_object->registerMethod(dnfdaemon::INTERFACE_REPO, "disable", "as", "", [this](sdbus::MethodCall call) -> void { + session.get_threads_manager().handle_method(*this, &Repo::disable, call, session.session_locale); + }); } sdbus::MethodReply Repo::confirm_key(sdbus::MethodCall & call) { @@ -340,3 +350,52 @@ sdbus::MethodReply Repo::list(sdbus::MethodCall & call) { reply << out_repositories; return reply; } + +void Repo::enable_disable_repos(const std::vector & ids, const bool enable) { + Configuration cfg(session); + cfg.read_configuration(); + + auto missing_ids = ids | std::views::filter([&](auto & id) { return !cfg.find_repo(id); }); + if (!std::ranges::empty(missing_ids)) { + std::vector missing_ids_vector = {std::begin(missing_ids), std::end(missing_ids)}; + throw sdbus::Error( + dnfdaemon::ERROR_REPO_ID_UNKNOWN, + std::string("No matching repositories found for following ids: ") + + libdnf5::utils::string::join(missing_ids_vector, ",")); + } + + std::vector changed_config_files; + for (auto & repoid : ids) { + auto repoinfo = cfg.find_repo(repoid); + if (repoinfo->repoconfig->get_enabled_option().get_value() != enable) { + auto parser = cfg.find_parser(repoinfo->file_path); + if (parser) { + parser->set_value(repoid, "enabled", enable ? "1" : "0"); + changed_config_files.push_back(repoinfo->file_path); + } + } + } + for (auto & config_file : changed_config_files) { + try { + cfg.find_parser(config_file)->write(config_file, false); + } catch (std::exception & e) { + throw sdbus::Error( + dnfdaemon::ERROR_REPOCONF, std::string("Unable to write configuration file: ") + e.what()); + } + } +} + +sdbus::MethodReply Repo::enable_disable(sdbus::MethodCall && call, const bool & enable) { + auto sender = call.getSender(); + std::vector ids; + call >> ids; + auto is_authorized = session.check_authorization(dnfdaemon::POLKIT_REPOCONF_WRITE, sender); + if (!is_authorized) { + throw sdbus::Error(dnfdaemon::ERROR_REPOCONF, "Not authorized."); + } + + enable_disable_repos(ids, enable); + + auto reply = call.createReply(); + return reply; +} diff --git a/dnf5daemon-server/services/repo/repo.hpp b/dnf5daemon-server/services/repo/repo.hpp index f7c798a990..4f0d475900 100644 --- a/dnf5daemon-server/services/repo/repo.hpp +++ b/dnf5daemon-server/services/repo/repo.hpp @@ -37,6 +37,11 @@ class Repo : public IDbusSessionService { private: sdbus::MethodReply list(sdbus::MethodCall & call); sdbus::MethodReply confirm_key(sdbus::MethodCall & call); + sdbus::MethodReply enable_disable(sdbus::MethodCall && call, const bool & enable); + sdbus::MethodReply enable(sdbus::MethodCall & call) { return enable_disable(std::move(call), true); }; + sdbus::MethodReply disable(sdbus::MethodCall & call) { return enable_disable(std::move(call), false); }; + + void enable_disable_repos(const std::vector & ids, const bool enable); }; #endif diff --git a/dnf5daemon-server/services/repoconf/repo_conf.cpp b/dnf5daemon-server/services/repoconf/repo_conf.cpp deleted file mode 100644 index ad9607a21c..0000000000 --- a/dnf5daemon-server/services/repoconf/repo_conf.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -Copyright Contributors to the libdnf project. - -This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ - -Libdnf is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -Libdnf is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with libdnf. If not, see . -*/ - -#include "repo_conf.hpp" - -#include "configuration.hpp" -#include "dbus.hpp" -#include "utils.hpp" - -#include - -#include - -void RepoConf::dbus_register() { - auto dbus_object = session.get_dbus_object(); - dbus_object->registerMethod( - dnfdaemon::INTERFACE_REPOCONF, "list", "a{sv}", "aa{sv}", [this](sdbus::MethodCall call) -> void { - session.get_threads_manager().handle_method(*this, &RepoConf::list, call, session.session_locale); - }); - dbus_object->registerMethod( - dnfdaemon::INTERFACE_REPOCONF, "get", "s", "a{sv}", [this](sdbus::MethodCall call) -> void { - session.get_threads_manager().handle_method(*this, &RepoConf::get, call, session.session_locale); - }); - dbus_object->registerMethod( - dnfdaemon::INTERFACE_REPOCONF, "enable", "as", "as", [this](sdbus::MethodCall call) -> void { - session.get_threads_manager().handle_method(*this, &RepoConf::enable, call, session.session_locale); - }); - dbus_object->registerMethod( - dnfdaemon::INTERFACE_REPOCONF, "disable", "as", "as", [this](sdbus::MethodCall call) -> void { - session.get_threads_manager().handle_method(*this, &RepoConf::disable, call, session.session_locale); - }); -} - -dnfdaemon::KeyValueMapList RepoConf::repo_list(const std::vector & ids) { - Configuration cfg(session); - cfg.read_configuration(); - - bool empty_ids = ids.empty(); - dnfdaemon::KeyValueMapList out; - for (auto & repo : cfg.get_repos()) { - if (empty_ids || std::find(ids.begin(), ids.end(), repo.first) != ids.end()) { - auto parser = cfg.find_parser(repo.second->file_path); - if (parser) { - dnfdaemon::KeyValueMap dbus_repo; - dbus_repo.emplace(std::make_pair("repoid", repo.first)); - for (const auto & section : parser->get_data()) { - if (section.first == repo.first) { - for (const auto & line : section.second) { - if (line.first[0] != '#') { - dbus_repo.emplace(std::make_pair(line.first, line.second)); - } - } - } - } - out.push_back(dbus_repo); - } - } - } - return out; -} - -sdbus::MethodReply RepoConf::list(sdbus::MethodCall & call) { - dnfdaemon::KeyValueMap options; - std::vector default_ids{}; - call >> options; - std::vector ids = key_value_map_get>(options, "ids", default_ids); - auto out = repo_list(std::move(ids)); - auto reply = call.createReply(); - reply << out; - - return reply; -} - -sdbus::MethodReply RepoConf::get(sdbus::MethodCall & call) { - std::string id; - call >> id; - auto ids = std::vector{std::move(id)}; - auto lst = repo_list(ids); - if (lst.empty()) { - throw sdbus::Error(dnfdaemon::ERROR_REPOCONF, "Repository not found"); - } else if (lst.size() > 1) { - throw sdbus::Error(dnfdaemon::ERROR_REPOCONF, "Multiple repositories found"); - } else { - auto reply = call.createReply(); - reply << lst[0]; - return reply; - } -} - -std::vector RepoConf::enable_disable_repos(const std::vector & ids, const bool enable) { - Configuration cfg(session); - cfg.read_configuration(); - - std::vector out; - std::vector changed_config_files; - for (auto & repoid : ids) { - auto repoinfo = cfg.find_repo(repoid); - if (repoinfo && repoinfo->repoconfig->get_enabled_option().get_value() != enable) { - auto parser = cfg.find_parser(repoinfo->file_path); - if (parser) { - parser->set_value(repoid, "enabled", enable ? "1" : "0"); - changed_config_files.push_back(repoinfo->file_path); - out.push_back(repoid); - } - } - } - for (auto & config_file : changed_config_files) { - try { - cfg.find_parser(config_file)->write(config_file, false); - } catch (std::exception & e) { - throw sdbus::Error( - dnfdaemon::ERROR_REPOCONF, std::string("Unable to write configuration file: ") + e.what()); - } - } - - return out; -} - -sdbus::MethodReply RepoConf::enable_disable(sdbus::MethodCall && call, const bool & enable) { - auto sender = call.getSender(); - std::vector ids; - call >> ids; - auto is_authorized = session.check_authorization(dnfdaemon::POLKIT_REPOCONF_WRITE, sender); - if (!is_authorized) { - throw sdbus::Error(dnfdaemon::ERROR_REPOCONF, "Not authorized."); - } - auto reply = call.createReply(); - reply << enable_disable_repos(ids, enable); - return reply; -} diff --git a/dnf5daemon-server/services/repoconf/repo_conf.hpp b/dnf5daemon-server/services/repoconf/repo_conf.hpp deleted file mode 100644 index c677e6470c..0000000000 --- a/dnf5daemon-server/services/repoconf/repo_conf.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright Contributors to the libdnf project. - -This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ - -Libdnf is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -Libdnf is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with libdnf. If not, see . -*/ - -#ifndef DNF5DAEMON_SERVER_SERVICES_REPOCONF_HPP -#define DNF5DAEMON_SERVER_SERVICES_REPOCONF_HPP - -#include "dbus.hpp" -#include "session.hpp" - -#include - -#include -#include - -class RepoConf : public IDbusSessionService { -public: - using IDbusSessionService::IDbusSessionService; - ~RepoConf() = default; - void dbus_register(); - void dbus_deregister(); - -private: - sdbus::MethodReply list(sdbus::MethodCall & call); - sdbus::MethodReply get(sdbus::MethodCall & call); - sdbus::MethodReply enable_disable(sdbus::MethodCall && call, const bool & enable); - sdbus::MethodReply enable(sdbus::MethodCall & call) { return enable_disable(std::move(call), true); }; - sdbus::MethodReply disable(sdbus::MethodCall & call) { return enable_disable(std::move(call), false); }; - - dnfdaemon::KeyValueMapList repo_list(const std::vector & ids); - std::vector enable_disable_repos(const std::vector & ids, const bool enable); -}; - -#endif diff --git a/dnf5daemon-server/session.cpp b/dnf5daemon-server/session.cpp index 5322ddc08b..41375d1983 100644 --- a/dnf5daemon-server/session.cpp +++ b/dnf5daemon-server/session.cpp @@ -26,7 +26,6 @@ along with libdnf. If not, see . #include "services/comps/group.hpp" #include "services/goal/goal.hpp" #include "services/repo/repo.hpp" -#include "services/repoconf/repo_conf.hpp" #include "services/rpm/rpm.hpp" #include "utils.hpp" @@ -119,7 +118,6 @@ Session::Session( // instantiate all services provided by the daemon services.emplace_back(std::make_unique(*this)); - services.emplace_back(std::make_unique(*this)); services.emplace_back(std::make_unique(*this)); services.emplace_back(std::make_unique(*this)); services.emplace_back(std::make_unique(*this));