]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/window/LoginWindow.js
ui: pci map edit: fix typos in warnings and use gettexts
[pve-manager.git] / www / manager6 / window / LoginWindow.js
CommitLineData
6a1c9c29 1/*global u2f*/
88d5be7d
DM
2Ext.define('PVE.window.LoginWindow', {
3 extend: 'Ext.window.Window',
4
3dd99bab
DM
5 viewModel: {
6 data: {
7 openid: false,
8 },
9 formulas: {
10 button_text: function(get) {
11 if (get("openid") === true) {
12 return gettext("Login (OpenID redirect)");
13 } else {
14 return gettext("Login");
15 }
16 },
17 },
18 },
19
04237985
DM
20 controller: {
21
22 xclass: 'Ext.app.ViewController',
da096950 23
f7447963 24 onLogon: async function() {
da096950
DM
25 var me = this;
26
27 var form = this.lookupReference('loginForm');
65532495
DC
28 var unField = this.lookupReference('usernameField');
29 var saveunField = this.lookupReference('saveunField');
da096950
DM
30 var view = this.getView();
31
24d2ed8c
WB
32 if (!form.isValid()) {
33 return;
34 }
35
3dd99bab
DM
36 let creds = form.getValues();
37
38 if (this.getViewModel().data.openid === true) {
39 const redirectURL = location.origin;
40 Proxmox.Utils.API2Request({
41 url: '/api2/extjs/access/openid/auth-url',
42 params: {
43 realm: creds.realm,
44 "redirect-url": redirectURL,
45 },
46 method: 'POST',
47 success: function(resp, opts) {
48 window.location = resp.result.data;
49 },
50 failure: function(resp, opts) {
51 Proxmox.Utils.authClear();
52 form.unmask();
53 Ext.MessageBox.alert(
54 gettext('Error'),
cfc9f960 55 gettext('OpenID redirect failed.') + `<br>${resp.htmlStatus}`,
3dd99bab
DM
56 );
57 },
58 });
59 return;
60 }
61
24d2ed8c
WB
62 view.el.mask(gettext('Please wait...'), 'x-mask-loading');
63
64 // set or clear username
65 var sp = Ext.state.Manager.getProvider();
66 if (saveunField.getValue() === true) {
67 sp.set(unField.getStateId(), unField.getValue());
68 } else {
69 sp.clear(unField.getStateId());
70 }
71 sp.set(saveunField.getStateId(), saveunField.getValue());
72
f7447963
WB
73 try {
74 // Request updated authentication mechanism:
75 creds['new-format'] = 1;
da096950 76
f7447963
WB
77 let resp = await Proxmox.Async.api2({
78 url: '/api2/extjs/access/ticket',
79 params: creds,
80 method: 'POST',
81 });
82
83 let data = resp.result.data;
84 if (data.ticket.startsWith("PVE:!tfa!")) {
85 // Store first factor login information first:
86 data.LoggedOut = true;
87 Proxmox.Utils.setAuthData(data);
88
89 data = await me.performTFAChallenge(data);
90
91 // Fill in what we copy over from the 1st factor:
92 data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
93 data.username = Proxmox.UserName;
94 me.success(data);
95 } else if (Ext.isDefined(data.NeedTFA)) {
96 // Store first factor login information first:
97 data.LoggedOut = true;
98 Proxmox.Utils.setAuthData(data);
99
100 if (Ext.isDefined(data.U2FChallenge)) {
101 me.perform_u2f(data);
24d2ed8c 102 } else {
f7447963 103 me.perform_otp();
24d2ed8c 104 }
f7447963
WB
105 } else {
106 me.success(data);
107 }
108 } catch (error) {
109 me.failure(error);
110 }
111 },
112
113 /* START NEW TFA CODE (pbs copy) */
114 performTFAChallenge: async function(data) {
115 let me = this;
116
117 let userid = data.username;
118 let ticket = data.ticket;
119 let challenge = JSON.parse(decodeURIComponent(
120 ticket.split(':')[1].slice("!tfa!".length),
121 ));
122
123 let resp = await new Promise((resolve, reject) => {
124 Ext.create('Proxmox.window.TfaLoginWindow', {
125 userid,
126 ticket,
127 challenge,
128 onResolve: value => resolve(value),
129 onReject: reject,
130 }).show();
24d2ed8c 131 });
f7447963
WB
132
133 return resp.result.data;
4c86db12 134 },
f7447963
WB
135 /* END NEW TFA CODE (pbs copy) */
136
4c86db12
TL
137 failure: function(resp) {
138 var me = this;
139 var view = me.getView();
140 view.el.unmask();
141 var handler = function() {
142 var uf = me.lookupReference('usernameField');
143 uf.focus(true, true);
24d2ed8c 144 };
65532495 145
f41b67ab
OB
146 let emsg = gettext("Login failed. Please try again");
147
148 if (resp.failureType === "connect") {
e5d8aebb 149 emsg = gettext("Connection failure. Network error or Proxmox VE services not running?");
f41b67ab
OB
150 }
151
152 Ext.MessageBox.alert(gettext('Error'), emsg, handler);
4c86db12
TL
153 },
154 success: function(data) {
155 var me = this;
156 var view = me.getView();
157 var handler = view.handler || Ext.emptyFn;
158 handler.call(me, data);
159 view.close();
160 },
161
313eb589
WB
162 perform_otp: function() {
163 var me = this;
164 var win = Ext.create('PVE.window.TFALoginWindow', {
165 onLogin: function(value) {
166 me.finish_tfa(value);
167 },
168 onCancel: function() {
169 Proxmox.LoggedOut = false;
170 Proxmox.Utils.authClear();
171 me.getView().show();
f6710aac 172 },
313eb589
WB
173 });
174 win.show();
175 },
176
4c86db12
TL
177 perform_u2f: function(data) {
178 var me = this;
4c86db12
TL
179 // Show the message:
180 var msg = Ext.Msg.show({
181 title: 'U2F: '+gettext('Verification'),
182 message: gettext('Please press the button on your U2F Device'),
f6710aac 183 buttons: [],
4c86db12
TL
184 });
185 var chlg = data.U2FChallenge;
186 var key = {
187 version: chlg.version,
f6710aac 188 keyHandle: chlg.keyHandle,
24d2ed8c 189 };
4c86db12
TL
190 u2f.sign(chlg.appId, chlg.challenge, [key], function(res) {
191 msg.close();
192 if (res.errorCode) {
193 Proxmox.Utils.authClear();
f7447963 194 Ext.Msg.alert(gettext('Error'), PVE.Utils.render_u2f_error(res.errorCode));
4c86db12
TL
195 return;
196 }
197 delete res.errorCode;
313eb589 198 me.finish_tfa(JSON.stringify(res));
4c86db12
TL
199 });
200 },
313eb589 201 finish_tfa: function(res) {
4c86db12
TL
202 var me = this;
203 var view = me.getView();
204 view.el.mask(gettext('Please wait...'), 'x-mask-loading');
4c86db12
TL
205 Proxmox.Utils.API2Request({
206 url: '/api2/extjs/access/tfa',
a901e4ad
TL
207 params: {
208 response: res,
209 },
4c86db12
TL
210 method: 'POST',
211 timeout: 5000, // it'll delay both success & failure
212 success: function(resp, opts) {
213 view.el.unmask();
214 // Fill in what we copy over from the 1st factor:
215 var data = resp.result.data;
216 data.CSRFPreventionToken = Proxmox.CSRFPreventionToken;
217 data.username = Proxmox.UserName;
218 // Finish logging in:
219 me.success(data);
220 },
221 failure: function(resp, opts) {
222 Proxmox.Utils.authClear();
223 me.failure(resp);
f6710aac 224 },
4c86db12 225 });
da096950
DM
226 },
227
228 control: {
229 'field[name=username]': {
230 specialkey: function(f, e) {
231 if (e.getKey() === e.ENTER) {
232 var pf = this.lookupReference('passwordField');
26031ab1 233 if (!pf.getValue()) {
da096950
DM
234 pf.focus(false);
235 }
236 }
f6710aac 237 },
da096950 238 },
da096950
DM
239 'field[name=lang]': {
240 change: function(f, value) {
241 var dt = Ext.Date.add(new Date(), Ext.Date.YEAR, 10);
242 Ext.util.Cookies.set('PVELangCookie', value, dt);
243 this.getView().mask(gettext('Please wait...'), 'x-mask-loading');
244 window.location.reload();
f6710aac 245 },
da096950 246 },
3dd99bab
DM
247 'field[name=realm]': {
248 change: function(f, value) {
249 let record = f.store.getById(value);
250 if (record === undefined) return;
251 let data = record.data;
252 this.getViewModel().set("openid", data.type === "openid");
253 },
254 },
255 'button[reference=loginButton]': {
f6710aac 256 click: 'onLogon',
a901e4ad 257 },
65532495
DC
258 '#': {
259 show: function() {
3dd99bab
DM
260 var me = this;
261
65532495
DC
262 var sp = Ext.state.Manager.getProvider();
263 var checkboxField = this.lookupReference('saveunField');
264 var unField = this.lookupReference('usernameField');
265
266 var checked = sp.get(checkboxField.getStateId());
267 checkboxField.setValue(checked);
268
8058410f 269 if (checked === true) {
65532495 270 var username = sp.get(unField.getStateId());
65532495
DC
271 unField.setValue(username);
272 var pwField = this.lookupReference('passwordField');
273 pwField.focus();
274 }
3dd99bab
DM
275
276 let auth = Proxmox.Utils.getOpenIDRedirectionAuthorization();
277 if (auth !== undefined) {
278 Proxmox.Utils.authClear();
279
280 let loginForm = this.lookupReference('loginForm');
281 loginForm.mask(gettext('OpenID login - please wait...'), 'x-mask-loading');
282
283 const redirectURL = location.origin;
284
285 Proxmox.Utils.API2Request({
286 url: '/api2/extjs/access/openid/login',
287 params: {
288 state: auth.state,
289 code: auth.code,
290 "redirect-url": redirectURL,
291 },
292 method: 'POST',
293 failure: function(response) {
294 loginForm.unmask();
295 let error = response.htmlStatus;
296 Ext.MessageBox.alert(
297 gettext('Error'),
298 gettext('OpenID login failed, please try again') + `<br>${error}`,
299 () => { window.location = redirectURL; },
300 );
301 },
302 success: function(response, options) {
303 loginForm.unmask();
304 let data = response.result.data;
305 history.replaceState(null, '', redirectURL);
306 me.success(data);
307 },
308 });
309 }
f6710aac
TL
310 },
311 },
312 },
04237985 313 },
da096950 314
3262415b 315 width: 400,
3262415b 316 modal: true,
3262415b 317 border: false,
3262415b 318 draggable: true,
3262415b 319 closable: false,
3262415b 320 resizable: false,
3262415b
DM
321 layout: 'auto',
322
323 title: gettext('Proxmox VE Login'),
324
a765aeca 325 defaultFocus: 'usernameField',
551456ff
DC
326 defaultButton: 'loginButton',
327
da096950
DM
328 items: [{
329 xtype: 'form',
330 layout: 'form',
331 url: '/api2/extjs/access/ticket',
332 reference: 'loginForm',
333
334 fieldDefaults: {
335 labelAlign: 'right',
f6710aac 336 allowBlank: false,
da096950
DM
337 },
338
339 items: [
340 {
341 xtype: 'textfield',
342 fieldLabel: gettext('User name'),
343 name: 'username',
a765aeca 344 itemId: 'usernameField',
da096950 345 reference: 'usernameField',
f6710aac 346 stateId: 'login-username',
3dd99bab
DM
347 bind: {
348 visible: "{!openid}",
349 disabled: "{openid}",
350 },
da096950
DM
351 },
352 {
353 xtype: 'textfield',
354 inputType: 'password',
355 fieldLabel: gettext('Password'),
356 name: 'password',
f6710aac 357 reference: 'passwordField',
3dd99bab
DM
358 bind: {
359 visible: "{!openid}",
360 disabled: "{openid}",
361 },
da096950 362 },
da096950 363 {
2892e744 364 xtype: 'pmxRealmComboBox',
f6710aac 365 name: 'realm',
da096950
DM
366 },
367 {
14580653 368 xtype: 'proxmoxLanguageSelector',
da096950 369 fieldLabel: gettext('Language'),
f4aa76c5 370 value: Ext.util.Cookies.get('PVELangCookie') || Proxmox.defaultLang || 'en',
da096950
DM
371 name: 'lang',
372 reference: 'langField',
f6710aac
TL
373 submitValue: false,
374 },
da096950
DM
375 ],
376 buttons: [
65532495
DC
377 {
378 xtype: 'checkbox',
379 fieldLabel: gettext('Save User name'),
380 name: 'saveusername',
381 reference: 'saveunField',
382 stateId: 'login-saveusername',
ecf4b557 383 labelWidth: 250,
65532495 384 labelAlign: 'right',
f6710aac 385 submitValue: false,
3dd99bab
DM
386 bind: {
387 visible: "{!openid}",
388 },
65532495 389 },
da096950 390 {
3dd99bab
DM
391 bind: {
392 text: "{button_text}",
393 },
f6710aac
TL
394 reference: 'loginButton',
395 },
396 ],
397 }],
da096950 398 });