[gnome-initial-setup: 14/20] password: Add a parent-mode property for collecting parent password



commit 5df9054b899a6751d8c850dc9365a96687628bc1
Author: Philip Withnall <withnall endlessm com>
Date:   Thu Feb 6 13:08:31 2020 +0000

    password: Add a parent-mode property for collecting parent password
    
    If parental controls are enabled, show the password page twice: the
    first time to collect the child user’s password, and the second time to
    collect the parent user’s.
    
    Use the same underlying `GisPasswordPage` to implement both, but
    construct it with a `GisPasswordPage:parent-mode` property set to `TRUE`
    the second time round, which tweaks the UI and save data mechanism
    slightly.
    
    Using the same underlying implementation means the two pages will stay
    in sync in future.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>

 gnome-initial-setup/gnome-initial-setup.c          |   3 +
 .../pages/password/gis-password-page.c             | 145 ++++++++++++++++++++-
 .../pages/password/gis-password-page.h             |   1 +
 .../pages/password/gis-password-page.ui            |   3 +-
 4 files changed, 147 insertions(+), 5 deletions(-)
---
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index b1eedb9..b3cb9b6 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -70,6 +70,9 @@ static PageData page_table[] = {
   PAGE (goa,      FALSE),
   PAGE (account,  TRUE),
   PAGE (password, TRUE),
+#ifdef HAVE_PARENTAL_CONTROLS
+  PAGE (parent_password, TRUE),
+#endif
   PAGE (summary,  FALSE),
   { NULL },
 };
diff --git a/gnome-initial-setup/pages/password/gis-password-page.c 
b/gnome-initial-setup/pages/password/gis-password-page.c
index 4b32a3f..7bd4b7c 100644
--- a/gnome-initial-setup/pages/password/gis-password-page.c
+++ b/gnome-initial-setup/pages/password/gis-password-page.c
@@ -46,15 +46,65 @@ struct _GisPasswordPagePrivate
   GtkWidget *password_strength;
   GtkWidget *password_explanation;
   GtkWidget *confirm_explanation;
+  GtkWidget *header;
+
   gboolean valid_confirm;
   gboolean valid_password;
   guint timeout_id;
   const gchar *username;
+  gboolean parent_mode;
 };
 typedef struct _GisPasswordPagePrivate GisPasswordPagePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GisPasswordPage, gis_password_page, GIS_TYPE_PAGE);
 
+typedef enum
+{
+  PROP_PARENT_MODE = 1,
+} GisPasswordPageProperty;
+
+static GParamSpec *obj_props[PROP_PARENT_MODE + 1];
+
+static void
+update_header (GisPasswordPage *page)
+{
+  GisPasswordPagePrivate *priv = gis_password_page_get_instance_private (page);
+  const gchar *title, *subtitle;
+
+  if (!priv->parent_mode)
+    {
+      title = _("Set a User Password");
+      subtitle = _("Be careful not to lose your password.");
+    }
+  else
+    {
+      title = _("Set a Parent Password");
+      subtitle = _("This password will control access to the parental controls for the child’s user 
account.");
+    }
+
+  g_object_set (G_OBJECT (priv->header),
+                "title", title,
+                "subtitle", subtitle,
+                NULL);
+}
+
+static void
+set_parent_mode (GisPasswordPage *page,
+                 gboolean         parent_mode)
+{
+  GisPasswordPagePrivate *priv = gis_password_page_get_instance_private (page);
+
+  g_return_if_fail (GIS_IS_PASSWORD_PAGE (page));
+
+  if (priv->parent_mode == parent_mode)
+    return;
+
+  priv->parent_mode = parent_mode;
+  g_object_notify_by_pspec (G_OBJECT (page), obj_props[PROP_PARENT_MODE]);
+
+  update_header (page);
+}
+
 static gboolean
 page_validate (GisPasswordPage *page)
 {
@@ -83,9 +133,14 @@ gis_password_page_save_data (GisPage *gis_page)
 
   account_mode = gis_driver_get_account_mode (gis_page->driver);
 
-  gis_driver_get_user_permissions (gis_page->driver, &act_user, &password);
+  if (!priv->parent_mode)
+    gis_driver_get_user_permissions (gis_page->driver, &act_user, &password);
+  else
+    gis_driver_get_parent_permissions (gis_page->driver, &act_user, &password);
 
   if (account_mode == UM_ENTERPRISE) {
+    g_assert (!priv->parent_mode);
+
     if (password != NULL)
       gis_update_login_keyring_password (password);
     return;
@@ -98,9 +153,13 @@ gis_password_page_save_data (GisPage *gis_page)
   else
     act_user_set_password (act_user, password, "");
 
-  gis_driver_set_user_permissions (gis_page->driver, act_user, password);
+  if (!priv->parent_mode)
+    gis_driver_set_user_permissions (gis_page->driver, act_user, password);
+  else
+    gis_driver_set_parent_permissions (gis_page->driver, act_user, password);
 
-  gis_update_login_keyring_password (password);
+  if (!priv->parent_mode)
+    gis_update_login_keyring_password (password);
 }
 
 static void
@@ -154,6 +213,13 @@ validate (GisPasswordPage *page)
     }
   }
 
+  /*
+   * We deliberately don’t validate that the parent password and main user
+   * password are different. It’s more feasible that someone would usefully
+   * want to set their system up that way, than it is that the parent and child
+   * would accidentally choose the same password.
+   */
+
   update_page_validation (page);
 
   return FALSE;
@@ -252,10 +318,50 @@ gis_password_page_constructed (GObject *object)
                     G_CALLBACK (username_changed), page);
 
   validate (page);
+  update_header (page);
 
   gtk_widget_show (GTK_WIDGET (page));
 }
 
+static void
+gis_password_page_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GisPasswordPage *page = GIS_PASSWORD_PAGE (object);
+  GisPasswordPagePrivate *priv = gis_password_page_get_instance_private (page);
+
+  switch ((GisPasswordPageProperty) prop_id)
+    {
+    case PROP_PARENT_MODE:
+      g_value_set_boolean (value, priv->parent_mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gis_password_page_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GisPasswordPage *page = GIS_PASSWORD_PAGE (object);
+
+  switch ((GisPasswordPageProperty) prop_id)
+    {
+    case PROP_PARENT_MODE:
+      set_parent_mode (page, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 static void
 gis_password_page_dispose (GObject *object)
 {
@@ -285,6 +391,7 @@ gis_password_page_class_init (GisPasswordPageClass *klass)
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisPasswordPage, 
password_strength);
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisPasswordPage, 
password_explanation);
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisPasswordPage, 
confirm_explanation);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisPasswordPage, header);
 
   page_class->page_id = PAGE_ID;
   page_class->locale_changed = gis_password_page_locale_changed;
@@ -292,7 +399,27 @@ gis_password_page_class_init (GisPasswordPageClass *klass)
   page_class->shown = gis_password_page_shown;
 
   object_class->constructed = gis_password_page_constructed;
+  object_class->get_property = gis_password_page_get_property;
+  object_class->set_property = gis_password_page_set_property;
   object_class->dispose = gis_password_page_dispose;
+
+  /**
+   * GisPasswordPage:parent-mode:
+   *
+   * If %FALSE (the default), this page will collect a password for the main
+   * user account. If %TRUE, it will collect a password for controlling access
+   * to parental controls — this will affect where the password is stored, and
+   * the appearance of the page.
+   *
+   * Since: 3.36
+   */
+  obj_props[PROP_PARENT_MODE] =
+    g_param_spec_boolean ("parent-mode", "Parent Mode",
+                          "Whether to collect a password for the main user account or a parent account.",
+                          FALSE,
+                          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
 }
 
 static void
@@ -321,3 +448,15 @@ gis_prepare_password_page (GisDriver *driver)
                        NULL);
 }
 
+GisPage *
+gis_prepare_parent_password_page (GisDriver *driver)
+{
+  /* Skip prompting for the parent password if parental controls aren’t enabled. */
+  if (!gis_driver_get_parental_controls_enabled (driver))
+    return NULL;
+
+  return g_object_new (GIS_TYPE_PASSWORD_PAGE,
+                       "driver", driver,
+                       "parent-mode", TRUE,
+                       NULL);
+}
diff --git a/gnome-initial-setup/pages/password/gis-password-page.h 
b/gnome-initial-setup/pages/password/gis-password-page.h
index 954782f..2a4d1c6 100644
--- a/gnome-initial-setup/pages/password/gis-password-page.h
+++ b/gnome-initial-setup/pages/password/gis-password-page.h
@@ -51,6 +51,7 @@ struct _GisPasswordPageClass
 GType gis_password_page_get_type (void);
 
 GisPage *gis_prepare_password_page (GisDriver *driver);
+GisPage *gis_prepare_parent_password_page (GisDriver *driver);
 
 G_END_DECLS
 
diff --git a/gnome-initial-setup/pages/password/gis-password-page.ui 
b/gnome-initial-setup/pages/password/gis-password-page.ui
index 500d0d3..b21010c 100644
--- a/gnome-initial-setup/pages/password/gis-password-page.ui
+++ b/gnome-initial-setup/pages/password/gis-password-page.ui
@@ -13,8 +13,7 @@
           <object class="GisPageHeader" id="header">
             <property name="visible">True</property>
             <property name="margin_top">24</property>
-            <property name="title" translatable="yes">Set a Password</property>
-            <property name="subtitle" translatable="yes">Be careful not to lose your password.</property>
+            <!-- title and subtitle are set in code, so are not set here -->
             <property name="icon_name">dialog-password-symbolic</property>
             <property name="show_icon" bind-source="GisPasswordPage" bind-property="small-screen" 
bind-flags="invert-boolean|sync-create"/>
           </object>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]