[f19-branch/master 2/2] Add password strength to root password spoke

Brian C. Lane bcl at redhat.com
Mon Jun 3 18:08:27 UTC 2013


From: "Brian C. Lane" <bcl at redhat.com>

---
 pyanaconda/ui/gui/spokes/password.glade | 55 ++++++++++++++++++++++++++++--
 pyanaconda/ui/gui/spokes/password.py    | 59 ++++++++++++++++++++++++++++++++-
 2 files changed, 111 insertions(+), 3 deletions(-)

diff --git a/pyanaconda/ui/gui/spokes/password.glade b/pyanaconda/ui/gui/spokes/password.glade
index 75ac957..cfd12a5 100644
--- a/pyanaconda/ui/gui/spokes/password.glade
+++ b/pyanaconda/ui/gui/spokes/password.glade
@@ -74,7 +74,7 @@
                       </object>
                       <packing>
                         <property name="left_attach">0</property>
-                        <property name="top_attach">2</property>
+                        <property name="top_attach">3</property>
                         <property name="width">1</property>
                         <property name="height">1</property>
                       </packing>
@@ -85,6 +85,7 @@
                         <property name="can_focus">True</property>
                         <property name="visibility">False</property>
                         <property name="invisible_char">●</property>
+                        <signal name="changed" handler="_checkPassword" swapped="no"/>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -100,10 +101,11 @@
                         <property name="visibility">False</property>
                         <property name="invisible_char">●</property>
                         <property name="activates_default">True</property>
+                        <signal name="changed" handler="_checkPassword" swapped="no"/>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
-                        <property name="top_attach">2</property>
+                        <property name="top_attach">3</property>
                         <property name="width">1</property>
                         <property name="height">1</property>
                       </packing>
@@ -122,6 +124,55 @@
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkBox" id="box2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkLevelBar" id="password_bar">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="spacing">2</property>
+                            <property name="mode">GTK_LEVEL_BAR_MODE_DISCRETE</property>
+                            <property name="min-value">0</property>
+                            <property name="max-value">4</property>
+                            <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+                            <property name="value">2</property>
+                            <property name="halign">fill</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="password_label">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="valign">center</property>
+                            <property name="xpad">6</property>
+                            <property name="label" translatable="yes">empty password</property>
+                            <attributes>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">2</property>
+                        <property name="width">1</property>
+                        <property name="height">1</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkLabel" id="details">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
diff --git a/pyanaconda/ui/gui/spokes/password.py b/pyanaconda/ui/gui/spokes/password.py
index ff029ea..b496283 100644
--- a/pyanaconda/ui/gui/spokes/password.py
+++ b/pyanaconda/ui/gui/spokes/password.py
@@ -28,7 +28,8 @@ from pwquality import PWQError
 from pyanaconda.ui.gui.spokes import NormalSpoke
 from pyanaconda.ui.gui.categories.user_settings import UserSettingsCategory
 from pyanaconda.ui.common import FirstbootSpokeMixIn
-#from _isys import isCapsLockEnabled
+
+import pwquality
 
 __all__ = ["PasswordSpoke"]
 
@@ -62,6 +63,13 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke):
             self.pw.set_placeholder_text(_("The password was set by kickstart."))
             self.confirm.set_placeholder_text(_("The password was set by kickstart."))
 
+        # set up passphrase quality checker
+        self._pwq = pwquality.PWQSettings()
+        self._pwq.read_config()
+
+        self.pw_bar = self.builder.get_object("password_bar")
+        self.pw_label = self.builder.get_object("password_label")
+
     def refresh(self):
 #        self.setCapsLockLabel()
         self.pw.grab_focus()
@@ -107,6 +115,55 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke):
     def completed(self):
         return bool(self.data.rootpw.password or self.data.rootpw.lock)
 
+    def _checkPassword(self, editable = None, data = None):
+        """This method updates the password indicators according
+        to the passwords entered by the user. It is called by
+        the changed Gtk event handler.
+        """
+        try:
+            strength = self._pwq.check(self.pw.get_text(), None, None)
+            _pwq_error = None
+        except pwquality.PWQError as (e, msg):
+            _pwq_error = msg
+            strength = 0
+
+        if strength < 50:
+            val = 1
+            text = _("Weak")
+            self._error = _("The password you have provided is weak")
+            if _pwq_error:
+                self._error += ": %s. " % _pwq_error
+            else:
+                self._error += ". "
+            self._error += _("You will have to press Done twice to confirm it.")
+        elif strength < 75:
+            val = 2
+            text = _("Fair")
+            self._error = False
+        elif strength < 90:
+            val = 3
+            text = _("Good")
+            self._error = False
+        else:
+            val = 4
+            text = _("Strong")
+            self._error = False
+
+        if not self.pw.get_text():
+            val = 0
+            text = _("Empty!")
+            self._error = _("The password is empty!")
+        elif self.confirm.get_text() and self.pw.get_text() != self.confirm.get_text():
+            self._error = _("The passwords do not match!")
+
+        self.pw_bar.set_value(val)
+        self.pw_label.set_text(text)
+
+        self.clear_info()
+        if self._error:
+            self.set_warning(self._error)
+            self.window.show_all()
+
     def _validatePassword(self):
         # Do various steps to validate the password
         # sets self._error to an error string
-- 
1.8.1.4



More information about the anaconda-patches mailing list