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));