Blame SOURCES/0003-account-display-nag-screen-periodically.patch

fbd155
From 31844edad70876e26ab995179bc67fb3b23a1793 Mon Sep 17 00:00:00 2001
fbd155
From: Ray Strode <rstrode@redhat.com>
fbd155
Date: Mon, 6 Nov 2017 16:39:55 -0500
fbd155
Subject: [PATCH 3/4] account: display nag screen periodically
fbd155
fbd155
This is configurable via a gsettings key.
fbd155
---
fbd155
 data/meson.build                              |  1 +
fbd155
 ...ings-daemon.plugins.account.gschema.xml.in |  9 +++
fbd155
 plugins/account/gsd-account-manager.c         | 55 +++++++++++++++++++
fbd155
 3 files changed, 65 insertions(+)
fbd155
 create mode 100644 data/org.gnome.settings-daemon.plugins.account.gschema.xml.in
fbd155
fbd155
diff --git a/data/meson.build b/data/meson.build
fbd155
index e93ba641..5a2cd5a7 100644
fbd155
--- a/data/meson.build
fbd155
+++ b/data/meson.build
fbd155
@@ -1,36 +1,37 @@
fbd155
 data_inc = include_directories('.')
fbd155
 
fbd155
 schemas = [
fbd155
   'org.gnome.settings-daemon.peripherals.gschema.xml',
fbd155
   'org.gnome.settings-daemon.peripherals.wacom.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.gschema.xml',
fbd155
+  'org.gnome.settings-daemon.plugins.account.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.color.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.housekeeping.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.media-keys.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.power.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.sharing.gschema.xml',
fbd155
   'org.gnome.settings-daemon.plugins.xsettings.gschema.xml'
fbd155
 ]
fbd155
 
fbd155
 schema_conf = configuration_data()
fbd155
 schema_conf.set('GETTEXT_PACKAGE', meson.project_name())
fbd155
 
fbd155
 schemas_xml = []
fbd155
 foreach schema: schemas
fbd155
   schemas_xml += [configure_file(
fbd155
     input: schema + '.in',
fbd155
     output: schema,
fbd155
     configuration: schema_conf,
fbd155
     install: true,
fbd155
     install_dir: gsd_schemadir
fbd155
   )]
fbd155
 endforeach
fbd155
 
fbd155
 enums_header = files('gsd-enums.h')
fbd155
 
fbd155
 mkenums = gnome.mkenums(
fbd155
   'org.gnome.settings-daemon.enums.xml',
fbd155
   sources: enums_header,
fbd155
   comments: '',
fbd155
   fhead: '<schemalist>',
fbd155
   vhead: '  <@type@ id="org.gnome.settings-daemon.@EnumName@">',
fbd155
diff --git a/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in b/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in
fbd155
new file mode 100644
fbd155
index 00000000..f3d59e81
fbd155
--- /dev/null
fbd155
+++ b/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in
fbd155
@@ -0,0 +1,9 @@
fbd155
+<schemalist>
fbd155
+  <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.account" path="/org/gnome/settings-daemon/plugins/account/">
fbd155
+    <key name="notify-period" type="i">
fbd155
+      <default>1440</default>
fbd155
+      <summary>Time before repeated warning about account password expiration</summary>
fbd155
+      <description>If a user's account is expiring, a notification will get displayed periodically after the specified number of minutes</description>
fbd155
+    </key>
fbd155
+  </schema>
fbd155
+</schemalist>
fbd155
diff --git a/plugins/account/gsd-account-manager.c b/plugins/account/gsd-account-manager.c
fbd155
index cb37f466..ff054edd 100644
fbd155
--- a/plugins/account/gsd-account-manager.c
fbd155
+++ b/plugins/account/gsd-account-manager.c
fbd155
@@ -20,126 +20,135 @@
fbd155
 #include "config.h"
fbd155
 
fbd155
 #include <sys/types.h>
fbd155
 #include <sys/wait.h>
fbd155
 #include <stdlib.h>
fbd155
 #include <stdio.h>
fbd155
 #include <unistd.h>
fbd155
 #include <string.h>
fbd155
 #include <errno.h>
fbd155
 
fbd155
 #include <locale.h>
fbd155
 
fbd155
 #include <glib.h>
fbd155
 #include <glib/gi18n.h>
fbd155
 #include <glib/gstdio.h>
fbd155
 
fbd155
 #include <cups/cups.h>
fbd155
 #include <cups/ppd.h>
fbd155
 #include <libnotify/notify.h>
fbd155
 
fbd155
 #include "gnome-settings-profile.h"
fbd155
 #include "gnome-settings-bus.h"
fbd155
 #include "gsd-account-manager.h"
fbd155
 #include "org.freedesktop.Accounts.h"
fbd155
 #include "org.freedesktop.Accounts.User.h"
fbd155
 
fbd155
 #define GSD_ACCOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_ACCOUNT_MANAGER, GsdAccountManagerPrivate))
fbd155
 
fbd155
 struct GsdAccountManagerPrivate
fbd155
 {
fbd155
+        GSettings            *settings;
fbd155
+
fbd155
         GsdAccounts          *accounts_proxy;
fbd155
         GsdAccountsUser      *accounts_user_proxy;
fbd155
         GCancellable         *cancellable;
fbd155
 
fbd155
         GsdScreenSaver       *screensaver_proxy;
fbd155
 
fbd155
         gint64                expiration_time;
fbd155
         gint64                last_change_time;
fbd155
         gint64                min_days_between_changes;
fbd155
         gint64                max_days_between_changes;
fbd155
         gint64                days_to_warn;
fbd155
         gint64                days_after_expiration_until_lock;
fbd155
 
fbd155
         NotifyNotification   *notification;
fbd155
+
fbd155
+        gint64                last_notify_time;
fbd155
+        int                   notify_period;
fbd155
+        guint                 notify_period_timeout_id;
fbd155
 };
fbd155
 
fbd155
 static void     gsd_account_manager_class_init  (GsdAccountManagerClass *klass);
fbd155
 static void     gsd_account_manager_init        (GsdAccountManager      *account_manager);
fbd155
 static void     gsd_account_manager_finalize    (GObject                *object);
fbd155
+static void     fetch_password_expiration_policy (GsdAccountManager *manager);
fbd155
 
fbd155
 G_DEFINE_TYPE (GsdAccountManager, gsd_account_manager, G_TYPE_OBJECT)
fbd155
 
fbd155
 static gpointer manager_object = NULL;
fbd155
 
fbd155
 static void
fbd155
 on_notification_closed (NotifyNotification *notification,
fbd155
                         gpointer            user_data)
fbd155
 {
fbd155
         GsdAccountManager *manager = user_data;
fbd155
 
fbd155
         g_clear_object (&manager->priv->notification);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 hide_notification (GsdAccountManager *manager)
fbd155
 {
fbd155
         if (manager->priv->notification == NULL)
fbd155
                 return;
fbd155
 
fbd155
         notify_notification_close (manager->priv->notification, NULL);
fbd155
         g_clear_object (&manager->priv->notification);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 show_notification (GsdAccountManager *manager,
fbd155
                    const char        *primary_text,
fbd155
                    const char        *secondary_text)
fbd155
 {
fbd155
         g_assert (manager->priv->notification == NULL);
fbd155
 
fbd155
         manager->priv->notification = notify_notification_new (primary_text,
fbd155
                                                                secondary_text,
fbd155
                                                                "avatar-default-symbolic");
fbd155
         notify_notification_set_app_name (manager->priv->notification, _("User Account"));
fbd155
         notify_notification_set_hint (manager->priv->notification,
fbd155
                                       "resident",
fbd155
                                       g_variant_new_boolean (TRUE));
fbd155
         notify_notification_set_timeout (manager->priv->notification,
fbd155
                                          NOTIFY_EXPIRES_NEVER);
fbd155
 
fbd155
         g_signal_connect (manager->priv->notification,
fbd155
                           "closed",
fbd155
                           G_CALLBACK (on_notification_closed),
fbd155
                           manager);
fbd155
 
fbd155
         notify_notification_show (manager->priv->notification, NULL);
fbd155
+
fbd155
+        manager->priv->last_notify_time = g_get_monotonic_time ();
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 update_password_notification (GsdAccountManager *manager)
fbd155
 {
fbd155
         gint64           days_since_epoch;
fbd155
         gint64           days_until_expiration = -1;
fbd155
         gint64           days_since_last_change = -1;
fbd155
         gint64           days_left = -1;
fbd155
         g_autofree char *primary_text = NULL;
fbd155
         g_autofree char *secondary_text = NULL;
fbd155
         gboolean         password_already_expired = FALSE;
fbd155
 
fbd155
         hide_notification (manager);
fbd155
 
fbd155
         days_since_epoch = g_get_real_time () / G_USEC_PER_SEC / 60 / 60 / 24;
fbd155
 
fbd155
         if (manager->priv->expiration_time > 0) {
fbd155
                 days_until_expiration = manager->priv->expiration_time - days_since_epoch;
fbd155
 
fbd155
                 if (days_until_expiration <= 0) {
fbd155
                         password_already_expired = TRUE;
fbd155
                         goto out;
fbd155
                 }
fbd155
         }
fbd155
 
fbd155
         if (manager->priv->last_change_time == 0) {
fbd155
                 password_already_expired = TRUE;
fbd155
                 goto out;
fbd155
         }
fbd155
@@ -181,99 +190,127 @@ out:
fbd155
                 primary_text = g_strdup_printf (_("Password Expired"));
fbd155
                 secondary_text = g_strdup_printf (_("Your password is expired. Please update it."));
fbd155
         } else if (days_left >= 0) {
fbd155
                 primary_text = g_strdup_printf (_("Password Expiring Soon"));
fbd155
                 if (days_left == 0)
fbd155
                     secondary_text = g_strdup_printf (_("Your password is expiring today."));
fbd155
                 else if (days_left == 1)
fbd155
                     secondary_text = g_strdup_printf (_("Your password is expiring in a day."));
fbd155
                 else
fbd155
                     secondary_text = g_strdup_printf (_("Your password is expiring in %ld days."),
fbd155
                                                       days_left);
fbd155
         }
fbd155
 
fbd155
         if (primary_text != NULL && secondary_text != NULL)
fbd155
                 show_notification (manager,
fbd155
                                    primary_text,
fbd155
                                    secondary_text);
fbd155
 }
fbd155
 
fbd155
 static gboolean
fbd155
 set_policy_number (gint64 *destination,
fbd155
                    gint64  source)
fbd155
 {
fbd155
         if (*destination == source)
fbd155
                 return FALSE;
fbd155
 
fbd155
         *destination = source;
fbd155
         return TRUE;
fbd155
 }
fbd155
 
fbd155
+static gboolean
fbd155
+on_notify_period_elapsed (GsdAccountManager *manager)
fbd155
+{
fbd155
+        manager->priv->notify_period_timeout_id = 0;
fbd155
+        fetch_password_expiration_policy (manager);
fbd155
+        return G_SOURCE_REMOVE;
fbd155
+}
fbd155
+
fbd155
+static void
fbd155
+queue_periodic_timeout (GsdAccountManager *manager)
fbd155
+{
fbd155
+        if (manager->priv->notify_period_timeout_id != 0) {
fbd155
+                g_source_remove (manager->priv->notify_period_timeout_id);
fbd155
+                manager->priv->notify_period_timeout_id = 0;
fbd155
+        }
fbd155
+
fbd155
+        if (manager->priv->notify_period > 0) {
fbd155
+                gint64 already_elapsed_time;
fbd155
+
fbd155
+                already_elapsed_time = MAX (0, (g_get_monotonic_time () - manager->priv->last_notify_time) / G_USEC_PER_SEC);
fbd155
+
fbd155
+                manager->priv->notify_period_timeout_id = g_timeout_add_seconds (MAX (0, manager->priv->notify_period * 60 - already_elapsed_time),
fbd155
+                                                                                 (GSourceFunc) on_notify_period_elapsed,
fbd155
+                                                                                 manager);
fbd155
+        }
fbd155
+}
fbd155
+
fbd155
 static void
fbd155
 on_got_password_expiration_policy (GsdAccountsUser *accounts_user_proxy,
fbd155
                                    GAsyncResult    *res,
fbd155
                                    gpointer         user_data)
fbd155
 {
fbd155
         GsdAccountManager *manager = user_data;
fbd155
         g_autoptr(GError)  error = NULL;
fbd155
         gboolean           succeeded;
fbd155
         gint64             expiration_time;
fbd155
         gint64             last_change_time;
fbd155
         gint64             min_days_between_changes;
fbd155
         gint64             max_days_between_changes;
fbd155
         gint64             days_to_warn;
fbd155
         gint64             days_after_expiration_until_lock;
fbd155
 
fbd155
         gnome_settings_profile_start (NULL);
fbd155
         succeeded = gsd_accounts_user_call_get_password_expiration_policy_finish (accounts_user_proxy,
fbd155
                                                                                   &expiration_time,
fbd155
                                                                                   &last_change_time,
fbd155
                                                                                   &min_days_between_changes,
fbd155
                                                                                   &max_days_between_changes,
fbd155
                                                                                   &days_to_warn,
fbd155
                                                                                   &days_after_expiration_until_lock,
fbd155
                                                                                   res,
fbd155
                                                                                   &error);
fbd155
 
fbd155
         if (!succeeded) {
fbd155
                 g_warning ("Failed to get password expiration policy for user: %s", error->message);
fbd155
                 goto out;
fbd155
         }
fbd155
 
fbd155
         set_policy_number (&manager->priv->expiration_time, expiration_time);
fbd155
         set_policy_number (&manager->priv->last_change_time, last_change_time);
fbd155
         set_policy_number (&manager->priv->min_days_between_changes, min_days_between_changes);
fbd155
         set_policy_number (&manager->priv->max_days_between_changes, max_days_between_changes);
fbd155
         set_policy_number (&manager->priv->days_to_warn, days_to_warn);
fbd155
         set_policy_number (&manager->priv->days_after_expiration_until_lock, days_after_expiration_until_lock);
fbd155
 
fbd155
         update_password_notification (manager);
fbd155
+        queue_periodic_timeout (manager);
fbd155
 out:
fbd155
         gnome_settings_profile_end (NULL);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 fetch_password_expiration_policy (GsdAccountManager *manager)
fbd155
 {
fbd155
         gsd_accounts_user_call_get_password_expiration_policy (manager->priv->accounts_user_proxy,
fbd155
                                                                manager->priv->cancellable,
fbd155
                                                                (GAsyncReadyCallback)
fbd155
                                                                on_got_password_expiration_policy,
fbd155
                                                                manager);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 on_screensaver_signal (GDBusProxy  *proxy,
fbd155
                        const gchar *sender_name,
fbd155
                        const gchar *signal_name,
fbd155
                        GVariant    *parameters,
fbd155
                        gpointer     user_data)
fbd155
 {
fbd155
         GsdAccountManager *manager = user_data;
fbd155
 
fbd155
         if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
fbd155
                 gboolean active;
fbd155
 
fbd155
                 g_variant_get (parameters, "(b)", &active);
fbd155
 
fbd155
                 if (!active) {
fbd155
                         fetch_password_expiration_policy (manager);
fbd155
@@ -346,91 +383,109 @@ on_got_user_object_path (GsdAccounts  *accounts_proxy,
fbd155
                                      manager);
fbd155
 
fbd155
 out:
fbd155
         gnome_settings_profile_end (NULL);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 on_got_accounts_proxy (GObject      *source_object,
fbd155
                        GAsyncResult *res,
fbd155
                        gpointer      user_data)
fbd155
 {
fbd155
         GsdAccountManager *manager = user_data;
fbd155
         g_autoptr(GError)  error = NULL;
fbd155
 
fbd155
         gnome_settings_profile_start (NULL);
fbd155
         manager->priv->accounts_proxy = gsd_accounts_proxy_new_for_bus_finish (res, &error);
fbd155
 
fbd155
         if (manager->priv->accounts_proxy != NULL) {
fbd155
                 gsd_accounts_call_find_user_by_id (manager->priv->accounts_proxy,
fbd155
                                                    getuid (),
fbd155
                                                    manager->priv->cancellable,
fbd155
                                                    (GAsyncReadyCallback)
fbd155
                                                    on_got_user_object_path,
fbd155
                                                    manager);
fbd155
         } else {
fbd155
                 g_warning ("Failed to get proxy to accounts service: %s", error->message);
fbd155
         }
fbd155
         gnome_settings_profile_end (NULL);
fbd155
 }
fbd155
 
fbd155
+static void
fbd155
+on_notify_period_changed (GsdAccountManager *manager)
fbd155
+{
fbd155
+        manager->priv->notify_period = g_settings_get_int (manager->priv->settings, "notify-period");
fbd155
+
fbd155
+        queue_periodic_timeout (manager);
fbd155
+}
fbd155
+
fbd155
 gboolean
fbd155
 gsd_account_manager_start (GsdAccountManager  *manager,
fbd155
                            GError            **error)
fbd155
 {
fbd155
         g_debug ("Starting accounts manager");
fbd155
 
fbd155
         gnome_settings_profile_start (NULL);
fbd155
         manager->priv->cancellable = g_cancellable_new ();
fbd155
+        manager->priv->settings = g_settings_new ("org.gnome.settings-daemon.plugins.account");
fbd155
+
fbd155
+        manager->priv->notify_period = g_settings_get_int (manager->priv->settings, "notify-period");
fbd155
+        g_signal_connect_object (G_OBJECT (manager->priv->settings),
fbd155
+                          "changed::notify-period",
fbd155
+                          G_CALLBACK (on_notify_period_changed),
fbd155
+                          manager,
fbd155
+                          G_CONNECT_SWAPPED);
fbd155
+
fbd155
         gsd_accounts_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
fbd155
                                         G_DBUS_PROXY_FLAGS_NONE,
fbd155
                                         "org.freedesktop.Accounts",
fbd155
                                         "/org/freedesktop/Accounts",
fbd155
                                         manager->priv->cancellable,
fbd155
                                         (GAsyncReadyCallback)
fbd155
                                         on_got_accounts_proxy,
fbd155
                                         manager);
fbd155
         gnome_settings_profile_end (NULL);
fbd155
 
fbd155
         return TRUE;
fbd155
 }
fbd155
 
fbd155
 void
fbd155
 gsd_account_manager_stop (GsdAccountManager *manager)
fbd155
 {
fbd155
         g_debug ("Stopping accounts manager");
fbd155
 
fbd155
         if (manager->priv->cancellable != NULL) {
fbd155
                 g_cancellable_cancel (manager->priv->cancellable);
fbd155
                 g_clear_object (&manager->priv->cancellable);
fbd155
         }
fbd155
 
fbd155
+        g_clear_object (&manager->priv->settings);
fbd155
         g_clear_object (&manager->priv->accounts_proxy);
fbd155
         g_clear_object (&manager->priv->accounts_user_proxy);
fbd155
         g_clear_object (&manager->priv->notification);
fbd155
         g_clear_object (&manager->priv->screensaver_proxy);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 gsd_account_manager_class_init (GsdAccountManagerClass *klass)
fbd155
 {
fbd155
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
fbd155
 
fbd155
         object_class->finalize = gsd_account_manager_finalize;
fbd155
 
fbd155
         notify_init ("gnome-settings-daemon");
fbd155
 
fbd155
         g_type_class_add_private (klass, sizeof (GsdAccountManagerPrivate));
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 gsd_account_manager_init (GsdAccountManager *manager)
fbd155
 {
fbd155
         manager->priv = GSD_ACCOUNT_MANAGER_GET_PRIVATE (manager);
fbd155
 }
fbd155
 
fbd155
 static void
fbd155
 gsd_account_manager_finalize (GObject *object)
fbd155
 {
fbd155
         GsdAccountManager *manager;
fbd155
 
fbd155
         g_return_if_fail (object != NULL);
fbd155
-- 
fbd155
2.21.0
fbd155