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.
476 lines
18 KiB
476 lines
18 KiB
7 years ago
|
From 457ca3295017c34c6805c9dd18599b760705afc5 Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Mon, 6 Nov 2017 16:39:55 -0500
|
||
|
Subject: [PATCH 3/3] account: display nag screen periodically
|
||
|
|
||
|
This is configurable via a gsettings key.
|
||
|
---
|
||
|
configure.ac | 1 +
|
||
|
...ttings-daemon.plugins.account.gschema.xml.in.in | 9 ++++
|
||
|
plugins/account/gsd-account-manager.c | 55 ++++++++++++++++++++++
|
||
|
3 files changed, 65 insertions(+)
|
||
|
create mode 100644 data/org.gnome.settings-daemon.plugins.account.gschema.xml.in.in
|
||
|
|
||
|
diff --git a/configure.ac b/configure.ac
|
||
|
index 5bd742e5..ed5374db 100644
|
||
|
--- a/configure.ac
|
||
|
+++ b/configure.ac
|
||
|
@@ -508,60 +508,61 @@ AC_SUBST(DEBUG_CFLAGS)
|
||
|
|
||
|
AC_CONFIG_FILES([
|
||
|
Makefile
|
||
|
gnome-settings-daemon/Makefile
|
||
|
plugins/Makefile
|
||
|
plugins/a11y-keyboard/Makefile
|
||
|
plugins/a11y-settings/Makefile
|
||
|
plugins/account/Makefile
|
||
|
plugins/clipboard/Makefile
|
||
|
plugins/color/Makefile
|
||
|
plugins/common/Makefile
|
||
|
plugins/datetime/Makefile
|
||
|
plugins/dummy/Makefile
|
||
|
plugins/power/Makefile
|
||
|
plugins/housekeeping/Makefile
|
||
|
plugins/keyboard/Makefile
|
||
|
plugins/media-keys/Makefile
|
||
|
plugins/media-keys/gvc/Makefile
|
||
|
plugins/mouse/Makefile
|
||
|
plugins/print-notifications/Makefile
|
||
|
plugins/rfkill/Makefile
|
||
|
plugins/screensaver-proxy/Makefile
|
||
|
plugins/sharing/Makefile
|
||
|
plugins/smartcard/Makefile
|
||
|
plugins/sound/Makefile
|
||
|
plugins/wacom/Makefile
|
||
|
plugins/xsettings/Makefile
|
||
|
data/Makefile
|
||
|
data/gnome-settings-daemon.pc
|
||
|
data/org.gnome.settings-daemon.plugins.gschema.xml.in
|
||
|
+data/org.gnome.settings-daemon.plugins.account.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.color.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.media-keys.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.peripherals.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.plugins.sharing.gschema.xml.in
|
||
|
data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in
|
||
|
po/Makefile.in
|
||
|
tests/Makefile
|
||
|
])
|
||
|
AC_OUTPUT
|
||
|
|
||
|
dnl ---------------------------------------------------------------------------
|
||
|
dnl - Show summary
|
||
|
dnl ---------------------------------------------------------------------------
|
||
|
|
||
|
echo "
|
||
|
gnome-settings-daemon $VERSION
|
||
|
=============================
|
||
|
|
||
|
prefix: ${prefix}
|
||
|
exec_prefix: ${exec_prefix}
|
||
|
libdir: ${libdir}
|
||
|
bindir: ${bindir}
|
||
|
sbindir: ${sbindir}
|
||
|
sysconfdir: ${sysconfdir}
|
||
|
sysconfsubdir: ${sysconfsubdir}
|
||
|
localstatedir: ${localstatedir}
|
||
|
plugindir: ${plugindir}
|
||
|
diff --git a/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in.in
|
||
|
new file mode 100644
|
||
|
index 00000000..0b3a9d97
|
||
|
--- /dev/null
|
||
|
+++ b/data/org.gnome.settings-daemon.plugins.account.gschema.xml.in.in
|
||
|
@@ -0,0 +1,9 @@
|
||
|
+<schemalist>
|
||
|
+ <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.account" path="/org/gnome/settings-daemon/plugins/account/">
|
||
|
+ <key name="notify-period" type="i">
|
||
|
+ <default>1440</default>
|
||
|
+ <_summary>Time before repeated warning about account password expiration</_summary>
|
||
|
+ <_description>If a user's account is expiring, a notification will get displayed periodically after the specified number of minutes</_description>
|
||
|
+ </key>
|
||
|
+ </schema>
|
||
|
+</schemalist>
|
||
|
diff --git a/plugins/account/gsd-account-manager.c b/plugins/account/gsd-account-manager.c
|
||
|
index 948679b1..f6db04f8 100644
|
||
|
--- a/plugins/account/gsd-account-manager.c
|
||
|
+++ b/plugins/account/gsd-account-manager.c
|
||
|
@@ -20,126 +20,135 @@
|
||
|
#include "config.h"
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/wait.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include <locale.h>
|
||
|
|
||
|
#include <glib.h>
|
||
|
#include <glib/gi18n.h>
|
||
|
#include <glib/gstdio.h>
|
||
|
|
||
|
#include <cups/cups.h>
|
||
|
#include <cups/ppd.h>
|
||
|
#include <libnotify/notify.h>
|
||
|
|
||
|
#include "gnome-settings-profile.h"
|
||
|
#include "gnome-settings-bus.h"
|
||
|
#include "gsd-account-manager.h"
|
||
|
#include "org.freedesktop.Accounts.h"
|
||
|
#include "org.freedesktop.Accounts.User.h"
|
||
|
|
||
|
#define GSD_ACCOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_ACCOUNT_MANAGER, GsdAccountManagerPrivate))
|
||
|
|
||
|
struct GsdAccountManagerPrivate
|
||
|
{
|
||
|
+ GSettings *settings;
|
||
|
+
|
||
|
GsdAccounts *accounts_proxy;
|
||
|
GsdAccountsUser *accounts_user_proxy;
|
||
|
GCancellable *cancellable;
|
||
|
|
||
|
GsdScreenSaver *screensaver_proxy;
|
||
|
|
||
|
gint64 expiration_time;
|
||
|
gint64 last_change_time;
|
||
|
gint64 min_days_between_changes;
|
||
|
gint64 max_days_between_changes;
|
||
|
gint64 days_to_warn;
|
||
|
gint64 days_after_expiration_until_lock;
|
||
|
|
||
|
NotifyNotification *notification;
|
||
|
+
|
||
|
+ gint64 last_notify_time;
|
||
|
+ int notify_period;
|
||
|
+ guint notify_period_timeout_id;
|
||
|
};
|
||
|
|
||
|
static void gsd_account_manager_class_init (GsdAccountManagerClass *klass);
|
||
|
static void gsd_account_manager_init (GsdAccountManager *account_manager);
|
||
|
static void gsd_account_manager_finalize (GObject *object);
|
||
|
+static void fetch_password_expiration_policy (GsdAccountManager *manager);
|
||
|
|
||
|
G_DEFINE_TYPE (GsdAccountManager, gsd_account_manager, G_TYPE_OBJECT)
|
||
|
|
||
|
static gpointer manager_object = NULL;
|
||
|
|
||
|
static void
|
||
|
on_notification_closed (NotifyNotification *notification,
|
||
|
gpointer user_data)
|
||
|
{
|
||
|
GsdAccountManager *manager = user_data;
|
||
|
|
||
|
g_clear_object (&manager->priv->notification);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
hide_notification (GsdAccountManager *manager)
|
||
|
{
|
||
|
if (manager->priv->notification == NULL)
|
||
|
return;
|
||
|
|
||
|
notify_notification_close (manager->priv->notification, NULL);
|
||
|
g_clear_object (&manager->priv->notification);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
show_notification (GsdAccountManager *manager,
|
||
|
const char *primary_text,
|
||
|
const char *secondary_text)
|
||
|
{
|
||
|
g_assert (manager->priv->notification == NULL);
|
||
|
|
||
|
manager->priv->notification = notify_notification_new (primary_text,
|
||
|
secondary_text,
|
||
|
"avatar-default-symbolic");
|
||
|
notify_notification_set_app_name (manager->priv->notification, _("User Account"));
|
||
|
notify_notification_set_hint (manager->priv->notification,
|
||
|
"resident",
|
||
|
g_variant_new_boolean (TRUE));
|
||
|
notify_notification_set_timeout (manager->priv->notification,
|
||
|
NOTIFY_EXPIRES_NEVER);
|
||
|
|
||
|
g_signal_connect (manager->priv->notification,
|
||
|
"closed",
|
||
|
G_CALLBACK (on_notification_closed),
|
||
|
manager);
|
||
|
|
||
|
notify_notification_show (manager->priv->notification, NULL);
|
||
|
+
|
||
|
+ manager->priv->last_notify_time = g_get_monotonic_time ();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
update_password_notification (GsdAccountManager *manager)
|
||
|
{
|
||
|
gint64 days_since_epoch;
|
||
|
gint64 days_until_expiration = -1;
|
||
|
gint64 days_since_last_change = -1;
|
||
|
gint64 days_left = -1;
|
||
|
g_autofree char *primary_text = NULL;
|
||
|
g_autofree char *secondary_text = NULL;
|
||
|
gboolean password_already_expired = FALSE;
|
||
|
|
||
|
hide_notification (manager);
|
||
|
|
||
|
days_since_epoch = g_get_real_time () / G_USEC_PER_SEC / 60 / 60 / 24;
|
||
|
|
||
|
if (manager->priv->expiration_time > 0) {
|
||
|
days_until_expiration = manager->priv->expiration_time - days_since_epoch;
|
||
|
|
||
|
if (days_until_expiration <= 0) {
|
||
|
password_already_expired = TRUE;
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (manager->priv->last_change_time == 0) {
|
||
|
password_already_expired = TRUE;
|
||
|
goto out;
|
||
|
}
|
||
|
@@ -181,99 +190,127 @@ out:
|
||
|
primary_text = g_strdup_printf (_("Password Expired"));
|
||
|
secondary_text = g_strdup_printf (_("Your password is expired. Please update it."));
|
||
|
} else if (days_left >= 0) {
|
||
|
primary_text = g_strdup_printf (_("Password Expiring Soon"));
|
||
|
if (days_left == 0)
|
||
|
secondary_text = g_strdup_printf (_("Your password is expiring today."));
|
||
|
else if (days_left == 1)
|
||
|
secondary_text = g_strdup_printf (_("Your password is expiring in a day."));
|
||
|
else
|
||
|
secondary_text = g_strdup_printf (_("Your password is expiring in %ld days."),
|
||
|
days_left);
|
||
|
}
|
||
|
|
||
|
if (primary_text != NULL && secondary_text != NULL)
|
||
|
show_notification (manager,
|
||
|
primary_text,
|
||
|
secondary_text);
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
set_policy_number (gint64 *destination,
|
||
|
gint64 source)
|
||
|
{
|
||
|
if (*destination == source)
|
||
|
return FALSE;
|
||
|
|
||
|
*destination = source;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+static gboolean
|
||
|
+on_notify_period_elapsed (GsdAccountManager *manager)
|
||
|
+{
|
||
|
+ manager->priv->notify_period_timeout_id = 0;
|
||
|
+ fetch_password_expiration_policy (manager);
|
||
|
+ return G_SOURCE_REMOVE;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+queue_periodic_timeout (GsdAccountManager *manager)
|
||
|
+{
|
||
|
+ if (manager->priv->notify_period_timeout_id != 0) {
|
||
|
+ g_source_remove (manager->priv->notify_period_timeout_id);
|
||
|
+ manager->priv->notify_period_timeout_id = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (manager->priv->notify_period > 0) {
|
||
|
+ gint64 already_elapsed_time;
|
||
|
+
|
||
|
+ already_elapsed_time = MAX (0, (g_get_monotonic_time () - manager->priv->last_notify_time) / G_USEC_PER_SEC);
|
||
|
+
|
||
|
+ manager->priv->notify_period_timeout_id = g_timeout_add_seconds (MAX (0, manager->priv->notify_period * 60 - already_elapsed_time),
|
||
|
+ (GSourceFunc) on_notify_period_elapsed,
|
||
|
+ manager);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
on_got_password_expiration_policy (GsdAccountsUser *accounts_user_proxy,
|
||
|
GAsyncResult *res,
|
||
|
gpointer user_data)
|
||
|
{
|
||
|
GsdAccountManager *manager = user_data;
|
||
|
g_autoptr(GError) error = NULL;
|
||
|
gboolean succeeded;
|
||
|
gint64 expiration_time;
|
||
|
gint64 last_change_time;
|
||
|
gint64 min_days_between_changes;
|
||
|
gint64 max_days_between_changes;
|
||
|
gint64 days_to_warn;
|
||
|
gint64 days_after_expiration_until_lock;
|
||
|
|
||
|
gnome_settings_profile_start (NULL);
|
||
|
succeeded = gsd_accounts_user_call_get_password_expiration_policy_finish (accounts_user_proxy,
|
||
|
&expiration_time,
|
||
|
&last_change_time,
|
||
|
&min_days_between_changes,
|
||
|
&max_days_between_changes,
|
||
|
&days_to_warn,
|
||
|
&days_after_expiration_until_lock,
|
||
|
res,
|
||
|
&error);
|
||
|
|
||
|
if (!succeeded) {
|
||
|
g_warning ("Failed to get password expiration policy for user: %s", error->message);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
set_policy_number (&manager->priv->expiration_time, expiration_time);
|
||
|
set_policy_number (&manager->priv->last_change_time, last_change_time);
|
||
|
set_policy_number (&manager->priv->min_days_between_changes, min_days_between_changes);
|
||
|
set_policy_number (&manager->priv->max_days_between_changes, max_days_between_changes);
|
||
|
set_policy_number (&manager->priv->days_to_warn, days_to_warn);
|
||
|
set_policy_number (&manager->priv->days_after_expiration_until_lock, days_after_expiration_until_lock);
|
||
|
|
||
|
update_password_notification (manager);
|
||
|
+ queue_periodic_timeout (manager);
|
||
|
out:
|
||
|
gnome_settings_profile_end (NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
fetch_password_expiration_policy (GsdAccountManager *manager)
|
||
|
{
|
||
|
gsd_accounts_user_call_get_password_expiration_policy (manager->priv->accounts_user_proxy,
|
||
|
manager->priv->cancellable,
|
||
|
(GAsyncReadyCallback)
|
||
|
on_got_password_expiration_policy,
|
||
|
manager);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
on_screensaver_signal (GDBusProxy *proxy,
|
||
|
const gchar *sender_name,
|
||
|
const gchar *signal_name,
|
||
|
GVariant *parameters,
|
||
|
gpointer user_data)
|
||
|
{
|
||
|
GsdAccountManager *manager = user_data;
|
||
|
|
||
|
if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
|
||
|
gboolean active;
|
||
|
|
||
|
g_variant_get (parameters, "(b)", &active);
|
||
|
|
||
|
if (!active) {
|
||
|
fetch_password_expiration_policy (manager);
|
||
|
@@ -346,91 +383,109 @@ on_got_user_object_path (GsdAccounts *accounts_proxy,
|
||
|
manager);
|
||
|
|
||
|
out:
|
||
|
gnome_settings_profile_end (NULL);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
on_got_accounts_proxy (GObject *source_object,
|
||
|
GAsyncResult *res,
|
||
|
gpointer user_data)
|
||
|
{
|
||
|
GsdAccountManager *manager = user_data;
|
||
|
g_autoptr(GError) error = NULL;
|
||
|
|
||
|
gnome_settings_profile_start (NULL);
|
||
|
manager->priv->accounts_proxy = gsd_accounts_proxy_new_for_bus_finish (res, &error);
|
||
|
|
||
|
if (manager->priv->accounts_proxy != NULL) {
|
||
|
gsd_accounts_call_find_user_by_id (manager->priv->accounts_proxy,
|
||
|
getuid (),
|
||
|
manager->priv->cancellable,
|
||
|
(GAsyncReadyCallback)
|
||
|
on_got_user_object_path,
|
||
|
manager);
|
||
|
} else {
|
||
|
g_warning ("Failed to get proxy to accounts service: %s", error->message);
|
||
|
}
|
||
|
gnome_settings_profile_end (NULL);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+on_notify_period_changed (GsdAccountManager *manager)
|
||
|
+{
|
||
|
+ manager->priv->notify_period = g_settings_get_int (manager->priv->settings, "notify-period");
|
||
|
+
|
||
|
+ queue_periodic_timeout (manager);
|
||
|
+}
|
||
|
+
|
||
|
gboolean
|
||
|
gsd_account_manager_start (GsdAccountManager *manager,
|
||
|
GError **error)
|
||
|
{
|
||
|
g_debug ("Starting accounts manager");
|
||
|
|
||
|
gnome_settings_profile_start (NULL);
|
||
|
manager->priv->cancellable = g_cancellable_new ();
|
||
|
+ manager->priv->settings = g_settings_new ("org.gnome.settings-daemon.plugins.account");
|
||
|
+
|
||
|
+ manager->priv->notify_period = g_settings_get_int (manager->priv->settings, "notify-period");
|
||
|
+ g_signal_connect_object (G_OBJECT (manager->priv->settings),
|
||
|
+ "changed::notify-period",
|
||
|
+ G_CALLBACK (on_notify_period_changed),
|
||
|
+ manager,
|
||
|
+ G_CONNECT_SWAPPED);
|
||
|
+
|
||
|
gsd_accounts_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||
|
"org.freedesktop.Accounts",
|
||
|
"/org/freedesktop/Accounts",
|
||
|
manager->priv->cancellable,
|
||
|
(GAsyncReadyCallback)
|
||
|
on_got_accounts_proxy,
|
||
|
manager);
|
||
|
gnome_settings_profile_end (NULL);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gsd_account_manager_stop (GsdAccountManager *manager)
|
||
|
{
|
||
|
g_debug ("Stopping accounts manager");
|
||
|
|
||
|
if (manager->priv->cancellable != NULL) {
|
||
|
g_cancellable_cancel (manager->priv->cancellable);
|
||
|
g_clear_object (&manager->priv->cancellable);
|
||
|
}
|
||
|
|
||
|
+ g_clear_object (&manager->priv->settings);
|
||
|
g_clear_object (&manager->priv->accounts_proxy);
|
||
|
g_clear_object (&manager->priv->accounts_user_proxy);
|
||
|
g_clear_object (&manager->priv->notification);
|
||
|
g_clear_object (&manager->priv->screensaver_proxy);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gsd_account_manager_class_init (GsdAccountManagerClass *klass)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
|
||
|
object_class->finalize = gsd_account_manager_finalize;
|
||
|
|
||
|
notify_init ("gnome-settings-daemon");
|
||
|
|
||
|
g_type_class_add_private (klass, sizeof (GsdAccountManagerPrivate));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gsd_account_manager_init (GsdAccountManager *manager)
|
||
|
{
|
||
|
manager->priv = GSD_ACCOUNT_MANAGER_GET_PRIVATE (manager);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gsd_account_manager_finalize (GObject *object)
|
||
|
{
|
||
|
GsdAccountManager *manager;
|
||
|
|
||
|
g_return_if_fail (object != NULL);
|
||
|
--
|
||
|
2.14.2
|
||
|
|