dnfdaemon: Make it possible to set 'interactive' option for Offline::cancel(), Offline::clean(), Offline::set_finish_action()
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:
parent
0f1b5f2dc8
commit
2ae58eed2e
|
@ -37,6 +37,25 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
|
|||
<arg name="transaction_status" type="a{sv}" direction="out" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
cancel_with_options:
|
||||
@options: an array of key/value pairs to modify the call behavior
|
||||
@success: boolean, returns `false` if there was an error during the transaction cancellation, or if the offline transaction was initiated by another tool than dnf5. Returns `true` if the offline transaction was successfully cancelled or if no offline transaction was configured.
|
||||
@error_msg: string, contains error encountered while cancelling the transaction
|
||||
|
||||
Cancel the dnf5 offline transaction configured for the next reboot. Offline updates scheduled by another tool are not cancelled.
|
||||
|
||||
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="cancel_with_options">
|
||||
<arg name="options" type="a{sv}" direction="in" />
|
||||
<arg name="success" type="b" direction="out" />
|
||||
<arg name="error_msg" type="s" direction="out" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
cancel:
|
||||
|
@ -44,20 +63,67 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
|
|||
@error_msg: string, contains error encountered while cancelling the transaction
|
||||
|
||||
Cancel the dnf5 offline transaction configured for the next reboot. Offline updates scheduled by another tool are not cancelled.
|
||||
|
||||
This is equivalent to call "cancel_with_options()" with empty options.
|
||||
-->
|
||||
<method name="cancel">
|
||||
<arg name="success" type="b" direction="out" />
|
||||
<arg name="error_msg" type="s" direction="out" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
clean_with_options:
|
||||
@options: an array of key/value pairs to modify the call behavior
|
||||
@success: boolean, returns `false` if there was an error during the transaction cleanup. Returns `true` if the offline transaction was successfully cleaned or if no offline transaction was configured.
|
||||
@error_msg: string, contains error encountered while cleaning the transaction
|
||||
|
||||
Cancel the dnf5 offline transaction configured for the next reboot and remove all stored offline transaction data, including downloaded packages. Offline updates scheduled by another tool are not affected.
|
||||
|
||||
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="success" type="b" direction="out" />
|
||||
<arg name="error_msg" type="s" direction="out" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
clean:
|
||||
@success: boolean, returns `false` if there was an error during the transaction cleanup. Returns `true` if the offline transaction was successfully cleaned or if no offline transaction was configured.
|
||||
@error_msg: string, contains error encountered while cleaning the transaction
|
||||
|
||||
Cancel the dnf5 offline transaction configured for the next reboot and remove all stored offline transaction data, including downloaded packages. Offline updates scheduled by another tool are not affected.
|
||||
|
||||
This is equivalent to call "clean_with_options()" with empty options.
|
||||
-->
|
||||
<method name="clean">
|
||||
<arg name="options" type="a{sv}" direction="in" />
|
||||
<arg name="success" type="b" direction="out" />
|
||||
<arg name="error_msg" type="s" direction="out" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
set_finish_action_with_options:
|
||||
@action: string, one of "poweroff", or "reboot". If set to "poweroff", the system will be powered off after applying the offline transaction. Otherwise the system will reboot.
|
||||
@options: an array of key/value pairs to modify the call behavior
|
||||
@success: boolean, true if the action was successfully set
|
||||
@error_msg: string, contains error encountered while setting the action
|
||||
|
||||
Set the action that should be performed after the offline transaction is applied. If the `action` is "poweroff", the system will be powered off, otherwise it will be rebooted (which is default).
|
||||
The call might fail in case there is no scheduled offline transaction, or the transaction was not scheduled using libdnf5.
|
||||
|
||||
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="set_finish_action_with_options">
|
||||
<arg name="action" 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>
|
||||
|
@ -70,6 +136,9 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
Set the action that should be performed after the offline transaction is applied. If the `action` is "poweroff", the system will be powered off, otherwise it will be rebooted (which is default).
|
||||
The call might fail in case there is no scheduled offline transaction, or the transaction was not scheduled using libdnf5.
|
||||
|
||||
|
||||
This is equivalent to call "set_finish_action_with_options()" with empty options.
|
||||
-->
|
||||
<method name="set_finish_action">
|
||||
<arg name="action" type="s" direction="in" />
|
||||
|
|
|
@ -55,6 +55,16 @@ void Offline::dbus_register() {
|
|||
#ifdef SDBUS_CPP_VERSION_2
|
||||
dbus_object
|
||||
->addVTable(
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"cancel_with_options"},
|
||||
sdbus::Signature{"a{sv}"},
|
||||
{"options"},
|
||||
sdbus::Signature{"bs"},
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::cancel_with_options, call, session.session_locale);
|
||||
},
|
||||
{}},
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"cancel"},
|
||||
{},
|
||||
|
@ -76,6 +86,16 @@ void Offline::dbus_register() {
|
|||
*this, &Offline::get_status, call, session.session_locale);
|
||||
},
|
||||
{}},
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"clean_with_options"},
|
||||
sdbus::Signature{"a{sv}"},
|
||||
{"options"},
|
||||
sdbus::Signature{"bs"},
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::clean_with_options, call, session.session_locale);
|
||||
},
|
||||
{}},
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"clean"},
|
||||
{},
|
||||
|
@ -86,6 +106,17 @@ void Offline::dbus_register() {
|
|||
session.get_threads_manager().handle_method(*this, &Offline::clean, call, session.session_locale);
|
||||
},
|
||||
{}},
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"set_finish_action_with_options"},
|
||||
sdbus::Signature{"sa{sv}"},
|
||||
{"action", "options"},
|
||||
sdbus::Signature{"bs"},
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(
|
||||
*this, &Offline::set_finish_action_with_options, call, session.session_locale);
|
||||
},
|
||||
{}},
|
||||
sdbus::MethodVTableItem{
|
||||
sdbus::MethodName{"set_finish_action"},
|
||||
sdbus::Signature{"s"},
|
||||
|
@ -99,6 +130,16 @@ void Offline::dbus_register() {
|
|||
{}})
|
||||
.forInterface(dnfdaemon::INTERFACE_OFFLINE);
|
||||
#else
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"cancel_with_options",
|
||||
{"a{sv}"},
|
||||
{"options"},
|
||||
"bs",
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::cancel_with_options, call, session.session_locale);
|
||||
});
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"cancel",
|
||||
|
@ -119,6 +160,16 @@ void Offline::dbus_register() {
|
|||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::get_status, call, session.session_locale);
|
||||
});
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"clean_with_options",
|
||||
{"a{sv}"},
|
||||
{"options"},
|
||||
"bs",
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::clean_with_options, call, session.session_locale);
|
||||
});
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"clean",
|
||||
|
@ -129,6 +180,17 @@ void Offline::dbus_register() {
|
|||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(*this, &Offline::clean, call, session.session_locale);
|
||||
});
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"set_finish_action_with_options",
|
||||
"sa{sv}",
|
||||
{"action", "options"},
|
||||
"bs",
|
||||
{"success", "error_msg"},
|
||||
[this](sdbus::MethodCall call) -> void {
|
||||
session.get_threads_manager().handle_method(
|
||||
*this, &Offline::set_finish_action_with_options, call, session.session_locale);
|
||||
});
|
||||
dbus_object->registerMethod(
|
||||
dnfdaemon::INTERFACE_OFFLINE,
|
||||
"set_finish_action",
|
||||
|
@ -167,8 +229,9 @@ sdbus::MethodReply Offline::get_status(sdbus::MethodCall & call) {
|
|||
return reply;
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::cancel(sdbus::MethodCall & call) {
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender())) {
|
||||
sdbus::MethodReply Offline::impl_cancel(sdbus::MethodCall & call, const dnfdaemon::KeyValueMap & options) {
|
||||
bool interactive = dnfdaemon::key_value_map_get<bool>(options, "interactive", true);
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender(), interactive)) {
|
||||
throw std::runtime_error("Not authorized");
|
||||
}
|
||||
bool success = true;
|
||||
|
@ -194,8 +257,20 @@ sdbus::MethodReply Offline::cancel(sdbus::MethodCall & call) {
|
|||
return reply;
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::clean(sdbus::MethodCall & call) {
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender())) {
|
||||
sdbus::MethodReply Offline::cancel_with_options(sdbus::MethodCall & call) {
|
||||
dnfdaemon::KeyValueMap options;
|
||||
call >> options;
|
||||
return impl_cancel(call, options);
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::cancel(sdbus::MethodCall & call) {
|
||||
dnfdaemon::KeyValueMap options{};
|
||||
return impl_cancel(call, options);
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::impl_clean(sdbus::MethodCall & call, const dnfdaemon::KeyValueMap & options) {
|
||||
bool interactive = dnfdaemon::key_value_map_get<bool>(options, "interactive", true);
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender(), interactive)) {
|
||||
throw std::runtime_error("Not authorized");
|
||||
}
|
||||
std::vector<std::string> error_msgs;
|
||||
|
@ -223,19 +298,30 @@ sdbus::MethodReply Offline::clean(sdbus::MethodCall & call) {
|
|||
return reply;
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::set_finish_action(sdbus::MethodCall & call) {
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender())) {
|
||||
sdbus::MethodReply Offline::clean_with_options(sdbus::MethodCall & call) {
|
||||
dnfdaemon::KeyValueMap options;
|
||||
call >> options;
|
||||
return impl_clean(call, options);
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::clean(sdbus::MethodCall & call) {
|
||||
dnfdaemon::KeyValueMap options{};
|
||||
return impl_clean(call, options);
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::impl_set_finish_action(sdbus::MethodCall & call, const std::string & action,
|
||||
const dnfdaemon::KeyValueMap & options) {
|
||||
bool interactive = dnfdaemon::key_value_map_get<bool>(options, "interactive", true);
|
||||
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRUSTED_TRANSACTION, call.getSender(), interactive)) {
|
||||
throw std::runtime_error("Not authorized");
|
||||
}
|
||||
bool success{false};
|
||||
std::string error_msg{};
|
||||
|
||||
std::string finish_action;
|
||||
call >> finish_action;
|
||||
// check finish_action validity
|
||||
if (finish_action != "poweroff" && finish_action != "reboot") {
|
||||
if (action != "poweroff" && action != "reboot") {
|
||||
error_msg = fmt::format(
|
||||
"Unsupported finish action \"{}\". Valid options are \"reboot\", or \"poweroff\".", finish_action);
|
||||
"Unsupported finish action \"{}\". Valid options are \"reboot\", or \"poweroff\".", action);
|
||||
} else {
|
||||
const std::filesystem::path state_path{get_datadir() / libdnf5::offline::TRANSACTION_STATE_FILENAME};
|
||||
std::error_code ec;
|
||||
|
@ -248,7 +334,7 @@ sdbus::MethodReply Offline::set_finish_action(sdbus::MethodCall & call) {
|
|||
const auto & read_exception = state.get_read_exception();
|
||||
if (read_exception == nullptr) {
|
||||
// set the poweroff_after item accordingly
|
||||
state.get_data().set_poweroff_after(finish_action == "poweroff");
|
||||
state.get_data().set_poweroff_after(action == "poweroff");
|
||||
// write the new state
|
||||
state.write();
|
||||
success = true;
|
||||
|
@ -266,3 +352,17 @@ sdbus::MethodReply Offline::set_finish_action(sdbus::MethodCall & call) {
|
|||
reply << error_msg;
|
||||
return reply;
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::set_finish_action_with_options(sdbus::MethodCall & call) {
|
||||
std::string action;
|
||||
dnfdaemon::KeyValueMap options;
|
||||
call >> action >> options;
|
||||
return impl_set_finish_action(call, action, options);
|
||||
}
|
||||
|
||||
sdbus::MethodReply Offline::set_finish_action(sdbus::MethodCall & call) {
|
||||
std::string action;
|
||||
dnfdaemon::KeyValueMap options{};
|
||||
call >> action;
|
||||
return impl_set_finish_action(call, action, options);
|
||||
}
|
||||
|
|
|
@ -34,9 +34,15 @@ public:
|
|||
void dbus_deregister();
|
||||
|
||||
private:
|
||||
sdbus::MethodReply impl_cancel(sdbus::MethodCall & call, const dnfdaemon::KeyValueMap & options);
|
||||
sdbus::MethodReply cancel_with_options(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply cancel(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply impl_clean(sdbus::MethodCall & call, const dnfdaemon::KeyValueMap & options);
|
||||
sdbus::MethodReply clean_with_options(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply clean(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply get_status(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply impl_set_finish_action(sdbus::MethodCall & call, const std::string & action, const dnfdaemon::KeyValueMap & options);
|
||||
sdbus::MethodReply set_finish_action_with_options(sdbus::MethodCall & call);
|
||||
sdbus::MethodReply set_finish_action(sdbus::MethodCall & call);
|
||||
|
||||
enum class Scheduled { NOT_SCHEDULED, ANOTHER_TOOL, SCHEDULED };
|
||||
|
|
Loading…
Reference in New Issue