mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-06-24 14:01:36 +00:00

Make origin optional, as it actually is, and its not covered by the challenge anyway. Also, not the thing we name rp, but the ID is important for the validity of existing webauthn records, this error comes from the confusing use of the same named thing in different ways by browsers, us and the webauthn rust crate... Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
357 lines
9.1 KiB
JavaScript
357 lines
9.1 KiB
JavaScript
Ext.define('PVE.dc.OptionView', {
|
|
extend: 'Proxmox.grid.ObjectGrid',
|
|
alias: ['widget.pveDcOptionView'],
|
|
|
|
onlineHelp: 'datacenter_configuration_file',
|
|
|
|
monStoreErrors: true,
|
|
|
|
add_inputpanel_row: function(name, text, opts) {
|
|
var me = this;
|
|
|
|
opts = opts || {};
|
|
me.rows = me.rows || {};
|
|
|
|
let canEdit = !Object.prototype.hasOwnProperty.call(opts, 'caps') || opts.caps;
|
|
me.rows[name] = {
|
|
required: true,
|
|
defaultValue: opts.defaultValue,
|
|
header: text,
|
|
renderer: opts.renderer,
|
|
editor: canEdit ? {
|
|
xtype: 'proxmoxWindowEdit',
|
|
width: opts.width || 350,
|
|
subject: text,
|
|
onlineHelp: opts.onlineHelp,
|
|
fieldDefaults: {
|
|
labelWidth: opts.labelWidth || 100,
|
|
},
|
|
setValues: function(values) {
|
|
var edit_value = values[name];
|
|
|
|
if (opts.parseBeforeSet) {
|
|
edit_value = PVE.Parser.parsePropertyString(edit_value);
|
|
}
|
|
|
|
Ext.Array.each(this.query('inputpanel'), function(panel) {
|
|
panel.setValues(edit_value);
|
|
});
|
|
},
|
|
url: opts.url,
|
|
items: [{
|
|
xtype: 'inputpanel',
|
|
onGetValues: function(values) {
|
|
if (values === undefined || Object.keys(values).length === 0) {
|
|
return { 'delete': name };
|
|
}
|
|
var ret_val = {};
|
|
ret_val[name] = PVE.Parser.printPropertyString(values);
|
|
return ret_val;
|
|
},
|
|
items: opts.items,
|
|
}],
|
|
} : undefined,
|
|
};
|
|
},
|
|
|
|
render_bwlimits: function(value) {
|
|
if (!value) {
|
|
return gettext("None");
|
|
}
|
|
|
|
let parsed = PVE.Parser.parsePropertyString(value);
|
|
return Object.entries(parsed)
|
|
.map(([k, v]) => k + ": " + Proxmox.Utils.format_size(v * 1024) + "/s")
|
|
.join(',');
|
|
},
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
me.add_combobox_row('keyboard', gettext('Keyboard Layout'), {
|
|
renderer: PVE.Utils.render_kvm_language,
|
|
comboItems: Object.entries(PVE.Utils.kvm_keymaps),
|
|
defaultValue: '__default__',
|
|
deleteEmpty: true,
|
|
});
|
|
me.add_text_row('http_proxy', gettext('HTTP proxy'), {
|
|
defaultValue: Proxmox.Utils.noneText,
|
|
vtype: 'HttpProxy',
|
|
deleteEmpty: true,
|
|
});
|
|
me.add_combobox_row('console', gettext('Console Viewer'), {
|
|
renderer: PVE.Utils.render_console_viewer,
|
|
comboItems: Object.entries(PVE.Utils.console_map),
|
|
defaultValue: '__default__',
|
|
deleteEmpty: true,
|
|
});
|
|
me.add_text_row('email_from', gettext('Email from address'), {
|
|
deleteEmpty: true,
|
|
vtype: 'proxmoxMail',
|
|
defaultValue: 'root@$hostname',
|
|
});
|
|
me.add_text_row('mac_prefix', gettext('MAC address prefix'), {
|
|
deleteEmpty: true,
|
|
vtype: 'MacPrefix',
|
|
defaultValue: Proxmox.Utils.noneText,
|
|
});
|
|
me.add_inputpanel_row('migration', gettext('Migration Settings'), {
|
|
renderer: PVE.Utils.render_as_property_string,
|
|
labelWidth: 120,
|
|
url: "/api2/extjs/cluster/options",
|
|
defaultKey: 'type',
|
|
items: [{
|
|
xtype: 'displayfield',
|
|
name: 'type',
|
|
fieldLabel: gettext('Type'),
|
|
value: 'secure',
|
|
submitValue: true,
|
|
}, {
|
|
xtype: 'proxmoxNetworkSelector',
|
|
name: 'network',
|
|
fieldLabel: gettext('Network'),
|
|
value: null,
|
|
emptyText: Proxmox.Utils.defaultText,
|
|
autoSelect: false,
|
|
skipEmptyText: true,
|
|
}],
|
|
});
|
|
me.add_inputpanel_row('ha', gettext('HA Settings'), {
|
|
renderer: PVE.Utils.render_dc_ha_opts,
|
|
labelWidth: 120,
|
|
url: "/api2/extjs/cluster/options",
|
|
onlineHelp: 'ha_manager_shutdown_policy',
|
|
items: [{
|
|
xtype: 'proxmoxKVComboBox',
|
|
name: 'shutdown_policy',
|
|
fieldLabel: gettext('Shutdown Policy'),
|
|
deleteEmpty: false,
|
|
value: '__default__',
|
|
comboItems: [
|
|
['__default__', Proxmox.Utils.defaultText + ' (conditional)'],
|
|
['freeze', 'freeze'],
|
|
['failover', 'failover'],
|
|
['migrate', 'migrate'],
|
|
['conditional', 'conditional'],
|
|
],
|
|
defaultValue: '__default__',
|
|
}],
|
|
});
|
|
me.add_inputpanel_row('u2f', gettext('U2F Settings'), {
|
|
renderer: v => !v ? Proxmox.Utils.NoneText : PVE.Parser.printPropertyString(v),
|
|
width: 450,
|
|
url: "/api2/extjs/cluster/options",
|
|
onlineHelp: 'pveum_configure_u2f',
|
|
items: [{
|
|
xtype: 'textfield',
|
|
name: 'appid',
|
|
fieldLabel: gettext('U2F AppID URL'),
|
|
emptyText: gettext('Defaults to origin'),
|
|
value: '',
|
|
deleteEmpty: true,
|
|
skipEmptyText: true,
|
|
submitEmptyText: false,
|
|
}, {
|
|
xtype: 'textfield',
|
|
name: 'origin',
|
|
fieldLabel: gettext('U2F Origin'),
|
|
emptyText: gettext('Defaults to requesting host URI'),
|
|
value: '',
|
|
deleteEmpty: true,
|
|
skipEmptyText: true,
|
|
submitEmptyText: false,
|
|
},
|
|
{
|
|
xtype: 'box',
|
|
height: 25,
|
|
html: `<span class='pmx-hint'>${gettext('Note:')}</span> `
|
|
+ Ext.String.format(gettext('{0} is deprecated, use {1}'), 'U2F', 'WebAuthn'),
|
|
},
|
|
{
|
|
xtype: 'displayfield',
|
|
userCls: 'pmx-hint',
|
|
value: gettext('NOTE: Changing an AppID breaks existing U2F registrations!'),
|
|
}],
|
|
});
|
|
me.add_inputpanel_row('webauthn', gettext('WebAuthn Settings'), {
|
|
renderer: v => !v ? Proxmox.Utils.NoneText : PVE.Parser.printPropertyString(v),
|
|
width: 450,
|
|
url: "/api2/extjs/cluster/options",
|
|
onlineHelp: 'pveum_configure_webauthn',
|
|
items: [{
|
|
xtype: 'textfield',
|
|
fieldLabel: gettext('Relying Party'),
|
|
name: 'rp',
|
|
allowBlank: false,
|
|
},
|
|
{
|
|
xtype: 'textfield',
|
|
fieldLabel: gettext('Origin'),
|
|
emptyText: Ext.String.format(gettext("Domain Lockdown (e.g., {0})"), document.location.origin),
|
|
name: 'origin',
|
|
allowBlank: true,
|
|
},
|
|
{
|
|
xtype: 'textfield',
|
|
fieldLabel: 'ID',
|
|
name: 'id',
|
|
allowBlank: false,
|
|
listeners: {
|
|
dirtychange: (f, isDirty) =>
|
|
f.up('panel').down('box[id=idChangeWarning]').setHidden(!f.originalValue || !isDirty),
|
|
},
|
|
},
|
|
{
|
|
xtype: 'container',
|
|
layout: 'hbox',
|
|
items: [
|
|
{
|
|
xtype: 'box',
|
|
flex: 1,
|
|
},
|
|
{
|
|
xtype: 'button',
|
|
text: gettext('Auto-fill'),
|
|
iconCls: 'fa fa-fw fa-pencil-square-o',
|
|
handler: function(button, ev) {
|
|
let panel = this.up('panel');
|
|
let fqdn = document.location.hostname;
|
|
|
|
panel.down('field[name=rp]').setValue(fqdn);
|
|
|
|
let idField = panel.down('field[name=id]');
|
|
let currentID = idField.getValue();
|
|
if (!currentID || currentID.length === 0) {
|
|
idField.setValue(fqdn);
|
|
}
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
xtype: 'box',
|
|
height: 25,
|
|
html: `<span class='pmx-hint'>${gettext('Note:')}</span> `
|
|
+ gettext('WebAuthn requires using a trusted certificate.'),
|
|
},
|
|
{
|
|
xtype: 'box',
|
|
id: 'idChangeWarning',
|
|
hidden: true,
|
|
padding: '5 0 0 0',
|
|
html: '<i class="fa fa-exclamation-triangle warning"></i> '
|
|
+ gettext('Changing the ID breaks existing WebAuthn TFA entries.'),
|
|
}],
|
|
});
|
|
me.add_inputpanel_row('bwlimit', gettext('Bandwidth Limits'), {
|
|
renderer: me.render_bwlimits,
|
|
width: 450,
|
|
url: "/api2/extjs/cluster/options",
|
|
parseBeforeSet: true,
|
|
labelWidth: 120,
|
|
items: [{
|
|
xtype: 'pveBandwidthField',
|
|
name: 'default',
|
|
fieldLabel: gettext('Default'),
|
|
emptyText: gettext('none'),
|
|
backendUnit: "KiB",
|
|
},
|
|
{
|
|
xtype: 'pveBandwidthField',
|
|
name: 'restore',
|
|
fieldLabel: gettext('Backup Restore'),
|
|
emptyText: gettext('default'),
|
|
backendUnit: "KiB",
|
|
},
|
|
{
|
|
xtype: 'pveBandwidthField',
|
|
name: 'migration',
|
|
fieldLabel: gettext('Migration'),
|
|
emptyText: gettext('default'),
|
|
backendUnit: "KiB",
|
|
},
|
|
{
|
|
xtype: 'pveBandwidthField',
|
|
name: 'clone',
|
|
fieldLabel: gettext('Clone'),
|
|
emptyText: gettext('default'),
|
|
backendUnit: "KiB",
|
|
},
|
|
{
|
|
xtype: 'pveBandwidthField',
|
|
name: 'move',
|
|
fieldLabel: gettext('Disk Move'),
|
|
emptyText: gettext('default'),
|
|
backendUnit: "KiB",
|
|
}],
|
|
});
|
|
me.add_integer_row('max_workers', gettext('Maximal Workers/bulk-action'), {
|
|
deleteEmpty: true,
|
|
defaultValue: 4,
|
|
minValue: 1,
|
|
maxValue: 64, // arbitrary but generous limit as limits are good
|
|
});
|
|
me.add_inputpanel_row('next-id', gettext('Next Free VMID Range'), {
|
|
renderer: PVE.Utils.render_as_property_string,
|
|
url: "/api2/extjs/cluster/options",
|
|
items: [{
|
|
xtype: 'proxmoxintegerfield',
|
|
name: 'lower',
|
|
fieldLabel: gettext('Lower'),
|
|
emptyText: '100',
|
|
minValue: 100,
|
|
maxValue: 1000 * 1000 * 1000 - 1,
|
|
submitValue: true,
|
|
}, {
|
|
xtype: 'proxmoxintegerfield',
|
|
name: 'upper',
|
|
fieldLabel: gettext('Upper'),
|
|
emptyText: '1.000.000',
|
|
minValue: 100,
|
|
maxValue: 1000 * 1000 * 1000 - 1,
|
|
submitValue: true,
|
|
}],
|
|
});
|
|
|
|
me.selModel = Ext.create('Ext.selection.RowModel', {});
|
|
|
|
Ext.apply(me, {
|
|
tbar: [{
|
|
text: gettext('Edit'),
|
|
xtype: 'proxmoxButton',
|
|
disabled: true,
|
|
handler: function() { me.run_editor(); },
|
|
selModel: me.selModel,
|
|
}],
|
|
url: "/api2/json/cluster/options",
|
|
editorConfig: {
|
|
url: "/api2/extjs/cluster/options",
|
|
},
|
|
interval: 5000,
|
|
cwidth1: 200,
|
|
listeners: {
|
|
itemdblclick: me.run_editor,
|
|
},
|
|
});
|
|
|
|
me.callParent();
|
|
|
|
// set the new value for the default console
|
|
me.mon(me.rstore, 'load', function(store, records, success) {
|
|
if (!success) {
|
|
return;
|
|
}
|
|
|
|
var rec = store.getById('console');
|
|
PVE.VersionInfo.console = rec.data.value;
|
|
if (rec.data.value === '__default__') {
|
|
delete PVE.VersionInfo.console;
|
|
}
|
|
});
|
|
|
|
me.on('activate', me.rstore.startUpdate);
|
|
me.on('destroy', me.rstore.stopUpdate);
|
|
me.on('deactivate', me.rstore.stopUpdate);
|
|
},
|
|
});
|