]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/Workspace.js
ui: add TokenView with fixed userid
[pve-manager.git] / www / manager6 / Workspace.js
1 /*
2 * Workspace base class
3 *
4 * popup login window when auth fails (call onLogin handler)
5 * update (re-login) ticket every 15 minutes
6 *
7 */
8
9 Ext.define('PVE.Workspace', {
10 extend: 'Ext.container.Viewport',
11
12 title: 'Proxmox Virtual Environment',
13
14 loginData: null, // Data from last login call
15
16 onLogin: function(loginData) {},
17
18 // private
19 updateLoginData: function(loginData) {
20 var me = this;
21 me.loginData = loginData;
22 Proxmox.Utils.setAuthData(loginData);
23
24 var rt = me.down('pveResourceTree');
25 rt.setDatacenterText(loginData.clustername);
26
27 if (loginData.cap) {
28 Ext.state.Manager.set('GuiCap', loginData.cap);
29 }
30 me.response401count = 0;
31
32 me.onLogin(loginData);
33 },
34
35 // private
36 showLogin: function() {
37 var me = this;
38
39 Proxmox.Utils.authClear();
40 Proxmox.UserName = null;
41 me.loginData = null;
42
43 if (!me.login) {
44 me.login = Ext.create('PVE.window.LoginWindow', {
45 handler: function(data) {
46 me.login = null;
47 me.updateLoginData(data);
48 Proxmox.Utils.checked_command(function() {}); // display subscription status
49 }
50 });
51 }
52 me.onLogin(null);
53 me.login.show();
54 },
55
56 initComponent : function() {
57 var me = this;
58
59 Ext.tip.QuickTipManager.init();
60
61 // fixme: what about other errors
62 Ext.Ajax.on('requestexception', function(conn, response, options) {
63 if (response.status == 401 && !PVE.Utils.silenceAuthFailures) { // auth failure
64 // don't immediately show as logged out to cope better with some big
65 // upgrades, which may temporarily produce a false positive 401 err
66 me.response401count++;
67 if (me.response401count > 5) {
68 me.showLogin();
69 }
70 }
71 });
72
73 me.callParent();
74
75 if (!Proxmox.Utils.authOK()) {
76 me.showLogin();
77 } else {
78 if (me.loginData) {
79 me.onLogin(me.loginData);
80 }
81 }
82
83 Ext.TaskManager.start({
84 run: function() {
85 var ticket = Proxmox.Utils.authOK();
86 if (!ticket || !Proxmox.UserName) {
87 return;
88 }
89
90 Ext.Ajax.request({
91 params: {
92 username: Proxmox.UserName,
93 password: ticket
94 },
95 url: '/api2/json/access/ticket',
96 method: 'POST',
97 success: function(response, opts) {
98 var obj = Ext.decode(response.responseText);
99 me.updateLoginData(obj.data);
100 }
101 });
102 },
103 interval: 15*60*1000
104 });
105
106 }
107 });
108
109 Ext.define('PVE.StdWorkspace', {
110 extend: 'PVE.Workspace',
111
112 alias: ['widget.pveStdWorkspace'],
113
114 // private
115 setContent: function(comp) {
116 var me = this;
117
118 var cont = me.child('#content');
119
120 var lay = cont.getLayout();
121
122 var cur = lay.getActiveItem();
123
124 if (comp) {
125 Proxmox.Utils.setErrorMask(cont, false);
126 comp.border = false;
127 cont.add(comp);
128 if (cur !== null && lay.getNext()) {
129 lay.next();
130 var task = Ext.create('Ext.util.DelayedTask', function(){
131 cont.remove(cur);
132 });
133 task.delay(10);
134 }
135 }
136 else {
137 // helper for cleaning the content when logging out
138 cont.removeAll();
139 }
140 },
141
142 selectById: function(nodeid) {
143 var me = this;
144 var tree = me.down('pveResourceTree');
145 tree.selectById(nodeid);
146 },
147
148 onLogin: function(loginData) {
149 var me = this;
150
151 me.updateUserInfo();
152
153 if (loginData) {
154 PVE.data.ResourceStore.startUpdate();
155
156 Proxmox.Utils.API2Request({
157 url: '/version',
158 method: 'GET',
159 success: function(response) {
160 PVE.VersionInfo = response.result.data;
161 me.updateVersionInfo();
162 }
163 });
164
165 Proxmox.Utils.API2Request({
166 url: '/cluster/sdn',
167 method: 'GET',
168 success: function(response) {
169 PVE.SDNInfo = response.result.data;
170 },
171 failure: function(response) {
172 PVE.SDNInfo = null;
173 let ui = Ext.ComponentQuery.query('treelistitem[text="SDN"]')[0];
174 if (ui) {
175 ui.addCls('x-hidden-display');
176 }
177 },
178 });
179 }
180 },
181
182 updateUserInfo: function() {
183 var me = this;
184 var ui = me.query('#userinfo')[0];
185 ui.setText(Proxmox.UserName || '');
186 ui.updateLayout();
187 },
188
189 updateVersionInfo: function() {
190 var me = this;
191
192 var ui = me.query('#versioninfo')[0];
193
194 if (PVE.VersionInfo) {
195 var version = PVE.VersionInfo.version;
196 ui.update('Virtual Environment ' + version);
197 } else {
198 ui.update('Virtual Environment');
199 }
200 ui.updateLayout();
201 },
202
203 initComponent : function() {
204 var me = this;
205
206 Ext.History.init();
207
208 var sprovider = Ext.create('PVE.StateProvider');
209 Ext.state.Manager.setProvider(sprovider);
210
211 var selview = Ext.create('PVE.form.ViewSelector');
212
213 var rtree = Ext.createWidget('pveResourceTree', {
214 viewFilter: selview.getViewFilter(),
215 flex: 1,
216 selModel: {
217 selType: 'treemodel',
218 listeners: {
219 selectionchange: function(sm, selected) {
220 if (selected.length > 0) {
221 var n = selected[0];
222 var tlckup = {
223 root: 'PVE.dc.Config',
224 node: 'PVE.node.Config',
225 qemu: 'PVE.qemu.Config',
226 lxc: 'PVE.lxc.Config',
227 storage: 'PVE.storage.Browser',
228 sdn: 'PVE.sdn.Browser',
229 pool: 'pvePoolConfig'
230 };
231 var comp = {
232 xtype: tlckup[n.data.type || 'root'] ||
233 'pvePanelConfig',
234 showSearch: (n.data.id === 'root') ||
235 Ext.isDefined(n.data.groupbyid),
236 pveSelNode: n,
237 workspace: me,
238 viewFilter: selview.getViewFilter()
239 };
240 PVE.curSelectedNode = n;
241 me.setContent(comp);
242 }
243 }
244 }
245 }
246 });
247
248 selview.on('select', function(combo, records) {
249 if (records) {
250 var view = combo.getViewFilter();
251 rtree.setViewFilter(view);
252 }
253 });
254
255 var caps = sprovider.get('GuiCap');
256
257 var createVM = Ext.createWidget('button', {
258 pack: 'end',
259 margin: '3 5 0 0',
260 baseCls: 'x-btn',
261 iconCls: 'fa fa-desktop',
262 text: gettext("Create VM"),
263 disabled: !caps.vms['VM.Allocate'],
264 handler: function() {
265 var wiz = Ext.create('PVE.qemu.CreateWizard', {});
266 wiz.show();
267 }
268 });
269
270 var createCT = Ext.createWidget('button', {
271 pack: 'end',
272 margin: '3 5 0 0',
273 baseCls: 'x-btn',
274 iconCls: 'fa fa-cube',
275 text: gettext("Create CT"),
276 disabled: !caps.vms['VM.Allocate'],
277 handler: function() {
278 var wiz = Ext.create('PVE.lxc.CreateWizard', {});
279 wiz.show();
280 }
281 });
282
283 sprovider.on('statechange', function(sp, key, value) {
284 if (key === 'GuiCap' && value) {
285 caps = value;
286 createVM.setDisabled(!caps.vms['VM.Allocate']);
287 createCT.setDisabled(!caps.vms['VM.Allocate']);
288 }
289 });
290
291 Ext.apply(me, {
292 layout: { type: 'border' },
293 border: false,
294 items: [
295 {
296 region: 'north',
297 layout: {
298 type: 'hbox',
299 align: 'middle'
300 },
301 baseCls: 'x-plain',
302 defaults: {
303 baseCls: 'x-plain'
304 },
305 border: false,
306 margin: '2 0 2 5',
307 items: [
308 {
309 html: '<a class="x-unselectable" target=_blank href="https://www.proxmox.com">' +
310 '<img style="padding-top:4px;padding-right:5px" src="/pve2/images/proxmox_logo.png"/></a>'
311 },
312 {
313 minWidth: 150,
314 id: 'versioninfo',
315 html: 'Virtual Environment'
316 },
317 {
318 xtype: 'pveGlobalSearchField',
319 tree: rtree
320 },
321 {
322 flex: 1
323 },
324 {
325 xtype: 'proxmoxHelpButton',
326 hidden: false,
327 baseCls: 'x-btn',
328 iconCls: 'fa fa-book x-btn-icon-el-default-toolbar-small ',
329 listenToGlobalEvent: false,
330 onlineHelp: 'pve_documentation_index',
331 text: gettext('Documentation'),
332 margin: '0 5 0 0'
333 },
334 createVM,
335 createCT,
336 {
337 pack: 'end',
338 margin: '0 5 0 0',
339 id: 'userinfo',
340 xtype: 'button',
341 baseCls: 'x-btn',
342 style: {
343 // proxmox dark grey p light grey as border
344 backgroundColor: '#464d4d',
345 borderColor: '#ABBABA'
346 },
347 iconCls: 'fa fa-user',
348 menu: [
349 {
350 iconCls: 'fa fa-gear',
351 text: gettext('My Settings'),
352 handler: function() {
353 var win = Ext.create('PVE.window.Settings');
354 win.show();
355 }
356 },
357 {
358 text: gettext('Password'),
359 iconCls: 'fa fa-fw fa-key',
360 handler: function() {
361 var win = Ext.create('Proxmox.window.PasswordEdit', {
362 userid: Proxmox.UserName
363 });
364 win.show();
365 }
366 },
367 {
368 text: 'TFA',
369 iconCls: 'fa fa-fw fa-lock',
370 handler: function(btn, event, rec) {
371 var win = Ext.create('PVE.window.TFAEdit',{
372 userid: Proxmox.UserName
373 });
374 win.show();
375 }
376 },
377 {
378 text: gettext('API Tokens'),
379 iconCls: 'fa fa-fw fa-user-o',
380 handler: function(btn, event, rec) {
381 var win = Ext.create('PVE.window.TokenView',{
382 userid: Proxmox.UserName
383 });
384 win.show();
385 }
386 },
387 '-',
388 {
389 iconCls: 'fa fa-fw fa-sign-out',
390 text: gettext("Logout"),
391 handler: function() {
392 PVE.data.ResourceStore.loadData([], false);
393 me.showLogin();
394 me.setContent(null);
395 var rt = me.down('pveResourceTree');
396 rt.setDatacenterText(undefined);
397 rt.clearTree();
398
399 // empty the stores of the StatusPanel child items
400 var statusPanels = Ext.ComponentQuery.query('pveStatusPanel grid');
401 Ext.Array.forEach(statusPanels, function(comp) {
402 if (comp.getStore()) {
403 comp.getStore().loadData([], false);
404 }
405 });
406 }
407 }
408 ]
409 }
410 ]
411 },
412 {
413 region: 'center',
414 stateful: true,
415 stateId: 'pvecenter',
416 minWidth: 100,
417 minHeight: 100,
418 id: 'content',
419 xtype: 'container',
420 layout: { type: 'card' },
421 border: false,
422 margin: '0 5 0 0',
423 items: []
424 },
425 {
426 region: 'west',
427 stateful: true,
428 stateId: 'pvewest',
429 itemId: 'west',
430 xtype: 'container',
431 border: false,
432 layout: { type: 'vbox', align: 'stretch' },
433 margin: '0 0 0 5',
434 split: true,
435 width: 200,
436 items: [ selview, rtree ],
437 listeners: {
438 resize: function(panel, width, height) {
439 var viewWidth = me.getSize().width;
440 if (width > viewWidth - 100) {
441 panel.setWidth(viewWidth - 100);
442 }
443 }
444 }
445 },
446 {
447 xtype: 'pveStatusPanel',
448 stateful: true,
449 stateId: 'pvesouth',
450 itemId: 'south',
451 region: 'south',
452 margin:'0 5 5 5',
453 title: gettext('Logs'),
454 collapsible: true,
455 header: false,
456 height: 200,
457 split:true,
458 listeners: {
459 resize: function(panel, width, height) {
460 var viewHeight = me.getSize().height;
461 if (height > (viewHeight - 150)) {
462 panel.setHeight(viewHeight - 150);
463 }
464 }
465 }
466 }
467 ]
468 });
469
470 me.callParent();
471
472 me.updateUserInfo();
473
474 // on resize, center all modal windows
475 Ext.on('resize', function(){
476 var wins = Ext.ComponentQuery.query('window[modal]');
477 if (wins.length > 0) {
478 wins.forEach(function(win){
479 win.alignTo(me, 'c-c');
480 });
481 }
482 });
483 }
484 });
485