]> git.proxmox.com Git - proxmox-backup.git/blob - www/LoginView.js
ui: dashboard: fix missing prune jobs on task summary
[proxmox-backup.git] / www / LoginView.js
1 Ext.define('PBS.LoginView', {
2 extend: 'Ext.container.Container',
3 xtype: 'loginview',
4
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
20 controller: {
21 xclass: 'Ext.app.ViewController',
22
23 submitForm: async function() {
24 var me = this;
25 var loginForm = me.lookupReference('loginForm');
26 var unField = me.lookupReference('usernameField');
27 var saveunField = me.lookupReference('saveunField');
28
29 if (!loginForm.isValid()) {
30 return;
31 }
32
33 let creds = loginForm.getValues();
34
35 if (this.getViewModel().data.openid === true) {
36 const redirectURL = location.origin;
37 try {
38 let resp = await Proxmox.Async.api2({
39 url: '/api2/extjs/access/openid/auth-url',
40 params: {
41 realm: creds.realm,
42 "redirect-url": redirectURL,
43 },
44 method: 'POST',
45 });
46 window.location = resp.result.data;
47 } catch (response) {
48 Proxmox.Utils.authClear();
49 loginForm.unmask();
50 Ext.MessageBox.alert(
51 gettext('Error'),
52 gettext('OpenID redirect failed, please try again') + `<br>${response.result.message}`,
53 );
54 }
55 return;
56 }
57
58 creds.username = `${creds.username}@${creds.realm}`;
59 delete creds.realm;
60
61 if (loginForm.isVisible()) {
62 loginForm.mask(gettext('Please wait...'), 'x-mask-loading');
63 }
64
65 // set or clear username
66 var sp = Ext.state.Manager.getProvider();
67 if (saveunField.getValue() === true) {
68 sp.set(unField.getStateId(), unField.getValue());
69 } else {
70 sp.clear(unField.getStateId());
71 }
72 sp.set(saveunField.getStateId(), saveunField.getValue());
73
74 try {
75 let resp = await Proxmox.Async.api2({
76 url: '/api2/extjs/access/ticket',
77 params: creds,
78 method: 'POST',
79 });
80
81 let data = resp.result.data;
82 if (data.ticket.startsWith("PBS:!tfa!")) {
83 data = await me.performTFAChallenge(data);
84 }
85
86 PBS.Utils.updateLoginData(data);
87 PBS.app.changeView('mainview');
88 } catch (error) {
89 Proxmox.Utils.authClear();
90 loginForm.unmask();
91 Ext.MessageBox.alert(
92 gettext('Error'),
93 gettext('Login failed. Please try again'),
94 );
95 }
96 },
97
98 performTFAChallenge: async function(data) {
99 let me = this;
100
101 let userid = data.username;
102 let ticket = data.ticket;
103 let challenge = JSON.parse(decodeURIComponent(
104 ticket.split(':')[1].slice("!tfa!".length),
105 ));
106
107 let resp = await new Promise((resolve, reject) => {
108 Ext.create('Proxmox.window.TfaLoginWindow', {
109 userid,
110 ticket,
111 challenge,
112 onResolve: value => resolve(value),
113 onReject: reject,
114 }).show();
115 });
116
117 return resp.result.data;
118 },
119
120 control: {
121 'field[name=username]': {
122 specialkey: function(f, e) {
123 if (e.getKey() === e.ENTER) {
124 var pf = this.lookupReference('passwordField');
125 if (!pf.getValue()) {
126 pf.focus(false);
127 }
128 }
129 },
130 },
131 'field[name=lang]': {
132 change: function(f, value) {
133 var dt = Ext.Date.add(new Date(), Ext.Date.YEAR, 10);
134 Ext.util.Cookies.set('PBSLangCookie', value, dt);
135 this.getView().mask(gettext('Please wait...'), 'x-mask-loading');
136 window.location.reload();
137 },
138 },
139 'field[name=realm]': {
140 change: function(f, value) {
141 let record = f.store.getById(value);
142 if (record === undefined) return;
143 let data = record.data;
144 this.getViewModel().set("openid", data.type === "openid");
145 },
146 },
147 'button[reference=loginButton]': {
148 click: 'submitForm',
149 },
150 'window[reference=loginwindow]': {
151 show: function() {
152 var sp = Ext.state.Manager.getProvider();
153 var checkboxField = this.lookupReference('saveunField');
154 var unField = this.lookupReference('usernameField');
155
156 var checked = sp.get(checkboxField.getStateId());
157 checkboxField.setValue(checked);
158
159 if (checked === true) {
160 var username = sp.get(unField.getStateId());
161 unField.setValue(username);
162 var pwField = this.lookupReference('passwordField');
163 pwField.focus();
164 }
165
166 let auth = Proxmox.Utils.getOpenIDRedirectionAuthorization();
167 if (auth !== undefined) {
168 Proxmox.Utils.authClear();
169
170 let loginForm = this.lookupReference('loginForm');
171 loginForm.mask(gettext('OpenID login - please wait...'), 'x-mask-loading');
172
173 // openID checks the original redirection URL we used, so pass that too
174 const redirectURL = location.origin;
175
176 Proxmox.Utils.API2Request({
177 url: '/api2/extjs/access/openid/login',
178 params: {
179 state: auth.state,
180 code: auth.code,
181 "redirect-url": redirectURL,
182 },
183 method: 'POST',
184 failure: function(response) {
185 loginForm.unmask();
186 let error = response.htmlStatus;
187 Ext.MessageBox.alert(
188 gettext('Error'),
189 gettext('OpenID login failed, please try again') + `<br>${error}`,
190 () => { window.location = redirectURL; },
191 );
192 },
193 success: function(response, options) {
194 loginForm.unmask();
195 let creds = response.result.data;
196 PBS.Utils.updateLoginData(creds);
197 PBS.app.changeView('mainview');
198 history.replaceState(null, '', `${redirectURL}#pbsDashboard`);
199 },
200 });
201 }
202 },
203 },
204 },
205 },
206
207 plugins: 'viewport',
208
209 layout: {
210 type: 'border',
211 },
212
213 items: [
214 {
215 region: 'north',
216 xtype: 'container',
217 layout: {
218 type: 'hbox',
219 align: 'middle',
220 },
221 margin: '2 5 2 5',
222 height: 38,
223 items: [
224 {
225 xtype: 'proxmoxlogo',
226 prefix: '',
227 },
228 {
229 xtype: 'versioninfo',
230 makeApiCall: false,
231 },
232 ],
233 },
234 {
235 region: 'center',
236 },
237 {
238 xtype: 'window',
239 closable: false,
240 resizable: false,
241 reference: 'loginwindow',
242 autoShow: true,
243 modal: true,
244 width: 400,
245
246 defaultFocus: 'usernameField',
247
248 layout: {
249 type: 'auto',
250 },
251
252 title: gettext('Proxmox Backup Server Login'),
253
254 items: [
255 {
256 xtype: 'form',
257 layout: {
258 type: 'form',
259 },
260 defaultButton: 'loginButton',
261 url: '/api2/extjs/access/ticket',
262 reference: 'loginForm',
263
264 fieldDefaults: {
265 labelAlign: 'right',
266 allowBlank: false,
267 },
268
269 items: [
270 {
271 xtype: 'textfield',
272 fieldLabel: gettext('User name'),
273 name: 'username',
274 itemId: 'usernameField',
275 reference: 'usernameField',
276 stateId: 'login-username',
277 bind: {
278 visible: "{!openid}",
279 disabled: "{openid}",
280 },
281 },
282 {
283 xtype: 'textfield',
284 inputType: 'password',
285 fieldLabel: gettext('Password'),
286 name: 'password',
287 itemId: 'passwordField',
288 reference: 'passwordField',
289 bind: {
290 visible: "{!openid}",
291 disabled: "{openid}",
292 },
293 },
294 {
295 xtype: 'pmxRealmComboBox',
296 name: 'realm',
297 },
298 {
299 xtype: 'proxmoxLanguageSelector',
300 fieldLabel: gettext('Language'),
301 value: Ext.util.Cookies.get('PBSLangCookie') || Proxmox.defaultLang || '__default__',
302 name: 'lang',
303 reference: 'langField',
304 submitValue: false,
305 },
306 ],
307 buttons: [
308 {
309 xtype: 'checkbox',
310 fieldLabel: gettext('Save User name'),
311 name: 'saveusername',
312 reference: 'saveunField',
313 stateId: 'login-saveusername',
314 labelWidth: 250,
315 labelAlign: 'right',
316 submitValue: false,
317 bind: {
318 visible: "{!openid}",
319 },
320 },
321 {
322 bind: {
323 text: "{button_text}",
324 },
325 reference: 'loginButton',
326 formBind: true,
327 },
328 ],
329 },
330 ],
331 },
332 ],
333 });