on xenial help sign in
Fix not being locked out after a reboot
b2372a5Michael Terry
data/com.canonical.Unity8.gschema.xml+8
@@ -12,4 +12,12 @@
12 <description>The usage mode chosen will affect the Window Management behaviour.</description>
12 <description>The usage mode chosen will affect the Window Management behaviour.</description>
13 </key>
13 </key>
14 </schema>
14 </schema>
15+
16+ <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
17+ <key type="t" name="locked-out-until">
18+ <default>0</default>
19+ <summary>When the greeter will no longer be locked.</summary>
20+ <description>If too many unsuccessful login attempts have been made in a row, the greeter locks you out for a while. This unix timestamp indicates when you will be able to log back in.</description>
21+ </key>
22+ </schema>
15</schemalist>
23</schemalist>
qml/Greeter/Greeter.qml+20−4
@@ -181,6 +181,11 @@ Showable {
181 }
181 }
182 }
182 }
183
183
184+ GSettings {
185+ id: greeterSettings
186+ schema.id: "com.canonical.Unity8.Greeter"
187+ }
188+
184 Timer {
189 Timer {
185 id: forcedDelayTimer
190 id: forcedDelayTimer
186
191
@@ -193,10 +198,9 @@ Showable {
193 property int delayMinutes;
198 property int delayMinutes;
194
199
195 function forceDelay(delay /* in minutes */) {
200 function forceDelay(delay /* in minutes */) {
196− delayTarget = new Date();
197− delayTarget.setTime(delayTarget.getTime() + delay * 60000);
201+ var when = new Date().getTime() + delay * 60000;
198− delayMinutes = Math.ceil(delay);
202+ greeterSettings.lockedOutUntil = when;
199− start();
203+ // code below that watches GSettings will pick up the change
200 }
204 }
201
205
202 onTriggered: {
206 onTriggered: {
@@ -208,6 +212,18 @@ Showable {
208 delayMinutes = 0;
212 delayMinutes = 0;
209 }
213 }
210 }
214 }
215+
216+ function checkForForcedDelay() {
217+ delayTarget = new Date();
218+ delayTarget.setTime(greeterSettings.lockedOutUntil);
219+ trigger();
220+ }
221+
222+ Connections {
223+ target: greeterSettings
224+ onLockedOutUntilChanged: checkForForcedDelay()
225+ }
226+ Component.onCompleted: checkForForcedDelay()
211 }
227 }
212
228
213 // event eater
229 // event eater
tests/mocks/GSettings.1.0/fake_gsettings.cpp+31
@@ -62,6 +62,19 @@ void GSettingsControllerQml::setUsageMode(const QString &usageMode)
62 }
62 }
63}
63}
64
64
65+quint64 GSettingsControllerQml::lockedOutUntil() const
66+{
67+ return m_lockedOutUntil;
68+}
69+
70+void GSettingsControllerQml::setLockedOutUntil(quint64 timestamp)
71+{
72+ if (m_lockedOutUntil != timestamp) {
73+ m_lockedOutUntil = timestamp;
74+ Q_EMIT lockedOutUntilChanged(m_lockedOutUntil);
75+ }
76+}
77+
65GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
78GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
66}
79}
67
80
@@ -99,6 +112,8 @@ GSettingsQml::GSettingsQml(QObject *parent)
99 this, SIGNAL(pictureUriChanged(const QString &)));
112 this, SIGNAL(pictureUriChanged(const QString &)));
100 connect(GSettingsControllerQml::instance(), SIGNAL(usageModeChanged(const QString &)),
113 connect(GSettingsControllerQml::instance(), SIGNAL(usageModeChanged(const QString &)),
101 this, SIGNAL(usageModeChanged(const QString &)));
114 this, SIGNAL(usageModeChanged(const QString &)));
115+ connect(GSettingsControllerQml::instance(), SIGNAL(lockedOutUntilChanged(quint64)),
116+ this, SIGNAL(lockedOutUntilChanged(quint64)));
102}
117}
103
118
104GSettingsSchemaQml * GSettingsQml::schema() const {
119GSettingsSchemaQml * GSettingsQml::schema() const {
@@ -136,3 +151,19 @@ void GSettingsQml::setUsageMode(const QString &usageMode)
136 GSettingsControllerQml::instance()->setUsageMode(usageMode);
151 GSettingsControllerQml::instance()->setUsageMode(usageMode);
137 }
152 }
138}
153}
154+
155+quint64 GSettingsQml::lockedOutUntil() const
156+{
157+ if (m_schema->id() == "com.canonical.Unity8.Greeter") {
158+ return GSettingsControllerQml::instance()->lockedOutUntil();
159+ } else {
160+ return 0;
161+ }
162+}
163+
164+void GSettingsQml::setLockedOutUntil(quint64 timestamp)
165+{
166+ if (m_schema->id() == "com.canonical.Unity8.Greeter") {
167+ GSettingsControllerQml::instance()->setLockedOutUntil(timestamp);
168+ }
169+}
tests/mocks/GSettings.1.0/fake_gsettings.h+9
@@ -47,6 +47,7 @@ class GSettingsQml: public QObject
47 Q_PROPERTY(GSettingsSchemaQml* schema READ schema NOTIFY schemaChanged)
47 Q_PROPERTY(GSettingsSchemaQml* schema READ schema NOTIFY schemaChanged)
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
48 Q_PROPERTY(QString pictureUri READ pictureUri WRITE setPictureUri NOTIFY pictureUriChanged)
49 Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged)
49 Q_PROPERTY(QString usageMode READ usageMode WRITE setUsageMode NOTIFY usageModeChanged)
50+ Q_PROPERTY(quint64 lockedOutUntil READ lockedOutUntil WRITE setLockedOutUntil NOTIFY lockedOutUntilChanged)
50
51
51public:
52public:
52 GSettingsQml(QObject *parent = nullptr);
53 GSettingsQml(QObject *parent = nullptr);
@@ -54,14 +55,17 @@ public:
54 GSettingsSchemaQml * schema() const;
55 GSettingsSchemaQml * schema() const;
55 QString pictureUri() const;
56 QString pictureUri() const;
56 QString usageMode() const;
57 QString usageMode() const;
58+ quint64 lockedOutUntil() const;
57
59
58 void setPictureUri(const QString &str);
60 void setPictureUri(const QString &str);
59 void setUsageMode(const QString &usageMode);
61 void setUsageMode(const QString &usageMode);
62+ void setLockedOutUntil(quint64 timestamp);
60
63
61Q_SIGNALS:
64Q_SIGNALS:
62 void schemaChanged();
65 void schemaChanged();
63 void pictureUriChanged(const QString&);
66 void pictureUriChanged(const QString&);
64 void usageModeChanged(const QString&);
67 void usageModeChanged(const QString&);
68+ void lockedOutUntilChanged(quint64);
65
69
66private:
70private:
67 GSettingsSchemaQml* m_schema;
71 GSettingsSchemaQml* m_schema;
@@ -83,15 +87,20 @@ public:
83 QString usageMode() const;
87 QString usageMode() const;
84 Q_INVOKABLE void setUsageMode(const QString &usageMode);
88 Q_INVOKABLE void setUsageMode(const QString &usageMode);
85
89
90+ quint64 lockedOutUntil() const;
91+ Q_INVOKABLE void setLockedOutUntil(quint64 timestamp);
92+
86Q_SIGNALS:
93Q_SIGNALS:
87 void pictureUriChanged(const QString&);
94 void pictureUriChanged(const QString&);
88 void usageModeChanged(const QString&);
95 void usageModeChanged(const QString&);
96+ void lockedOutUntilChanged(quint64 timestamp);
89
97
90private:
98private:
91 GSettingsControllerQml();
99 GSettingsControllerQml();
92
100
93 QString m_pictureUri;
101 QString m_pictureUri;
94 QString m_usageMode;
102 QString m_usageMode;
103+ quint64 m_lockedOutUntil;
95
104
96 static GSettingsControllerQml* s_controllerInstance;
105 static GSettingsControllerQml* s_controllerInstance;
97 QList<GSettingsQml *> m_registeredGSettings;
106 QList<GSettingsQml *> m_registeredGSettings;
tests/qmltests/Greeter/tst_Greeter.qml+27−1
@@ -431,7 +431,33 @@ Item {
431 compare(LightDM.Infographic.username, "has-password");
431 compare(LightDM.Infographic.username, "has-password");
432 }
432 }
433
433
434− function test_forcedDelay() {
434+ function test_forcedDelayIntoGSettings() {
435+ greeter.failedLoginsDelayAttempts = 1;
436+ greeter.failedLoginsDelayMinutes = 1;
437+ selectUser("has-password");
438+ tryCompare(viewShowPromptSpy, "count", 1);
439+ view.responded("wr0ng p4ssw0rd");
440+
441+ var timestamp = new Date().getTime() + 60000;
442+ compare(GSettingsController.lockedOutUntil, timestamp);
443+ }
444+
445+ function test_forcedDelayFromGSettings() {
446+ compare(view.delayMinutes, 0);
447+ var timestamp = new Date().getTime() + 30; // in 30 seconds
448+ GSettingsController.lockedOutUntil = timestamp;
449+ tryCompare(view, "delayMinutes", 1);
450+ }
451+
452+ function test_forcedDelayOnConstruction() {
453+ var timestamp = new Date().getTime() + 30; // in 30 seconds
454+ GSettingsController.lockedOutUntil = timestamp;
455+ cleanup();
456+ init();
457+ tryCompare(view, "delayMinutes", 1);
458+ }
459+
460+ function test_forcedDelayRoundTrip() {
435 greeter.failedLoginsDelayAttempts = 1;
461 greeter.failedLoginsDelayAttempts = 1;
436 greeter.failedLoginsDelayMinutes = 0.001; // make delay very short
462 greeter.failedLoginsDelayMinutes = 0.001; // make delay very short
437
463