+/*global u2f*/
Ext.define('PVE.window.LoginWindow', {
extend: 'Ext.window.Window',
return;
}
- var perform_u2f_fn;
- var finish_u2f_fn;
-
- var failure_fn = function(resp) {
- view.el.unmask();
- var handler = function() {
- var uf = me.lookupReference('usernameField');
- uf.focus(true, true);
- };
-
- Ext.MessageBox.alert(gettext('Error'),
- gettext("Login failed. Please try again"),
- handler);
- };
-
- var success_fn = function(data) {
- var handler = view.handler || Ext.emptyFn;
- handler.call(me, data);
- view.close();
- };
-
view.el.mask(gettext('Please wait...'), 'x-mask-loading');
// set or clear username
form.submit({
failure: function(f, resp){
- failure_fn(resp);
+ me.failure(resp);
},
success: function(f, resp){
view.el.unmask();
var data = resp.result.data;
- if (Ext.isDefined(data.U2FChallenge)) {
- perform_u2f_fn(data);
+ if (Ext.isDefined(data.NeedTFA)) {
+ // Store first factor login information first:
+ data.LoggedOut = true;
+ Proxmox.Utils.setAuthData(data);
+
+ if (Ext.isDefined(data.U2FChallenge)) {
+ me.perform_u2f(data);
+ } else {
+ me.perform_otp();
+ }
} else {
- success_fn(data);
+ me.success(data);
}
}
});
- perform_u2f_fn = function(data) {
- // Store first factor login information first:
- data.LoggedOut = true;
- Proxmox.Utils.setAuthData(data);
- // Show the message:
- var msg = Ext.Msg.show({
- title: 'U2F: '+gettext('Verification'),
- message: gettext('Please press the button on your U2F Device'),
- buttons: []
- });
- var chlg = data.U2FChallenge;
- var key = {
- version: chlg.version,
- keyHandle: chlg.keyHandle
- };
- u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
- msg.close();
- if (res.errorCode) {
- Proxmox.Utils.authClear();
- Ext.Msg.alert(gettext('Error'), "U2F Error: "+res.errorCode);
- return;
- }
- delete res.errorCode;
- finish_u2f_fn(res);
- });
+ },
+ failure: function(resp) {
+ var me = this;
+ var view = me.getView();
+ view.el.unmask();
+ var handler = function() {
+ var uf = me.lookupReference('usernameField');
+ uf.focus(true, true);
};
- finish_u2f_fn = function(res) {
- view.el.mask(gettext('Please wait...'), 'x-mask-loading');
- var params = { response: JSON.stringify(res) };
- Proxmox.Utils.API2Request({
- url: '/api2/extjs/access/tfa',
- params: params,
- method: 'POST',
- timeout: 5000, // it'll delay both success & failure
- success: function(resp, opts) {
- view.el.unmask();
- // Fill in what we copy over from the 1st factor:
- var data = resp.result.data;
- data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
- data.username = Proxmox.UserName;
- // Finish logging in:
- success_fn(data);
- },
- failure: function(resp, opts) {
- Proxmox.Utils.authClear();
- failure_fn(resp);
- }
- });
+ let emsg = gettext("Login failed. Please try again");
+
+ if (resp.failureType === "connect") {
+ emsg = gettext("Connection failure. Network error or Proxmox VE services not running?");
+ }
+
+ Ext.MessageBox.alert(gettext('Error'), emsg, handler);
+ },
+ success: function(data) {
+ var me = this;
+ var view = me.getView();
+ var handler = view.handler || Ext.emptyFn;
+ handler.call(me, data);
+ view.close();
+ },
+
+ perform_otp: function() {
+ var me = this;
+ var win = Ext.create('PVE.window.TFALoginWindow', {
+ onLogin: function(value) {
+ me.finish_tfa(value);
+ },
+ onCancel: function() {
+ Proxmox.LoggedOut = false;
+ Proxmox.Utils.authClear();
+ me.getView().show();
+ }
+ });
+ win.show();
+ },
+
+ perform_u2f: function(data) {
+ var me = this;
+ // Show the message:
+ var msg = Ext.Msg.show({
+ title: 'U2F: '+gettext('Verification'),
+ message: gettext('Please press the button on your U2F Device'),
+ buttons: []
+ });
+ var chlg = data.U2FChallenge;
+ var key = {
+ version: chlg.version,
+ keyHandle: chlg.keyHandle
};
+ u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
+ msg.close();
+ if (res.errorCode) {
+ Proxmox.Utils.authClear();
+ Ext.Msg.alert(gettext('Error'), PVE.Utils.render_u2f_error(res.errorCode));
+ return;
+ }
+ delete res.errorCode;
+ me.finish_tfa(JSON.stringify(res));
+ });
+ },
+ finish_tfa: function(res) {
+ var me = this;
+ var view = me.getView();
+ view.el.mask(gettext('Please wait...'), 'x-mask-loading');
+ var params = { response: res };
+ Proxmox.Utils.API2Request({
+ url: '/api2/extjs/access/tfa',
+ params: params,
+ method: 'POST',
+ timeout: 5000, // it'll delay both success & failure
+ success: function(resp, opts) {
+ view.el.unmask();
+ // Fill in what we copy over from the 1st factor:
+ var data = resp.result.data;
+ data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
+ data.username = Proxmox.UserName;
+ // Finish logging in:
+ me.success(data);
+ },
+ failure: function(resp, opts) {
+ Proxmox.Utils.authClear();
+ me.failure(resp);
+ }
+ });
},
control: {
}
}
},
- 'field[name=realm]': {
- change: function(f, value) {
- var otp_field = this.lookupReference('otpField');
- if (f.needOTP(value)) {
- otp_field.setConfig('allowBlank', false);
- otp_field.setEmptyText(gettext('2nd factor'));
- } else {
- otp_field.setConfig('allowBlank', true);
- otp_field.setEmptyText(gettext('2nd factor, if required'));
- }
- otp_field.validate();
- }
- },
'field[name=lang]': {
change: function(f, value) {
var dt = Ext.Date.add(new Date(), Ext.Date.YEAR, 10);
},
width: 400,
-
modal: true,
-
border: false,
-
draggable: true,
-
closable: false,
-
resizable: false,
-
layout: 'auto',
title: gettext('Proxmox VE Login'),
defaultFocus: 'usernameField',
-
defaultButton: 'loginButton',
items: [{
reference: 'passwordField'
},
{
- xtype: 'textfield',
- fieldLabel: gettext('OTP'),
- name: 'otp',
- reference: 'otpField',
- allowBlank: true,
- emptyText: gettext('2nd factor, if required')
- },
- {
- xtype: 'pveRealmComboBox',
+ xtype: 'pmxRealmComboBox',
name: 'realm'
},
{
name: 'saveusername',
reference: 'saveunField',
stateId: 'login-saveusername',
- labelWidth: 'auto',
+ labelWidth: 250,
labelAlign: 'right',
submitValue: false
},
]
}]
});
+Ext.define('PVE.window.TFALoginWindow', {
+ extend: 'Ext.window.Window',
+
+ modal: true,
+ resizable: false,
+ title: 'Two-Factor Authentication',
+ layout: 'form',
+ defaultButton: 'loginButton',
+ defaultFocus: 'otpField',
+
+ controller: {
+ xclass: 'Ext.app.ViewController',
+ login: function() {
+ var me = this;
+ var view = me.getView();
+ view.onLogin(me.lookup('otpField').getValue());
+ view.close();
+ },
+ cancel: function() {
+ var me = this;
+ var view = me.getView();
+ view.onCancel();
+ view.close();
+ }
+ },
+
+ items: [
+ {
+ xtype: 'textfield',
+ fieldLabel: gettext('Please enter your OTP verification code:'),
+ name: 'otp',
+ itemId: 'otpField',
+ reference: 'otpField',
+ allowBlank: false
+ }
+ ],
+
+ buttons: [
+ {
+ text: gettext('Login'),
+ reference: 'loginButton',
+ handler: 'login'
+ },
+ {
+ text: gettext('Cancel'),
+ handler: 'cancel'
+ }
+ ]
+});