]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/grid/FirewallRules.js
1 Ext
.define('PVE.form.FWMacroSelector', {
2 extend
: 'Proxmox.form.ComboGrid',
3 alias
: 'widget.pveFWMacroSelector',
11 header
: gettext('Macro'),
17 header
: gettext('Description'),
18 renderer
: Ext
.String
.htmlEncode
,
24 initComponent: function() {
27 var store
= Ext
.create('Ext.data.Store', {
29 fields
: ['macro', 'descr'],
33 url
: "/api2/json/cluster/firewall/macros",
49 Ext
.define('PVE.FirewallRulePanel', {
50 extend
: 'Proxmox.panel.InputPanel',
54 list_refs_url
: undefined,
56 onGetValues: function(values
) {
59 // hack: editable ComboGrid returns nothing when empty, so we need to set ''
60 // Also, disabled text fields return nothing, so we need to set ''
62 Ext
.Array
.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport', 'log'], function(key
) {
63 if (values
[key
] === undefined) {
68 delete values
.modified_marker
;
73 initComponent: function() {
76 if (!me
.list_refs_url
) {
77 throw "no list_refs_url specified";
82 // hack: we use this field to mark the form 'dirty' when the
83 // record has errors- so that the user can safe the unmodified
86 name
: 'modified_marker',
90 xtype
: 'proxmoxKVComboBox',
93 comboItems
: [['in', 'in'], ['out', 'out']],
94 fieldLabel
: gettext('Direction'),
98 xtype
: 'proxmoxKVComboBox',
101 comboItems
: [['ACCEPT', 'ACCEPT'], ['DROP', 'DROP'], ['REJECT', 'REJECT']],
102 fieldLabel
: gettext('Action'),
107 if (me
.allow_iface
) {
109 xtype
: 'proxmoxtextfield',
111 deleteEmpty
: !me
.isCreate
,
113 fieldLabel
: gettext('Interface'),
117 xtype
: 'displayfield',
125 xtype
: 'displayfield',
131 xtype
: 'pveIPRefSelector',
135 base_url
: me
.list_refs_url
,
137 fieldLabel
: gettext('Source'),
141 xtype
: 'pveIPRefSelector',
145 base_url
: me
.list_refs_url
,
147 fieldLabel
: gettext('Destination'),
154 xtype
: 'proxmoxcheckbox',
158 fieldLabel
: gettext('Enable'),
161 xtype
: 'pveFWMacroSelector',
163 fieldLabel
: gettext('Macro'),
167 change: function(f
, value
) {
168 if (value
=== null) {
169 me
.down('field[name=proto]').setDisabled(false);
170 me
.down('field[name=sport]').setDisabled(false);
171 me
.down('field[name=dport]').setDisabled(false);
173 me
.down('field[name=proto]').setDisabled(true);
174 me
.down('field[name=proto]').setValue('');
175 me
.down('field[name=sport]').setDisabled(true);
176 me
.down('field[name=sport]').setValue('');
177 me
.down('field[name=dport]').setDisabled(true);
178 me
.down('field[name=dport]').setValue('');
184 xtype
: 'pveIPProtocolSelector',
189 fieldLabel
: gettext('Protocol'),
192 xtype
: 'displayfield',
201 fieldLabel
: gettext('Source port'),
207 fieldLabel
: gettext('Dest. port'),
211 me
.advancedColumn1
= [
213 xtype
: 'pveFirewallLogLevels',
222 fieldLabel
: gettext('Comment'),
230 Ext
.define('PVE.FirewallRuleEdit', {
231 extend
: 'Proxmox.window.Edit',
234 list_refs_url
: undefined,
238 initComponent: function() {
242 throw "no base_url specified";
244 if (!me
.list_refs_url
) {
245 throw "no list_refs_url specified";
248 me
.isCreate
= (me
.rule_pos
=== undefined);
251 me
.url
= '/api2/extjs' + me
.base_url
;
254 me
.url
= '/api2/extjs' + me
.base_url
+ '/' + me
.rule_pos
.toString();
258 var ipanel
= Ext
.create('PVE.FirewallRulePanel', {
259 isCreate
: me
.isCreate
,
260 list_refs_url
: me
.list_refs_url
,
261 allow_iface
: me
.allow_iface
,
262 rule_pos
: me
.rule_pos
,
266 subject
: gettext('Rule'),
275 success: function(response
, options
) {
276 var values
= response
.result
.data
;
277 ipanel
.setValues(values
);
279 var field
= me
.query('[isFormField][name=modified_marker]')[0];
281 Ext
.Function
.defer(function() {
282 var form
= ipanel
.up('form').getForm();
283 form
.markInvalid(values
.errors
);
289 ipanel
.setValues(me
.rec
.data
);
294 Ext
.define('PVE.FirewallGroupRuleEdit', {
295 extend
: 'Proxmox.window.Edit',
301 initComponent: function() {
304 me
.isCreate
= (me
.rule_pos
=== undefined);
307 me
.url
= '/api2/extjs' + me
.base_url
;
310 me
.url
= '/api2/extjs' + me
.base_url
+ '/' + me
.rule_pos
.toString();
316 xtype
: 'hiddenfield',
321 xtype
: 'pveSecurityGroupsSelector',
324 fieldLabel
: gettext('Security Group'),
329 if (me
.allow_iface
) {
331 xtype
: 'proxmoxtextfield',
333 deleteEmpty
: !me
.isCreate
,
335 fieldLabel
: gettext('Interface'),
339 var ipanel
= Ext
.create('Proxmox.panel.InputPanel', {
340 isCreate
: me
.isCreate
,
344 xtype
: 'proxmoxcheckbox',
348 fieldLabel
: gettext('Enable'),
356 fieldLabel
: gettext('Comment'),
362 subject
: gettext('Rule'),
371 success: function(response
, options
) {
372 var values
= response
.result
.data
;
373 ipanel
.setValues(values
);
380 Ext
.define('PVE.FirewallRules', {
381 extend
: 'Ext.grid.Panel',
382 alias
: 'widget.pveFirewallRules',
384 onlineHelp
: 'chapter_pve_firewall',
387 stateId
: 'grid-firewall-rules',
390 list_refs_url
: undefined,
393 removeBtn
: undefined,
397 tbar_prefix
: undefined,
402 setBaseUrl: function(url
) {
407 if (url
=== undefined) {
408 me
.addBtn
.setDisabled(true);
410 me
.groupBtn
.setDisabled(true);
412 me
.store
.removeAll();
414 me
.addBtn
.setDisabled(false);
415 me
.removeBtn
.baseurl
= url
+ '/';
417 me
.groupBtn
.setDisabled(false);
421 url
: '/api2/json' + url
,
428 moveRule: function(from, to
) {
435 Proxmox
.Utils
.API2Request({
436 url
: me
.base_url
+ "/" + from,
438 params
: { moveto
: to
},
440 failure: function(response
, options
) {
441 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
443 callback: function() {
449 updateRule: function(rule
) {
456 rule
.enable
= rule
.enable
? 1 : 0;
462 Proxmox
.Utils
.API2Request({
463 url
: me
.base_url
+ '/' + pos
.toString(),
467 failure: function(response
, options
) {
468 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
470 callback: function() {
477 initComponent: function() {
480 if (!me
.list_refs_url
) {
481 throw "no list_refs_url specified";
484 var store
= Ext
.create('Ext.data.Store', {
485 model
: 'pve-fw-rule',
488 var reload = function() {
492 var sm
= Ext
.create('Ext.selection.RowModel', {});
494 var run_editor = function() {
495 var rec
= sm
.getSelection()[0];
499 var type
= rec
.data
.type
;
502 if (type
=== 'in' || type
=== 'out') {
503 editor
= 'PVE.FirewallRuleEdit';
504 } else if (type
=== 'group') {
505 editor
= 'PVE.FirewallGroupRuleEdit';
510 var win
= Ext
.create(editor
, {
511 digest
: rec
.data
.digest
,
512 allow_iface
: me
.allow_iface
,
513 base_url
: me
.base_url
,
514 list_refs_url
: me
.list_refs_url
,
515 rule_pos
: rec
.data
.pos
,
519 win
.on('destroy', reload
);
522 me
.editBtn
= Ext
.create('Proxmox.button.Button', {
523 text
: gettext('Edit'),
529 me
.addBtn
= Ext
.create('Ext.Button', {
530 text
: gettext('Add'),
532 handler: function() {
533 var win
= Ext
.create('PVE.FirewallRuleEdit', {
534 allow_iface
: me
.allow_iface
,
535 base_url
: me
.base_url
,
536 list_refs_url
: me
.list_refs_url
,
538 win
.on('destroy', reload
);
543 var run_copy_editor = function() {
544 var rec
= sm
.getSelection()[0];
549 var type
= rec
.data
.type
;
552 if (!(type
=== 'in' || type
=== 'out')) {
556 var win
= Ext
.create('PVE.FirewallRuleEdit', {
557 allow_iface
: me
.allow_iface
,
558 base_url
: me
.base_url
,
559 list_refs_url
: me
.list_refs_url
,
564 win
.on('destroy', reload
);
567 me
.copyBtn
= Ext
.create('Proxmox.button.Button', {
568 text
: gettext('Copy'),
570 enableFn: function(rec
) {
571 return (rec
.data
.type
=== 'in' || rec
.data
.type
=== 'out');
574 handler
: run_copy_editor
,
577 if (me
.allow_groups
) {
578 me
.groupBtn
= Ext
.create('Ext.Button', {
579 text
: gettext('Insert') + ': ' +
580 gettext('Security Group'),
582 handler: function() {
583 var win
= Ext
.create('PVE.FirewallGroupRuleEdit', {
584 allow_iface
: me
.allow_iface
,
585 base_url
: me
.base_url
,
587 win
.on('destroy', reload
);
593 me
.removeBtn
= Ext
.create('Proxmox.button.StdRemoveButton', {
595 baseurl
: me
.base_url
+ '/',
597 getRecordName: function(rec
) {
599 return rule
.pos
.toString() +
600 '?digest=' + encodeURIComponent(rule
.digest
);
602 callback: function() {
607 var tbar
= me
.tbar_prefix
? [me
.tbar_prefix
] : [];
608 tbar
.push(me
.addBtn
, me
.copyBtn
);
610 tbar
.push(me
.groupBtn
);
612 tbar
.push(me
.removeBtn
, me
.editBtn
);
614 var render_errors = function(name
, value
, metaData
, record
) {
615 var errors
= record
.data
.errors
;
616 if (errors
&& errors
[name
]) {
617 metaData
.tdCls
= 'proxmox-invalid-row';
618 var html
= '<p>' + Ext
.htmlEncode(errors
[name
]) + '</p>';
619 metaData
.tdAttr
= 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
620 html
.replace(/\"/g, '"') + '"';
627 // similar to xtype: 'rownumberer',
635 renderer: function(value
, metaData
, record
, rowIdx
, colIdx
, store
) {
636 metaData
.tdCls
= Ext
.baseCSSPrefix
+ 'grid-cell-special';
644 xtype
: 'checkcolumn',
645 header
: gettext('Enable'),
648 checkchange: function(column
, recordIndex
, checked
) {
649 var record
= me
.getStore().getData().items
[recordIndex
];
652 Ext
.Array
.forEach(record
.getFields(), function(field
) {
653 data
[field
.name
] = record
.get(field
.name
);
655 if (!me
.allow_iface
|| !data
.iface
) {
664 header
: gettext('Type'),
666 renderer: function(value
, metaData
, record
) {
667 return render_errors('type', value
, metaData
, record
);
672 header
: gettext('Action'),
674 renderer: function(value
, metaData
, record
) {
675 return render_errors('action', value
, metaData
, record
);
680 header
: gettext('Macro'),
682 renderer: function(value
, metaData
, record
) {
683 return render_errors('macro', value
, metaData
, record
);
689 if (me
.allow_iface
) {
691 header
: gettext('Interface'),
693 renderer: function(value
, metaData
, record
) {
694 return render_errors('iface', value
, metaData
, record
);
702 header
: gettext('Source'),
704 renderer: function(value
, metaData
, record
) {
705 return render_errors('source', value
, metaData
, record
);
710 header
: gettext('Destination'),
712 renderer: function(value
, metaData
, record
) {
713 return render_errors('dest', value
, metaData
, record
);
718 header
: gettext('Protocol'),
720 renderer: function(value
, metaData
, record
) {
721 return render_errors('proto', value
, metaData
, record
);
726 header
: gettext('Dest. port'),
728 renderer: function(value
, metaData
, record
) {
729 return render_errors('dport', value
, metaData
, record
);
734 header
: gettext('Source port'),
736 renderer: function(value
, metaData
, record
) {
737 return render_errors('sport', value
, metaData
, record
);
742 header
: gettext('Log level'),
744 renderer: function(value
, metaData
, record
) {
745 return render_errors('log', value
, metaData
, record
);
750 header
: gettext('Comment'),
751 dataIndex
: 'comment',
753 renderer: function(value
, metaData
, record
) {
754 return render_errors('comment', Ext
.util
.Format
.htmlEncode(value
), metaData
, record
);
766 ptype
: 'gridviewdragdrop',
767 dragGroup
: 'FWRuleDDGroup',
768 dropGroup
: 'FWRuleDDGroup',
772 beforedrop: function(node
, data
, dropRec
, dropPosition
) {
774 return false; // empty view
776 var moveto
= dropRec
.get('pos');
777 if (dropPosition
=== 'after') {
780 var pos
= data
.records
[0].get('pos');
781 me
.moveRule(pos
, moveto
);
784 itemdblclick
: run_editor
,
787 sortableColumns
: false,
794 me
.setBaseUrl(me
.base_url
); // load
798 Ext
.define('pve-fw-rule', {
799 extend
: 'Ext.data.Model',
800 fields
: [{ name
: 'enable', type
: 'boolean' },
801 'type', 'action', 'macro', 'source', 'dest', 'proto', 'iface',
802 'dport', 'sport', 'comment', 'pos', 'digest', 'errors'],