You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3575 lines
124 KiB
3575 lines
124 KiB
From d85d6eb0ceeaabc65f71ec9b163d00a1e0840b81 Mon Sep 17 00:00:00 2001 |
|
From: Richard Hughes <rhughes@redhat.com> |
|
Date: Thu, 20 Aug 2020 11:16:09 -0400 |
|
Subject: [PATCH 01/19] subman: Add a new plugin to provide system subscription |
|
registration |
|
|
|
--- |
|
meson.build | 1 + |
|
plugins/meson.build | 1 + |
|
plugins/subman/README.md | 56 + |
|
plugins/subman/gsd-subman-common.c | 36 + |
|
plugins/subman/gsd-subman-common.h | 40 + |
|
plugins/subman/gsd-subman-helper.c | 378 +++++++ |
|
plugins/subman/gsd-subscription-manager.c | 982 ++++++++++++++++++ |
|
plugins/subman/gsd-subscription-manager.h | 63 ++ |
|
plugins/subman/main.c | 8 + |
|
plugins/subman/meson.build | 56 + |
|
...ome.SettingsDaemon.Subscription.desktop.in | 9 + |
|
...ettings-daemon.plugins.subman.policy.in.in | 27 + |
|
...gnome.settings-daemon.plugins.subman.rules | 7 + |
|
13 files changed, 1664 insertions(+) |
|
create mode 100644 plugins/subman/README.md |
|
create mode 100644 plugins/subman/gsd-subman-common.c |
|
create mode 100644 plugins/subman/gsd-subman-common.h |
|
create mode 100644 plugins/subman/gsd-subman-helper.c |
|
create mode 100644 plugins/subman/gsd-subscription-manager.c |
|
create mode 100644 plugins/subman/gsd-subscription-manager.h |
|
create mode 100644 plugins/subman/main.c |
|
create mode 100644 plugins/subman/meson.build |
|
create mode 100644 plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in |
|
create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in |
|
create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.rules |
|
|
|
diff --git a/meson.build b/meson.build |
|
index ba2a90ca..3cef1ae1 100644 |
|
--- a/meson.build |
|
+++ b/meson.build |
|
@@ -102,6 +102,7 @@ libcanberra_gtk_dep = dependency('libcanberra-gtk3') |
|
libgeoclue_dep = dependency('libgeoclue-2.0', version: '>= 2.3.1') |
|
libnotify_dep = dependency('libnotify', version: '>= 0.7.3') |
|
libpulse_mainloop_glib_dep = dependency('libpulse-mainloop-glib', version: '>= 2.0') |
|
+jsonglib_dep = dependency('json-glib-1.0', version: '>= 1.1.1') |
|
pango_dep = dependency('pango', version: '>= 1.20.0') |
|
polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114') |
|
upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8') |
|
diff --git a/plugins/meson.build b/plugins/meson.build |
|
index 16397dc6..920b5cc9 100644 |
|
--- a/plugins/meson.build |
|
+++ b/plugins/meson.build |
|
@@ -1,6 +1,7 @@ |
|
all_plugins = [ |
|
['a11y-settings', 'A11ySettings', 'GNOME accessibility'], |
|
['color', 'Color', 'GNOME color management'], |
|
+ ['subman', 'Subscription', 'GNOME subscription management'], |
|
['datetime', 'Datetime', 'GNOME date & time'], |
|
['power', 'Power', 'GNOME power management'], |
|
['housekeeping', 'Housekeeping', 'GNOME maintenance of expirable data'], |
|
diff --git a/plugins/subman/README.md b/plugins/subman/README.md |
|
new file mode 100644 |
|
index 00000000..3e1cc3cd |
|
--- /dev/null |
|
+++ b/plugins/subman/README.md |
|
@@ -0,0 +1,56 @@ |
|
+GNOME Settings Daemon: Subscription Manager Plugin |
|
+================================================== |
|
+ |
|
+Testing: |
|
+ |
|
+To add a test acccount on subscription.rhsm.stage.redhat.com, use Ethel: |
|
+http://account-manager-stage.app.eng.rdu2.redhat.com/#view |
|
+ |
|
+Register with a username and password |
|
+------------------------------------- |
|
+ |
|
+ gdbus call \ |
|
+ --session \ |
|
+ --dest org.gnome.SettingsDaemon.Subscription \ |
|
+ --object-path /org/gnome/SettingsDaemon/Subscription \ |
|
+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'username'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'username':<'rhughes_test'>,'password':<'barbaz'>}" |
|
+ |
|
+To register with a certificate |
|
+------------------------------ |
|
+ |
|
+ gdbus call \ |
|
+ --session \ |
|
+ --dest org.gnome.SettingsDaemon.Subscription \ |
|
+ --object-path /org/gnome/SettingsDaemon/Subscription \ |
|
+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'key'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'organisation':<'foo'>,'activation-key':<'barbaz'>}" |
|
+ |
|
+To unregister |
|
+------------- |
|
+ |
|
+ gdbus call \ |
|
+ --session \ |
|
+ --dest org.gnome.SettingsDaemon.Subscription \ |
|
+ --object-path /org/gnome/SettingsDaemon/Subscription \ |
|
+ --method org.gnome.SettingsDaemon.Subscription.Unregister |
|
+ |
|
+Debugging |
|
+--------- |
|
+ |
|
+Get the UNIX socket using `Subscription.Register` then call something like: |
|
+ |
|
+ sudo G_MESSAGES_DEBUG=all ./plugins/subman/gsd-subman-helper \ |
|
+ --address="unix:abstract=/var/run/dbus-ulGB1wfnbn,guid=71e6bf329d861ce366df7a1d5d036a5b" \ |
|
+ --kind="register-with-username" \ |
|
+ --username="rhughes_test" \ |
|
+ --password="barbaz" \ |
|
+ --hostname="subscription.rhsm.stage.redhat.com" \ |
|
+ --organisation="" |
|
+ |
|
+You can all see some basic debugging running `rhsmd` in the foreground: |
|
+ |
|
+ sudo /usr/libexec/rhsmd -d -k |
|
+ |
|
+Known Limitations |
|
+================= |
|
+ |
|
+Proxy servers are not supported, nor are custom host ports or prefixes. |
|
diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c |
|
new file mode 100644 |
|
index 00000000..e515131e |
|
--- /dev/null |
|
+++ b/plugins/subman/gsd-subman-common.c |
|
@@ -0,0 +1,36 @@ |
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
|
+ * |
|
+ * Copyright (C) 2019 Richard Hughes <rhughes@redhat.com> |
|
+ * |
|
+ * This program 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. |
|
+ * |
|
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>. |
|
+ * |
|
+ */ |
|
+ |
|
+#include "config.h" |
|
+ |
|
+#include "gsd-subman-common.h" |
|
+ |
|
+const gchar * |
|
+gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) |
|
+{ |
|
+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID) |
|
+ return "valid"; |
|
+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) |
|
+ return "invalid"; |
|
+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) |
|
+ return "disabled"; |
|
+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) |
|
+ return "partially-valid"; |
|
+ return "unknown"; |
|
+} |
|
diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h |
|
new file mode 100644 |
|
index 00000000..fccf9f6a |
|
--- /dev/null |
|
+++ b/plugins/subman/gsd-subman-common.h |
|
@@ -0,0 +1,40 @@ |
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
|
+ * |
|
+ * Copyright (C) 2019 Richard Hughes <rhughes@redhat.com> |
|
+ * |
|
+ * This program 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. |
|
+ * |
|
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>. |
|
+ * |
|
+ */ |
|
+ |
|
+#ifndef __GSD_SUBMAN_COMMON_H |
|
+#define __GSD_SUBMAN_COMMON_H |
|
+ |
|
+#include <glib-object.h> |
|
+ |
|
+G_BEGIN_DECLS |
|
+ |
|
+typedef enum { |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST |
|
+} GsdSubmanSubscriptionStatus; |
|
+ |
|
+const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); |
|
+ |
|
+G_END_DECLS |
|
+ |
|
+#endif /* __GSD_SUBMAN_COMMON_H */ |
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
new file mode 100644 |
|
index 00000000..182f7190 |
|
--- /dev/null |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -0,0 +1,372 @@ |
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- |
|
+ * |
|
+ * Copyright (C) 2019 Richard Hughes <rhughes@redhat.com> |
|
+ * |
|
+ * Licensed under the GNU General Public License Version 2 |
|
+ * |
|
+ * This program 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. |
|
+ * |
|
+ * This program 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 this program; if not, write to the Free Software |
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
+ */ |
|
+ |
|
+#include "config.h" |
|
+ |
|
+#include <sys/types.h> |
|
+#include <unistd.h> |
|
+#include <stdlib.h> |
|
+ |
|
+#include <gio/gio.h> |
|
+#include <json-glib/json-glib.h> |
|
+ |
|
+static void |
|
+_helper_convert_error (const gchar *json_txt, GError **error) |
|
+{ |
|
+ JsonNode *json_root; |
|
+ JsonObject *json_obj; |
|
+ const gchar *message; |
|
+ g_autoptr(JsonParser) json_parser = json_parser_new (); |
|
+ |
|
+ /* this may be plain text or JSON :| */ |
|
+ if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { |
|
+ g_set_error_literal (error, |
|
+ G_IO_ERROR, |
|
+ G_IO_ERROR_NOT_SUPPORTED, |
|
+ json_txt); |
|
+ return; |
|
+ } |
|
+ json_root = json_parser_get_root (json_parser); |
|
+ json_obj = json_node_get_object (json_root); |
|
+ if (!json_object_has_member (json_obj, "message")) { |
|
+ g_set_error (error, |
|
+ G_IO_ERROR, |
|
+ G_IO_ERROR_INVALID_DATA, |
|
+ "no message' in %s", json_txt); |
|
+ return; |
|
+ } |
|
+ message = json_object_get_string_member (json_obj, "message"); |
|
+ if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { |
|
+ g_set_error_literal (error, |
|
+ G_IO_ERROR, |
|
+ G_IO_ERROR_PERMISSION_DENIED, |
|
+ message); |
|
+ return; |
|
+ } |
|
+ g_set_error_literal (error, |
|
+ G_IO_ERROR, |
|
+ G_IO_ERROR_NOT_SUPPORTED, |
|
+ message); |
|
+} |
|
+ |
|
+static gboolean |
|
+_helper_unregister (GError **error) |
|
+{ |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
+ g_autoptr(GVariant) res = NULL; |
|
+ |
|
+ g_debug ("unregistering"); |
|
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ "/com/redhat/RHSM1/Unregister", |
|
+ "com.redhat.RHSM1.Unregister", |
|
+ NULL, error); |
|
+ if (proxy == NULL) { |
|
+ g_prefix_error (error, "Failed to get proxy: "); |
|
+ return FALSE; |
|
+ } |
|
+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); |
|
+ res = g_dbus_proxy_call_sync (proxy, |
|
+ "Unregister", |
|
+ g_variant_new ("(a{sv}s)", |
|
+ proxy_options, |
|
+ ""), /* lang */ |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ return res != NULL; |
|
+} |
|
+ |
|
+static gboolean |
|
+_helper_auto_attach (GError **error) |
|
+{ |
|
+ const gchar *str = NULL; |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
+ g_autoptr(GVariant) res = NULL; |
|
+ |
|
+ g_debug ("auto-attaching subscriptions"); |
|
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ "/com/redhat/RHSM1/Attach", |
|
+ "com.redhat.RHSM1.Attach", |
|
+ NULL, error); |
|
+ if (proxy == NULL) { |
|
+ g_prefix_error (error, "Failed to get proxy: "); |
|
+ return FALSE; |
|
+ } |
|
+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); |
|
+ res = g_dbus_proxy_call_sync (proxy, |
|
+ "AutoAttach", |
|
+ g_variant_new ("(sa{sv}s)", |
|
+ "", /* now? */ |
|
+ proxy_options, |
|
+ ""), /* lang */ |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (res == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (res, "(&s)", &str); |
|
+ g_debug ("Attach.AutoAttach: %s", str); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_helper_save_config (const gchar *key, const gchar *value, GError **error) |
|
+{ |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GVariant) res = NULL; |
|
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ "/com/redhat/RHSM1/Config", |
|
+ "com.redhat.RHSM1.Config", |
|
+ NULL, error); |
|
+ if (proxy == NULL) { |
|
+ g_prefix_error (error, "Failed to get proxy: "); |
|
+ return FALSE; |
|
+ } |
|
+ res = g_dbus_proxy_call_sync (proxy, "Set", |
|
+ g_variant_new ("(svs)", |
|
+ key, |
|
+ g_variant_new_string (value), |
|
+ ""), /* lang */ |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ return res != NULL; |
|
+} |
|
+ |
|
+int |
|
+main (int argc, char *argv[]) |
|
+{ |
|
+ const gchar *userlang = ""; /* as root, so no translations */ |
|
+ g_autofree gchar *activation_key = NULL; |
|
+ g_autofree gchar *address = NULL; |
|
+ g_autofree gchar *hostname = NULL; |
|
+ g_autofree gchar *kind = NULL; |
|
+ g_autofree gchar *organisation = NULL; |
|
+ g_autofree gchar *password = NULL; |
|
+ g_autofree gchar *port = NULL; |
|
+ g_autofree gchar *prefix = NULL; |
|
+ g_autofree gchar *proxy_server = NULL; |
|
+ g_autofree gchar *username = NULL; |
|
+ g_autoptr(GDBusConnection) conn_private = NULL; |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GError) error = NULL; |
|
+ g_autoptr(GOptionContext) context = g_option_context_new (NULL); |
|
+ g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
+ g_autoptr(GVariantBuilder) subman_conopts = NULL; |
|
+ g_autoptr(GVariantBuilder) subman_options = NULL; |
|
+ |
|
+ const GOptionEntry options[] = { |
|
+ { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &kind, "Kind, e.g. 'username' or 'key'", NULL }, |
|
+ { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &address, "UNIX address", NULL }, |
|
+ { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &username, "Username", NULL }, |
|
+ { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &password, "Password", NULL }, |
|
+ { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &organisation, "Organisation", NULL }, |
|
+ { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
+ &activation_key, "Activation keys", NULL }, |
|
+ { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
+ &hostname, "Registration server hostname", NULL }, |
|
+ { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
+ &prefix, "Registration server prefix", NULL }, |
|
+ { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
+ &port, "Registration server port", NULL }, |
|
+ { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
+ &proxy_server, "Proxy settings", NULL }, |
|
+ { NULL} |
|
+ }; |
|
+ |
|
+ /* check calling UID */ |
|
+ if (getuid () != 0 || geteuid () != 0) { |
|
+ g_printerr ("This program can only be used by the root user\n"); |
|
+ return G_IO_ERROR_NOT_SUPPORTED; |
|
+ } |
|
+ g_option_context_add_main_entries (context, options, NULL); |
|
+ if (!g_option_context_parse (context, &argc, &argv, &error)) { |
|
+ g_printerr ("Failed to parse arguments: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_SUPPORTED; |
|
+ } |
|
+ |
|
+ /* uncommon actions */ |
|
+ if (kind == NULL) { |
|
+ g_printerr ("No --kind specified\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ if (g_strcmp0 (kind, "unregister") == 0) { |
|
+ if (!_helper_unregister (&error)) { |
|
+ g_printerr ("Failed to Unregister: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_INITIALIZED; |
|
+ } |
|
+ return EXIT_SUCCESS; |
|
+ } |
|
+ if (g_strcmp0 (kind, "auto-attach") == 0) { |
|
+ if (!_helper_auto_attach (&error)) { |
|
+ g_printerr ("Failed to AutoAttach: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_INITIALIZED; |
|
+ } |
|
+ return EXIT_SUCCESS; |
|
+ } |
|
+ |
|
+ /* connect to abstract socket for reasons */ |
|
+ if (address == NULL) { |
|
+ g_printerr ("No --address specified\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ conn_private = g_dbus_connection_new_for_address_sync (address, |
|
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, |
|
+ NULL, NULL, |
|
+ &error); |
|
+ if (conn_private == NULL) { |
|
+ g_printerr ("Invalid --address specified: %s\n", error->message); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ proxy = g_dbus_proxy_new_sync (conn_private, |
|
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, |
|
+ NULL, /* GDBusInterfaceInfo */ |
|
+ NULL, /* name */ |
|
+ "/com/redhat/RHSM1/Register", |
|
+ "com.redhat.RHSM1.Register", |
|
+ NULL, &error); |
|
+ if (proxy == NULL) { |
|
+ g_printerr ("Count not contact RHSM: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_FOUND; |
|
+ } |
|
+ |
|
+ /* enable_content=1 auto attaches the subscription */ |
|
+ subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); |
|
+ |
|
+ g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); |
|
+ |
|
+ /* set registration server */ |
|
+ if (hostname == NULL || hostname[0] == '\0') |
|
+ hostname = g_strdup ("subscription.rhsm.redhat.com"); |
|
+ if (prefix == NULL || prefix[0] == '\0') |
|
+ prefix = g_strdup ("/subscription"); |
|
+ if (port == NULL || port[0] == '\0') |
|
+ port = g_strdup ("443"); |
|
+ subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); |
|
+ g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); |
|
+ g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); |
|
+ g_variant_builder_add (subman_conopts, "{ss}", "port", port); |
|
+ |
|
+ /* call into RHSM */ |
|
+ if (g_strcmp0 (kind, "register-with-key") == 0) { |
|
+ g_auto(GStrv) activation_keys = NULL; |
|
+ g_autoptr(GError) error_local = NULL; |
|
+ g_autoptr(GVariant) res = NULL; |
|
+ |
|
+ if (activation_key == NULL) { |
|
+ g_printerr ("Required --activation-key\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ if (organisation == NULL) { |
|
+ g_printerr ("Required --organisation\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ |
|
+ g_debug ("registering using activation key"); |
|
+ activation_keys = g_strsplit (activation_key, ",", -1); |
|
+ res = g_dbus_proxy_call_sync (proxy, |
|
+ "RegisterWithActivationKeys", |
|
+ g_variant_new ("(s^asa{ss}a{ss}s)", |
|
+ organisation, |
|
+ activation_keys, |
|
+ subman_options, |
|
+ subman_conopts, |
|
+ userlang), |
|
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
+ -1, NULL, &error_local); |
|
+ if (res == NULL) { |
|
+ g_dbus_error_strip_remote_error (error_local); |
|
+ _helper_convert_error (error_local->message, &error); |
|
+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); |
|
+ return error->code; |
|
+ } |
|
+ } else if (g_strcmp0 (kind, "register-with-username") == 0) { |
|
+ g_autoptr(GError) error_local = NULL; |
|
+ g_autoptr(GVariant) res = NULL; |
|
+ |
|
+ g_debug ("registering using username and password"); |
|
+ if (username == NULL) { |
|
+ g_printerr ("Required --username\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ if (password == NULL) { |
|
+ g_printerr ("Required --password\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ if (organisation == NULL) { |
|
+ g_printerr ("Required --organisation\n"); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ res = g_dbus_proxy_call_sync (proxy, |
|
+ "Register", |
|
+ g_variant_new ("(sssa{ss}a{ss}s)", |
|
+ organisation, |
|
+ username, |
|
+ password, |
|
+ subman_options, |
|
+ subman_conopts, |
|
+ userlang), |
|
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
+ -1, NULL, &error_local); |
|
+ if (res == NULL) { |
|
+ g_dbus_error_strip_remote_error (error_local); |
|
+ _helper_convert_error (error_local->message, &error); |
|
+ g_printerr ("Failed to Register: %s\n", error->message); |
|
+ return error->code; |
|
+ } |
|
+ } else { |
|
+ g_printerr ("Invalid --kind specified: %s\n", kind); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ |
|
+ /* set the new hostname */ |
|
+ if (!_helper_save_config ("server.hostname", hostname, &error)) { |
|
+ g_printerr ("Failed to save hostname: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_INITIALIZED; |
|
+ } |
|
+ if (!_helper_save_config ("server.prefix", prefix, &error)) { |
|
+ g_printerr ("Failed to save prefix: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_INITIALIZED; |
|
+ } |
|
+ if (!_helper_save_config ("server.port", port, &error)) { |
|
+ g_printerr ("Failed to save port: %s\n", error->message); |
|
+ return G_IO_ERROR_NOT_INITIALIZED; |
|
+ } |
|
+ |
|
+ return EXIT_SUCCESS; |
|
+} |
|
+ |
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
new file mode 100644 |
|
index 00000000..08b13fa6 |
|
--- /dev/null |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -0,0 +1,982 @@ |
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
|
+ * |
|
+ * Copyright (C) 2019 Richard Hughes <richard@hughsie.com> |
|
+ * |
|
+ * This program 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. |
|
+ * |
|
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>. |
|
+ * |
|
+ */ |
|
+ |
|
+#include "config.h" |
|
+ |
|
+#include <glib/gi18n.h> |
|
+#include <gdk/gdk.h> |
|
+#include <gtk/gtk.h> |
|
+#include <json-glib/json-glib.h> |
|
+#include <libnotify/notify.h> |
|
+ |
|
+#include "gnome-settings-profile.h" |
|
+#include "gsd-subman-common.h" |
|
+#include "gsd-subscription-manager.h" |
|
+ |
|
+#define GSD_DBUS_NAME "org.gnome.SettingsDaemon" |
|
+#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" |
|
+#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" |
|
+ |
|
+#define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" |
|
+#define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" |
|
+#define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" |
|
+ |
|
+static const gchar introspection_xml[] = |
|
+"<node>" |
|
+" <interface name='org.gnome.SettingsDaemon.Subscription'>" |
|
+" <method name='Register'>" |
|
+" <arg type='a{sv}' name='options' direction='in'/>" |
|
+" </method>" |
|
+" <method name='Unregister'/>" |
|
+" <property name='SubscriptionStatus' type='u' access='read'/>" |
|
+" </interface>" |
|
+"</node>"; |
|
+ |
|
+#define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) |
|
+ |
|
+typedef enum { |
|
+ _RHSM_INTERFACE_CONFIG, |
|
+ _RHSM_INTERFACE_REGISTER_SERVER, |
|
+ _RHSM_INTERFACE_ATTACH, |
|
+ _RHSM_INTERFACE_ENTITLEMENT, |
|
+ _RHSM_INTERFACE_PRODUCTS, |
|
+ _RHSM_INTERFACE_CONSUMER, |
|
+ _RHSM_INTERFACE_SYSPURPOSE, |
|
+ _RHSM_INTERFACE_LAST |
|
+} _RhsmInterface; |
|
+ |
|
+struct GsdSubscriptionManagerPrivate |
|
+{ |
|
+ /* D-Bus */ |
|
+ guint name_id; |
|
+ GDBusNodeInfo *introspection_data; |
|
+ GDBusConnection *connection; |
|
+ GCancellable *bus_cancellable; |
|
+ |
|
+ GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; |
|
+ const gchar *userlang; /* owned by GLib internally */ |
|
+ GHashTable *config; /* str:str */ |
|
+ gchar *address; |
|
+ |
|
+ GTimer *timer_last_notified; |
|
+ NotifyNotification *notification_expired; |
|
+ NotifyNotification *notification_registered; |
|
+ NotifyNotification *notification_registration_required; |
|
+ GsdSubmanSubscriptionStatus subscription_status; |
|
+ GsdSubmanSubscriptionStatus subscription_status_last; |
|
+}; |
|
+ |
|
+enum { |
|
+ PROP_0, |
|
+}; |
|
+ |
|
+static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); |
|
+static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); |
|
+static void gsd_subscription_manager_finalize (GObject *object); |
|
+ |
|
+G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) |
|
+ |
|
+static gpointer manager_object = NULL; |
|
+ |
|
+GQuark |
|
+gsd_subscription_manager_error_quark (void) |
|
+{ |
|
+ static GQuark quark = 0; |
|
+ if (!quark) |
|
+ quark = g_quark_from_static_string ("gsd_subscription_manager_error"); |
|
+ return quark; |
|
+} |
|
+ |
|
+static GsdSubmanSubscriptionStatus |
|
+_client_subscription_status_from_text (const gchar *status_txt) |
|
+{ |
|
+ if (g_strcmp0 (status_txt, "Unknown") == 0) |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
+ if (g_strcmp0 (status_txt, "Current") == 0) |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; |
|
+ if (g_strcmp0 (status_txt, "Invalid") == 0) |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; |
|
+ if (g_strcmp0 (status_txt, "Disabled") == 0) |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; |
|
+ if (g_strcmp0 (status_txt, "Insufficient") == 0) |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; |
|
+ g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? |
|
+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
+} |
|
+ |
|
+static void |
|
+_emit_property_changed (GsdSubscriptionManager *manager, |
|
+ const gchar *property_name, |
|
+ GVariant *property_value) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ GVariantBuilder builder; |
|
+ GVariantBuilder invalidated_builder; |
|
+ |
|
+ /* not yet connected */ |
|
+ if (priv->connection == NULL) |
|
+ return; |
|
+ |
|
+ /* build the dict */ |
|
+ g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); |
|
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); |
|
+ g_variant_builder_add (&builder, |
|
+ "{sv}", |
|
+ property_name, |
|
+ property_value); |
|
+ g_dbus_connection_emit_signal (priv->connection, |
|
+ NULL, |
|
+ GSD_SUBSCRIPTION_DBUS_PATH, |
|
+ "org.freedesktop.DBus.Properties", |
|
+ "PropertiesChanged", |
|
+ g_variant_new ("(sa{sv}as)", |
|
+ GSD_SUBSCRIPTION_DBUS_INTERFACE, |
|
+ &builder, |
|
+ &invalidated_builder), |
|
+ NULL); |
|
+ g_variant_builder_clear (&builder); |
|
+ g_variant_builder_clear (&invalidated_builder); |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ JsonNode *json_root; |
|
+ JsonObject *json_obj; |
|
+ const gchar *json_txt = NULL; |
|
+ const gchar *status_txt = NULL; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ g_autoptr(JsonParser) json_parser = json_parser_new (); |
|
+ |
|
+ /* save old value */ |
|
+ priv->subscription_status_last = priv->subscription_status; |
|
+ |
|
+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], |
|
+ "GetStatus", |
|
+ g_variant_new ("(ss)", |
|
+ "", /* assumed as 'now' */ |
|
+ priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (val, "(&s)", &json_txt); |
|
+ g_debug ("Entitlement.GetStatus JSON: %s", json_txt); |
|
+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) |
|
+ return FALSE; |
|
+ json_root = json_parser_get_root (json_parser); |
|
+ json_obj = json_node_get_object (json_root); |
|
+ if (!json_object_has_member (json_obj, "status")) { |
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, |
|
+ "no Entitlement.GetStatus status in %s", json_txt); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ status_txt = json_object_get_string_member (json_obj, "status"); |
|
+ g_debug ("Entitlement.GetStatus: %s", status_txt); |
|
+ priv->subscription_status = _client_subscription_status_from_text (status_txt); |
|
+ |
|
+ /* emit notification for g-c-c */ |
|
+ if (priv->subscription_status != priv->subscription_status_last) { |
|
+ _emit_property_changed (manager, "SubscriptionStatus", |
|
+ g_variant_new_uint32 (priv->subscription_status)); |
|
+ } |
|
+ |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ JsonNode *json_root; |
|
+ JsonObject *json_obj; |
|
+ const gchar *json_txt = NULL; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ g_autoptr(JsonParser) json_parser = json_parser_new (); |
|
+ |
|
+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], |
|
+ "GetSyspurpose", |
|
+ g_variant_new ("(s)", priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (val, "(&s)", &json_txt); |
|
+ g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); |
|
+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) |
|
+ return FALSE; |
|
+ json_root = json_parser_get_root (json_parser); |
|
+ json_obj = json_node_get_object (json_root); |
|
+ if (!json_object_has_member (json_obj, "status")) { |
|
+ g_debug ("Syspurpose.GetSyspurpose: Unknown"); |
|
+ return TRUE; |
|
+ } |
|
+ g_debug ("Syspurpose.GetSyspurpose: '%s", json_object_get_string_member (json_obj, "status")); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_register_start (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ const gchar *address = NULL; |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ |
|
+ /* already started */ |
|
+ if (priv->address != NULL) |
|
+ return TRUE; |
|
+ |
|
+ /* apparently: "we can't send registration credentials over the regular |
|
+ * system or session bus since those aren't really locked down..." */ |
|
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_NONE, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ "/com/redhat/RHSM1/RegisterServer", |
|
+ "com.redhat.RHSM1.RegisterServer", |
|
+ NULL, error); |
|
+ if (proxy == NULL) |
|
+ return FALSE; |
|
+ val = g_dbus_proxy_call_sync (proxy, "Start", |
|
+ g_variant_new ("(s)", priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (val, "(&s)", &address); |
|
+ g_debug ("RegisterServer.Start: %s", address); |
|
+ priv->address = g_strdup (address); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_register_stop (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ g_autoptr(GDBusProxy) proxy = NULL; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ |
|
+ /* already started */ |
|
+ if (priv->address == NULL) |
|
+ return TRUE; |
|
+ |
|
+ /* stop registration server */ |
|
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_NONE, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ "/com/redhat/RHSM1/RegisterServer", |
|
+ "com.redhat.RHSM1.RegisterServer", |
|
+ NULL, error); |
|
+ if (proxy == NULL) |
|
+ return FALSE; |
|
+ val = g_dbus_proxy_call_sync (proxy, "Stop", |
|
+ g_variant_new ("(s)", priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ g_clear_pointer (&priv->address, g_free); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_subprocess_wait_check (GSubprocess *subprocess, GError **error) |
|
+{ |
|
+ gint rc; |
|
+ if (!g_subprocess_wait (subprocess, NULL, error)) { |
|
+ g_prefix_error (error, "failed to run pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ rc = g_subprocess_get_exit_status (subprocess); |
|
+ if (rc != 0) { |
|
+ GInputStream *istream = g_subprocess_get_stderr_pipe (subprocess); |
|
+ gchar buf[1024] = { 0x0 }; |
|
+ gsize sz = 0; |
|
+ g_input_stream_read_all (istream, buf, sizeof(buf) - 1, &sz, NULL, NULL); |
|
+ if (sz == 0) { |
|
+ g_set_error_literal (error, G_IO_ERROR, rc, |
|
+ "Failed to run helper without stderr"); |
|
+ return FALSE; |
|
+ } |
|
+ g_set_error_literal (error, G_IO_ERROR, rc, buf); |
|
+ return FALSE; |
|
+ } |
|
+ return TRUE; |
|
+} |
|
+ |
|
+typedef enum { |
|
+ _NOTIFY_EXPIRED, |
|
+ _NOTIFY_REGISTRATION_REQUIRED, |
|
+ _NOTIFY_REGISTERED |
|
+} _NotifyKind; |
|
+ |
|
+static void |
|
+_show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ switch (notify_kind) { |
|
+ case _NOTIFY_EXPIRED: |
|
+ notify_notification_close (priv->notification_registered, NULL); |
|
+ notify_notification_close (priv->notification_registration_required, NULL); |
|
+ notify_notification_show (priv->notification_expired, NULL); |
|
+ break; |
|
+ case _NOTIFY_REGISTRATION_REQUIRED: |
|
+ notify_notification_close (priv->notification_registered, NULL); |
|
+ notify_notification_close (priv->notification_expired, NULL); |
|
+ notify_notification_show (priv->notification_registration_required, NULL); |
|
+ break; |
|
+ case _NOTIFY_REGISTERED: |
|
+ notify_notification_close (priv->notification_expired, NULL); |
|
+ notify_notification_close (priv->notification_registration_required, NULL); |
|
+ notify_notification_show (priv->notification_registered, NULL); |
|
+ break; |
|
+ default: |
|
+ break; |
|
+ } |
|
+ g_timer_reset (priv->timer_last_notified); |
|
+} |
|
+ |
|
+static void |
|
+_client_maybe__show_notification (GsdSubscriptionManager *manager) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ |
|
+ /* startup */ |
|
+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { |
|
+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
+ return; |
|
+ } |
|
+ |
|
+ /* something changed */ |
|
+ if (priv->subscription_status_last != priv->subscription_status) { |
|
+ g_debug ("transisition from subscription status '%s' to '%s'", |
|
+ gsd_subman_subscription_status_to_string (priv->subscription_status_last), |
|
+ gsd_subman_subscription_status_to_string (priv->subscription_status)); |
|
+ |
|
+ /* needs registration */ |
|
+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { |
|
+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
+ return; |
|
+ } |
|
+ |
|
+ /* was unregistered */ |
|
+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { |
|
+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
+ return; |
|
+ } |
|
+ |
|
+ /* registered */ |
|
+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { |
|
+ _show_notification (manager, _NOTIFY_REGISTERED); |
|
+ return; |
|
+ } |
|
+ } |
|
+ |
|
+ /* nag again */ |
|
+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
+ return; |
|
+ } |
|
+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && |
|
+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
+ _show_notification (manager, _NOTIFY_EXPIRED); |
|
+ return; |
|
+ } |
|
+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && |
|
+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
+ _show_notification (manager, _NOTIFY_EXPIRED); |
|
+ return; |
|
+ } |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_register_with_keys (GsdSubscriptionManager *manager, |
|
+ const gchar *hostname, |
|
+ const gchar *organisation, |
|
+ const gchar *activation_key, |
|
+ GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ g_autoptr(GSubprocess) subprocess = NULL; |
|
+ |
|
+ /* apparently: "we can't send registration credentials over the regular |
|
+ * system or session bus since those aren't really locked down..." */ |
|
+ if (!_client_register_start (manager, error)) |
|
+ return FALSE; |
|
+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
+ "pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
+ "--kind", "register-with-key", |
|
+ "--address", priv->address, |
|
+ "--hostname", hostname, |
|
+ "--organisation", organisation, |
|
+ "--activation-key", activation_key, |
|
+ NULL); |
|
+ if (subprocess == NULL) { |
|
+ g_prefix_error (error, "failed to find pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ if (!_client_subprocess_wait_check (subprocess, error)) |
|
+ return FALSE; |
|
+ |
|
+ /* FIXME: also do on error? */ |
|
+ if (!_client_register_stop (manager, error)) |
|
+ return FALSE; |
|
+ if (!_client_subscription_status_update (manager, error)) |
|
+ return FALSE; |
|
+ _client_maybe__show_notification (manager); |
|
+ |
|
+ /* success */ |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_register (GsdSubscriptionManager *manager, |
|
+ const gchar *hostname, |
|
+ const gchar *organisation, |
|
+ const gchar *username, |
|
+ const gchar *password, |
|
+ GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ g_autoptr(GSubprocess) subprocess = NULL; |
|
+ |
|
+ /* fallback */ |
|
+ if (organisation == NULL) |
|
+ organisation = ""; |
|
+ |
|
+ /* apparently: "we can't send registration credentials over the regular |
|
+ * system or session bus since those aren't really locked down..." */ |
|
+ if (!_client_register_start (manager, error)) |
|
+ return FALSE; |
|
+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
+ "pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
+ "--kind", "register-with-username", |
|
+ "--address", priv->address, |
|
+ "--hostname", hostname, |
|
+ "--organisation", organisation, |
|
+ "--username", username, |
|
+ "--password", password, |
|
+ NULL); |
|
+ if (subprocess == NULL) { |
|
+ g_prefix_error (error, "failed to find pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ if (!_client_subprocess_wait_check (subprocess, error)) |
|
+ return FALSE; |
|
+ |
|
+ /* FIXME: also do on error? */ |
|
+ if (!_client_register_stop (manager, error)) |
|
+ return FALSE; |
|
+ if (!_client_subscription_status_update (manager, error)) |
|
+ return FALSE; |
|
+ _client_maybe__show_notification (manager); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_unregister (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ g_autoptr(GSubprocess) subprocess = NULL; |
|
+ |
|
+ /* apparently: "we can't send registration credentials over the regular |
|
+ * system or session bus since those aren't really locked down..." */ |
|
+ if (!_client_register_start (manager, error)) |
|
+ return FALSE; |
|
+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
+ "pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
+ "--kind", "unregister", |
|
+ NULL); |
|
+ if (subprocess == NULL) { |
|
+ g_prefix_error (error, "failed to find pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ if (!_client_subprocess_wait_check (subprocess, error)) |
|
+ return FALSE; |
|
+ if (!_client_subscription_status_update (manager, error)) |
|
+ return FALSE; |
|
+ _client_maybe__show_notification (manager); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_update_config (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ g_autoptr(GVariant) val_server = NULL; |
|
+ g_autoptr(GVariantDict) dict = NULL; |
|
+ GVariantIter iter; |
|
+ gchar *key; |
|
+ gchar *value; |
|
+ |
|
+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], |
|
+ "GetAll", |
|
+ g_variant_new ("(s)", priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); |
|
+ val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); |
|
+ if (val_server != NULL) { |
|
+ g_variant_iter_init (&iter, val_server); |
|
+ while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { |
|
+ g_debug ("%s=%s", key, value); |
|
+ g_hash_table_insert (priv->config, |
|
+ g_steal_pointer (&key), |
|
+ g_steal_pointer (&value)); |
|
+ } |
|
+ } |
|
+ return TRUE; |
|
+} |
|
+ |
|
+static void |
|
+_subman_proxy_signal_cb (GDBusProxy *proxy, |
|
+ const gchar *sender_name, |
|
+ const gchar *signal_name, |
|
+ GVariant *parameters, |
|
+ GsdSubscriptionManager *manager) |
|
+{ |
|
+ g_autoptr(GError) error = NULL; |
|
+ if (!_client_syspurpose_update (manager, &error)) { |
|
+ g_warning ("failed to update syspurpose: %s", error->message); |
|
+ g_clear_error (&error); |
|
+ } |
|
+ if (!_client_subscription_status_update (manager, &error)) { |
|
+ g_warning ("failed to update subscription status: %s", error->message); |
|
+ g_clear_error (&error); |
|
+ } |
|
+ _client_maybe__show_notification (manager); |
|
+} |
|
+ |
|
+static void |
|
+_client_unload (GsdSubscriptionManager *manager) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) |
|
+ g_clear_object (&priv->proxies[i]); |
|
+ g_hash_table_unref (priv->config); |
|
+} |
|
+ |
|
+static const gchar * |
|
+_rhsm_interface_to_string (_RhsmInterface kind) |
|
+{ |
|
+ if (kind == _RHSM_INTERFACE_CONFIG) |
|
+ return "Config"; |
|
+ if (kind == _RHSM_INTERFACE_REGISTER_SERVER) |
|
+ return "RegisterServer"; |
|
+ if (kind == _RHSM_INTERFACE_ATTACH) |
|
+ return "Attach"; |
|
+ if (kind == _RHSM_INTERFACE_ENTITLEMENT) |
|
+ return "Entitlement"; |
|
+ if (kind == _RHSM_INTERFACE_PRODUCTS) |
|
+ return "Products"; |
|
+ if (kind == _RHSM_INTERFACE_CONSUMER) |
|
+ return "Consumer"; |
|
+ if (kind == _RHSM_INTERFACE_SYSPURPOSE) |
|
+ return "Syspurpose"; |
|
+ return NULL; |
|
+} |
|
+ |
|
+static gboolean |
|
+_client_load (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ |
|
+ priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); |
|
+ |
|
+ /* connect to all the interfaces on the *different* objects :| */ |
|
+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { |
|
+ const gchar *kind = _rhsm_interface_to_string (i); |
|
+ g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); |
|
+ g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); |
|
+ priv->proxies[i] = |
|
+ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
+ G_DBUS_PROXY_FLAGS_NONE, |
|
+ NULL, |
|
+ "com.redhat.RHSM1", |
|
+ opath, iface, |
|
+ NULL, |
|
+ error); |
|
+ if (priv->proxies[i] == NULL) |
|
+ return FALSE; |
|
+ /* we want to get notified if the status of the system changes */ |
|
+ g_signal_connect (priv->proxies[i], "g-signal", |
|
+ G_CALLBACK (_subman_proxy_signal_cb), manager); |
|
+ } |
|
+ |
|
+ /* get initial status */ |
|
+ priv->userlang = ""; |
|
+ if (!_client_update_config (manager, error)) |
|
+ return FALSE; |
|
+ if (!_client_subscription_status_update (manager, error)) |
|
+ return FALSE; |
|
+ if (!_client_syspurpose_update (manager, error)) |
|
+ return FALSE; |
|
+ |
|
+ /* success */ |
|
+ return TRUE; |
|
+} |
|
+ |
|
+gboolean |
|
+gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ gboolean ret; |
|
+ g_debug ("Starting subscription manager"); |
|
+ gnome_settings_profile_start (NULL); |
|
+ ret = _client_load (manager, error); |
|
+ _client_maybe__show_notification (manager); |
|
+ gnome_settings_profile_end (NULL); |
|
+ return ret; |
|
+} |
|
+ |
|
+void |
|
+gsd_subscription_manager_stop (GsdSubscriptionManager *manager) |
|
+{ |
|
+ g_debug ("Stopping subscription manager"); |
|
+ _client_unload (manager); |
|
+} |
|
+ |
|
+static void |
|
+gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) |
|
+{ |
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass); |
|
+ object_class->finalize = gsd_subscription_manager_finalize; |
|
+ notify_init ("gnome-settings-daemon"); |
|
+ g_type_class_add_private (klass, sizeof (GsdSubscriptionManagerPrivate)); |
|
+} |
|
+ |
|
+static void |
|
+_launch_info_overview (void) |
|
+{ |
|
+ const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; |
|
+ g_debug ("Running gnome-control-center info-overview"); |
|
+ g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, |
|
+ NULL, NULL, NULL, NULL); |
|
+} |
|
+ |
|
+static void |
|
+_notify_closed_cb (NotifyNotification *notification, gpointer user_data) |
|
+{ |
|
+ /* FIXME: only launch when clicking on the main body, not the window close */ |
|
+ if (notify_notification_get_closed_reason (notification) == 0x400) |
|
+ _launch_info_overview (); |
|
+} |
|
+ |
|
+static void |
|
+_notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) |
|
+{ |
|
+ _launch_info_overview (); |
|
+} |
|
+ |
|
+static void |
|
+gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); |
|
+ |
|
+ priv->timer_last_notified = g_timer_new (); |
|
+ |
|
+ /* expired */ |
|
+ priv->notification_expired = |
|
+ notify_notification_new (_("Subscription Has Expired"), |
|
+ _("Add or renew a subscription to continue receiving software updates."), |
|
+ NULL); |
|
+ notify_notification_set_app_name (priv->notification_expired, _("Subscription")); |
|
+ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); |
|
+ notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); |
|
+ notify_notification_add_action (priv->notification_expired, |
|
+ "info-overview", _("Subscribe System…"), |
|
+ _notify_clicked_cb, |
|
+ manager, NULL); |
|
+ g_signal_connect (priv->notification_expired, "closed", |
|
+ G_CALLBACK (_notify_closed_cb), manager); |
|
+ |
|
+ /* registered */ |
|
+ priv->notification_registered = |
|
+ notify_notification_new (_("Registration Successful"), |
|
+ _("The system has been registered and software updates have been enabled."), |
|
+ NULL); |
|
+ notify_notification_set_app_name (priv->notification_registered, _("Subscription")); |
|
+ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); |
|
+ notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); |
|
+ g_signal_connect (priv->notification_registered, "closed", |
|
+ G_CALLBACK (_notify_closed_cb), manager); |
|
+ |
|
+ /* registration required */ |
|
+ priv->notification_registration_required = |
|
+ notify_notification_new (_("System Not Registered"), |
|
+ _("Please register your system to receive software updates."), |
|
+ NULL); |
|
+ notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); |
|
+ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); |
|
+ notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); |
|
+ notify_notification_add_action (priv->notification_registration_required, |
|
+ "info-overview", _("Register System…"), |
|
+ _notify_clicked_cb, |
|
+ manager, NULL); |
|
+ g_signal_connect (priv->notification_registration_required, "closed", |
|
+ G_CALLBACK (_notify_closed_cb), manager); |
|
+} |
|
+ |
|
+static void |
|
+gsd_subscription_manager_finalize (GObject *object) |
|
+{ |
|
+ GsdSubscriptionManager *manager; |
|
+ |
|
+ g_return_if_fail (object != NULL); |
|
+ g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object)); |
|
+ |
|
+ manager = GSD_SUBSCRIPTION_MANAGER (object); |
|
+ |
|
+ gsd_subscription_manager_stop (manager); |
|
+ |
|
+ if (manager->priv->bus_cancellable != NULL) { |
|
+ g_cancellable_cancel (manager->priv->bus_cancellable); |
|
+ g_clear_object (&manager->priv->bus_cancellable); |
|
+ } |
|
+ |
|
+ g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); |
|
+ g_clear_object (&manager->priv->connection); |
|
+ g_clear_object (&manager->priv->notification_expired); |
|
+ g_clear_object (&manager->priv->notification_registered); |
|
+ g_timer_destroy (manager->priv->timer_last_notified); |
|
+ |
|
+ if (manager->priv->name_id != 0) { |
|
+ g_bus_unown_name (manager->priv->name_id); |
|
+ manager->priv->name_id = 0; |
|
+ } |
|
+ |
|
+ G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object); |
|
+} |
|
+ |
|
+static void |
|
+handle_method_call (GDBusConnection *connection, |
|
+ const gchar *sender, |
|
+ const gchar *object_path, |
|
+ const gchar *interface_name, |
|
+ const gchar *method_name, |
|
+ GVariant *parameters, |
|
+ GDBusMethodInvocation *invocation, |
|
+ gpointer user_data) |
|
+{ |
|
+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); |
|
+ g_autoptr(GError) error = NULL; |
|
+ |
|
+ if (g_strcmp0 (method_name, "Register") == 0) { |
|
+ const gchar *organisation = NULL; |
|
+ const gchar *hostname = NULL; |
|
+ |
|
+ if (FALSE) { |
|
+ g_dbus_method_invocation_return_error_literal (invocation, |
|
+ G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, |
|
+ "Cannot register at this time"); |
|
+ |
|
+ return; |
|
+ } |
|
+ |
|
+ g_autoptr(GVariantDict) dict = g_variant_dict_new (g_variant_get_child_value (parameters, 0)); |
|
+ |
|
+ const gchar *kind = NULL; |
|
+ if (!g_variant_dict_lookup (dict, "kind", "&s", &kind)) { |
|
+ g_dbus_method_invocation_return_error_literal (invocation, |
|
+ G_IO_ERROR, G_IO_ERROR_FAILED, |
|
+ "No kind specified"); |
|
+ |
|
+ return; |
|
+ } |
|
+ if (g_strcmp0 (kind, "username") == 0) { |
|
+ const gchar *username = NULL; |
|
+ const gchar *password = NULL; |
|
+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); |
|
+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); |
|
+ g_variant_dict_lookup (dict, "username", "&s", &username); |
|
+ g_variant_dict_lookup (dict, "password", "&s", &password); |
|
+ if (!_client_register (manager, |
|
+ hostname, |
|
+ organisation, |
|
+ username, |
|
+ password, |
|
+ &error)) { |
|
+ g_dbus_method_invocation_return_gerror (invocation, error); |
|
+ return; |
|
+ } |
|
+ } else if (g_strcmp0 (kind, "key") == 0) { |
|
+ const gchar *activation_key = NULL; |
|
+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); |
|
+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); |
|
+ g_variant_dict_lookup (dict, "activation-key", "&s", &activation_key); |
|
+ if (!_client_register_with_keys (manager, |
|
+ hostname, |
|
+ organisation, |
|
+ activation_key, |
|
+ &error)) { |
|
+ g_dbus_method_invocation_return_gerror (invocation, error); |
|
+ return; |
|
+ } |
|
+ } else { |
|
+ g_dbus_method_invocation_return_error_literal (invocation, |
|
+ G_IO_ERROR, G_IO_ERROR_FAILED, |
|
+ "Invalid kind specified"); |
|
+ |
|
+ return; |
|
+ } |
|
+ g_dbus_method_invocation_return_value (invocation, NULL); |
|
+ } else if (g_strcmp0 (method_name, "Unregister") == 0) { |
|
+ if (!_client_unregister (manager, &error)) { |
|
+ g_dbus_method_invocation_return_gerror (invocation, error); |
|
+ return; |
|
+ } |
|
+ g_dbus_method_invocation_return_value (invocation, NULL); |
|
+ } else { |
|
+ g_assert_not_reached (); |
|
+ } |
|
+} |
|
+ |
|
+static GVariant * |
|
+handle_get_property (GDBusConnection *connection, |
|
+ const gchar *sender, |
|
+ const gchar *object_path, |
|
+ const gchar *interface_name, |
|
+ const gchar *property_name, |
|
+ GError **error, gpointer user_data) |
|
+{ |
|
+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ |
|
+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { |
|
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
|
+ "No such interface: %s", interface_name); |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) |
|
+ return g_variant_new_uint32 (priv->subscription_status); |
|
+ |
|
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
|
+ "Failed to get property: %s", property_name); |
|
+ return NULL; |
|
+} |
|
+ |
|
+static gboolean |
|
+handle_set_property (GDBusConnection *connection, |
|
+ const gchar *sender, |
|
+ const gchar *object_path, |
|
+ const gchar *interface_name, |
|
+ const gchar *property_name, |
|
+ GVariant *value, |
|
+ GError **error, gpointer user_data) |
|
+{ |
|
+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { |
|
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
|
+ "No such interface: %s", interface_name); |
|
+ return FALSE; |
|
+ } |
|
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
|
+ "No such property: %s", property_name); |
|
+ return FALSE; |
|
+} |
|
+ |
|
+static const GDBusInterfaceVTable interface_vtable = |
|
+{ |
|
+ handle_method_call, |
|
+ handle_get_property, |
|
+ handle_set_property |
|
+}; |
|
+ |
|
+static void |
|
+name_lost_handler_cb (GDBusConnection *connection, const gchar *name, gpointer user_data) |
|
+{ |
|
+ g_debug ("lost name, so exiting"); |
|
+ gtk_main_quit (); |
|
+} |
|
+ |
|
+static void |
|
+on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdSubscriptionManager *manager) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ GDBusConnection *connection; |
|
+ g_autoptr(GError) error = NULL; |
|
+ |
|
+ connection = g_bus_get_finish (res, &error); |
|
+ if (connection == NULL) { |
|
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
|
+ g_warning ("Could not get session bus: %s", error->message); |
|
+ return; |
|
+ } |
|
+ |
|
+ priv->connection = connection; |
|
+ g_dbus_connection_register_object (connection, |
|
+ GSD_SUBSCRIPTION_DBUS_PATH, |
|
+ priv->introspection_data->interfaces[0], |
|
+ &interface_vtable, |
|
+ manager, |
|
+ NULL, |
|
+ NULL); |
|
+ priv->name_id = g_bus_own_name_on_connection (connection, |
|
+ GSD_SUBSCRIPTION_DBUS_NAME, |
|
+ G_BUS_NAME_OWNER_FLAGS_NONE, |
|
+ NULL, |
|
+ name_lost_handler_cb, |
|
+ manager, |
|
+ NULL); |
|
+} |
|
+ |
|
+static void |
|
+register_manager_dbus (GsdSubscriptionManager *manager) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ |
|
+ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); |
|
+ g_assert (priv->introspection_data != NULL); |
|
+ priv->bus_cancellable = g_cancellable_new (); |
|
+ |
|
+ g_bus_get (G_BUS_TYPE_SESSION, priv->bus_cancellable, |
|
+ (GAsyncReadyCallback) on_bus_gotten, manager); |
|
+} |
|
+ |
|
+GsdSubscriptionManager * |
|
+gsd_subscription_manager_new (void) |
|
+{ |
|
+ if (manager_object != NULL) { |
|
+ g_object_ref (manager_object); |
|
+ } else { |
|
+ manager_object = g_object_new (GSD_TYPE_SUBSCRIPTION_MANAGER, NULL); |
|
+ g_object_add_weak_pointer (manager_object, |
|
+ (gpointer *) &manager_object); |
|
+ register_manager_dbus (manager_object); |
|
+ } |
|
+ |
|
+ return GSD_SUBSCRIPTION_MANAGER (manager_object); |
|
+} |
|
diff --git a/plugins/subman/gsd-subscription-manager.h b/plugins/subman/gsd-subscription-manager.h |
|
new file mode 100644 |
|
index 00000000..6a524b1b |
|
--- /dev/null |
|
+++ b/plugins/subman/gsd-subscription-manager.h |
|
@@ -0,0 +1,63 @@ |
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
|
+ * |
|
+ * Copyright (C) 2019 Richard Hughes <richard@hughsie.com> |
|
+ * |
|
+ * This program 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. |
|
+ * |
|
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>. |
|
+ * |
|
+ */ |
|
+ |
|
+#ifndef __GSD_SUBSCRIPTION_MANAGER_H |
|
+#define __GSD_SUBSCRIPTION_MANAGER_H |
|
+ |
|
+#include <glib-object.h> |
|
+ |
|
+G_BEGIN_DECLS |
|
+ |
|
+#define GSD_TYPE_SUBSCRIPTION_MANAGER (gsd_subscription_manager_get_type ()) |
|
+#define GSD_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManager)) |
|
+#define GSD_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) |
|
+#define GSD_IS_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER)) |
|
+#define GSD_IS_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SUBSCRIPTION_MANAGER)) |
|
+#define GSD_SUBSCRIPTION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) |
|
+#define GSD_SUBSCRIPTION_MANAGER_ERROR (gsd_subscription_manager_error_quark ()) |
|
+ |
|
+typedef struct GsdSubscriptionManagerPrivate GsdSubscriptionManagerPrivate; |
|
+ |
|
+typedef struct |
|
+{ |
|
+ GObject parent; |
|
+ GsdSubscriptionManagerPrivate *priv; |
|
+} GsdSubscriptionManager; |
|
+ |
|
+typedef struct |
|
+{ |
|
+ GObjectClass parent_class; |
|
+} GsdSubscriptionManagerClass; |
|
+ |
|
+enum |
|
+{ |
|
+ GSD_SUBSCRIPTION_MANAGER_ERROR_FAILED |
|
+}; |
|
+ |
|
+GType gsd_subscription_manager_get_type (void); |
|
+GQuark gsd_subscription_manager_error_quark (void); |
|
+ |
|
+GsdSubscriptionManager *gsd_subscription_manager_new (void); |
|
+gboolean gsd_subscription_manager_start (GsdSubscriptionManager *manager, |
|
+ GError **error); |
|
+void gsd_subscription_manager_stop (GsdSubscriptionManager *manager); |
|
+ |
|
+G_END_DECLS |
|
+ |
|
+#endif /* __GSD_SUBSCRIPTION_MANAGER_H */ |
|
diff --git a/plugins/subman/main.c b/plugins/subman/main.c |
|
new file mode 100644 |
|
index 00000000..28ac995b |
|
--- /dev/null |
|
+++ b/plugins/subman/main.c |
|
@@ -0,0 +1,8 @@ |
|
+#define NEW gsd_subscription_manager_new |
|
+#define START gsd_subscription_manager_start |
|
+#define STOP gsd_subscription_manager_stop |
|
+#define MANAGER GsdSubscriptionManager |
|
+#define GDK_BACKEND "x11" |
|
+#include "gsd-subscription-manager.h" |
|
+ |
|
+#include "daemon-skeleton-gtk.h" |
|
diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build |
|
new file mode 100644 |
|
index 00000000..bfd073b6 |
|
--- /dev/null |
|
+++ b/plugins/subman/meson.build |
|
@@ -0,0 +1,56 @@ |
|
+sources = files( |
|
+ 'gsd-subscription-manager.c', |
|
+ 'gsd-subman-common.c', |
|
+ 'main.c' |
|
+) |
|
+ |
|
+deps = plugins_deps + [ |
|
+ libnotify_dep, |
|
+ gtk_dep, |
|
+ jsonglib_dep, |
|
+ m_dep, |
|
+] |
|
+ |
|
+cflags += ['-DBINDIR="@0@"'.format(gsd_bindir)] |
|
+cflags += ['-DLIBEXECDIR="@0@"'.format(gsd_libexecdir)] |
|
+ |
|
+executable( |
|
+ 'gsd-' + plugin_name, |
|
+ sources, |
|
+ include_directories: [top_inc, common_inc], |
|
+ dependencies: deps, |
|
+ c_args: cflags, |
|
+ install: true, |
|
+ install_rpath: gsd_pkglibdir, |
|
+ install_dir: gsd_libexecdir |
|
+) |
|
+ |
|
+# .Register needs to be called from root as subman can't do PolicyKit... |
|
+policy = 'org.gnome.settings-daemon.plugins.subman.policy' |
|
+policy_in = configure_file( |
|
+ input: policy + '.in.in', |
|
+ output: policy + '.in', |
|
+ configuration: plugins_conf |
|
+) |
|
+ |
|
+i18n.merge_file( |
|
+ policy, |
|
+ input: policy_in, |
|
+ output: policy, |
|
+ po_dir: po_dir, |
|
+ install: true, |
|
+ install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions') |
|
+) |
|
+ |
|
+install_data('org.gnome.settings-daemon.plugins.subman.rules', |
|
+ install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d')) |
|
+ |
|
+executable( |
|
+ 'gsd-subman-helper', |
|
+ 'gsd-subman-helper.c', |
|
+ include_directories: top_inc, |
|
+ dependencies: [gio_dep, jsonglib_dep], |
|
+ install: true, |
|
+ install_rpath: gsd_pkglibdir, |
|
+ install_dir: gsd_libexecdir |
|
+) |
|
diff --git a/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in |
|
new file mode 100644 |
|
index 00000000..14fe5915 |
|
--- /dev/null |
|
+++ b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in |
|
@@ -0,0 +1,9 @@ |
|
+[Desktop Entry] |
|
+Type=Application |
|
+Name=GNOME Settings Daemon's subscription manager plugin |
|
+Exec=@libexecdir@/gsd-subman |
|
+OnlyShowIn=GNOME; |
|
+NoDisplay=true |
|
+X-GNOME-Autostart-Phase=Initialization |
|
+X-GNOME-Autostart-Notify=true |
|
+X-GNOME-AutoRestart=true |
|
diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in |
|
new file mode 100644 |
|
index 00000000..59e9fdd4 |
|
--- /dev/null |
|
+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in |
|
@@ -0,0 +1,27 @@ |
|
+<?xml version="1.0" encoding="UTF-8"?> |
|
+<!DOCTYPE policyconfig PUBLIC |
|
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" |
|
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> |
|
+<policyconfig> |
|
+ |
|
+ <!-- |
|
+ Policy definitions for gnome-settings-daemon system-wide actions. |
|
+ Copyright (c) 2019 Richard Hughes <richard@hughsie.com> |
|
+ --> |
|
+ |
|
+ <vendor>GNOME Settings Daemon</vendor> |
|
+ <vendor_url>http://git.gnome.org/browse/gnome-settings-daemon</vendor_url> |
|
+ <icon_name>emblem-synchronizing</icon_name> |
|
+ |
|
+ <action id="org.gnome.settings-daemon.plugins.subman.register"> |
|
+ <description>Register the system</description> |
|
+ <message>Authentication is required to register the system</message> |
|
+ <defaults> |
|
+ <allow_any>no</allow_any> |
|
+ <allow_inactive>no</allow_inactive> |
|
+ <allow_active>auth_admin_keep</allow_active> |
|
+ </defaults> |
|
+ <annotate key="org.freedesktop.policykit.exec.path">@libexecdir@/gsd-subman-helper</annotate> |
|
+ </action> |
|
+ |
|
+</policyconfig> |
|
diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules |
|
new file mode 100644 |
|
index 00000000..1ed3a0ea |
|
--- /dev/null |
|
+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules |
|
@@ -0,0 +1,7 @@ |
|
+polkit.addRule(function(action, subject) { |
|
+ if (action.id == "org.gnome.settings-daemon.plugins.subman.register" && |
|
+ subject.active == true && subject.local == true && |
|
+ subject.isInGroup("wheel")) { |
|
+ return polkit.Result.YES; |
|
+ } |
|
+}); |
|
-- |
|
2.31.1 |
|
|
|
|
|
From dd5490fb4e962d82598bbf83d0dc600c030a10a3 Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Thu, 27 Jun 2019 16:12:00 +0200 |
|
Subject: [PATCH 02/19] subman: Add InstalledProducts dbus property for g-c-c |
|
|
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 135 ++++++++++++++++++++++ |
|
1 file changed, 135 insertions(+) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 08b13fa6..a8c18a26 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -1,6 +1,7 @@ |
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
|
* |
|
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com> |
|
+ * Copyright (C) 2019 Kalev Lember <klember@redhat.com> |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
@@ -44,6 +45,7 @@ static const gchar introspection_xml[] = |
|
" <arg type='a{sv}' name='options' direction='in'/>" |
|
" </method>" |
|
" <method name='Unregister'/>" |
|
+" <property name='InstalledProducts' type='aa{sv}' access='read'/>" |
|
" <property name='SubscriptionStatus' type='u' access='read'/>" |
|
" </interface>" |
|
"</node>"; |
|
@@ -72,6 +74,7 @@ struct GsdSubscriptionManagerPrivate |
|
GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; |
|
const gchar *userlang; /* owned by GLib internally */ |
|
GHashTable *config; /* str:str */ |
|
+ GPtrArray *installed_products; |
|
gchar *address; |
|
|
|
GTimer *timer_last_notified; |
|
@@ -92,6 +95,32 @@ static void gsd_subscription_manager_finalize (GObject *objec |
|
|
|
G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) |
|
|
|
+typedef struct |
|
+{ |
|
+ gchar *product_name; |
|
+ gchar *product_id; |
|
+ gchar *version; |
|
+ gchar *arch; |
|
+ gchar *status; |
|
+ gchar *starts; |
|
+ gchar *ends; |
|
+} ProductData; |
|
+ |
|
+static void |
|
+product_data_free (ProductData *product) |
|
+{ |
|
+ g_free (product->product_name); |
|
+ g_free (product->product_id); |
|
+ g_free (product->version); |
|
+ g_free (product->arch); |
|
+ g_free (product->status); |
|
+ g_free (product->starts); |
|
+ g_free (product->ends); |
|
+ g_free (product); |
|
+} |
|
+ |
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); |
|
+ |
|
static gpointer manager_object = NULL; |
|
|
|
GQuark |
|
@@ -120,6 +149,32 @@ _client_subscription_status_from_text (const gchar *status_txt) |
|
return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
} |
|
|
|
+static GVariant * |
|
+_make_installed_products_variant (GPtrArray *installed_products) |
|
+{ |
|
+ GVariantBuilder builder; |
|
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); |
|
+ |
|
+ for (guint i = 0; i < installed_products->len; i++) { |
|
+ ProductData *product = g_ptr_array_index (installed_products, i); |
|
+ g_auto(GVariantDict) dict; |
|
+ |
|
+ g_variant_dict_init (&dict, NULL); |
|
+ |
|
+ g_variant_dict_insert (&dict, "product-name", "s", product->product_name); |
|
+ g_variant_dict_insert (&dict, "product-id", "s", product->product_id); |
|
+ g_variant_dict_insert (&dict, "version", "s", product->version); |
|
+ g_variant_dict_insert (&dict, "arch", "s", product->arch); |
|
+ g_variant_dict_insert (&dict, "status", "s", product->status); |
|
+ g_variant_dict_insert (&dict, "starts", "s", product->starts); |
|
+ g_variant_dict_insert (&dict, "ends", "s", product->ends); |
|
+ |
|
+ g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); |
|
+ } |
|
+ |
|
+ return g_variant_builder_end (&builder); |
|
+} |
|
+ |
|
static void |
|
_emit_property_changed (GsdSubscriptionManager *manager, |
|
const gchar *property_name, |
|
@@ -154,6 +209,69 @@ _emit_property_changed (GsdSubscriptionManager *manager, |
|
g_variant_builder_clear (&invalidated_builder); |
|
} |
|
|
|
+static gboolean |
|
+_client_installed_products_update (GsdSubscriptionManager *manager, GError **error) |
|
+{ |
|
+ GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ JsonNode *json_root; |
|
+ JsonArray *json_products_array; |
|
+ const gchar *json_txt = NULL; |
|
+ g_autoptr(GVariant) val = NULL; |
|
+ g_autoptr(JsonParser) json_parser = json_parser_new (); |
|
+ |
|
+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS], |
|
+ "ListInstalledProducts", |
|
+ g_variant_new ("(sa{sv}s)", |
|
+ "" /* filter_string */, |
|
+ NULL /* proxy_options */, |
|
+ priv->userlang), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (val == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (val, "(&s)", &json_txt); |
|
+ g_debug ("Products.ListInstalledProducts JSON: %s", json_txt); |
|
+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) |
|
+ return FALSE; |
|
+ json_root = json_parser_get_root (json_parser); |
|
+ json_products_array = json_node_get_array (json_root); |
|
+ if (json_products_array == NULL) { |
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, |
|
+ "no InstalledProducts array in %s", json_txt); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ g_ptr_array_set_size (priv->installed_products, 0); |
|
+ |
|
+ for (guint i = 0; i < json_array_get_length (json_products_array); i++) { |
|
+ JsonArray *json_product = json_array_get_array_element (json_products_array, i); |
|
+ g_autoptr(ProductData) product = g_new0 (ProductData, 1); |
|
+ |
|
+ if (json_product == NULL) |
|
+ continue; |
|
+ if (json_array_get_length (json_product) < 8) { |
|
+ g_debug ("Unexpected number of array elements in InstalledProducts JSON"); |
|
+ continue; |
|
+ } |
|
+ |
|
+ product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); |
|
+ product->product_id = g_strdup (json_array_get_string_element (json_product, 1)); |
|
+ product->version = g_strdup (json_array_get_string_element (json_product, 2)); |
|
+ product->arch = g_strdup (json_array_get_string_element (json_product, 3)); |
|
+ product->status = g_strdup (json_array_get_string_element (json_product, 4)); |
|
+ product->starts = g_strdup (json_array_get_string_element (json_product, 6)); |
|
+ product->ends = g_strdup (json_array_get_string_element (json_product, 7)); |
|
+ |
|
+ g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); |
|
+ } |
|
+ |
|
+ /* emit notification for g-c-c */ |
|
+ _emit_property_changed (manager, "InstalledProducts", |
|
+ _make_installed_products_variant (priv->installed_products)); |
|
+ |
|
+ return TRUE; |
|
+} |
|
+ |
|
static gboolean |
|
_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) |
|
{ |
|
@@ -450,6 +568,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
+ if (!_client_installed_products_update (manager, error)) |
|
+ return FALSE; |
|
_client_maybe__show_notification (manager); |
|
|
|
/* success */ |
|
@@ -497,6 +617,8 @@ _client_register (GsdSubscriptionManager *manager, |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
+ if (!_client_installed_products_update (manager, error)) |
|
+ return FALSE; |
|
_client_maybe__show_notification (manager); |
|
return TRUE; |
|
} |
|
@@ -523,6 +645,8 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
+ if (!_client_installed_products_update (manager, error)) |
|
+ return FALSE; |
|
_client_maybe__show_notification (manager); |
|
return TRUE; |
|
} |
|
@@ -575,6 +699,10 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, |
|
g_warning ("failed to update subscription status: %s", error->message); |
|
g_clear_error (&error); |
|
} |
|
+ if (!_client_installed_products_update (manager, &error)) { |
|
+ g_warning ("failed to update installed products: %s", error->message); |
|
+ g_clear_error (&error); |
|
+ } |
|
_client_maybe__show_notification (manager); |
|
} |
|
|
|
@@ -640,6 +768,8 @@ _client_load (GsdSubscriptionManager *manager, GError **error) |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
+ if (!_client_installed_products_update (manager, error)) |
|
+ return FALSE; |
|
if (!_client_syspurpose_update (manager, error)) |
|
return FALSE; |
|
|
|
@@ -703,6 +833,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
{ |
|
GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); |
|
|
|
+ priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); |
|
priv->timer_last_notified = g_timer_new (); |
|
|
|
/* expired */ |
|
@@ -767,6 +898,7 @@ gsd_subscription_manager_finalize (GObject *object) |
|
g_clear_object (&manager->priv->bus_cancellable); |
|
} |
|
|
|
+ g_clear_pointer (&manager->priv->installed_products, g_ptr_array_unref); |
|
g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); |
|
g_clear_object (&manager->priv->connection); |
|
g_clear_object (&manager->priv->notification_expired); |
|
@@ -884,6 +1016,9 @@ handle_get_property (GDBusConnection *connection, |
|
if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) |
|
return g_variant_new_uint32 (priv->subscription_status); |
|
|
|
+ if (g_strcmp0 (property_name, "InstalledProducts") == 0) |
|
+ return _make_installed_products_variant (priv->installed_products); |
|
+ |
|
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
|
"Failed to get property: %s", property_name); |
|
return NULL; |
|
-- |
|
2.31.1 |
|
|
|
|
|
From c67554c7ab37a4fea6abc80ca199de2671c34ee2 Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Fri, 28 Jun 2019 18:10:36 +0200 |
|
Subject: [PATCH 03/19] subman: Increase RHSM dbus call timeouts |
|
|
|
Increase the dbus timeouts to 5 minutes as the register/unregister calls |
|
seem to routinely take more than a minute. |
|
--- |
|
plugins/subman/gsd-subman-helper.c | 17 ++++++++++++----- |
|
1 file changed, 12 insertions(+), 5 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
index 182f7190..af7a82e9 100644 |
|
--- a/plugins/subman/gsd-subman-helper.c |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -28,6 +28,8 @@ |
|
#include <gio/gio.h> |
|
#include <json-glib/json-glib.h> |
|
|
|
+#define DBUS_TIMEOUT 300000 /* 5 minutes */ |
|
+ |
|
static void |
|
_helper_convert_error (const gchar *json_txt, GError **error) |
|
{ |
|
@@ -94,7 +96,8 @@ _helper_unregister (GError **error) |
|
proxy_options, |
|
""), /* lang */ |
|
G_DBUS_CALL_FLAGS_NONE, |
|
- -1, NULL, error); |
|
+ DBUS_TIMEOUT, |
|
+ NULL, error); |
|
return res != NULL; |
|
} |
|
|
|
@@ -127,7 +130,8 @@ _helper_auto_attach (GError **error) |
|
proxy_options, |
|
""), /* lang */ |
|
G_DBUS_CALL_FLAGS_NONE, |
|
- -1, NULL, error); |
|
+ DBUS_TIMEOUT, |
|
+ NULL, error); |
|
if (res == NULL) |
|
return FALSE; |
|
g_variant_get (res, "(&s)", &str); |
|
@@ -158,7 +162,8 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) |
|
g_variant_new_string (value), |
|
""), /* lang */ |
|
G_DBUS_CALL_FLAGS_NONE, |
|
- -1, NULL, error); |
|
+ DBUS_TIMEOUT, |
|
+ NULL, error); |
|
return res != NULL; |
|
} |
|
|
|
@@ -305,7 +310,8 @@ main (int argc, char *argv[]) |
|
subman_conopts, |
|
userlang), |
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
- -1, NULL, &error_local); |
|
+ DBUS_TIMEOUT, |
|
+ NULL, &error_local); |
|
if (res == NULL) { |
|
g_dbus_error_strip_remote_error (error_local); |
|
_helper_convert_error (error_local->message, &error); |
|
@@ -339,7 +345,8 @@ main (int argc, char *argv[]) |
|
subman_conopts, |
|
userlang), |
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
- -1, NULL, &error_local); |
|
+ DBUS_TIMEOUT, |
|
+ NULL, &error_local); |
|
if (res == NULL) { |
|
g_dbus_error_strip_remote_error (error_local); |
|
_helper_convert_error (error_local->message, &error); |
|
-- |
|
2.31.1 |
|
|
|
|
|
From efcbbf6a50eca888bde03f4425578bab9916ebaa Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Thu, 20 Aug 2020 11:20:47 -0400 |
|
Subject: [PATCH 04/19] subman: Drop userlang field |
|
|
|
It's currently always erroneously set to empty string. |
|
|
|
This commit drops it, and just uses "C.UTF-8" everywhere, |
|
which is what we actually want. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 14 ++++++-------- |
|
1 file changed, 6 insertions(+), 8 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index a8c18a26..46f051a5 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -72,7 +72,6 @@ struct GsdSubscriptionManagerPrivate |
|
GCancellable *bus_cancellable; |
|
|
|
GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; |
|
- const gchar *userlang; /* owned by GLib internally */ |
|
GHashTable *config; /* str:str */ |
|
GPtrArray *installed_products; |
|
gchar *address; |
|
@@ -224,7 +223,7 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err |
|
g_variant_new ("(sa{sv}s)", |
|
"" /* filter_string */, |
|
NULL /* proxy_options */, |
|
- priv->userlang), |
|
+ "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -290,7 +289,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
"GetStatus", |
|
g_variant_new ("(ss)", |
|
"", /* assumed as 'now' */ |
|
- priv->userlang), |
|
+ "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -332,7 +331,7 @@ _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) |
|
|
|
val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], |
|
"GetSyspurpose", |
|
- g_variant_new ("(s)", priv->userlang), |
|
+ g_variant_new ("(s)", "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -375,7 +374,7 @@ _client_register_start (GsdSubscriptionManager *manager, GError **error) |
|
if (proxy == NULL) |
|
return FALSE; |
|
val = g_dbus_proxy_call_sync (proxy, "Start", |
|
- g_variant_new ("(s)", priv->userlang), |
|
+ g_variant_new ("(s)", "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -408,7 +407,7 @@ _client_register_stop (GsdSubscriptionManager *manager, GError **error) |
|
if (proxy == NULL) |
|
return FALSE; |
|
val = g_dbus_proxy_call_sync (proxy, "Stop", |
|
- g_variant_new ("(s)", priv->userlang), |
|
+ g_variant_new ("(s)", "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -664,7 +663,7 @@ _client_update_config (GsdSubscriptionManager *manager, GError **error) |
|
|
|
val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], |
|
"GetAll", |
|
- g_variant_new ("(s)", priv->userlang), |
|
+ g_variant_new ("(s)", "C.UTF-8"), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
-1, NULL, error); |
|
if (val == NULL) |
|
@@ -763,7 +762,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) |
|
} |
|
|
|
/* get initial status */ |
|
- priv->userlang = ""; |
|
if (!_client_update_config (manager, error)) |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 3ff6f889049462b2b3029e26f7251e39904a3ddf Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 15:04:17 -0500 |
|
Subject: [PATCH 05/19] subman: Use user locale for registration/subscription |
|
operations |
|
|
|
This makes sure that error messages are in the correct locale. |
|
--- |
|
plugins/subman/gsd-subman-helper.c | 17 +++++++++++------ |
|
1 file changed, 11 insertions(+), 6 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
index af7a82e9..f84e91bf 100644 |
|
--- a/plugins/subman/gsd-subman-helper.c |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -24,11 +24,13 @@ |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
+#include <locale.h> |
|
|
|
#include <gio/gio.h> |
|
#include <json-glib/json-glib.h> |
|
|
|
#define DBUS_TIMEOUT 300000 /* 5 minutes */ |
|
+static const char *locale; |
|
|
|
static void |
|
_helper_convert_error (const gchar *json_txt, GError **error) |
|
@@ -94,7 +96,7 @@ _helper_unregister (GError **error) |
|
"Unregister", |
|
g_variant_new ("(a{sv}s)", |
|
proxy_options, |
|
- ""), /* lang */ |
|
+ locale), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
DBUS_TIMEOUT, |
|
NULL, error); |
|
@@ -128,7 +130,7 @@ _helper_auto_attach (GError **error) |
|
g_variant_new ("(sa{sv}s)", |
|
"", /* now? */ |
|
proxy_options, |
|
- ""), /* lang */ |
|
+ locale), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
DBUS_TIMEOUT, |
|
NULL, error); |
|
@@ -160,7 +162,7 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) |
|
g_variant_new ("(svs)", |
|
key, |
|
g_variant_new_string (value), |
|
- ""), /* lang */ |
|
+ locale), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
DBUS_TIMEOUT, |
|
NULL, error); |
|
@@ -170,7 +172,6 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) |
|
int |
|
main (int argc, char *argv[]) |
|
{ |
|
- const gchar *userlang = ""; /* as root, so no translations */ |
|
g_autofree gchar *activation_key = NULL; |
|
g_autofree gchar *address = NULL; |
|
g_autofree gchar *hostname = NULL; |
|
@@ -218,6 +219,10 @@ main (int argc, char *argv[]) |
|
g_printerr ("This program can only be used by the root user\n"); |
|
return G_IO_ERROR_NOT_SUPPORTED; |
|
} |
|
+ |
|
+ setlocale (LC_ALL, ""); |
|
+ locale = setlocale (LC_MESSAGES, NULL); |
|
+ |
|
g_option_context_add_main_entries (context, options, NULL); |
|
if (!g_option_context_parse (context, &argc, &argv, &error)) { |
|
g_printerr ("Failed to parse arguments: %s\n", error->message); |
|
@@ -308,7 +313,7 @@ main (int argc, char *argv[]) |
|
activation_keys, |
|
subman_options, |
|
subman_conopts, |
|
- userlang), |
|
+ locale), |
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
DBUS_TIMEOUT, |
|
NULL, &error_local); |
|
@@ -343,7 +348,7 @@ main (int argc, char *argv[]) |
|
password, |
|
subman_options, |
|
subman_conopts, |
|
- userlang), |
|
+ locale), |
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, |
|
DBUS_TIMEOUT, |
|
NULL, &error_local); |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 7bdca155acbe043c82e7abd9d2072c6502e10270 Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Thu, 20 Aug 2020 13:34:19 -0400 |
|
Subject: [PATCH 06/19] subman: Handle subscription-manager giving invalid |
|
status better |
|
|
|
subscription-manager potentially returns status messages that the |
|
subman plugin treats as enum values translated in some unknown |
|
other language. It could be tied to system locale, or due to a |
|
caching bug a previous locale used. |
|
|
|
This commit tries to work around that bug, by instead relying on |
|
the GetUUID() method and valid attribute. If there's no UUID we |
|
know the system is unregistered. If there's a UUID but the valid |
|
attribute is FALSE we know the system is registered, but hasn't |
|
got proper entitlements. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 69 ++++++++++++----------- |
|
1 file changed, 36 insertions(+), 33 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 46f051a5..e2c16056 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -131,23 +131,6 @@ gsd_subscription_manager_error_quark (void) |
|
return quark; |
|
} |
|
|
|
-static GsdSubmanSubscriptionStatus |
|
-_client_subscription_status_from_text (const gchar *status_txt) |
|
-{ |
|
- if (g_strcmp0 (status_txt, "Unknown") == 0) |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
- if (g_strcmp0 (status_txt, "Current") == 0) |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; |
|
- if (g_strcmp0 (status_txt, "Invalid") == 0) |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; |
|
- if (g_strcmp0 (status_txt, "Disabled") == 0) |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; |
|
- if (g_strcmp0 (status_txt, "Insufficient") == 0) |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; |
|
- g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? |
|
- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
-} |
|
- |
|
static GVariant * |
|
_make_installed_products_variant (GPtrArray *installed_products) |
|
{ |
|
@@ -275,40 +258,60 @@ static gboolean |
|
_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) |
|
{ |
|
GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ g_autoptr(GVariant) uuid = NULL; |
|
+ const gchar *uuid_txt = NULL; |
|
JsonNode *json_root; |
|
JsonObject *json_obj; |
|
const gchar *json_txt = NULL; |
|
- const gchar *status_txt = NULL; |
|
- g_autoptr(GVariant) val = NULL; |
|
+ g_autoptr(GVariant) status = NULL; |
|
g_autoptr(JsonParser) json_parser = json_parser_new (); |
|
|
|
/* save old value */ |
|
priv->subscription_status_last = priv->subscription_status; |
|
|
|
- val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], |
|
- "GetStatus", |
|
- g_variant_new ("(ss)", |
|
- "", /* assumed as 'now' */ |
|
- "C.UTF-8"), |
|
- G_DBUS_CALL_FLAGS_NONE, |
|
- -1, NULL, error); |
|
- if (val == NULL) |
|
+ uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], |
|
+ "GetUuid", |
|
+ g_variant_new ("(s)", |
|
+ "C.UTF-8"), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (uuid == NULL) |
|
return FALSE; |
|
- g_variant_get (val, "(&s)", &json_txt); |
|
+ |
|
+ g_variant_get (uuid, "(&s)", &uuid_txt); |
|
+ |
|
+ status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], |
|
+ "GetStatus", |
|
+ g_variant_new ("(ss)", |
|
+ "", /* assumed as 'now' */ |
|
+ "C.UTF-8"), |
|
+ G_DBUS_CALL_FLAGS_NONE, |
|
+ -1, NULL, error); |
|
+ if (status == NULL) |
|
+ return FALSE; |
|
+ g_variant_get (status, "(&s)", &json_txt); |
|
g_debug ("Entitlement.GetStatus JSON: %s", json_txt); |
|
if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) |
|
return FALSE; |
|
json_root = json_parser_get_root (json_parser); |
|
json_obj = json_node_get_object (json_root); |
|
- if (!json_object_has_member (json_obj, "status")) { |
|
+ if (!json_object_has_member (json_obj, "valid")) { |
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, |
|
- "no Entitlement.GetStatus status in %s", json_txt); |
|
+ "no Entitlement.GetStatus valid in %s", json_txt); |
|
return FALSE; |
|
} |
|
|
|
- status_txt = json_object_get_string_member (json_obj, "status"); |
|
- g_debug ("Entitlement.GetStatus: %s", status_txt); |
|
- priv->subscription_status = _client_subscription_status_from_text (status_txt); |
|
+ gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); |
|
+ |
|
+ if (uuid_txt[0] != '\0') { |
|
+ if (is_valid) { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; |
|
+ } else { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; |
|
+ } |
|
+ } else { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
+ } |
|
|
|
/* emit notification for g-c-c */ |
|
if (priv->subscription_status != priv->subscription_status_last) { |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 74fe856b8d2826520a7d324abe9727097cce8cfb Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Tue, 25 Aug 2020 10:34:03 -0400 |
|
Subject: [PATCH 07/19] subman: Force re-subscribe if the admin already |
|
subscribed |
|
|
|
It's possible for an admin to to half-enroll the system with RHN, |
|
using the CLI tools. |
|
|
|
Meaning, it's possible for them to register the system with the |
|
service, but not attach to a purchased license for the machine, |
|
the, so called, entitlements. |
|
|
|
The subman module always does both halves of the registration process |
|
in lock step. This means, if an admin tries to register using GNOME |
|
while in a half-registered state, subman will fail because the first |
|
step, the registration step, is already finished. |
|
|
|
This commit addresses that problem by trying to unregister up front |
|
before registering. |
|
--- |
|
plugins/subman/gsd-subman-helper.c | 11 +++++++++-- |
|
1 file changed, 9 insertions(+), 2 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
index f84e91bf..3931ef2e 100644 |
|
--- a/plugins/subman/gsd-subman-helper.c |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -78,7 +78,6 @@ _helper_unregister (GError **error) |
|
g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
g_autoptr(GVariant) res = NULL; |
|
|
|
- g_debug ("unregistering"); |
|
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, |
|
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | |
|
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, |
|
@@ -235,6 +234,7 @@ main (int argc, char *argv[]) |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
if (g_strcmp0 (kind, "unregister") == 0) { |
|
+ g_debug ("unregistering"); |
|
if (!_helper_unregister (&error)) { |
|
g_printerr ("Failed to Unregister: %s\n", error->message); |
|
return G_IO_ERROR_NOT_INITIALIZED; |
|
@@ -304,6 +304,9 @@ main (int argc, char *argv[]) |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
|
|
+ g_debug ("trying to unregister in case machine is already registered"); |
|
+ _helper_unregister (NULL); |
|
+ |
|
g_debug ("registering using activation key"); |
|
activation_keys = g_strsplit (activation_key, ",", -1); |
|
res = g_dbus_proxy_call_sync (proxy, |
|
@@ -327,7 +330,6 @@ main (int argc, char *argv[]) |
|
g_autoptr(GError) error_local = NULL; |
|
g_autoptr(GVariant) res = NULL; |
|
|
|
- g_debug ("registering using username and password"); |
|
if (username == NULL) { |
|
g_printerr ("Required --username\n"); |
|
return G_IO_ERROR_INVALID_DATA; |
|
@@ -340,6 +342,11 @@ main (int argc, char *argv[]) |
|
g_printerr ("Required --organisation\n"); |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
+ |
|
+ g_debug ("trying to unregister in case machine is already registered"); |
|
+ _helper_unregister (NULL); |
|
+ |
|
+ g_debug ("registering using username and password"); |
|
res = g_dbus_proxy_call_sync (proxy, |
|
"Register", |
|
g_variant_new ("(sssa{ss}a{ss}s)", |
|
-- |
|
2.31.1 |
|
|
|
|
|
From c0ca9c55632a52371acbbb76a279f28e26532e5e Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Tue, 25 Aug 2020 16:20:42 -0400 |
|
Subject: [PATCH 08/19] subman: Don't send secrets through command line |
|
|
|
The command line is introspectable with "ps", and it even gets logged |
|
to syslog, so it's not suitable for passing secrets. |
|
|
|
Unfortunately, the user's password is currently passed. |
|
|
|
This commit addresses that problem by passing the password through |
|
stdin, instead. |
|
--- |
|
plugins/subman/gsd-subman-helper.c | 32 ++++++++------ |
|
plugins/subman/gsd-subscription-manager.c | 52 ++++++++++++++++++++--- |
|
plugins/subman/meson.build | 2 +- |
|
3 files changed, 66 insertions(+), 20 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
index 3931ef2e..edf1e41f 100644 |
|
--- a/plugins/subman/gsd-subman-helper.c |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -21,12 +21,14 @@ |
|
|
|
#include "config.h" |
|
|
|
+ |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <locale.h> |
|
|
|
#include <gio/gio.h> |
|
+#include <gio/gunixinputstream.h> |
|
#include <json-glib/json-glib.h> |
|
|
|
#define DBUS_TIMEOUT 300000 /* 5 minutes */ |
|
@@ -176,7 +178,6 @@ main (int argc, char *argv[]) |
|
g_autofree gchar *hostname = NULL; |
|
g_autofree gchar *kind = NULL; |
|
g_autofree gchar *organisation = NULL; |
|
- g_autofree gchar *password = NULL; |
|
g_autofree gchar *port = NULL; |
|
g_autofree gchar *prefix = NULL; |
|
g_autofree gchar *proxy_server = NULL; |
|
@@ -188,6 +189,7 @@ main (int argc, char *argv[]) |
|
g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
g_autoptr(GVariantBuilder) subman_conopts = NULL; |
|
g_autoptr(GVariantBuilder) subman_options = NULL; |
|
+ g_autoptr(GInputStream) standard_input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE); |
|
|
|
const GOptionEntry options[] = { |
|
{ "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
@@ -196,12 +198,8 @@ main (int argc, char *argv[]) |
|
&address, "UNIX address", NULL }, |
|
{ "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
&username, "Username", NULL }, |
|
- { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
- &password, "Password", NULL }, |
|
{ "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
&organisation, "Organisation", NULL }, |
|
- { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, |
|
- &activation_key, "Activation keys", NULL }, |
|
{ "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
&hostname, "Registration server hostname", NULL }, |
|
{ "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, |
|
@@ -294,16 +292,20 @@ main (int argc, char *argv[]) |
|
g_auto(GStrv) activation_keys = NULL; |
|
g_autoptr(GError) error_local = NULL; |
|
g_autoptr(GVariant) res = NULL; |
|
+ gchar activation_key[PIPE_BUF + 1] = ""; |
|
|
|
- if (activation_key == NULL) { |
|
- g_printerr ("Required --activation-key\n"); |
|
- return G_IO_ERROR_INVALID_DATA; |
|
- } |
|
if (organisation == NULL) { |
|
g_printerr ("Required --organisation\n"); |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
|
|
+ g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local); |
|
+ |
|
+ if (error_local != NULL) { |
|
+ g_printerr ("Could not read activation key: %s\n", error_local->message); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ |
|
g_debug ("trying to unregister in case machine is already registered"); |
|
_helper_unregister (NULL); |
|
|
|
@@ -329,20 +331,24 @@ main (int argc, char *argv[]) |
|
} else if (g_strcmp0 (kind, "register-with-username") == 0) { |
|
g_autoptr(GError) error_local = NULL; |
|
g_autoptr(GVariant) res = NULL; |
|
+ gchar password[PIPE_BUF + 1] = ""; |
|
|
|
if (username == NULL) { |
|
g_printerr ("Required --username\n"); |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
- if (password == NULL) { |
|
- g_printerr ("Required --password\n"); |
|
- return G_IO_ERROR_INVALID_DATA; |
|
- } |
|
if (organisation == NULL) { |
|
g_printerr ("Required --organisation\n"); |
|
return G_IO_ERROR_INVALID_DATA; |
|
} |
|
|
|
+ g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local); |
|
+ |
|
+ if (error_local != NULL) { |
|
+ g_printerr ("Could not read password: %s\n", error_local->message); |
|
+ return G_IO_ERROR_INVALID_DATA; |
|
+ } |
|
+ |
|
g_debug ("trying to unregister in case machine is already registered"); |
|
_helper_unregister (NULL); |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index e2c16056..0838d490 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -21,6 +21,7 @@ |
|
#include "config.h" |
|
|
|
#include <glib/gi18n.h> |
|
+#include <gio/gunixinputstream.h> |
|
#include <gdk/gdk.h> |
|
#include <gtk/gtk.h> |
|
#include <json-glib/json-glib.h> |
|
@@ -544,26 +545,45 @@ _client_register_with_keys (GsdSubscriptionManager *manager, |
|
{ |
|
GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
g_autoptr(GSubprocess) subprocess = NULL; |
|
+ g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); |
|
+ g_autoptr(GBytes) stderr_buf = NULL; |
|
+ gint rc; |
|
|
|
/* apparently: "we can't send registration credentials over the regular |
|
* system or session bus since those aren't really locked down..." */ |
|
if (!_client_register_start (manager, error)) |
|
return FALSE; |
|
g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
"pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
"--kind", "register-with-key", |
|
"--address", priv->address, |
|
"--hostname", hostname, |
|
"--organisation", organisation, |
|
- "--activation-key", activation_key, |
|
NULL); |
|
if (subprocess == NULL) { |
|
g_prefix_error (error, "failed to find pkexec: "); |
|
return FALSE; |
|
} |
|
- if (!_client_subprocess_wait_check (subprocess, error)) |
|
+ |
|
+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { |
|
+ g_prefix_error (error, "failed to run pkexec: "); |
|
return FALSE; |
|
+ } |
|
+ |
|
+ rc = g_subprocess_get_exit_status (subprocess); |
|
+ if (rc != 0) { |
|
+ if (g_bytes_get_size (stderr_buf) == 0) { |
|
+ g_set_error_literal (error, G_IO_ERROR, rc, |
|
+ "Failed to run helper without stderr"); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ g_set_error (error, G_IO_ERROR, rc, |
|
+ "%.*s", |
|
+ g_bytes_get_size (stderr_buf), |
|
+ g_bytes_get_data (stderr_buf, NULL)); |
|
+ } |
|
|
|
/* FIXME: also do on error? */ |
|
if (!_client_register_stop (manager, error)) |
|
@@ -588,6 +608,9 @@ _client_register (GsdSubscriptionManager *manager, |
|
{ |
|
GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
g_autoptr(GSubprocess) subprocess = NULL; |
|
+ g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); |
|
+ g_autoptr(GBytes) stderr_buf = NULL; |
|
+ gint rc; |
|
|
|
/* fallback */ |
|
if (organisation == NULL) |
|
@@ -598,21 +621,38 @@ _client_register (GsdSubscriptionManager *manager, |
|
if (!_client_register_start (manager, error)) |
|
return FALSE; |
|
g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, |
|
+ error, |
|
"pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
"--kind", "register-with-username", |
|
"--address", priv->address, |
|
"--hostname", hostname, |
|
"--organisation", organisation, |
|
"--username", username, |
|
- "--password", password, |
|
NULL); |
|
if (subprocess == NULL) { |
|
g_prefix_error (error, "failed to find pkexec: "); |
|
return FALSE; |
|
} |
|
- if (!_client_subprocess_wait_check (subprocess, error)) |
|
+ |
|
+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { |
|
+ g_prefix_error (error, "failed to run pkexec: "); |
|
return FALSE; |
|
+ } |
|
+ |
|
+ rc = g_subprocess_get_exit_status (subprocess); |
|
+ if (rc != 0) { |
|
+ if (g_bytes_get_size (stderr_buf) == 0) { |
|
+ g_set_error_literal (error, G_IO_ERROR, rc, |
|
+ "Failed to run helper without stderr"); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ g_set_error (error, G_IO_ERROR, rc, |
|
+ "%.*s", |
|
+ g_bytes_get_size (stderr_buf), |
|
+ g_bytes_get_data (stderr_buf, NULL)); |
|
+ } |
|
|
|
/* FIXME: also do on error? */ |
|
if (!_client_register_stop (manager, error)) |
|
diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build |
|
index bfd073b6..e4b4589d 100644 |
|
--- a/plugins/subman/meson.build |
|
+++ b/plugins/subman/meson.build |
|
@@ -49,7 +49,7 @@ executable( |
|
'gsd-subman-helper', |
|
'gsd-subman-helper.c', |
|
include_directories: top_inc, |
|
- dependencies: [gio_dep, jsonglib_dep], |
|
+ dependencies: [gio_dep, gio_unix_dep, jsonglib_dep], |
|
install: true, |
|
install_rpath: gsd_pkglibdir, |
|
install_dir: gsd_libexecdir |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 590ad191dc3fec6c21dbfd22a5fc757a1409edbf Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Thu, 21 Jan 2021 09:52:19 -0500 |
|
Subject: [PATCH 09/19] subman: Don't treat failure to attach as fatal |
|
|
|
Many organizations don't require specific subscriptions to get |
|
updates (called "simple content access"). At the moment, |
|
those systems get an error when registering. |
|
|
|
This commit quiets the error. |
|
--- |
|
plugins/subman/gsd-subman-helper.c | 46 ++++++++++++++++++++++++------ |
|
1 file changed, 37 insertions(+), 9 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c |
|
index edf1e41f..53a4d56b 100644 |
|
--- a/plugins/subman/gsd-subman-helper.c |
|
+++ b/plugins/subman/gsd-subman-helper.c |
|
@@ -52,6 +52,17 @@ _helper_convert_error (const gchar *json_txt, GError **error) |
|
} |
|
json_root = json_parser_get_root (json_parser); |
|
json_obj = json_node_get_object (json_root); |
|
+ if (json_object_has_member (json_obj, "severity")) { |
|
+ const gchar *severity; |
|
+ |
|
+ /* warnings are non-fatal so we ignore them |
|
+ */ |
|
+ severity = json_object_get_string_member (json_obj, "severity"); |
|
+ if (g_strstr_len (severity, -1, "warning") != NULL) { |
|
+ return; |
|
+ } |
|
+ } |
|
+ |
|
if (!json_object_has_member (json_obj, "message")) { |
|
g_set_error (error, |
|
G_IO_ERROR, |
|
@@ -108,6 +119,7 @@ static gboolean |
|
_helper_auto_attach (GError **error) |
|
{ |
|
const gchar *str = NULL; |
|
+ g_autoptr(GError) error_local = NULL; |
|
g_autoptr(GDBusProxy) proxy = NULL; |
|
g_autoptr(GVariantBuilder) proxy_options = NULL; |
|
g_autoptr(GVariant) res = NULL; |
|
@@ -120,9 +132,12 @@ _helper_auto_attach (GError **error) |
|
"com.redhat.RHSM1", |
|
"/com/redhat/RHSM1/Attach", |
|
"com.redhat.RHSM1.Attach", |
|
- NULL, error); |
|
+ NULL, &error_local); |
|
if (proxy == NULL) { |
|
- g_prefix_error (error, "Failed to get proxy: "); |
|
+ g_dbus_error_strip_remote_error (error_local); |
|
+ g_propagate_prefixed_error (error, |
|
+ g_steal_pointer (&error_local), |
|
+ "Failed to get proxy: "); |
|
return FALSE; |
|
} |
|
proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); |
|
@@ -134,9 +149,18 @@ _helper_auto_attach (GError **error) |
|
locale), |
|
G_DBUS_CALL_FLAGS_NONE, |
|
DBUS_TIMEOUT, |
|
- NULL, error); |
|
- if (res == NULL) |
|
- return FALSE; |
|
+ NULL, &error_local); |
|
+ if (res == NULL) { |
|
+ g_dbus_error_strip_remote_error (error_local); |
|
+ _helper_convert_error (error_local->message, error); |
|
+ |
|
+ if (*error != NULL) { |
|
+ g_prefix_error (error, "Failed to get proxy: "); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ return TRUE; |
|
+ } |
|
g_variant_get (res, "(&s)", &str); |
|
g_debug ("Attach.AutoAttach: %s", str); |
|
return TRUE; |
|
@@ -325,8 +349,10 @@ main (int argc, char *argv[]) |
|
if (res == NULL) { |
|
g_dbus_error_strip_remote_error (error_local); |
|
_helper_convert_error (error_local->message, &error); |
|
- g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); |
|
- return error->code; |
|
+ if (error != NULL) { |
|
+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); |
|
+ return error->code; |
|
+ } |
|
} |
|
} else if (g_strcmp0 (kind, "register-with-username") == 0) { |
|
g_autoptr(GError) error_local = NULL; |
|
@@ -368,8 +394,10 @@ main (int argc, char *argv[]) |
|
if (res == NULL) { |
|
g_dbus_error_strip_remote_error (error_local); |
|
_helper_convert_error (error_local->message, &error); |
|
- g_printerr ("Failed to Register: %s\n", error->message); |
|
- return error->code; |
|
+ if (error != NULL) { |
|
+ g_printerr ("Failed to Register: %s\n", error->message); |
|
+ return error->code; |
|
+ } |
|
} |
|
} else { |
|
g_printerr ("Invalid --kind specified: %s\n", kind); |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 8c076516d48b5603132d3586a8040ef46011330f Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 11:24:36 -0500 |
|
Subject: [PATCH 10/19] subman: Add new no-installed-products state |
|
|
|
It's possible, though unlikley, the system has |
|
no packages installed from Red Hat supported package sets. |
|
|
|
This commit adds a new state to track that situation. |
|
--- |
|
plugins/subman/gsd-subman-common.c | 2 ++ |
|
plugins/subman/gsd-subman-common.h | 1 + |
|
plugins/subman/gsd-subscription-manager.c | 17 +++++++---------- |
|
3 files changed, 10 insertions(+), 10 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c |
|
index e515131e..eef5175d 100644 |
|
--- a/plugins/subman/gsd-subman-common.c |
|
+++ b/plugins/subman/gsd-subman-common.c |
|
@@ -32,5 +32,7 @@ gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) |
|
return "disabled"; |
|
if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) |
|
return "partially-valid"; |
|
+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS) |
|
+ return "no-installed-products"; |
|
return "unknown"; |
|
} |
|
diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h |
|
index fccf9f6a..f8a3d9f4 100644 |
|
--- a/plugins/subman/gsd-subman-common.h |
|
+++ b/plugins/subman/gsd-subman-common.h |
|
@@ -30,6 +30,7 @@ typedef enum { |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST |
|
} GsdSubmanSubscriptionStatus; |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 0838d490..46f8d35c 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -269,6 +269,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
|
|
/* save old value */ |
|
priv->subscription_status_last = priv->subscription_status; |
|
+ if (!_client_installed_products_update (manager, error)) |
|
+ goto out; |
|
+ |
|
+ if (priv->installed_products->len == 0) { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; |
|
+ goto out; |
|
+ } |
|
|
|
uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], |
|
"GetUuid", |
|
@@ -590,8 +597,6 @@ _client_register_with_keys (GsdSubscriptionManager *manager, |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
- if (!_client_installed_products_update (manager, error)) |
|
- return FALSE; |
|
_client_maybe__show_notification (manager); |
|
|
|
/* success */ |
|
@@ -659,8 +664,6 @@ _client_register (GsdSubscriptionManager *manager, |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
- if (!_client_installed_products_update (manager, error)) |
|
- return FALSE; |
|
_client_maybe__show_notification (manager); |
|
return TRUE; |
|
} |
|
@@ -741,10 +744,6 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, |
|
g_warning ("failed to update subscription status: %s", error->message); |
|
g_clear_error (&error); |
|
} |
|
- if (!_client_installed_products_update (manager, &error)) { |
|
- g_warning ("failed to update installed products: %s", error->message); |
|
- g_clear_error (&error); |
|
- } |
|
_client_maybe__show_notification (manager); |
|
} |
|
|
|
@@ -809,8 +808,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) |
|
return FALSE; |
|
if (!_client_subscription_status_update (manager, error)) |
|
return FALSE; |
|
- if (!_client_installed_products_update (manager, error)) |
|
- return FALSE; |
|
if (!_client_syspurpose_update (manager, error)) |
|
return FALSE; |
|
|
|
-- |
|
2.31.1 |
|
|
|
|
|
From fad6580e4cf9e7f350d0d537a064bbb439457540 Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 11:26:40 -0500 |
|
Subject: [PATCH 11/19] subman: Fix some build warnings |
|
|
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 8 ++++---- |
|
1 file changed, 4 insertions(+), 4 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 46f8d35c..1f9ca447 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -588,8 +588,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, |
|
|
|
g_set_error (error, G_IO_ERROR, rc, |
|
"%.*s", |
|
- g_bytes_get_size (stderr_buf), |
|
- g_bytes_get_data (stderr_buf, NULL)); |
|
+ (int) g_bytes_get_size (stderr_buf), |
|
+ (char *) g_bytes_get_data (stderr_buf, NULL)); |
|
} |
|
|
|
/* FIXME: also do on error? */ |
|
@@ -655,8 +655,8 @@ _client_register (GsdSubscriptionManager *manager, |
|
|
|
g_set_error (error, G_IO_ERROR, rc, |
|
"%.*s", |
|
- g_bytes_get_size (stderr_buf), |
|
- g_bytes_get_data (stderr_buf, NULL)); |
|
+ (int) g_bytes_get_size (stderr_buf), |
|
+ (char *) g_bytes_get_data (stderr_buf, NULL)); |
|
} |
|
|
|
/* FIXME: also do on error? */ |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 6c99ee2eee9a1be3765db5a7b80ae86a4444f00b Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 11:27:42 -0500 |
|
Subject: [PATCH 12/19] subman: Add DBus API to subscribe for updates on |
|
already registered system |
|
|
|
It's possible an admin may have registered their system without |
|
attaching any subscriptions to it. |
|
|
|
At the moment, gnome-settings-daemon only provides a way to register |
|
and subscribe in one step. |
|
|
|
This commit adds an API to support doing the last half of the process |
|
on its own. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 51 +++++++++++++++++++++++ |
|
1 file changed, 51 insertions(+) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 1f9ca447..705f8b11 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -46,6 +46,7 @@ static const gchar introspection_xml[] = |
|
" <arg type='a{sv}' name='options' direction='in'/>" |
|
" </method>" |
|
" <method name='Unregister'/>" |
|
+" <method name='Attach'/>" |
|
" <property name='InstalledProducts' type='aa{sv}' access='read'/>" |
|
" <property name='SubscriptionStatus' type='u' access='read'/>" |
|
" </interface>" |
|
@@ -696,6 +697,50 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) |
|
return TRUE; |
|
} |
|
|
|
+static gboolean |
|
+_client_attach (GsdSubscriptionManager *manager, |
|
+ GError **error) |
|
+{ |
|
+ g_autoptr(GSubprocess) subprocess = NULL; |
|
+ g_autoptr(GBytes) stderr_buf = NULL; |
|
+ gint rc; |
|
+ |
|
+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); |
|
+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, |
|
+ error, |
|
+ "pkexec", LIBEXECDIR "/gsd-subman-helper", |
|
+ "--kind", "auto-attach", |
|
+ NULL); |
|
+ if (subprocess == NULL) { |
|
+ g_prefix_error (error, "failed to find pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ if (!g_subprocess_communicate (subprocess, NULL, NULL, NULL, &stderr_buf, error)) { |
|
+ g_prefix_error (error, "failed to run pkexec: "); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ rc = g_subprocess_get_exit_status (subprocess); |
|
+ if (rc != 0) { |
|
+ if (g_bytes_get_size (stderr_buf) == 0) { |
|
+ g_set_error_literal (error, G_IO_ERROR, rc, |
|
+ "Failed to run helper without stderr"); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ g_set_error (error, G_IO_ERROR, rc, |
|
+ "%.*s", |
|
+ (int) g_bytes_get_size (stderr_buf), |
|
+ (char *) g_bytes_get_data (stderr_buf, NULL)); |
|
+ } |
|
+ |
|
+ if (!_client_subscription_status_update (manager, error)) |
|
+ return FALSE; |
|
+ _client_maybe__show_notification (manager); |
|
+ return TRUE; |
|
+} |
|
+ |
|
static gboolean |
|
_client_update_config (GsdSubscriptionManager *manager, GError **error) |
|
{ |
|
@@ -1029,6 +1074,12 @@ handle_method_call (GDBusConnection *connection, |
|
return; |
|
} |
|
g_dbus_method_invocation_return_value (invocation, NULL); |
|
+ } else if (g_strcmp0 (method_name, "Attach") == 0) { |
|
+ if (!_client_attach (manager, &error)) { |
|
+ g_dbus_method_invocation_return_gerror (invocation, error); |
|
+ return; |
|
+ } |
|
+ g_dbus_method_invocation_return_value (invocation, NULL); |
|
} else { |
|
g_assert_not_reached (); |
|
} |
|
-- |
|
2.31.1 |
|
|
|
|
|
From b340559f941ebd012711f357a8a0095776222d7a Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 11:34:03 -0500 |
|
Subject: [PATCH 13/19] subman: Improve subscription status handling |
|
|
|
This commit improves how subscription-manager status is |
|
parsed to give more detailed information about subscription |
|
state. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 33 +++++++++++++++++++---- |
|
1 file changed, 28 insertions(+), 5 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 705f8b11..6d80bfa9 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -289,6 +289,11 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
|
|
g_variant_get (uuid, "(&s)", &uuid_txt); |
|
|
|
+ if (uuid_txt[0] == '\0') { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
+ goto out; |
|
+ } |
|
+ |
|
status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], |
|
"GetStatus", |
|
g_variant_new ("(ss)", |
|
@@ -304,6 +309,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
return FALSE; |
|
json_root = json_parser_get_root (json_parser); |
|
json_obj = json_node_get_object (json_root); |
|
+ |
|
+ const gchar *status_id = NULL; |
|
+ |
|
+ if (json_object_has_member (json_obj, "status_id")) { |
|
+ status_id = json_object_get_string_member (json_obj, "status_id"); |
|
+ } |
|
+ |
|
if (!json_object_has_member (json_obj, "valid")) { |
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, |
|
"no Entitlement.GetStatus valid in %s", json_txt); |
|
@@ -312,16 +324,27 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
|
|
gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); |
|
|
|
- if (uuid_txt[0] != '\0') { |
|
- if (is_valid) { |
|
+ if (is_valid) { |
|
+ if (g_strcmp0 (status_id, "disabled") != 0) { |
|
priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; |
|
} else { |
|
- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; |
|
+ } |
|
+ goto out; |
|
+ } |
|
+ |
|
+ for (guint i = 0; i < priv->installed_products->len; i++) { |
|
+ ProductData *product = g_ptr_array_index (priv->installed_products, i); |
|
+ |
|
+ if (g_strcmp0 (product->status, "subscribed") == 0) { |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; |
|
+ goto out; |
|
} |
|
- } else { |
|
- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; |
|
} |
|
|
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; |
|
+ |
|
+out: |
|
/* emit notification for g-c-c */ |
|
if (priv->subscription_status != priv->subscription_status_last) { |
|
_emit_property_changed (manager, "SubscriptionStatus", |
|
-- |
|
2.31.1 |
|
|
|
|
|
From e2caf6d353dfe6e3314be9c2e604dd4c025d7dc1 Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 11:55:19 -0500 |
|
Subject: [PATCH 14/19] subman: Drop "LAST" from status enum |
|
|
|
It's unused, so get rid of it. |
|
--- |
|
plugins/subman/gsd-subman-common.h | 1 - |
|
1 file changed, 1 deletion(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h |
|
index f8a3d9f4..88226564 100644 |
|
--- a/plugins/subman/gsd-subman-common.h |
|
+++ b/plugins/subman/gsd-subman-common.h |
|
@@ -31,7 +31,6 @@ typedef enum { |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, |
|
- GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST |
|
} GsdSubmanSubscriptionStatus; |
|
|
|
const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 26ff144e7c5230f8b27a27e6eef5c109ae31ab0f Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Sun, 24 Jan 2021 12:41:20 -0500 |
|
Subject: [PATCH 15/19] subman: Clean up notification behavior |
|
|
|
Notifications were only displayed for some status transitions. |
|
|
|
This commit introduces some booleans based on the old and new |
|
statuses to make the code clearer and to make it easier to hit |
|
all the cases. |
|
--- |
|
plugins/subman/gsd-subman-common.h | 1 + |
|
plugins/subman/gsd-subscription-manager.c | 141 ++++++++++++++++++---- |
|
2 files changed, 120 insertions(+), 22 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h |
|
index 88226564..9397dbe4 100644 |
|
--- a/plugins/subman/gsd-subman-common.h |
|
+++ b/plugins/subman/gsd-subman-common.h |
|
@@ -25,6 +25,7 @@ |
|
G_BEGIN_DECLS |
|
|
|
typedef enum { |
|
+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ = -1, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, |
|
GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, |
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index 6d80bfa9..aaccbbc6 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -270,6 +270,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er |
|
|
|
/* save old value */ |
|
priv->subscription_status_last = priv->subscription_status; |
|
+ |
|
if (!_client_installed_products_update (manager, error)) |
|
goto out; |
|
|
|
@@ -512,55 +513,149 @@ static void |
|
_client_maybe__show_notification (GsdSubscriptionManager *manager) |
|
{ |
|
GsdSubscriptionManagerPrivate *priv = manager->priv; |
|
+ gboolean was_read, was_registered, had_subscriptions, needed_subscriptions; |
|
+ gboolean is_read, is_registered, has_subscriptions, needs_subscriptions; |
|
+ |
|
+ switch (priv->subscription_status_last) { |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: |
|
+ was_read = FALSE; |
|
+ was_registered = FALSE; |
|
+ needed_subscriptions = TRUE; |
|
+ had_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: |
|
+ was_read = TRUE; |
|
+ was_registered = FALSE; |
|
+ needed_subscriptions = TRUE; |
|
+ had_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: |
|
+ was_read = TRUE; |
|
+ was_registered = TRUE; |
|
+ needed_subscriptions = TRUE; |
|
+ had_subscriptions = TRUE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: |
|
+ was_read = TRUE; |
|
+ was_registered = TRUE; |
|
+ needed_subscriptions = TRUE; |
|
+ had_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: |
|
+ was_read = TRUE; |
|
+ was_registered = TRUE; |
|
+ needed_subscriptions = FALSE; |
|
+ had_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: |
|
+ was_read = TRUE; |
|
+ was_registered = TRUE; |
|
+ needed_subscriptions = TRUE; |
|
+ had_subscriptions = FALSE; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: |
|
+ was_read = TRUE; |
|
+ was_registered = FALSE; |
|
+ needed_subscriptions = FALSE; |
|
+ had_subscriptions = FALSE; |
|
+ break; |
|
+ } |
|
+ |
|
+ switch (priv->subscription_status) { |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: |
|
+ is_read = FALSE; |
|
+ is_registered = FALSE; |
|
+ needs_subscriptions = TRUE; |
|
+ has_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: |
|
+ is_read = TRUE; |
|
+ is_registered = FALSE; |
|
+ needs_subscriptions = TRUE; |
|
+ has_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: |
|
+ is_read = TRUE; |
|
+ is_registered = TRUE; |
|
+ needs_subscriptions = TRUE; |
|
+ has_subscriptions = TRUE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: |
|
+ is_read = TRUE; |
|
+ is_registered = TRUE; |
|
+ needs_subscriptions = TRUE; |
|
+ has_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: |
|
+ is_read = TRUE; |
|
+ is_registered = TRUE; |
|
+ needs_subscriptions = FALSE; |
|
+ has_subscriptions = FALSE; |
|
+ break; |
|
+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: |
|
+ is_read = TRUE; |
|
+ is_registered = FALSE; |
|
+ needs_subscriptions = FALSE; |
|
+ has_subscriptions = FALSE; |
|
+ break; |
|
+ } |
|
|
|
/* startup */ |
|
- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { |
|
+ if (!was_read && is_read && priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { |
|
_show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
return; |
|
} |
|
|
|
/* something changed */ |
|
- if (priv->subscription_status_last != priv->subscription_status) { |
|
+ if (was_read && is_read && priv->subscription_status_last != priv->subscription_status) { |
|
g_debug ("transisition from subscription status '%s' to '%s'", |
|
gsd_subman_subscription_status_to_string (priv->subscription_status_last), |
|
gsd_subman_subscription_status_to_string (priv->subscription_status)); |
|
|
|
- /* needs registration */ |
|
- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { |
|
- _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
+ /* needs subscription */ |
|
+ if (is_registered && needs_subscriptions && !has_subscriptions) { |
|
+ _show_notification (manager, _NOTIFY_EXPIRED); |
|
return; |
|
} |
|
|
|
/* was unregistered */ |
|
- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { |
|
+ if (was_registered && !is_registered) { |
|
_show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
return; |
|
} |
|
|
|
- /* registered */ |
|
- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && |
|
- g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { |
|
- _show_notification (manager, _NOTIFY_REGISTERED); |
|
- return; |
|
+ /* just registered */ |
|
+ if (!was_registered && is_registered) { |
|
+ if (!needs_subscriptions || has_subscriptions) { |
|
+ _show_notification (manager, _NOTIFY_REGISTERED); |
|
+ return; |
|
+ } |
|
+ } |
|
+ |
|
+ /* subscriptions changed */ |
|
+ if (was_registered && is_registered) { |
|
+ /* subscribed */ |
|
+ if (!had_subscriptions && |
|
+ needs_subscriptions && has_subscriptions) { |
|
+ _show_notification (manager, _NOTIFY_REGISTERED); |
|
+ return; |
|
+ } |
|
+ |
|
+ /* simple content access enabled */ |
|
+ if (needed_subscriptions && !had_subscriptions && !needs_subscriptions) { |
|
+ _show_notification (manager, _NOTIFY_REGISTERED); |
|
+ return; |
|
+ } |
|
} |
|
} |
|
|
|
/* nag again */ |
|
- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && |
|
+ if (!is_registered && |
|
g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
_show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); |
|
return; |
|
} |
|
- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && |
|
- g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
- _show_notification (manager, _NOTIFY_EXPIRED); |
|
- return; |
|
- } |
|
- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && |
|
+ if (is_registered && !has_subscriptions && needs_subscriptions && |
|
g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { |
|
_show_notification (manager, _NOTIFY_EXPIRED); |
|
return; |
|
@@ -941,6 +1036,8 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
|
|
priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); |
|
priv->timer_last_notified = g_timer_new (); |
|
+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; |
|
+ priv->subscription_status_last = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; |
|
|
|
/* expired */ |
|
priv->notification_expired = |
|
-- |
|
2.31.1 |
|
|
|
|
|
From e4ecab298c016127ab75634e1e04c6ff4eab3c4e Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Fri, 12 Feb 2021 14:51:29 +0100 |
|
Subject: [PATCH 16/19] subman: Update POTFILES.in |
|
|
|
--- |
|
po/POTFILES.in | 2 ++ |
|
1 file changed, 2 insertions(+) |
|
|
|
diff --git a/po/POTFILES.in b/po/POTFILES.in |
|
index e721f526..7d5b7e9d 100644 |
|
--- a/po/POTFILES.in |
|
+++ b/po/POTFILES.in |
|
@@ -24,6 +24,8 @@ plugins/print-notifications/gsd-printer.c |
|
plugins/print-notifications/gsd-print-notifications-manager.c |
|
plugins/smartcard/gsd-smartcard-manager.c |
|
plugins/smartcard/gsd-smartcard-service.c |
|
+plugins/subman/gsd-subscription-manager.c |
|
+plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in |
|
plugins/usb-protection/gsd-usb-protection-manager.c |
|
plugins/wacom/gsd-wacom-manager.c |
|
plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 0da1131d81b5ddee23d5afe9c21e8c0963180cc5 Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Mon, 6 Sep 2021 21:31:14 +0200 |
|
Subject: [PATCH 17/19] subman: Don't force X11 backend |
|
|
|
All of this should work just fine with Wayland. |
|
--- |
|
plugins/subman/main.c | 1 - |
|
1 file changed, 1 deletion(-) |
|
|
|
diff --git a/plugins/subman/main.c b/plugins/subman/main.c |
|
index 28ac995b..839c1b79 100644 |
|
--- a/plugins/subman/main.c |
|
+++ b/plugins/subman/main.c |
|
@@ -2,7 +2,6 @@ |
|
#define START gsd_subscription_manager_start |
|
#define STOP gsd_subscription_manager_stop |
|
#define MANAGER GsdSubscriptionManager |
|
-#define GDK_BACKEND "x11" |
|
#include "gsd-subscription-manager.h" |
|
|
|
#include "daemon-skeleton-gtk.h" |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 7b2f231fd6c87ca929bdd099177c53b14ccaaad5 Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Tue, 7 Sep 2021 13:08:12 +0200 |
|
Subject: [PATCH 18/19] subman: Fix desktop file hint for notifications |
|
|
|
We don't have a separate subman-panel. It's all part of |
|
info-overview-panel, as of now at least. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 6 +++--- |
|
1 file changed, 3 insertions(+), 3 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index aaccbbc6..be978fc3 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -1045,7 +1045,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
_("Add or renew a subscription to continue receiving software updates."), |
|
NULL); |
|
notify_notification_set_app_name (priv->notification_expired, _("Subscription")); |
|
- notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); |
|
notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); |
|
notify_notification_add_action (priv->notification_expired, |
|
@@ -1061,7 +1061,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
_("The system has been registered and software updates have been enabled."), |
|
NULL); |
|
notify_notification_set_app_name (priv->notification_registered, _("Subscription")); |
|
- notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); |
|
notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); |
|
g_signal_connect (priv->notification_registered, "closed", |
|
@@ -1073,7 +1073,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
_("Please register your system to receive software updates."), |
|
NULL); |
|
notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); |
|
- notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); |
|
+ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); |
|
notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); |
|
notify_notification_add_action (priv->notification_registration_required, |
|
-- |
|
2.31.1 |
|
|
|
|
|
From b610a954773262e60610c7732fbfeddbb3fa7fa0 Mon Sep 17 00:00:00 2001 |
|
From: Kalev Lember <klember@redhat.com> |
|
Date: Wed, 8 Sep 2021 13:25:07 +0200 |
|
Subject: [PATCH 19/19] subman: Use preferences-system icon for notifications |
|
|
|
Use it as a placeholder until we get a new icon for subscription |
|
management. |
|
--- |
|
plugins/subman/gsd-subscription-manager.c | 6 +++--- |
|
1 file changed, 3 insertions(+), 3 deletions(-) |
|
|
|
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c |
|
index be978fc3..dbb81098 100644 |
|
--- a/plugins/subman/gsd-subscription-manager.c |
|
+++ b/plugins/subman/gsd-subscription-manager.c |
|
@@ -1043,7 +1043,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
priv->notification_expired = |
|
notify_notification_new (_("Subscription Has Expired"), |
|
_("Add or renew a subscription to continue receiving software updates."), |
|
- NULL); |
|
+ "preferences-system"); |
|
notify_notification_set_app_name (priv->notification_expired, _("Subscription")); |
|
notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); |
|
@@ -1059,7 +1059,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
priv->notification_registered = |
|
notify_notification_new (_("Registration Successful"), |
|
_("The system has been registered and software updates have been enabled."), |
|
- NULL); |
|
+ "preferences-system"); |
|
notify_notification_set_app_name (priv->notification_registered, _("Subscription")); |
|
notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); |
|
@@ -1071,7 +1071,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) |
|
priv->notification_registration_required = |
|
notify_notification_new (_("System Not Registered"), |
|
_("Please register your system to receive software updates."), |
|
- NULL); |
|
+ "preferences-system"); |
|
notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); |
|
notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); |
|
notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); |
|
-- |
|
2.31.1 |
|
|
|
|