]>
Commit | Line | Data |
---|---|---|
34f956bc DM |
1 | Ext.define('PBS.LoginView', { |
2 | extend: 'Ext.container.Container', | |
3 | xtype: 'loginview', | |
4 | ||
cd975e57 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 | ||
34f956bc DM |
20 | controller: { |
21 | xclass: 'Ext.app.ViewController', | |
22 | ||
fbeac4ea | 23 | submitForm: async function() { |
34f956bc | 24 | var me = this; |
34f956bc | 25 | var loginForm = me.lookupReference('loginForm'); |
9abcae1b DM |
26 | var unField = me.lookupReference('usernameField'); |
27 | var saveunField = me.lookupReference('saveunField'); | |
34f956bc | 28 | |
9abcae1b DM |
29 | if (!loginForm.isValid()) { |
30 | return; | |
31 | } | |
32 | ||
e1d85f18 | 33 | let creds = loginForm.getValues(); |
9abcae1b | 34 | |
cd975e57 | 35 | if (this.getViewModel().data.openid === true) { |
e1d85f18 | 36 | const redirectURL = location.origin; |
cd975e57 | 37 | try { |
3006d70e | 38 | let resp = await Proxmox.Async.api2({ |
cd975e57 DM |
39 | url: '/api2/extjs/access/openid/auth-url', |
40 | params: { | |
e1d85f18 TL |
41 | realm: creds.realm, |
42 | "redirect-url": redirectURL, | |
cd975e57 DM |
43 | }, |
44 | method: 'POST', | |
45 | }); | |
46 | window.location = resp.result.data; | |
3006d70e | 47 | } catch (response) { |
cd975e57 DM |
48 | Proxmox.Utils.authClear(); |
49 | loginForm.unmask(); | |
50 | Ext.MessageBox.alert( | |
51 | gettext('Error'), | |
3006d70e | 52 | gettext('OpenID redirect failed, please try again') + `<br>${response.result.message}`, |
cd975e57 DM |
53 | ); |
54 | } | |
55 | return; | |
56 | } | |
57 | ||
e1d85f18 TL |
58 | creds.username = `${creds.username}@${creds.realm}`; |
59 | delete creds.realm; | |
9abcae1b DM |
60 | |
61 | if (loginForm.isVisible()) { | |
62 | loginForm.mask(gettext('Please wait...'), 'x-mask-loading'); | |
34f956bc | 63 | } |
9abcae1b DM |
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 | ||
fbeac4ea | 74 | try { |
3006d70e | 75 | let resp = await Proxmox.Async.api2({ |
fbeac4ea | 76 | url: '/api2/extjs/access/ticket', |
e1d85f18 | 77 | params: creds, |
fbeac4ea WB |
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) { | |
fbeac4ea WB |
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) => { | |
9a7431e2 | 108 | Ext.create('Proxmox.window.TfaLoginWindow', { |
fbeac4ea WB |
109 | userid, |
110 | ticket, | |
111 | challenge, | |
112 | onResolve: value => resolve(value), | |
113 | onReject: reject, | |
114 | }).show(); | |
9abcae1b | 115 | }); |
fbeac4ea WB |
116 | |
117 | return resp.result.data; | |
34f956bc DM |
118 | }, |
119 | ||
120 | control: { | |
9abcae1b DM |
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 | } | |
8acd4d9a | 129 | }, |
9abcae1b DM |
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(); | |
8acd4d9a | 137 | }, |
9abcae1b | 138 | }, |
cd975e57 DM |
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 | }, | |
34f956bc | 147 | 'button[reference=loginButton]': { |
8acd4d9a | 148 | click: 'submitForm', |
9abcae1b DM |
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 | ||
8acd4d9a | 159 | if (checked === true) { |
9abcae1b DM |
160 | var username = sp.get(unField.getStateId()); |
161 | unField.setValue(username); | |
162 | var pwField = this.lookupReference('passwordField'); | |
163 | pwField.focus(); | |
164 | } | |
cd975e57 | 165 | |
e1d85f18 TL |
166 | let auth = Proxmox.Utils.getOpenIDRedirectionAuthorization(); |
167 | if (auth !== undefined) { | |
cd975e57 DM |
168 | Proxmox.Utils.authClear(); |
169 | ||
170 | let loginForm = this.lookupReference('loginForm'); | |
171 | loginForm.mask(gettext('OpenID login - please wait...'), 'x-mask-loading'); | |
172 | ||
e1d85f18 TL |
173 | // openID checks the original redirection URL we used, so pass that too |
174 | const redirectURL = location.origin; | |
cd975e57 DM |
175 | |
176 | Proxmox.Utils.API2Request({ | |
177 | url: '/api2/extjs/access/openid/login', | |
178 | params: { | |
e1d85f18 TL |
179 | state: auth.state, |
180 | code: auth.code, | |
181 | "redirect-url": redirectURL, | |
cd975e57 DM |
182 | }, |
183 | method: 'POST', | |
184 | failure: function(response) { | |
185 | loginForm.unmask(); | |
85b6c4ea | 186 | let error = response.htmlStatus; |
cd975e57 DM |
187 | Ext.MessageBox.alert( |
188 | gettext('Error'), | |
85b6c4ea TL |
189 | gettext('OpenID login failed, please try again') + `<br>${error}`, |
190 | () => { window.location = redirectURL; }, | |
cd975e57 DM |
191 | ); |
192 | }, | |
193 | success: function(response, options) { | |
194 | loginForm.unmask(); | |
e1d85f18 TL |
195 | let creds = response.result.data; |
196 | PBS.Utils.updateLoginData(creds); | |
cd975e57 | 197 | PBS.app.changeView('mainview'); |
e1d85f18 | 198 | history.replaceState(null, '', `${redirectURL}#pbsDashboard`); |
cd975e57 DM |
199 | }, |
200 | }); | |
201 | } | |
8acd4d9a TL |
202 | }, |
203 | }, | |
204 | }, | |
34f956bc DM |
205 | }, |
206 | ||
207 | plugins: 'viewport', | |
208 | ||
209 | layout: { | |
8acd4d9a | 210 | type: 'border', |
34f956bc DM |
211 | }, |
212 | ||
213 | items: [ | |
214 | { | |
215 | region: 'north', | |
216 | xtype: 'container', | |
217 | layout: { | |
218 | type: 'hbox', | |
8acd4d9a | 219 | align: 'middle', |
34f956bc DM |
220 | }, |
221 | margin: '2 5 2 5', | |
222 | height: 38, | |
223 | items: [ | |
224 | { | |
1d8ef0dc DC |
225 | xtype: 'proxmoxlogo', |
226 | prefix: '', | |
34f956bc DM |
227 | }, |
228 | { | |
229 | xtype: 'versioninfo', | |
8acd4d9a TL |
230 | makeApiCall: false, |
231 | }, | |
232 | ], | |
34f956bc DM |
233 | }, |
234 | { | |
8acd4d9a | 235 | region: 'center', |
34f956bc DM |
236 | }, |
237 | { | |
238 | xtype: 'window', | |
239 | closable: false, | |
240 | resizable: false, | |
241 | reference: 'loginwindow', | |
242 | autoShow: true, | |
243 | modal: true, | |
9abcae1b | 244 | width: 400, |
34f956bc | 245 | |
9abcae1b | 246 | defaultFocus: 'usernameField', |
34f956bc DM |
247 | |
248 | layout: { | |
8acd4d9a | 249 | type: 'auto', |
34f956bc DM |
250 | }, |
251 | ||
252 | title: gettext('Proxmox Backup Server Login'), | |
253 | ||
254 | items: [ | |
255 | { | |
256 | xtype: 'form', | |
257 | layout: { | |
8acd4d9a | 258 | type: 'form', |
34f956bc DM |
259 | }, |
260 | defaultButton: 'loginButton', | |
261 | url: '/api2/extjs/access/ticket', | |
262 | reference: 'loginForm', | |
263 | ||
264 | fieldDefaults: { | |
265 | labelAlign: 'right', | |
8acd4d9a | 266 | allowBlank: false, |
34f956bc DM |
267 | }, |
268 | ||
269 | items: [ | |
270 | { | |
271 | xtype: 'textfield', | |
272 | fieldLabel: gettext('User name'), | |
273 | name: 'username', | |
274 | itemId: 'usernameField', | |
9abcae1b | 275 | reference: 'usernameField', |
8acd4d9a | 276 | stateId: 'login-username', |
24b1c641 | 277 | inputAttrTpl: 'autocomplete=username', |
cd975e57 DM |
278 | bind: { |
279 | visible: "{!openid}", | |
280 | disabled: "{openid}", | |
281 | }, | |
34f956bc DM |
282 | }, |
283 | { | |
284 | xtype: 'textfield', | |
285 | inputType: 'password', | |
286 | fieldLabel: gettext('Password'), | |
287 | name: 'password', | |
3a841004 TL |
288 | itemId: 'passwordField', |
289 | reference: 'passwordField', | |
24b1c641 | 290 | inputAttrTpl: 'autocomplete=current-password', |
cd975e57 DM |
291 | bind: { |
292 | visible: "{!openid}", | |
293 | disabled: "{openid}", | |
294 | }, | |
9abcae1b | 295 | }, |
1d8ef0dc DC |
296 | { |
297 | xtype: 'pmxRealmComboBox', | |
8acd4d9a | 298 | name: 'realm', |
1d8ef0dc | 299 | }, |
9abcae1b DM |
300 | { |
301 | xtype: 'proxmoxLanguageSelector', | |
302 | fieldLabel: gettext('Language'), | |
a554ac19 | 303 | value: Ext.util.Cookies.get('PBSLangCookie') || Proxmox.defaultLang || '__default__', |
9abcae1b DM |
304 | name: 'lang', |
305 | reference: 'langField', | |
8acd4d9a TL |
306 | submitValue: false, |
307 | }, | |
34f956bc DM |
308 | ], |
309 | buttons: [ | |
9abcae1b DM |
310 | { |
311 | xtype: 'checkbox', | |
312 | fieldLabel: gettext('Save User name'), | |
313 | name: 'saveusername', | |
314 | reference: 'saveunField', | |
315 | stateId: 'login-saveusername', | |
316 | labelWidth: 250, | |
317 | labelAlign: 'right', | |
8acd4d9a | 318 | submitValue: false, |
cd975e57 DM |
319 | bind: { |
320 | visible: "{!openid}", | |
321 | }, | |
9abcae1b | 322 | }, |
34f956bc | 323 | { |
cd975e57 DM |
324 | bind: { |
325 | text: "{button_text}", | |
326 | }, | |
34f956bc | 327 | reference: 'loginButton', |
8acd4d9a TL |
328 | formBind: true, |
329 | }, | |
330 | ], | |
331 | }, | |
332 | ], | |
333 | }, | |
334 | ], | |
34f956bc | 335 | }); |