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)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 877617797A for ; Wed, 28 Apr 2021 16:14:33 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 7D834FAC4 for ; Wed, 28 Apr 2021 16:14:03 +0200 (CEST) Received: from dana.proxmox.com (unknown [94.136.29.99]) by firstgate.proxmox.com (Proxmox) with ESMTP id 126EEFAA6 for ; Wed, 28 Apr 2021 16:13:59 +0200 (CEST) Received: by dana.proxmox.com (Postfix, from userid 10037) id CFA0B1C088F; Wed, 28 Apr 2021 16:13:58 +0200 (CEST) From: Lorenz Stechauner To: pve-devel@lists.proxmox.com Date: Wed, 28 Apr 2021 16:13:44 +0200 Message-Id: <20210428141346.240896-1-l.stechauner@proxmox.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 2 AWL -0.050 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records PROLO_LEO1 0.1 Meta Catches all Leo drug variations so far RDNS_NONE 1.274 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH manager 1/1] fix #1710: add retrieve from url button for storage X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Apr 2021 14:14:33 -0000 Add PVE.storage.Retrieve window and PVE.form.hashAlgorithmSelector. Users are now able to download/retrieve any .iso/... file onto their storages and verify file integrity with checksums. Signed-off-by: Lorenz Stechauner --- www/manager6/Makefile | 1 + www/manager6/form/HashAlgorithmSelector.js | 21 +++ www/manager6/storage/ContentView.js | 161 +++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 www/manager6/form/HashAlgorithmSelector.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index afed3283..8e6557d8 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -38,6 +38,7 @@ JSSRC= \ form/GlobalSearchField.js \ form/GroupSelector.js \ form/GuestIDSelector.js \ + form/HashAlgorithmSelector.js \ form/HotplugFeatureSelector.js \ form/IPProtocolSelector.js \ form/IPRefSelector.js \ diff --git a/www/manager6/form/HashAlgorithmSelector.js b/www/manager6/form/HashAlgorithmSelector.js new file mode 100644 index 00000000..4a72cc08 --- /dev/null +++ b/www/manager6/form/HashAlgorithmSelector.js @@ -0,0 +1,21 @@ +Ext.define('PVE.form.hashAlgorithmSelector', { + extend: 'Proxmox.form.KVComboBox', + alias: ['widget.pveHashAlgorithmSelector'], + comboItems: [], + hasNoneOption: false, + initComponent: function() { + var me = this; + me.comboItems = [ + ['md5', 'MD5'], + ['sha1', 'SHA-1'], + ['sha224', 'SHA-224'], + ['sha256', 'SHA-256'], + ['sha384', 'SHA-384'], + ['sha512', 'SHA-512'], + ]; + if (me.hasNoneOption) { + me.comboItems.unshift(['none', 'None']); + } + this.callParent(); + }, +}); diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js index dd6df4b1..7187ebbe 100644 --- a/www/manager6/storage/ContentView.js +++ b/www/manager6/storage/ContentView.js @@ -191,6 +191,153 @@ Ext.define('PVE.storage.Upload', { }, }); +Ext.define('PVE.storage.Retrieve', { + extend: 'Proxmox.window.Edit', + alias: 'widget.pveStorageRetrieve', + + resizable: false, + + modal: true, + + isCreate: true, + + showTaskViewer: true, + upidFieldName: 'upid', + + initComponent: function() { + var me = this; + + if (!me.nodename) { + throw "no node name specified"; + } + if (!me.storage) { + throw "no storage ID specified"; + } + + me.url = `/nodes/${me.nodename}/storage/${me.storage}/retrieve`; + me.method = 'POST'; + + let defaultContent = me.contents[0] || ''; + + let urlField = Ext.create('Ext.form.field.Text', { + name: 'url', + allowBlank: false, + fieldLabel: gettext('URL'), + }); + + let fileNameField = Ext.create('Ext.form.field.Text', { + name: 'filename', + allowBlank: false, + fieldLabel: gettext('File name'), + }); + + let fileSizeField = Ext.create('Ext.form.field.Text', { + name: 'size', + disabled: true, + fieldLabel: gettext('File size'), + emptyText: gettext('unknown'), + }); + + let checksumField = Ext.create('Ext.form.field.Text', { + name: 'checksum', + fieldLabel: gettext('Checksum'), + allowBlank: true, + disabled: true, + emptyText: gettext('none'), + }); + + let checksumAlgField = Ext.create('PVE.form.hashAlgorithmSelector', { + name: 'checksumalg', + fieldLabel: gettext('Hash algorithm'), + allowBlank: true, + hasNoneOption: true, + value: 'none', + }); + + let inputPanel = Ext.create('Proxmox.panel.InputPanel', { + method: 'POST', + waitMsgTarget: true, + border: false, + columnT: [ + urlField, + fileNameField, + ], + column1: [ + { + xtype: 'pveContentTypeSelector', + cts: me.contents, + fieldLabel: gettext('Content'), + name: 'content', + value: defaultContent, + allowBlank: false, + }, + ], + column2: [ + fileSizeField, + ], + advancedColumn1: [ + checksumField, + checksumAlgField, + ], + advancedColumn2: [ + { + xtype: 'checkbox', + name: 'insecure', + fieldLabel: gettext('Trust invalid certificates'), + labelWidth: 150, + }, + ], + }); + + urlField.on('change', function() { + urlField.setValidation("Waiting for response..."); + urlField.validate(); + fileSizeField.setValue(""); + Proxmox.Utils.API2Request({ + url: me.url, + method: 'POST', + params: { + metaonly: 1, + url: me.getValues()['url'], + content: me.getValues()['content'], + }, + failure: function(res, opt) { + urlField.setValidation(res.result.message); + urlField.validate(); + fileSizeField.setValue(""); + }, + success: function(res, opt) { + urlField.setValidation(); + urlField.validate(); + + let data = res.result.data; + fileNameField.setValue(data.filename); + fileSizeField.setValue(Proxmox.Utils.format_size(data.size)); + }, + }); + }); + + checksumAlgField.on('change', function() { + if (this.getValue() === 'none') { + checksumField.setDisabled(true); + checksumField.setValue(""); + checksumField.allowBlank = true; + } else { + checksumField.setDisabled(false); + checksumField.allowBlank = false; + } + }); + + Ext.apply(me, { + title: gettext('Retrieve from URL'), + items: inputPanel, + submitText: gettext('Download'), + }); + + me.callParent(); + }, +}); + Ext.define('PVE.storage.ContentView', { extend: 'Ext.grid.GridPanel', @@ -262,6 +409,19 @@ Ext.define('PVE.storage.ContentView', { }, }); + let retrieveButton = Ext.create('Proxmox.button.Button', { + text: gettext('Retrieve from URL'), + handler: function() { + let win = Ext.create('PVE.storage.Retrieve', { + nodename: nodename, + storage: storage, + contents: [content], + }); + win.show(); + win.on('destroy', reload); + }, + }); + let removeButton = Ext.create('Proxmox.button.StdRemoveButton', { selModel: sm, delay: 5, @@ -276,6 +436,7 @@ Ext.define('PVE.storage.ContentView', { } if (me.useUploadButton) { me.tbar.push(uploadButton); + me.tbar.push(retrieveButton); } if (!me.useCustomRemoveButton) { me.tbar.push(removeButton); -- 2.20.1