[pmg-devel] [PATCH widget-toolkit 5/7] add ACME account panel
Dominik Csapak
d.csapak at proxmox.com
Thu Mar 11 14:51:01 CET 2021
high level question/remark:
would it not be nicer if we set the acmeUrl
in Proxmox.Utils to e.g., /config/acme
and overwrite that in pve ? (like
we do with task descriptions?)
this way the caller does not have to concern
itself with the url and we only set it one time per product
On 3/9/21 3:13 PM, Wolfgang Bumiller wrote:
> Copied from PVE with URLs now being based on the 'acmeUrl'
> property which should point to the acme/ root containing
> /tos, /directories, etc.
>
> Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
> ---
> src/Makefile | 2 +
> src/panel/ACMEAccount.js | 116 ++++++++++++++++++++++
> src/window/ACMEAccount.js | 204 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 322 insertions(+)
> create mode 100644 src/panel/ACMEAccount.js
> create mode 100644 src/window/ACMEAccount.js
>
> diff --git a/src/Makefile b/src/Makefile
> index d782e92..00a25c7 100644
> --- a/src/Makefile
> +++ b/src/Makefile
> @@ -50,6 +50,7 @@ JSSRC= \
> panel/RRDChart.js \
> panel/GaugeWidget.js \
> panel/Certificates.js \
> + panel/ACMEAccount.js \
> window/Edit.js \
> window/PasswordEdit.js \
> window/SafeDestroy.js \
> @@ -58,6 +59,7 @@ JSSRC= \
> window/DiskSmart.js \
> window/ZFSDetail.js \
> window/Certificates.js \
> + window/ACMEAccount.js \
> node/APT.js \
> node/NetworkEdit.js \
> node/NetworkView.js \
> diff --git a/src/panel/ACMEAccount.js b/src/panel/ACMEAccount.js
> new file mode 100644
> index 0000000..c7d329e
> --- /dev/null
> +++ b/src/panel/ACMEAccount.js
> @@ -0,0 +1,116 @@
> +Ext.define('Proxmox.panel.ACMEAccounts', {
> + extend: 'Ext.grid.Panel',
> + xtype: 'pmxACMEAccounts',
> +
> + title: gettext('Accounts'),
> +
> + acmeUrl: undefined,
> +
> + controller: {
> + xclass: 'Ext.app.ViewController',
> +
> + addAccount: function() {
> + let me = this;
> + let view = me.getView();
> + let defaultExists = view.getStore().findExact('name', 'default') !== -1;
> + Ext.create('Proxmox.window.ACMEAccountCreate', {
> + defaultExists,
> + acmeUrl: view.acmeUrl,
> + taskDone: function() {
> + me.reload();
> + },
> + }).show();
> + },
> +
> + viewAccount: function() {
> + let me = this;
> + let view = me.getView();
> + let selection = view.getSelection();
> + if (selection.length < 1) return;
> + Ext.create('Proxmox.window.ACMEAccountView', {
> + url: `${view.acmeUrl}/account/${selection[0].data.name}`,
> + }).show();
> + },
> +
> + reload: function() {
> + let me = this;
> + let view = me.getView();
> + view.getStore().rstore.load();
> + },
> +
> + showTaskAndReload: function(options, success, response) {
> + let me = this;
> + if (!success) return;
> +
> + let upid = response.result.data;
> + Ext.create('Proxmox.window.TaskProgress', {
> + upid,
> + taskDone: function() {
> + me.reload();
> + },
> + }).show();
> + },
> + },
> +
> + minHeight: 150,
> + emptyText: gettext('No Accounts configured'),
> +
> + columns: [
> + {
> + dataIndex: 'name',
> + text: gettext('Name'),
> + renderer: Ext.String.htmlEncode,
> + flex: 1,
> + },
> + ],
> +
> + listeners: {
> + itemdblclick: 'viewAccount',
> + },
> +
> + store: {
> + type: 'diff',
> + autoDestroy: true,
> + autoDestroyRstore: true,
> + rstore: {
> + type: 'update',
> + storeid: 'proxmox-acme-accounts',
> + model: 'proxmox-acme-accounts',
> + autoStart: true,
> + },
> + sorters: 'name',
> + },
> +
> + initComponent: function() {
> + let me = this;
> +
> + if (!me.acmeUrl) {
> + throw "no acmeUrl given";
> + }
> +
> + Ext.apply(me, {
> + tbar: [
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('Add'),
> + selModel: false,
> + handler: 'addAccount',
> + },
> + {
> + xtype: 'proxmoxButton',
> + text: gettext('View'),
> + handler: 'viewAccount',
> + disabled: true,
> + },
> + {
> + xtype: 'proxmoxStdRemoveButton',
> + baseurl: `${me.acmeUrl}/account`,
> + callback: 'showTaskAndReload',
> + },
> + ],
> + });
> +
> + me.callParent();
> + me.store.rstore.proxy.setUrl(`/api2/json/${me.acmeUrl}/account`);
> + },
> +});
> diff --git a/src/window/ACMEAccount.js b/src/window/ACMEAccount.js
> new file mode 100644
> index 0000000..05278a8
> --- /dev/null
> +++ b/src/window/ACMEAccount.js
> @@ -0,0 +1,204 @@
> +Ext.define('Proxmox.window.ACMEAccountCreate', {
> + extend: 'Proxmox.window.Edit',
> + mixins: ['Proxmox.Mixin.CBind'],
> + xtype: 'pmxACMEAccountCreate',
> +
> + acmeUrl: undefined,
> +
> + width: 450,
> + title: gettext('Register Account'),
> + isCreate: true,
> + method: 'POST',
> + submitText: gettext('Register'),
> + showTaskViewer: true,
> + defaultExists: false,
> +
> + items: [
> + {
> + xtype: 'proxmoxtextfield',
> + fieldLabel: gettext('Account Name'),
> + name: 'name',
> + cbind: {
> + emptyText: (get) => get('defaultExists') ? '' : 'default',
> + allowBlank: (get) => !get('defaultExists'),
> + },
> + },
> + {
> + xtype: 'textfield',
> + name: 'contact',
> + vtype: 'email',
> + allowBlank: false,
> + fieldLabel: gettext('E-Mail'),
> + },
> + {
> + xtype: 'proxmoxComboGrid',
> + name: 'directory',
> + reference: 'directory',
> + allowBlank: false,
> + valueField: 'url',
> + displayField: 'name',
> + fieldLabel: gettext('ACME Directory'),
> + store: {
> + autoLoad: true,
> + fields: ['name', 'url'],
> + idProperty: ['name'],
> + proxy: { type: 'proxmox' },
> + sorters: {
> + property: 'name',
> + order: 'ASC',
> + },
> + },
> + listConfig: {
> + columns: [
> + {
> + header: gettext('Name'),
> + dataIndex: 'name',
> + flex: 1,
> + },
> + {
> + header: gettext('URL'),
> + dataIndex: 'url',
> + flex: 1,
> + },
> + ],
> + },
> + listeners: {
> + change: function(combogrid, value) {
> + let me = this;
> +
> + if (!value) {
> + return;
> + }
> +
> + let acmeUrl = me.up('window').acmeUrl;
> +
> + let disp = me.up('window').down('#tos_url_display');
> + let field = me.up('window').down('#tos_url');
> + let checkbox = me.up('window').down('#tos_checkbox');
> +
> + disp.setValue(gettext('Loading'));
> + field.setValue(undefined);
> + checkbox.setValue(undefined);
> + checkbox.setHidden(true);
> +
> + Proxmox.Utils.API2Request({
> + url: `${acmeUrl}/tos`,
> + method: 'GET',
> + params: {
> + directory: value,
> + },
> + success: function(response, opt) {
> + field.setValue(response.result.data);
> + disp.setValue(response.result.data);
> + checkbox.setHidden(false);
> + },
> + failure: function(response, opt) {
> + Ext.Msg.alert(gettext('Error'), response.htmlStatus);
> + },
> + });
> + },
> + },
> + },
> + {
> + xtype: 'displayfield',
> + itemId: 'tos_url_display',
> + renderer: Proxmox.Utils.render_optional_url,
> + name: 'tos_url_display',
> + },
> + {
> + xtype: 'hidden',
> + itemId: 'tos_url',
> + name: 'tos_url',
> + },
> + {
> + xtype: 'proxmoxcheckbox',
> + itemId: 'tos_checkbox',
> + boxLabel: gettext('Accept TOS'),
> + submitValue: false,
> + validateValue: function(value) {
> + if (value && this.checked) {
> + return true;
> + }
> + return false;
> + },
> + },
> + ],
> +
> + initComponent: function() {
> + let me = this;
> +
> + if (!me.acmeUrl) {
> + throw "no acmeUrl given";
> + }
> +
> + me.url = `${me.acmeUrl}/account`;
> +
> + me.callParent();
> +
> + me.lookup('directory')
> + .store
> + .proxy
> + .setUrl(`/api2/json/${me.acmeUrl}/directories`);
> + },
> +});
> +
> +Ext.define('Proxmox.window.ACMEAccountView', {
> + extend: 'Proxmox.window.Edit',
> + xtype: 'pmxACMEAccountView',
> +
> + width: 600,
> + fieldDefaults: {
> + labelWidth: 140,
> + },
> +
> + title: gettext('Account'),
> +
> + items: [
> + {
> + xtype: 'displayfield',
> + fieldLabel: gettext('E-Mail'),
> + name: 'email',
> + },
> + {
> + xtype: 'displayfield',
> + fieldLabel: gettext('Created'),
> + name: 'createdAt',
> + },
> + {
> + xtype: 'displayfield',
> + fieldLabel: gettext('Status'),
> + name: 'status',
> + },
> + {
> + xtype: 'displayfield',
> + fieldLabel: gettext('Directory'),
> + renderer: Proxmox.Utils.render_optional_url,
> + name: 'directory',
> + },
> + {
> + xtype: 'displayfield',
> + fieldLabel: gettext('Terms of Services'),
> + renderer: Proxmox.Utils.render_optional_url,
> + name: 'tos',
> + },
> + ],
> +
> + initComponent: function() {
> + var me = this;
> +
> + me.callParent();
> +
> + // hide OK/Reset button, because we just want to show data
> + me.down('toolbar[dock=bottom]').setVisible(false);
> +
> + me.load({
> + success: function(response) {
> + var data = response.result.data;
> + data.email = data.account.contact[0];
> + data.createdAt = data.account.createdAt;
> + data.status = data.account.status;
> + me.setValues(data);
> + },
> + });
> + },
> +});
>
More information about the pmg-devel
mailing list