dnfdaemon: Make it possible to set 'interactive' option for Base::clean()

The operation can require root privileges, for which it can ask the user
through polkit. It's okay when the operation is interactive, aka issued
by a user, but when the operation is ran by a background service, then
the password prompt coming out of blue is wrong. This change allows to
tell the daemon server whether it can ask for the root password or not.
This commit is contained in:
Milan Crha 2025-07-02 18:09:50 +02:00
parent f30888b5b8
commit 25b181098e
3 changed files with 69 additions and 6 deletions

View File

@ -35,14 +35,37 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
<arg name="success" type="b" direction="out"/>
</method>
<!--
clean_with_options:
@cache_type: cache type to clean up. Supported types are "all", "packages", "metadata", "dbcache", and "expire-cache".
@options: an array of key/value pairs to modify the call behavior
@success: `true` if the cache was successfully cleaned, `false` otherwise.
@error_msg: string, contains errors encountered while cleaning the cache.
Remove or expire cached data.
Following @options are supported:
- interactive: boolean, default true
Set to "true", when the operation is done by a user, thus user interaction like password prompts can be done.
Unknown options are ignored.
-->
<method name="clean_with_options">
<arg name="cache_type" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in" />
<arg name="success" type="b" direction="out"/>
<arg name="error_msg" type="s" direction="out"/>
</method>
<!--
clean:
@cache_type: cache type to clean up. Supported types are "all", "packages", "metadata", "dbcache", and "expire-cache".
@success: `true` if the cache was successfully cleaned, `false` otherwise.
@error_msg: string, contains errors encountered while cleaning the cache.
Remove or expire cached data.
This is equivalent to call "clean_with_options()" with empty options.
-->
<method name="clean">
<arg name="cache_type" type="s" direction="in"/>

View File

@ -59,6 +59,16 @@ void Base::dbus_register() {
*this, &Base::read_all_repos, call, session.session_locale);
},
{}},
sdbus::MethodVTableItem{
sdbus::MethodName{"clean_with_options"},
sdbus::Signature{"sa{sv}"},
{"cache_type", "options"},
sdbus::Signature{"bs"},
{"success", "error_msg"},
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Base::clean_with_options, call, session.session_locale);
},
{}},
sdbus::MethodVTableItem{
sdbus::MethodName{"clean"},
sdbus::Signature{"s"},
@ -110,6 +120,16 @@ void Base::dbus_register() {
dnfdaemon::INTERFACE_BASE, "read_all_repos", "", {}, "b", {"success"}, [this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Base::read_all_repos, call, session.session_locale);
});
dbus_object->registerMethod(
dnfdaemon::INTERFACE_BASE,
"clean_with_options",
"sa{sv}",
{"cache_type", "options"},
"bs",
{"success", "error_msg"},
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Base::clean_with_options, call, session.session_locale);
});
dbus_object->registerMethod(
dnfdaemon::INTERFACE_BASE,
"clean",
@ -166,13 +186,14 @@ sdbus::MethodReply Base::read_all_repos(sdbus::MethodCall & call) {
return reply;
}
sdbus::MethodReply Base::clean(sdbus::MethodCall & call) {
// let the "expire-cache" do anyone, just as read_all_repos()
std::string cache_type{};
call >> cache_type;
sdbus::MethodReply Base::impl_clean(sdbus::MethodCall & call,
const std::string & cache_type,
const dnfdaemon::KeyValueMap & options) {
bool interactive = dnfdaemon::key_value_map_get<bool>(options, "interactive", true);
// let the "expire-cache" do anyone, just as read_all_repos()
if (cache_type != "expire-cache" &&
!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender())) {
!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender(), interactive)) {
throw std::runtime_error("Not authorized");
}
@ -223,6 +244,22 @@ sdbus::MethodReply Base::clean(sdbus::MethodCall & call) {
return reply;
}
sdbus::MethodReply Base::clean_with_options(sdbus::MethodCall & call) {
std::string cache_type{};
dnfdaemon::KeyValueMap options;
call >> cache_type >> options;
return impl_clean(call, cache_type, options);
}
sdbus::MethodReply Base::clean(sdbus::MethodCall & call) {
std::string cache_type{};
dnfdaemon::KeyValueMap options{};
call >> cache_type;
return impl_clean(call, cache_type, options);
}
sdbus::MethodReply Base::reset(sdbus::MethodCall & call) {
bool success{true};
std::string error_msg{};

View File

@ -35,6 +35,9 @@ public:
void dbus_deregister();
private:
sdbus::MethodReply impl_clean(sdbus::MethodCall & call, const std::string & cache_type,
const dnfdaemon::KeyValueMap & options);
sdbus::MethodReply clean_with_options(sdbus::MethodCall & call);
sdbus::MethodReply clean(sdbus::MethodCall & call);
sdbus::MethodReply reset(sdbus::MethodCall & call);
sdbus::MethodReply read_all_repos(sdbus::MethodCall & call);