]> git.proxmox.com Git - pmg-gui.git/commitdiff
add Custom Scores panel to the Spam Detector
authorDominik Csapak <d.csapak@proxmox.com>
Thu, 14 Nov 2019 11:18:55 +0000 (12:18 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 15 Nov 2019 09:01:17 +0000 (10:01 +0100)
with this panel, users can manually override a rule score for
SpamAssassin rules. This can be useful sometimes, e.g. if
a certain rule always triggers in a certain environment which
is considered spam by the SpamAssassin rules

after adding/editing a rule, we show diff, similar to the network
panel, and offer a button to apply those changes (and restart
pmg-smtp-filter). the changes can also be reverted

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
js/Makefile
js/SpamDetectorConfiguration.js
js/SpamDetectorCustom.js [new file with mode: 0644]

index 762b43ddc36e96755e40d05e04dfa602c4456a46..e0ac0268f78a87e5551c277293be86a30b72a28e 100644 (file)
@@ -54,6 +54,7 @@ JSSRC=                                                        \
        SpamQuarantineOptions.js                        \
        SpamDetectorStatus.js                           \
        SpamDetectorConfiguration.js                    \
+       SpamDetectorCustom.js                           \
        VirusDetectorOptions.js                         \
        VirusQuarantineOptions.js                       \
        VirusQuarantine.js                              \
index f10c8dc451b773164c449c84e6f7f1ea5c1c7179..2c0d7550aba6a622dc3e3823018eeef9c8fc8161 100644 (file)
@@ -23,7 +23,12 @@ Ext.define('PMG.SpamDetectorConfiguration', {
            title: gettext('Status'),
            itemId: 'status',
            xtype: 'pmgSpamDetectorStatus'
-       }
+       },
+       {
+           title: gettext('Custom Scores'),
+           itemId: 'scores',
+           xtype: 'pmgSpamDetectorCustomScores'
+       },
     ]
 });
 
diff --git a/js/SpamDetectorCustom.js b/js/SpamDetectorCustom.js
new file mode 100644 (file)
index 0000000..34cd95d
--- /dev/null
@@ -0,0 +1,308 @@
+Ext.define('pmg-sa-custom', {
+    extend: 'Ext.data.Model',
+    fields: [ 'name', 'score', 'comment', 'digest' ],
+    idProperty: 'name'
+});
+
+Ext.define('PMG.SpamDetectorCustomScores', {
+    extend: 'Ext.panel.Panel',
+    xtype: 'pmgSpamDetectorCustomScores',
+
+    layout: 'border',
+
+    viewModel: {
+       data: {
+           applied: true,
+           changetext: '',
+           digest: null,
+       },
+    },
+
+    controller: {
+       xclass: 'Ext.app.ViewController',
+
+       reload: function() {
+           var me = this;
+           var vm = this.getViewModel();
+           var grid = me.lookup('grid');
+
+           Proxmox.Utils.API2Request({
+               url: '/config/customscores',
+               failure: function(response, opts) {
+                   grid.getStore().loadData({});
+                   Proxmox.Utils.setErrorMask(grid, response.htmlStatus);
+                   vm.set('digest', null);
+                   vm.set('applied', true);
+                   vm.set('changetext', '');
+               },
+               success: function(response, opts) {
+                   let data = response.result.data;
+                   let digestel = data.pop(); // last element is digest
+                   let changes = response.result.changes;
+                   grid.getStore().loadData(data);
+
+                   vm.set('digest', digestel.digest);
+                   vm.set('applied', !changes);
+                   vm.set('changetext', `<pre>${changes || ''}</pre>`);
+               }
+           });
+       },
+
+       revert: function() {
+           var me = this;
+           var vm = this.getViewModel();
+
+           Proxmox.Utils.API2Request({
+               url: '/config/customscores',
+               method: 'DELETE',
+               param: {
+                   digest: vm.get('digest'),
+               },
+               failure: function(response, opts) {
+                   grid.getStore().loadData({});
+                   Proxmox.Utils.setErrorMask(grid, response.htmlStatus);
+                   vm.set('digest', null);
+                   vm.set('applied', true);
+                   vm.set('changetext', '');
+               },
+               success: () => { me.reload(); },
+           });
+       },
+
+       restart: function() {
+           var me = this;
+           var vm = this.getViewModel();
+
+           var win = Ext.createWidget('proxmoxWindowEdit', {
+               method: 'PUT',
+               url: "/api2/extjs/config/customscores",
+               isCreate: true,
+               submitText: gettext('Apply'),
+               showProgress: true,
+               taskDone: () => { me.reload(); },
+
+               title: gettext("Apply Custom Scores"),
+
+               items: [
+                   {
+                       xtype: 'proxmoxcheckbox',
+                       name: 'restart-daemon',
+                       fieldLabel: gettext('Restart pmg-smtp-filter'),
+                       labelWidth: 150,
+                       checked: true,
+                   },
+                   {
+                       xtype: 'hiddenfield',
+                       name: 'digest',
+                       value: vm.get('digest'),
+                   }
+               ]
+           }).show();
+       },
+
+       create_custom: function() {
+           var me = this;
+           var vm = this.getViewModel();
+
+           var win = Ext.createWidget('proxmoxWindowEdit', {
+               method: 'POST',
+               url: "/api2/extjs/config/customscores",
+               isCreate: true,
+               subject: gettext("Custom Rule Score"),
+               items: [
+                   {
+                       xtype: 'proxmoxtextfield',
+                       name: 'name',
+                       allowBlank: false,
+                       fieldLabel: gettext('Name')
+                   },
+                   {
+                       xtype: 'numberfield',
+                       name: 'score',
+                       allowBlank: false,
+                       fieldLabel: gettext('Score')
+                   },
+
+                   {
+                       xtype: 'proxmoxtextfield',
+                       name: 'comment',
+                       fieldLabel: gettext("Comment")
+                   },
+                   {
+                       xtype: 'hiddenfield',
+                       name: 'digest',
+                       value: vm.get('digest'),
+                   }
+               ]
+           });
+
+           win.on('destroy', me.reload, me);
+           win.show();
+       },
+
+       run_editor: function() {
+           var me = this;
+           var vm = this.getViewModel();
+           var grid = me.lookup('grid');
+           var rec = grid.getSelection()[0];
+           if (!rec) {
+               return;
+           }
+
+           var win = Ext.createWidget('proxmoxWindowEdit', {
+               url: "/api2/extjs/config/customscores/" + rec.data.name,
+               method: 'PUT',
+               subject: gettext("Custom Rule Score"),
+               items: [
+                   {
+                       xtype: 'displayfield',
+                       name: 'name',
+                       fieldLabel: gettext('Name')
+                   },
+                   {
+                       xtype: 'numberfield',
+                       name: 'score',
+                       allowBlank: false,
+                       fieldLabel: gettext('Score')
+                   },
+
+                   {
+                       xtype: 'proxmoxtextfield',
+                       name: 'comment',
+                       fieldLabel: gettext("Comment")
+                   },
+                   {
+                       xtype: 'hiddenfield',
+                       name: 'digest',
+                       value: vm.get('digest'),
+                   }
+               ]
+           });
+
+           win.load();
+           win.on('destroy', me.reload, me);
+           win.show();
+       },
+    },
+
+    listeners: {
+       activate: 'reload',
+    },
+
+    defaults: {
+       border: 0,
+    },
+
+    items: [
+       {
+           xtype: 'gridpanel',
+           region: 'center',
+           reference: 'grid',
+
+           store: {
+               model: 'pmg-sa-custom',
+               proxy: {
+                   type: 'proxmox',
+                   url: "/api2/json/config/customscores"
+               },
+               sorters: {
+                   property: 'name',
+               }
+           },
+
+           tbar: [
+               {
+                   xtype: 'proxmoxButton',
+                   text: gettext('Edit'),
+                   disabled: true,
+                   handler: 'run_editor'
+               },
+               {
+                   text: gettext('Create'),
+                   handler: 'create_custom',
+               },
+               {
+                   xtype: 'proxmoxStdRemoveButton',
+                   getUrl: function(rec) {
+                       let digest = this.up('grid').digest;
+                       let url = `/config/customscores/${rec.getId()}`;
+                       if (digest) {
+                           url += `?digest=${digest}`
+                       }
+                       return url;
+                   },
+                   callback: 'reload',
+               },
+               ' ',
+               {
+                   text: gettext('Revert'),
+                   reference: 'revert_btn',
+                   handler: 'revert',
+                   disabled: true,
+                   bind: {
+                       disabled: '{applied}',
+                   },
+               },
+               '-',
+               {
+                   text: gettext('Apply Custom Scores'),
+                   reference: 'restart_btn',
+                   disabled: true,
+                   bind: {
+                       disabled: '{applied}',
+                   },
+                   handler: 'restart',
+               }
+           ],
+
+           viewConfig: {
+               trackOver: false
+           },
+
+           columns: [
+               {
+                   header: gettext('Name'),
+                   width: 200,
+                   sortable: true,
+                   dataIndex: 'name'
+               },
+               {
+                   header: gettext('Score'),
+                   width: 200,
+                   sortable: true,
+                   dataIndex: 'score'
+               },
+               {
+                   header: gettext('Comment'),
+                   sortable: false,
+                   renderer: Ext.String.htmlEncode,
+                   dataIndex: 'comment',
+                   flex: 1
+               }
+           ],
+
+           listeners: {
+               itemdblclick: 'run_editor',
+           }
+       },
+       {
+           xtype: 'panel',
+           bodyPadding: 5,
+           region: 'south',
+           autoScroll: true,
+           flex: 0.5,
+           hidden: true,
+           bind: {
+               hidden: '{applied}',
+               html: '{changetext}'
+           },
+           reference: 'changes',
+           tbar: [
+               gettext('Pending changes') + ' (' +
+               gettext('Please restart pmg-smtp-filter to activate changes') + ')'
+           ],
+           split: true,
+       }
+    ],
+
+});