on xenial help sign in
factor out password strength meter into its own component
commitda86a880681798d97f25548806f8f5046579e71b authorLukáš Tinkl <lukas.tinkl@canonical.com> dateTue 14 Jul 2015, 19:51 (11 years ago) parent3855f5e
3 files changed+106−81
qml/Wizard/Pages/60-uaccount-signup.qml+13−3 qml/Wizard/Pages/password-set.qml+10−78 qml/Wizard/PasswordMeter.qml+83
qml/Wizard/Pages/60-uaccount-signup.qml+13−3
@@ -99,13 +99,23 @@ LocalComponents.Page {
9999 KeyNavigation.tab: pass2Input
100100 }
101101
102+ // password meter
103+ LocalComponents.PasswordMeter {
104+ id: passMeter
105+ anchors.left: parent.left
106+ anchors.right: parent.right
107+ anchors.top: passInput.bottom
108+ anchors.topMargin: units.gu(1)
109+ password: passInput.text
110+ }
111+
102112 // repeat password
103113 Label {
104114 id: pass2Label
105115 anchors.left: parent.left
106116 anchors.right: parent.right
107− anchors.top: passInput.bottom
108− anchors.topMargin: units.gu(3)
117+ anchors.top: passMeter.bottom
118+ anchors.topMargin: passInput.text !== "" ? units.gu(6) : units.gu(3)
109119 wrapMode: Text.Wrap
110120 text: i18n.tr("Repeat password:")
111121 color: "#525252"
@@ -167,7 +177,7 @@ LocalComponents.Page {
167177 LocalComponents.StackButton {
168178 enabled: emailInput.acceptableInput &&
169179 //termsCheck.checked && // FIXME re-enable when the checkboxes get visible again
170− passInput.text !== "" && pass2Input.text !== "" && passInput.text === pass2Input.text
180+ pass2Input.text.length > 5 && passInput.text === pass2Input.text
171181 text: i18n.tr("Sign Up")
172182 onClicked: pageStack.next() // TODO sign up against U1
173183 }
qml/Wizard/Pages/password-set.qml+10−78
@@ -33,7 +33,6 @@ LocalComponents.Page {
3333 backButtonText: i18n.tr("Cancel")
3434
3535 property alias password: passwordField.text
36− readonly property int passwordScore: scorePassword(password)
3736 property bool confirmPhase: false
3837
3938 // If we are entering this page, clear any saved password and get focus
@@ -71,39 +70,10 @@ LocalComponents.Page {
7170 if (!!text) {
7271 infoLabel.text = text
7372 } else {
74− infoLabel.text = i18n.tr("Enter at least 4 characters")
73+ infoLabel.text = i18n.tr("Enter at least 6 characters")
7574 }
7675 }
7776
78− function scorePassword(pass) {
79− var score = 0;
80− if (!pass)
81− return score;
82−
83− // award every unique letter until 5 repetitions
84− var letters = Object();
85− for (var i=0; i<pass.length; i++) {
86− letters[pass[i]] = (letters[pass[i]] || 0) + 1;
87− score += 5.0 / letters[pass[i]];
88− }
89−
90− // bonus points for mixing it up
91− var variations = {
92− digits: /\d/.test(pass),
93− lower: /[a-z]/.test(pass),
94− upper: /[A-Z]/.test(pass),
95− nonWords: /\W/.test(pass),
96− }
97−
98− var variationCount = 0;
99− for (var check in variations) {
100− variationCount += (variations[check] === true) ? 1 : 0;
101− }
102− score += (variationCount - 1) * 10;
103−
104− return parseInt(score);
105− }
106−
10777 Item {
10878 id: column
10979 anchors.fill: content
@@ -139,59 +109,21 @@ LocalComponents.Page {
139109 }
140110 }
141111
142− Rectangle {
143− id: passwordStrengthMeter
144− anchors {
145− left: parent.left
146− right: parent.right
147− top: passwordField.bottom
148− topMargin: units.gu(1)
149− }
150− width: parent.width
151− height: units.gu(1)
152− color: {
153− if (passwordScore > 80)
154− return "green";
155− if (passwordScore > 60)
156− return "orange";
157− if (passwordScore >= 30)
158− return "red";
159−
160− return "red";
161− }
162− visible: password.length > 0
163− }
164−
165− Label {
166− id: passwordStrengthInfo
167− anchors {
168− left: parent.left
169− right: parent.right
170− top: passwordStrengthMeter.bottom
171− topMargin: units.gu(1)
172− }
173− wrapMode: Text.Wrap
174− text: {
175− if (passwordScore > 80)
176− return i18n.tr("Strong password");
177− else if (passwordScore > 60)
178− return i18n.tr("Medium password")
179− if (passwordScore >= 30)
180− return i18n.tr("Weak password");
181−
182− return i18n.tr("Very weak password");
183− }
184− color: "#888888"
185− fontSize: "small"
186− font.weight: Font.Light
187− visible: password.length > 0
112+ // password meter
113+ LocalComponents.PasswordMeter {
114+ id: passMeter
115+ anchors.left: parent.left
116+ anchors.right: parent.right
117+ anchors.top: passwordField.bottom
118+ anchors.topMargin: units.gu(1)
119+ password: passwordField.text
188120 }
189121 }
190122
191123 Component {
192124 id: forwardButton
193125 LocalComponents.StackButton {
194− enabled: confirmPhase ? password === root.password : password.length >= 4 // TODO set more sensible restrictions for the length?
126+ enabled: confirmPhase ? password === root.password : password.length > 5 // TODO set more sensible restrictions for the length?
195127 text: i18n.tr("OK")
196128 onClicked: {
197129 if (confirmPhase) {
qml/Wizard/PasswordMeter.qmlnew file+83
@@ -0,0 +1,83 @@
1+import QtQuick 2.3
2+import Ubuntu.Components 1.2
3+
4+Item {
5+ property string password: ""
6+ readonly property int passwordScore: scorePassword(password)
7+
8+ function scorePassword(pass) {
9+ var score = 0;
10+ if (!pass)
11+ return score;
12+
13+ // award every unique letter until 5 repetitions
14+ var letters = Object();
15+ for (var i=0; i<pass.length; i++) {
16+ letters[pass[i]] = (letters[pass[i]] || 0) + 1;
17+ score += 5.0 / letters[pass[i]];
18+ }
19+
20+ // bonus points for mixing it up
21+ var variations = {
22+ digits: /\d/.test(pass),
23+ lower: /[a-z]/.test(pass),
24+ upper: /[A-Z]/.test(pass),
25+ nonWords: /\W/.test(pass),
26+ }
27+
28+ var variationCount = 0;
29+ for (var check in variations) {
30+ variationCount += (variations[check] === true) ? 1 : 0;
31+ }
32+ score += (variationCount - 1) * 10;
33+
34+ return parseInt(score);
35+ }
36+
37+ Rectangle {
38+ id: passwordStrengthMeter
39+ anchors {
40+ left: parent.left
41+ right: parent.right
42+ }
43+ width: parent.width
44+ height: units.gu(1)
45+ color: {
46+ if (passwordScore > 80)
47+ return "green";
48+ else if (passwordScore > 60)
49+ return "orange";
50+ else if (passwordScore >= 30)
51+ return "red";
52+
53+ return "red";
54+ }
55+ visible: password.length > 0
56+ }
57+
58+ Label {
59+ id: passwordStrengthInfo
60+ anchors {
61+ left: parent.left
62+ right: parent.right
63+ top: passwordStrengthMeter.bottom
64+ }
65+ wrapMode: Text.Wrap
66+ text: {
67+ if (password.length < 6)
68+ return i18n.tr("Password too short")
69+ else if (passwordScore > 80)
70+ return i18n.tr("Strong password");
71+ else if (passwordScore > 60)
72+ return i18n.tr("Fair password")
73+ if (passwordScore >= 30)
74+ return i18n.tr("Weak password");
75+
76+ return i18n.tr("Very weak password");
77+ }
78+ color: "#888888"
79+ fontSize: "small"
80+ font.weight: Font.Light
81+ visible: password.length > 0
82+ }
83+}