[pve-devel] [PATCH manager 5/5] ui: node/ACME: rework ACME grid for plugin based domains

Dominik Csapak d.csapak at proxmox.com
Wed May 6 14:15:11 CEST 2020


This is basically a complete rework of the ACME grid.
Instead of having an ObjectGrid, we now have a normal
GridPanel which allows us to show a row for each Domain.

But to achieve this, we need to manually fill the store with data
from the 'acme' and 'acmedomainX' entries of the node config.

We also add an AccountSelector to the tbar and a link to the
datacenter->acme panel (when there is no account)

this also removes the 'register account' and 'view account' buttons,
since those are now available in datacenter->acme

removes the old 'acmeeditor' since that is no longer needed

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
 www/manager6/node/ACME.js | 420 +++++++++++++++++++++++---------------
 1 file changed, 254 insertions(+), 166 deletions(-)

diff --git a/www/manager6/node/ACME.js b/www/manager6/node/ACME.js
index a8bb39d6..f6499d6e 100644
--- a/www/manager6/node/ACME.js
+++ b/www/manager6/node/ACME.js
@@ -1,49 +1,3 @@
-Ext.define('PVE.node.ACMEEditor', {
-    extend: 'Proxmox.window.Edit',
-    xtype: 'pveACMEEditor',
-
-    subject: gettext('Domains'),
-    items: [
-	{
-	    xtype: 'inputpanel',
-	    items: [
-		{
-		    xtype: 'textarea',
-		    fieldLabel: gettext('Domains'),
-		    emptyText: "domain1.example.com\ndomain2.example.com",
-		    name: 'domains'
-		}
-	    ],
-	    onGetValues: function(values) {
-		if (!values.domains) {
-		    return {
-			'delete': 'acme'
-		    };
-		}
-		var domains = values.domains.split(/\n/).join(';');
-		return {
-		    'acme': 'domains=' + domains
-		};
-	    }
-	}
-    ],
-
-    initComponent: function() {
-	var me = this;
-	me.callParent();
-
-	me.load({
-	    success: function(response, opts) {
-		var res = PVE.Parser.parseACME(response.result.data.acme);
-		if (res) {
-		    res.domains = res.domains.join(' ');
-		    me.setValues(res);
-		}
-	    }
-	});
-    }
-});
-
 Ext.define('PVE.node.ACMEAccountCreate', {
     extend: 'Proxmox.window.Edit',
 
@@ -366,138 +320,279 @@ Ext.define('PVE.node.ACMEDomainEdit', {
     },
 });
 
+Ext.define('pve-acme-domains', {
+    extend: 'Ext.data.Model',
+    fields: ['domain', 'type', 'alias', 'plugin', 'configkey'],
+    idProperty: 'domain',
+});
+
 Ext.define('PVE.node.ACME', {
-    extend: 'Proxmox.grid.ObjectGrid',
-    xtype: 'pveACMEView',
+    extend: 'Ext.grid.Panel',
+    alias: 'widget.pveACMEView',
 
     margin: '10 0 0 0',
     title: 'ACME',
 
+    controller: {
+	xclass: 'Ext.app.ViewController',
+
+	addDomain: function() {
+	    let me = this;
+	    let view = me.getView();
+
+	    Ext.create('PVE.node.ACMEDomainEdit', {
+		nodename: view.nodename,
+		nodeconfig: view.nodeconfig,
+		apiCallDone: function() {
+		    me.reload();
+		},
+	    }).show();
+	},
+
+	editDomain: function() {
+	    let me = this;
+	    let view = me.getView();
+
+	    let selection = view.getSelection();
+	    if (selection.length < 1) return;
+
+	    Ext.create('PVE.node.ACMEDomainEdit', {
+		nodename: view.nodename,
+		nodeconfig: view.nodeconfig,
+		domain: selection[0].data,
+		apiCallDone: function() {
+		    me.reload();
+		},
+	    }).show();
+	},
+
+	removeDomain: function() {
+	    let me = this;
+	    let view = me.getView();
+	    let selection = view.getSelection();
+	    if (selection.length < 1) return;
+
+	    let rec = selection[0].data;
+	    let params = {};
+	    if (rec.configkey !== 'acme') {
+		params.delete = rec.configkey;
+	    } else {
+		let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
+		PVE.Utils.remove_domain_from_acme(acme, rec.domain);
+		params.acme = PVE.Parser.printACME(acme);
+	    }
+
+	    Proxmox.Utils.API2Request({
+		method: 'PUT',
+		url: `/nodes/${view.nodename}/config`,
+		params,
+		success: function(response, opt) {
+		    me.reload();
+		},
+		failure: function(response, opt) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		},
+	    });
+	},
+
+	changeAccount: function(cb, value, oldvalue) {
+	    if (value === oldvalue) return;
+	    let me = this;
+	    let view = me.getView();
+	    let params = {};
+
+	    let acme = PVE.Parser.parseACME(view.nodeconfig.acme);
+	    acme.account = value;
+	    params.acme = PVE.Parser.printACME(acme);
+
+	    Proxmox.Utils.API2Request({
+		method: 'PUT',
+		url: `/nodes/${view.nodename}/config`,
+		params,
+		success: function(response, opt) {
+		    me.reload();
+		},
+		failure: function(response, opt) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		},
+	    });
+	},
+
+	order: function() {
+	    let me = this;
+	    let view = me.getView();
+
+	    Proxmox.Utils.API2Request({
+		method: 'POST',
+		params: {
+		    force: 1,
+		},
+		url: `/nodes/${view.nodename}/certificates/acme/certificate`,
+		success: function(response, opt) {
+		    Ext.create('Proxmox.window.TaskViewer', {
+		        upid: response.result.data,
+		        taskDone: function(success) {
+			    me.orderFinished(success);
+		        },
+		    }).show();
+		},
+		failure: function(response, opt) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		},
+	    });
+	},
+
+	orderFinished: function(success) {
+	    if (!success) return;
+	    var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
+	    Ext.getBody().mask(txt, ['pve-static-mask']);
+	    // reload after 10 seconds automatically
+	    Ext.defer(function() {
+		window.location.reload(true);
+	    }, 10000);
+	},
+
+	reload: function() {
+	    let me = this;
+	    let view = me.getView();
+	    view.rstore.load();
+	},
+
+	gotoAccounts: function() {
+	    let sp = Ext.state.Manager.getProvider();
+	    sp.set('dctab', { value: 'acme' }, true);
+	    Ext.ComponentQuery.query('pveResourceTree')[0].selectById('root');
+	},
+    },
+
     tbar: [
 	{
-	    xtype: 'button',
-	    itemId: 'edit',
-	    text: gettext('Edit Domains'),
-	    handler: function() {
-		this.up('grid').run_editor();
-	    }
+	    xtype: 'proxmoxButton',
+	    text: gettext('Add'),
+	    handler: 'addDomain',
+	    selModel: false,
 	},
 	{
-	    xtype: 'button',
-	    itemId: 'createaccount',
-	    text: gettext('Register Account'),
-	    handler: function() {
-		var me = this.up('grid');
-		var win = Ext.create('PVE.node.ACMEAccountCreate', {
-		    taskDone: function() {
-			me.load_account();
-			me.reload();
-		    }
-		});
-		win.show();
-	    }
+	    xtype: 'proxmoxButton',
+	    text: gettext('Edit'),
+	    disabled: true,
+	    handler: 'editDomain',
 	},
 	{
-	    xtype: 'button',
-	    itemId: 'viewaccount',
-	    text: gettext('View Account'),
-	    handler: function() {
-		var me = this.up('grid');
-		var win = Ext.create('PVE.node.ACMEAccountView', {
-		    accountname: 'default'
-		});
-		win.show();
-	    }
+	    xtype: 'proxmoxStdRemoveButton',
+	    handler: 'removeDomain',
 	},
+	'-',
 	{
 	    xtype: 'button',
 	    itemId: 'order',
 	    text: gettext('Order Certificate'),
-	    handler: function() {
-		var me = this.up('grid');
-
-		Proxmox.Utils.API2Request({
-		    method: 'POST',
-		    params: {
-			force: 1
-		    },
-		    url: '/nodes/' + me.nodename + '/certificates/acme/certificate',
-		    success: function(response, opt) {
-			var win = Ext.create('Proxmox.window.TaskViewer', {
-			    upid: response.result.data,
-			    taskDone: function(success) {
-				me.certificate_order_finished(success);
-			    }
-			});
-			win.show();
-		    },
-		    failure: function(response, opt) {
-			Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-		    }
-		});
-	    }
+	    handler: 'order',
+	},
+	'-',
+	{
+	    xtype: 'pveACMEAccountSelector',
+	    itemId: 'accountselector',
+	    fieldLabel: gettext('Account'),
+	    listeners: {
+		change: 'changeAccount',
+	    },
+	},
+	{
+	    xtype: 'button',
+	    hidden: true,
+	    itemId: 'accountlink',
+	    text: gettext('Go to ACME Accounts'),
+	    handler: 'gotoAccounts',
 	}
     ],
 
-    certificate_order_finished: function(success) {
-	if (!success) {
-	    return;
-	}
-	var txt = gettext('pveproxy will be restarted with new certificates, please reload the GUI!');
-	Ext.getBody().mask(txt, ['pve-static-mask']);
-	// reload after 10 seconds automatically
-	Ext.defer(function() {
-	    window.location.reload(true);
-	}, 10000);
+    set_account: function(account) {
+	var me = this;
+	let accountselector = me.down('#accountselector');
+	accountselector.setValue(account);
+	me.down('#accountlink').setVisible(accountselector.isEmpty());
+	me.down('#order').setDisabled(!accountselector.isValid());
+	Proxmox.Utils.setErrorMask(me, false);
     },
 
-    set_button_status: function() {
-	var me = this;
+    updateStore: function(store, records, success) {
+	let me = this;
+	let data = [];
+	let rec;
+	if (success && records.length > 0) {
+	    rec = records[0];
+	} else {
+	    rec = {
+		data: {}
+	    };
+	}
 
-	var account = !!me.account;
-	var acmeObj = PVE.Parser.parseACME(me.getObjectValue('acme'));
-	var domains = acmeObj ? acmeObj.domains.length : 0;
+	me.nodeconfig = rec.data; // save nodeconfig for updates
 
-	var order = me.down('#order');
-	order.setVisible(account);
-	order.setDisabled(!account || !domains);
+	let account = 'default';
 
-	me.down('#createaccount').setVisible(!account);
-	me.down('#viewaccount').setVisible(account);
-    },
+	if (rec.data.acme) {
+	    let obj = PVE.Parser.parseACME(rec.data.acme);
+	    (obj.domains || []).forEach(domain => {
+		if (domain === '') return;
+		let record = {
+		    domain,
+		    type: 'standalone',
+		    configkey: 'acme',
+		};
+		data.push(record);
+	    });
 
-    load_account: function() {
-	var me = this;
+	    if (obj.account) {
+		account = obj.account;
+	    }
+	}
 
-	// for now we only use the 'default' account
 	Proxmox.Utils.API2Request({
-	    url: '/cluster/acme/account/default',
+	    url: `/cluster/acme/account/${account}`,
 	    success: function(response, opt) {
-		me.account = response.result.data;
-		me.set_button_status();
+		me.set_account(account);
 	    },
 	    failure: function(response, opt) {
-		me.account = undefined;
-		me.set_button_status();
-	    }
+		me.set_account(undefined);
+	    },
 	});
-    },
 
-    run_editor: function() {
-	var me = this;
-	var win = Ext.create(me.rows.acme.editor, me.editorConfig);
-	win.show();
-	win.on('destroy', me.reload, me);
+	for (let i = 0; i < PVE.Utils.acmedomain_count; i++) {
+	    let acmedomain = rec.data[`acmedomain${i}`];
+	    if (!acmedomain) continue;
+
+	    let record = PVE.Parser.parsePropertyString(acmedomain, 'domain');
+	    record.type = 'dns';
+	    record.configkey = `acmedomain${i}`;
+	    data.push(record);
+	}
+
+	me.store.loadData(data, false);
     },
 
     listeners: {
-	itemdblclick: 'run_editor'
+	itemdblclick: 'editDomain',
     },
 
-    // account data gets loaded here
-    account: undefined,
-
-    disableSelection: true,
+    columns: [
+	{
+	    dataIndex: 'domain',
+	    flex: 1,
+	    text: gettext('Domain'),
+	},
+	{
+	    dataIndex: 'type',
+	    width: 100,
+	    text: gettext('Type'),
+	},
+	{
+	    dataIndex: 'plugin',
+	    width: 100,
+	    text: gettext('Plugin'),
+	},
+    ],
 
     initComponent: function() {
 	var me = this;
@@ -506,32 +601,25 @@ Ext.define('PVE.node.ACME', {
 	    throw "no nodename given";
 	}
 
-	me.url = '/api2/json/nodes/' + me.nodename + '/config';
-
-	me.editorConfig = {
-	    url: '/api2/extjs/nodes/' + me.nodename + '/config'
-	};
-	/*jslint confusion: true*/
-	/*acme is a string above*/
-	me.rows = {
-	    acme: {
-		defaultValue: '',
-		header: gettext('Domains'),
-		editor: 'PVE.node.ACMEEditor',
-		renderer: function(value) {
-		    var acmeObj = PVE.Parser.parseACME(value);
-		    if (acmeObj) {
-			return acmeObj.domains.join('<br>');
-		    }
-		    return Proxmox.Utils.noneText;
-		}
-	    }
-	};
-	/*jslint confusion: false*/
+	me.rstore = Ext.create('Proxmox.data.UpdateStore', {
+	    autoLoad: true,
+	    interval: 5 * 1000,
+	    autoStart: true,
+	    storeid: `pve-node-domains-${me.nodename}`,
+	    proxy: {
+		type: 'proxmox',
+		url: `/api2/json/nodes/${me.nodename}/config`,
+	    },
+	});
+
+	me.store = Ext.create('Ext.data.Store', {
+	    model: 'pve-acme-domains',
+	    sorters: 'domain',
+	});
 
 	me.callParent();
-	me.mon(me.rstore, 'load', me.set_button_status, me);
+	me.mon(me.rstore, 'load', 'updateStore', me);
 	me.rstore.startUpdate();
-	me.load_account();
-    }
+	Proxmox.Utils.setErrorMask(me, true);
+    },
 });
-- 
2.20.1





More information about the pve-devel mailing list