From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 9280D69888 for ; Thu, 11 Mar 2021 14:51:04 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 8526629787 for ; Thu, 11 Mar 2021 14:51:04 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id E28A629777 for ; Thu, 11 Mar 2021 14:51:02 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id ACDB441DBC for ; Thu, 11 Mar 2021 14:51:02 +0100 (CET) To: pmg-devel@lists.proxmox.com References: <20210309141401.19237-1-w.bumiller@proxmox.com> <20210309141401.19237-16-w.bumiller@proxmox.com> From: Dominik Csapak Message-ID: Date: Thu, 11 Mar 2021 14:51:01 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.7.1 MIME-Version: 1.0 In-Reply-To: <20210309141401.19237-16-w.bumiller@proxmox.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.191 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment NICE_REPLY_A -0.001 Looks like a legit reply (A) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pmg-devel] [PATCH widget-toolkit 5/7] add ACME account panel X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Mar 2021 13:51:04 -0000 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 > --- > 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); > + }, > + }); > + }, > +}); >