Login/UnlockDialog: don't reset immediately if auth fails
Instead of showing a notification, add a small message immediately below the entry, and give the user two more attempts to login, before going back to the welcome or lock screen. https://bugzilla.gnome.org/show_bug.cgi?id=682544
This commit is contained in:
parent
ec4f6b7f91
commit
db20a54861
@ -2189,6 +2189,10 @@ StButton.popup-menu-item:insensitive {
|
|||||||
background-gradient-end: #74a0d0;
|
background-gradient-end: #74a0d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-dialog-message-warning {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
.unlock-dialog-user-name-container {
|
.unlock-dialog-user-name-container {
|
||||||
spacing: .4em;
|
spacing: .4em;
|
||||||
}
|
}
|
||||||
|
@ -647,7 +647,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
|
|
||||||
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
|
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
|
||||||
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
|
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
|
||||||
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
|
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
||||||
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
||||||
|
|
||||||
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
||||||
@ -715,6 +715,10 @@ const LoginDialog = new Lang.Class({
|
|||||||
x_fill: true,
|
x_fill: true,
|
||||||
y_fill: false,
|
y_fill: false,
|
||||||
x_align: St.Align.START });
|
x_align: St.Align.START });
|
||||||
|
|
||||||
|
this._promptMessage = new St.Label({ visible: false });
|
||||||
|
this._promptBox.add(this._promptMessage, { x_fill: true });
|
||||||
|
|
||||||
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' });
|
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint-message' });
|
||||||
this._promptLoginHint.hide();
|
this._promptLoginHint.hide();
|
||||||
this._promptBox.add(this._promptLoginHint);
|
this._promptBox.add(this._promptLoginHint);
|
||||||
@ -797,6 +801,8 @@ const LoginDialog = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onReset: function(client, serviceName) {
|
_onReset: function(client, serviceName) {
|
||||||
|
this._promptMessage.hide();
|
||||||
|
|
||||||
let tasks = [this._hidePrompt,
|
let tasks = [this._hidePrompt,
|
||||||
|
|
||||||
new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
|
new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
|
||||||
@ -826,6 +832,12 @@ const LoginDialog = new Lang.Class({
|
|||||||
this._sessionList.setActiveSession(sessionId);
|
this._sessionList.setActiveSession(sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_showMessage: function(userVerifier, message, styleClass) {
|
||||||
|
this._promptMessage.text = message;
|
||||||
|
this._promptMessage.styleClass = styleClass;
|
||||||
|
GdmUtil.fadeInActor(this._promptMessage);
|
||||||
|
},
|
||||||
|
|
||||||
_showLoginHint: function(verifier, message) {
|
_showLoginHint: function(verifier, message) {
|
||||||
this._promptLoginHint.set_text(message)
|
this._promptLoginHint.set_text(message)
|
||||||
GdmUtil.fadeInActor(this._promptLoginHint);
|
GdmUtil.fadeInActor(this._promptLoginHint);
|
||||||
@ -1081,10 +1093,6 @@ const LoginDialog = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_onVerificationFailed: function() {
|
|
||||||
this._userVerifier.cancel();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onNotListedClicked: function(user) {
|
_onNotListedClicked: function(user) {
|
||||||
let tasks = [function() {
|
let tasks = [function() {
|
||||||
return this._userList.hideItems();
|
return this._userList.hideItems();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const Batch = imports.gdm.batch;
|
const Batch = imports.gdm.batch;
|
||||||
@ -19,6 +20,7 @@ const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
|
|||||||
const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
|
const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
|
||||||
const BANNER_MESSAGE_KEY = 'banner-message-enable';
|
const BANNER_MESSAGE_KEY = 'banner-message-enable';
|
||||||
const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
|
const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
|
||||||
|
const ALLOWED_FAILURES_KEY = 'allowed-failures';
|
||||||
|
|
||||||
const LOGO_KEY = 'logo';
|
const LOGO_KEY = 'logo';
|
||||||
|
|
||||||
@ -81,6 +83,8 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
|
|
||||||
this._fprintManager = new Fprint.FprintManager();
|
this._fprintManager = new Fprint.FprintManager();
|
||||||
this._realmManager = new Realmd.Manager();
|
this._realmManager = new Realmd.Manager();
|
||||||
|
|
||||||
|
this._failCounter = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
begin: function(userName, hold) {
|
begin: function(userName, hold) {
|
||||||
@ -242,7 +246,7 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
// to indicate the user can swipe their finger instead
|
// to indicate the user can swipe their finger instead
|
||||||
this.emit('show-login-hint', _("(or swipe finger)"));
|
this.emit('show-login-hint', _("(or swipe finger)"));
|
||||||
} else if (serviceName == PASSWORD_SERVICE_NAME) {
|
} else if (serviceName == PASSWORD_SERVICE_NAME) {
|
||||||
Main.notifyError(info);
|
this.emit('show-message', info, 'login-dialog-message-info');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -251,7 +255,7 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
// users who haven't enrolled their fingerprint.
|
// users who haven't enrolled their fingerprint.
|
||||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
if (serviceName != PASSWORD_SERVICE_NAME)
|
||||||
return;
|
return;
|
||||||
Main.notifyError(problem);
|
this.emit('show-message', problem, 'login-dialog-message-warning');
|
||||||
},
|
},
|
||||||
|
|
||||||
_showRealmLoginHint: function() {
|
_showRealmLoginHint: function() {
|
||||||
@ -290,8 +294,10 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_onReset: function() {
|
_onReset: function() {
|
||||||
this._userVerifier.run_dispose();
|
this.clear();
|
||||||
this._userVerifier = null;
|
|
||||||
|
// Clear previous attempts to authenticate
|
||||||
|
this._failCounter = 0;
|
||||||
|
|
||||||
this.emit('reset');
|
this.emit('reset');
|
||||||
},
|
},
|
||||||
@ -300,12 +306,34 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
this.emit('verification-complete');
|
this.emit('verification-complete');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_verificationFailed: function() {
|
||||||
|
// For Not Listed / enterprise logins, immediately reset
|
||||||
|
// the dialog
|
||||||
|
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
|
||||||
|
// go back to the welcome screen.
|
||||||
|
|
||||||
|
if (!this._userName ||
|
||||||
|
(++this._failCounter) == this._settings.get_int(ALLOWED_FAILURES_KEY)) {
|
||||||
|
// Allow some time to see the message, then reset everything
|
||||||
|
Mainloop.timeout_add(3000, Lang.bind(this, function() {
|
||||||
|
this.cancel();
|
||||||
|
|
||||||
|
this._onReset();
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
this.clear();
|
||||||
|
this.begin(this._userName, new Batch.Hold());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('verification-failed');
|
||||||
|
},
|
||||||
|
|
||||||
_onConversationStopped: function(client, serviceName) {
|
_onConversationStopped: function(client, serviceName) {
|
||||||
// if the password service fails, then cancel everything.
|
// if the password service fails, then cancel everything.
|
||||||
// But if, e.g., fingerprint fails, still give
|
// But if, e.g., fingerprint fails, still give
|
||||||
// password authentication a chance to succeed
|
// password authentication a chance to succeed
|
||||||
if (serviceName == PASSWORD_SERVICE_NAME) {
|
if (serviceName == PASSWORD_SERVICE_NAME) {
|
||||||
this.emit('verification-failed');
|
this._verificationFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('hide-login-hint');
|
this.emit('hide-login-hint');
|
||||||
|
@ -89,13 +89,15 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._userName = GLib.get_user_name();
|
this._userName = GLib.get_user_name();
|
||||||
this._user = this._userManager.get_user(this._userName);
|
this._user = this._userManager.get_user(this._userName);
|
||||||
|
|
||||||
|
this._failCounter = 0;
|
||||||
|
|
||||||
this._greeterClient = new Gdm.Client();
|
this._greeterClient = new Gdm.Client();
|
||||||
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true });
|
this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient, { reauthenticationOnly: true });
|
||||||
|
|
||||||
this._userVerifier.connect('reset', Lang.bind(this, this._reset));
|
|
||||||
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
|
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
|
||||||
|
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
||||||
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
||||||
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
|
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
||||||
|
|
||||||
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
||||||
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
||||||
@ -122,6 +124,9 @@ const UnlockDialog = new Lang.Class({
|
|||||||
|
|
||||||
this.contentLayout.add_actor(this._promptLayout);
|
this.contentLayout.add_actor(this._promptLayout);
|
||||||
|
|
||||||
|
this._promptMessage = new St.Label({ visible: false });
|
||||||
|
this.contentLayout.add(this._promptMessage, { x_fill: true });
|
||||||
|
|
||||||
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint' });
|
this._promptLoginHint = new St.Label({ style_class: 'login-dialog-prompt-login-hint' });
|
||||||
this._promptLoginHint.hide();
|
this._promptLoginHint.hide();
|
||||||
this.contentLayout.add_actor(this._promptLoginHint);
|
this.contentLayout.add_actor(this._promptLoginHint);
|
||||||
@ -135,7 +140,6 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this.setButtons([cancelButton, this._okButton]);
|
this.setButtons([cancelButton, this._okButton]);
|
||||||
|
|
||||||
this._updateOkButton(false);
|
this._updateOkButton(false);
|
||||||
this._reset();
|
|
||||||
|
|
||||||
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
|
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
|
||||||
style_class: 'login-dialog-not-listed-label' });
|
style_class: 'login-dialog-not-listed-label' });
|
||||||
@ -150,6 +154,9 @@ const UnlockDialog = new Lang.Class({
|
|||||||
{ x_align: St.Align.START,
|
{ x_align: St.Align.START,
|
||||||
x_fill: false });
|
x_fill: false });
|
||||||
|
|
||||||
|
let batch = new Batch.Hold();
|
||||||
|
this._userVerifier.begin(this._userName, batch);
|
||||||
|
|
||||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||||
this.emit('loaded');
|
this.emit('loaded');
|
||||||
return false;
|
return false;
|
||||||
@ -165,9 +172,10 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._okButton.button.reactive = sensitive;
|
this._okButton.button.reactive = sensitive;
|
||||||
},
|
},
|
||||||
|
|
||||||
_reset: function() {
|
_showMessage: function(userVerifier, message, styleClass) {
|
||||||
this._userVerifier.clear();
|
this._promptMessage.text = message;
|
||||||
this._userVerifier.begin(this._userName, new Batch.Hold());
|
this._promptMessage.styleClass = styleClass;
|
||||||
|
GdmUtil.fadeInActor(this._promptMessage);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
|
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
|
||||||
@ -207,13 +215,13 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this.emit('unlocked');
|
this.emit('unlocked');
|
||||||
},
|
},
|
||||||
|
|
||||||
_onVerificationFailed: function() {
|
_onReset: function() {
|
||||||
this._userVerifier.cancel();
|
|
||||||
this.emit('failed');
|
this.emit('failed');
|
||||||
},
|
},
|
||||||
|
|
||||||
_escape: function() {
|
_escape: function() {
|
||||||
this._onVerificationFailed();
|
this._userVerifier.cancel();
|
||||||
|
this.emit('failed');
|
||||||
},
|
},
|
||||||
|
|
||||||
_otherUserClicked: function(button, event) {
|
_otherUserClicked: function(button, event) {
|
||||||
|
Loading…
Reference in New Issue
Block a user