From 0023ef6ab26464ec5ec9edaeac0192e6496ae0b7 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Thu, 10 Oct 2019 11:22:04 +0200 Subject: [PATCH] add Attachment Quarantine the Quarantine part is mostly copied from VirusQuarantine and adapted the AttachmentGrid is inspired by the SpamScore list this adds a new quarantine type 'Attachment' in the gui, where the admins can review and control the mails in the attachment quarantine it also shows a list of attachment/parts and a link where they can be downloaded (in case the admin want to only forward a single attachment or review the file in detail) Signed-off-by: Dominik Csapak Reviewed-By: Stoiko Ivanov Tested-By: Stoiko Ivanov --- js/AttachmentGrid.js | 61 ++++++++++++ js/AttachmentQuarantine.js | 185 +++++++++++++++++++++++++++++++++++++ js/Makefile | 2 + js/NavigationTree.js | 6 ++ 4 files changed, 254 insertions(+) create mode 100644 js/AttachmentGrid.js create mode 100644 js/AttachmentQuarantine.js diff --git a/js/AttachmentGrid.js b/js/AttachmentGrid.js new file mode 100644 index 0000000..e31bd12 --- /dev/null +++ b/js/AttachmentGrid.js @@ -0,0 +1,61 @@ +Ext.define('PMG.grid.AttachmentGrid',{ + extend: 'Ext.grid.GridPanel', + xtype: 'pmgAttachmentGrid', + + store: { + autoDestroy: true, + fields: [ 'name', 'content-type', 'size' ], + proxy: { + type: 'proxmox', + } + }, + + setID: function(rec) { + var me = this; + if (!rec || !rec.data || !rec.data.id) { + me.getStore().removeAll(); + return; + } + var url = '/api2/json/quarantine/listattachments?id=' + rec.data.id; + me.mailid = rec.data.id; + me.store.proxy.setUrl(url); + me.store.load(); + }, + + emptyText: gettext('No Attachments'), + + download: function() { + alert(arguments); + }, + + columns: [ + { + text: gettext('Filename'), + dataIndex: 'name', + flex: 1, + }, + { + text: gettext('Filetype'), + dataIndex: 'content-type', + renderer: PMG.Utils.render_filetype, + flex: 1, + }, + { + text: gettext('Size'), + renderer: Proxmox.Utils.format_size, + dataIndex: 'size', + flex: 1, + }, + { + header: gettext('Download'), + renderer: function(value, mD, rec) { + var me = this; + let url = '/api2/json/quarantine/download'; + url += '?mailid=' + me.mailid; + url += '&attachmentid=' + rec.data.id; + return ""; + }, + } + ] +}); diff --git a/js/AttachmentQuarantine.js b/js/AttachmentQuarantine.js new file mode 100644 index 0000000..c143d6a --- /dev/null +++ b/js/AttachmentQuarantine.js @@ -0,0 +1,185 @@ +/*global Proxmox*/ +/*jslint confusion: true*/ +/*format is a string and a function*/ +Ext.define('pmg-attachment-list', { + extend: 'Ext.data.Model', + fields: [ 'id', 'envelope_sender', 'from', 'sender', 'receiver', 'subject', + { type: 'integer', name: 'bytes' }, + { type: 'date', dateFormat: 'timestamp', name: 'time' }, + { + type: 'string', + name: 'day', + convert: function(v, rec) { + return Ext.Date.format(rec.get('time'), 'Y-m-d'); + }, depends: ['time'] + } + ], + proxy: { + type: 'proxmox', + url: "/api2/json/quarantine/attachment" + }, + idProperty: 'id' +}); + +Ext.define('PMG.AttachmentQuarantine', { + extend: 'Ext.container.Container', + xtype: 'pmgAttachmentQuarantine', + + border: false, + layout: { type: 'border' }, + + defaults: { border: false }, + + controller: { + + xclass: 'Ext.app.ViewController', + + updatePreview: function(raw, rec) { + var preview = this.lookupReference('preview'); + + if (!rec || !rec.data || !rec.data.id) { + preview.update(''); + preview.setDisabled(true); + return; + } + + var url = '/api2/htmlmail/quarantine/content?id=' + rec.data.id + ((raw)?'&raw=1':''); + preview.setDisabled(false); + preview.update(""); + }, + + toggleRaw: function(button) { + var me = this; + var list = this.lookupReference('list'); + var rec = list.getSelection()[0] || {}; + me.raw = !me.raw; + me.updatePreview(me.raw, rec); + }, + + btnHandler: function(button, e) { + var list = this.lookupReference('list'); + var selected = list.getSelection(); + if (!selected.length) { + return; + } + + var action = button.reference; + + PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() { + list.getController().load(); + }); + }, + + onSelectMail: function() { + var me = this; + var list = this.lookupReference('list'); + var rec = list.getSelection()[0] || {}; + + me.updatePreview(me.raw || false, rec); + this.lookupReference('attachmentlist').setID(rec); + }, + + control: { + 'button[reference=raw]': { + click: 'toggleRaw' + }, + 'pmgQuarantineList': { + selectionChange: 'onSelectMail' + } + } + + }, + + items: [ + { + title: gettext('Attachment Quarantine'), + xtype: 'pmgQuarantineList', + emptyText: gettext('No data in database'), + emailSelection: false, + reference: 'list', + region: 'west', + width: 500, + split: true, + collapsible: false, + store: { + model: 'pmg-attachment-list', + groupField: 'day', + groupDir: 'DESC', + sorters: [{ + property: 'time', + direction: 'DESC' + }] + }, + + columns: [ + { + header: gettext('Sender/Subject'), + dataIndex: 'subject', + renderer: PMG.Utils.sender_renderer, + flex: 1 + }, + { + header: gettext('Size') + ' (KB)', + renderer: function(v) { return Ext.Number.toFixed(v/1024, 0); }, + dataIndex: 'bytes', + align: 'right', + width: 90 + }, + { + header: gettext('Date'), + dataIndex: 'day', + hidden: true + }, + { + xtype: 'datecolumn', + header: gettext('Time'), + dataIndex: 'time', + format: 'H:i:s' + } + ] + }, + { + title: gettext('Selected Mail'), + border: false, + region: 'center', + split: true, + reference: 'preview', + disabled: true, + dockedItems: [ + { + xtype: 'toolbar', + dock: 'top', + items: [ + { + xtype: 'button', + reference: 'raw', + text: gettext('Toggle Raw'), + enableToggle: true, + iconCls: 'fa fa-file-code-o' + }, + '->', + { + reference: 'deliver', + text: gettext('Deliver'), + iconCls: 'fa fa-paper-plane-o', + handler: 'btnHandler' + }, + { + reference: 'delete', + text: gettext('Delete'), + iconCls: 'fa fa-trash-o', + handler: 'btnHandler' + } + ] + }, + { + xtype: 'pmgAttachmentGrid', + minHeight: 50, + maxHeight: 250, + scrollable: true, + reference: 'attachmentlist', + } + ] + } + ] +}); diff --git a/js/Makefile b/js/Makefile index 6f4d449..d377c32 100644 --- a/js/Makefile +++ b/js/Makefile @@ -55,6 +55,8 @@ JSSRC= \ VirusDetectorOptions.js \ VirusQuarantineOptions.js \ VirusQuarantine.js \ + AttachmentQuarantine.js \ + AttachmentGrid.js \ ClamAVDatabase.js \ VirusDetectorConfiguration.js \ LDAPConfig.js \ diff --git a/js/NavigationTree.js b/js/NavigationTree.js index 342c715..b14cf1f 100644 --- a/js/NavigationTree.js +++ b/js/NavigationTree.js @@ -106,6 +106,12 @@ Ext.define('PMG.store.NavigationStore', { path: 'pmgVirusQuarantine', leaf: true }, + { + text: gettext('Attachment Quarantine'), + iconCls: 'fa fa-paperclip', + path: 'pmgAttachmentQuarantine', + leaf: true + }, { text: gettext('User Whitelist'), iconCls: 'fa fa-file-o',