]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/dc/OptionView.js
ui: dc/options: show depreacation notice in u2f settings
[pve-manager.git] / www / manager6 / dc / OptionView.js
1 Ext.define('PVE.dc.OptionView', {
2 extend: 'Proxmox.grid.ObjectGrid',
3 alias: ['widget.pveDcOptionView'],
4
5 onlineHelp: 'datacenter_configuration_file',
6
7 monStoreErrors: true,
8
9 add_inputpanel_row: function(name, text, opts) {
10 var me = this;
11
12 opts = opts || {};
13 me.rows = me.rows || {};
14
15 let canEdit = !Object.prototype.hasOwnProperty.call(opts, 'caps') || opts.caps;
16 me.rows[name] = {
17 required: true,
18 defaultValue: opts.defaultValue,
19 header: text,
20 renderer: opts.renderer,
21 editor: canEdit ? {
22 xtype: 'proxmoxWindowEdit',
23 width: opts.width || 350,
24 subject: text,
25 onlineHelp: opts.onlineHelp,
26 fieldDefaults: {
27 labelWidth: opts.labelWidth || 100,
28 },
29 setValues: function(values) {
30 var edit_value = values[name];
31
32 if (opts.parseBeforeSet) {
33 edit_value = PVE.Parser.parsePropertyString(edit_value);
34 }
35
36 Ext.Array.each(this.query('inputpanel'), function(panel) {
37 panel.setValues(edit_value);
38 });
39 },
40 url: opts.url,
41 items: [{
42 xtype: 'inputpanel',
43 onGetValues: function(values) {
44 if (values === undefined || Object.keys(values).length === 0) {
45 return { 'delete': name };
46 }
47 var ret_val = {};
48 ret_val[name] = PVE.Parser.printPropertyString(values);
49 return ret_val;
50 },
51 items: opts.items,
52 }],
53 } : undefined,
54 };
55 },
56
57 render_bwlimits: function(value) {
58 if (!value) {
59 return gettext("None");
60 }
61
62 let parsed = PVE.Parser.parsePropertyString(value);
63 return Object.entries(parsed)
64 .map(([k, v]) => k + ": " + Proxmox.Utils.format_size(v * 1024) + "/s")
65 .join(',');
66 },
67
68 initComponent: function() {
69 var me = this;
70
71 me.add_combobox_row('keyboard', gettext('Keyboard Layout'), {
72 renderer: PVE.Utils.render_kvm_language,
73 comboItems: PVE.Utils.kvm_keymap_array(),
74 defaultValue: '__default__',
75 deleteEmpty: true,
76 });
77 me.add_text_row('http_proxy', gettext('HTTP proxy'), {
78 defaultValue: Proxmox.Utils.noneText,
79 vtype: 'HttpProxy',
80 deleteEmpty: true,
81 });
82 me.add_combobox_row('console', gettext('Console Viewer'), {
83 renderer: PVE.Utils.render_console_viewer,
84 comboItems: PVE.Utils.console_viewer_array(),
85 defaultValue: '__default__',
86 deleteEmpty: true,
87 });
88 me.add_text_row('email_from', gettext('Email from address'), {
89 deleteEmpty: true,
90 vtype: 'proxmoxMail',
91 defaultValue: 'root@$hostname',
92 });
93 me.add_text_row('mac_prefix', gettext('MAC address prefix'), {
94 deleteEmpty: true,
95 vtype: 'MacPrefix',
96 defaultValue: Proxmox.Utils.noneText,
97 });
98 me.add_inputpanel_row('migration', gettext('Migration Settings'), {
99 renderer: PVE.Utils.render_dc_ha_opts,
100 labelWidth: 120,
101 url: "/api2/extjs/cluster/options",
102 defaultKey: 'type',
103 items: [{
104 xtype: 'displayfield',
105 name: 'type',
106 fieldLabel: gettext('Type'),
107 value: 'secure',
108 submitValue: true,
109 }, {
110 xtype: 'proxmoxNetworkSelector',
111 name: 'network',
112 fieldLabel: gettext('Network'),
113 value: null,
114 emptyText: Proxmox.Utils.defaultText,
115 autoSelect: false,
116 skipEmptyText: true,
117 }],
118 });
119 me.add_inputpanel_row('ha', gettext('HA Settings'), {
120 renderer: PVE.Utils.render_dc_ha_opts,
121 labelWidth: 120,
122 url: "/api2/extjs/cluster/options",
123 onlineHelp: 'ha_manager_shutdown_policy',
124 items: [{
125 xtype: 'proxmoxKVComboBox',
126 name: 'shutdown_policy',
127 fieldLabel: gettext('Shutdown Policy'),
128 deleteEmpty: false,
129 value: '__default__',
130 comboItems: [
131 ['__default__', Proxmox.Utils.defaultText + ' (conditional)'],
132 ['freeze', 'freeze'],
133 ['failover', 'failover'],
134 ['migrate', 'migrate'],
135 ['conditional', 'conditional'],
136 ],
137 defaultValue: '__default__',
138 }],
139 });
140 me.add_inputpanel_row('u2f', gettext('U2F Settings'), {
141 renderer: PVE.Utils.render_dc_ha_opts,
142 width: 450,
143 url: "/api2/extjs/cluster/options",
144 onlineHelp: 'pveum_configure_u2f',
145 items: [{
146 xtype: 'textfield',
147 name: 'appid',
148 fieldLabel: gettext('U2F AppID URL'),
149 emptyText: gettext('Defaults to origin'),
150 value: '',
151 deleteEmpty: true,
152 skipEmptyText: true,
153 submitEmptyText: false,
154 }, {
155 xtype: 'textfield',
156 name: 'origin',
157 fieldLabel: gettext('U2F Origin'),
158 emptyText: gettext('Defaults to requesting host URI'),
159 value: '',
160 deleteEmpty: true,
161 skipEmptyText: true,
162 submitEmptyText: false,
163 },
164 {
165 xtype: 'box',
166 height: 25,
167 html: `<span class='pmx-hint'>${gettext('Note:')}</span> `
168 + Ext.String.format(gettext('{0} is deprecated, use {1}'), 'U2F', 'WebAuthn'),
169 },
170 {
171 xtype: 'displayfield',
172 userCls: 'pmx-hint',
173 value: gettext('NOTE: Changing an AppID breaks existing U2F registrations!'),
174 }],
175 });
176 me.add_inputpanel_row('webauthn', gettext('WebAuthn Settings'), {
177 renderer: PVE.Utils.render_dc_ha_opts,
178 width: 450,
179 url: "/api2/extjs/cluster/options",
180 //onlineHelp: 'pveum_configure_webauthn',
181 items: [{
182 xtype: 'textfield',
183 fieldLabel: gettext('Relying Party'),
184 name: 'rp',
185 allowBlank: false,
186 listeners: {
187 dirtychange: (f, isDirty) =>
188 f.up('panel').down('box[id=rpChangeWarning]').setHidden(!f.originalValue || !isDirty),
189 },
190 },
191 {
192 xtype: 'textfield',
193 fieldLabel: gettext('Origin'),
194 name: 'origin',
195 allowBlank: false,
196 },
197 {
198 xtype: 'textfield',
199 fieldLabel: 'ID',
200 name: 'id',
201 allowBlank: false,
202 },
203 {
204 xtype: 'container',
205 layout: 'hbox',
206 items: [
207 {
208 xtype: 'box',
209 flex: 1,
210 },
211 {
212 xtype: 'button',
213 text: gettext('Auto-fill'),
214 iconCls: 'fa fa-fw fa-pencil-square-o',
215 handler: function(button, ev) {
216 let panel = this.up('panel');
217 panel.down('field[name=rp]').setValue(document.location.hostname);
218 panel.down('field[name=origin]').setValue(document.location.origin);
219 panel.down('field[name=id]').setValue(document.location.hostname);
220 },
221 },
222 ],
223 },
224 {
225 xtype: 'box',
226 height: 25,
227 html: `<span class='pmx-hint'>${gettext('Note:')}</span> `
228 + gettext('WebAuthn requires using a trusted certificate.'),
229 },
230 {
231 xtype: 'box',
232 id: 'rpChangeWarning',
233 hidden: true,
234 padding: '5 0 0 0',
235 html: '<i class="fa fa-exclamation-triangle warning"></i> '
236 + gettext('Changing the Relying Party may break existing webAuthn TFA entries.'),
237 }],
238 });
239 me.add_inputpanel_row('bwlimit', gettext('Bandwidth Limits'), {
240 renderer: me.render_bwlimits,
241 width: 450,
242 url: "/api2/extjs/cluster/options",
243 parseBeforeSet: true,
244 labelWidth: 120,
245 items: [{
246 xtype: 'pveBandwidthField',
247 name: 'default',
248 fieldLabel: gettext('Default'),
249 emptyText: gettext('none'),
250 backendUnit: "KiB",
251 },
252 {
253 xtype: 'pveBandwidthField',
254 name: 'restore',
255 fieldLabel: gettext('Backup Restore'),
256 emptyText: gettext('default'),
257 backendUnit: "KiB",
258 },
259 {
260 xtype: 'pveBandwidthField',
261 name: 'migration',
262 fieldLabel: gettext('Migration'),
263 emptyText: gettext('default'),
264 backendUnit: "KiB",
265 },
266 {
267 xtype: 'pveBandwidthField',
268 name: 'clone',
269 fieldLabel: gettext('Clone'),
270 emptyText: gettext('default'),
271 backendUnit: "KiB",
272 },
273 {
274 xtype: 'pveBandwidthField',
275 name: 'move',
276 fieldLabel: gettext('Disk Move'),
277 emptyText: gettext('default'),
278 backendUnit: "KiB",
279 }],
280 });
281 me.add_integer_row('max_workers', gettext('Maximal Workers/bulk-action'), {
282 deleteEmpty: true,
283 defaultValue: 4,
284 minValue: 1,
285 maxValue: 64, // arbitrary but generous limit as limits are good
286 });
287
288 me.selModel = Ext.create('Ext.selection.RowModel', {});
289
290 Ext.apply(me, {
291 tbar: [{
292 text: gettext('Edit'),
293 xtype: 'proxmoxButton',
294 disabled: true,
295 handler: function() { me.run_editor(); },
296 selModel: me.selModel,
297 }],
298 url: "/api2/json/cluster/options",
299 editorConfig: {
300 url: "/api2/extjs/cluster/options",
301 },
302 interval: 5000,
303 cwidth1: 200,
304 listeners: {
305 itemdblclick: me.run_editor,
306 },
307 });
308
309 me.callParent();
310
311 // set the new value for the default console
312 me.mon(me.rstore, 'load', function(store, records, success) {
313 if (!success) {
314 return;
315 }
316
317 var rec = store.getById('console');
318 PVE.VersionInfo.console = rec.data.value;
319 if (rec.data.value === '__default__') {
320 delete PVE.VersionInfo.console;
321 }
322 });
323
324 me.on('activate', me.rstore.startUpdate);
325 me.on('destroy', me.rstore.stopUpdate);
326 me.on('deactivate', me.rstore.stopUpdate);
327 },
328 });