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