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

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