]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/grid/FirewallRules.js
api/apt: remove unused variable
[pve-manager.git] / www / manager6 / grid / FirewallRules.js
CommitLineData
435cce27 1Ext.define('PVE.form.FWMacroSelector', {
0fc95a12 2 extend: 'Proxmox.form.ComboGrid',
435cce27 3 alias: 'widget.pveFWMacroSelector',
3d990919
EK
4 allowBlank: true,
5 autoSelect: false,
6 valueField: 'macro',
7 displayField: 'macro',
8 listConfig: {
9 columns: [
10 {
11 header: gettext('Macro'),
12 dataIndex: 'macro',
13 hideable: false,
14 width: 100
15 },
16 {
17 header: gettext('Description'),
91535f2b 18 renderer: Ext.String.htmlEncode,
3d990919
EK
19 flex: 1,
20 dataIndex: 'descr'
21 }
22 ]
23 },
435cce27
DM
24 initComponent: function() {
25 var me = this;
26
27 var store = Ext.create('Ext.data.Store', {
28 autoLoad: true,
29 fields: [ 'macro', 'descr' ],
30 idProperty: 'macro',
31 proxy: {
56a353b9 32 type: 'proxmox',
435cce27
DM
33 url: "/api2/json/cluster/firewall/macros"
34 },
35 sorters: {
36 property: 'macro',
37 order: 'DESC'
38 }
39 });
40
41 Ext.apply(me, {
22f2f9d6 42 store: store
435cce27
DM
43 });
44
45 me.callParent();
46 }
47});
48
49Ext.define('PVE.FirewallRulePanel', {
ef4ef788 50 extend: 'Proxmox.panel.InputPanel',
435cce27
DM
51
52 allow_iface: false,
53
54 list_refs_url: undefined,
55
56 onGetValues: function(values) {
57 var me = this;
58
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 ''
61
1fafdce8 62 Ext.Array.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport'], function(key) {
435cce27
DM
63 if (values[key] === undefined) {
64 values[key] = '';
65 }
66 });
67
68 delete values.modified_marker;
69
70 return values;
71 },
72
73 initComponent : function() {
74 var me = this;
75
76 if (!me.list_refs_url) {
77 throw "no list_refs_url specified";
78 }
79
80 me.column1 = [
81 {
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
84 // form again.
85 xtype: 'hiddenfield',
86 name: 'modified_marker',
22f2f9d6 87 value: ''
435cce27
DM
88 },
89 {
09cacce7 90 xtype: 'proxmoxKVComboBox',
435cce27
DM
91 name: 'type',
92 value: 'in',
e7bc7f31 93 comboItems: [['in', 'in'], ['out', 'out']],
435cce27
DM
94 fieldLabel: gettext('Direction'),
95 allowBlank: false
96 },
97 {
09cacce7 98 xtype: 'proxmoxKVComboBox',
435cce27
DM
99 name: 'action',
100 value: 'ACCEPT',
e7bc7f31 101 comboItems: [['ACCEPT', 'ACCEPT'], ['DROP', 'DROP'], ['REJECT', 'REJECT']],
435cce27
DM
102 fieldLabel: gettext('Action'),
103 allowBlank: false
104 }
105 ];
106
107 if (me.allow_iface) {
108 me.column1.push({
dbed4c1c 109 xtype: 'proxmoxtextfield',
435cce27 110 name: 'iface',
d5e771ce 111 deleteEmpty: !me.isCreate,
435cce27
DM
112 value: '',
113 fieldLabel: gettext('Interface')
114 });
115 } else {
116 me.column1.push({
117 xtype: 'displayfield',
118 fieldLabel: '',
435cce27
DM
119 value: ''
120 });
121 }
122
fa94a977 123 me.column1.push(
435cce27
DM
124 {
125 xtype: 'displayfield',
126 fieldLabel: '',
127 height: 7,
128 value: ''
129 },
130 {
131 xtype: 'pveIPRefSelector',
132 name: 'source',
133 autoSelect: false,
134 editable: true,
135 base_url: me.list_refs_url,
136 value: '',
137 fieldLabel: gettext('Source')
138
139 },
140 {
141 xtype: 'pveIPRefSelector',
142 name: 'dest',
143 autoSelect: false,
144 editable: true,
145 base_url: me.list_refs_url,
146 value: '',
147 fieldLabel: gettext('Destination')
148 }
fa94a977 149 );
435cce27
DM
150
151
152 me.column2 = [
153 {
896c0d50 154 xtype: 'proxmoxcheckbox',
435cce27
DM
155 name: 'enable',
156 checked: false,
435cce27
DM
157 uncheckedValue: 0,
158 fieldLabel: gettext('Enable')
159 },
160 {
161 xtype: 'pveFWMacroSelector',
162 name: 'macro',
435cce27 163 fieldLabel: gettext('Macro'),
1fafdce8 164 editable: true,
435cce27
DM
165 allowBlank: true,
166 listeners: {
167 change: function(f, value) {
1fafdce8 168 if (value === null) {
435cce27
DM
169 me.down('field[name=proto]').setDisabled(false);
170 me.down('field[name=sport]').setDisabled(false);
171 me.down('field[name=dport]').setDisabled(false);
172 } else {
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);
7c7ae44f 178 me.down('field[name=dport]').setValue('');
435cce27
DM
179 }
180 }
181 }
182 },
183 {
184 xtype: 'pveIPProtocolSelector',
185 name: 'proto',
186 autoSelect: false,
187 editable: true,
188 value: '',
189 fieldLabel: gettext('Protocol')
190 },
191 {
192 xtype: 'displayfield',
193 fieldLabel: '',
194 height: 7,
195 value: ''
196 },
197 {
198 xtype: 'textfield',
199 name: 'sport',
200 value: '',
201 fieldLabel: gettext('Source port')
202 },
203 {
204 xtype: 'textfield',
205 name: 'dport',
435cce27
DM
206 value: '',
207 fieldLabel: gettext('Dest. port')
208 }
209 ];
210
211 me.columnB = [
212 {
213 xtype: 'textfield',
214 name: 'comment',
215 value: '',
216 fieldLabel: gettext('Comment')
217 }
218 ];
219
220 me.callParent();
221 }
222});
223
224Ext.define('PVE.FirewallRuleEdit', {
9fccc702 225 extend: 'Proxmox.window.Edit',
435cce27
DM
226
227 base_url: undefined,
228 list_refs_url: undefined,
229
230 allow_iface: false,
231
232 initComponent : function() {
d5e771ce 233
435cce27
DM
234 var me = this;
235
236 if (!me.base_url) {
237 throw "no base_url specified";
238 }
239 if (!me.list_refs_url) {
240 throw "no list_refs_url specified";
241 }
242
d5e771ce 243 me.isCreate = (me.rule_pos === undefined);
435cce27 244
d5e771ce 245 if (me.isCreate) {
435cce27
DM
246 me.url = '/api2/extjs' + me.base_url;
247 me.method = 'POST';
248 } else {
249 me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
250 me.method = 'PUT';
251 }
252
253 var ipanel = Ext.create('PVE.FirewallRulePanel', {
d5e771ce 254 isCreate: me.isCreate,
435cce27
DM
255 list_refs_url: me.list_refs_url,
256 allow_iface: me.allow_iface,
257 rule_pos: me.rule_pos
258 });
259
260 Ext.apply(me, {
261 subject: gettext('Rule'),
262 isAdd: true,
263 items: [ ipanel ]
264 });
265
266 me.callParent();
267
d5e771ce 268 if (!me.isCreate) {
435cce27
DM
269 me.load({
270 success: function(response, options) {
271 var values = response.result.data;
272 ipanel.setValues(values);
273 if (values.errors) {
274 var field = me.query('[isFormField][name=modified_marker]')[0];
275 field.setValue(1);
276 Ext.Function.defer(function() {
277 var form = ipanel.up('form').getForm();
a764c5f7 278 form.markInvalid(values.errors);
435cce27
DM
279 }, 100);
280 }
281 }
282 });
330020d2
WL
283 } else if (me.rec) {
284 ipanel.setValues(me.rec.data);
435cce27
DM
285 }
286 }
287});
288
289Ext.define('PVE.FirewallGroupRuleEdit', {
9fccc702 290 extend: 'Proxmox.window.Edit',
435cce27
DM
291
292 base_url: undefined,
293
294 allow_iface: false,
295
296 initComponent : function() {
d5e771ce 297
435cce27
DM
298 var me = this;
299
d5e771ce 300 me.isCreate = (me.rule_pos === undefined);
435cce27 301
d5e771ce 302 if (me.isCreate) {
435cce27
DM
303 me.url = '/api2/extjs' + me.base_url;
304 me.method = 'POST';
305 } else {
306 me.url = '/api2/extjs' + me.base_url + '/' + me.rule_pos.toString();
307 me.method = 'PUT';
308 }
309
310 var column1 = [
311 {
312 xtype: 'hiddenfield',
313 name: 'type',
314 value: 'group'
315 },
316 {
317 xtype: 'pveSecurityGroupsSelector',
318 name: 'action',
319 value: '',
320 fieldLabel: gettext('Security Group'),
321 allowBlank: false
322 }
323 ];
324
325 if (me.allow_iface) {
326 column1.push({
dbed4c1c 327 xtype: 'proxmoxtextfield',
435cce27 328 name: 'iface',
d5e771ce 329 deleteEmpty: !me.isCreate,
435cce27
DM
330 value: '',
331 fieldLabel: gettext('Interface')
332 });
333 }
334
ef4ef788 335 var ipanel = Ext.create('Proxmox.panel.InputPanel', {
d5e771ce 336 isCreate: me.isCreate,
435cce27
DM
337 column1: column1,
338 column2: [
339 {
896c0d50 340 xtype: 'proxmoxcheckbox',
435cce27
DM
341 name: 'enable',
342 checked: false,
435cce27
DM
343 uncheckedValue: 0,
344 fieldLabel: gettext('Enable')
345 }
346 ],
347 columnB: [
348 {
349 xtype: 'textfield',
350 name: 'comment',
351 value: '',
352 fieldLabel: gettext('Comment')
353 }
354 ]
355 });
356
357 Ext.apply(me, {
358 subject: gettext('Rule'),
359 isAdd: true,
360 items: [ ipanel ]
361 });
362
363 me.callParent();
364
d5e771ce 365 if (!me.isCreate) {
435cce27
DM
366 me.load({
367 success: function(response, options) {
368 var values = response.result.data;
369 ipanel.setValues(values);
370 }
371 });
372 }
373 }
374});
375
376Ext.define('PVE.FirewallRules', {
377 extend: 'Ext.grid.Panel',
378 alias: 'widget.pveFirewallRules',
379
ba93a9c6
DC
380 onlineHelp: 'chapter_pve_firewall',
381
123e1c80
DC
382 stateful: true,
383 stateId: 'grid-firewall-rules',
384
435cce27
DM
385 base_url: undefined,
386 list_refs_url: undefined,
387
388 addBtn: undefined,
389 removeBtn: undefined,
390 editBtn: undefined,
391 groupBtn: undefined,
392
393 tbar_prefix: undefined,
394
395 allow_groups: true,
396 allow_iface: false,
397
398 setBaseUrl: function(url) {
399 var me = this;
400
401 me.base_url = url;
402
403 if (url === undefined) {
404 me.addBtn.setDisabled(true);
405 if (me.groupBtn) {
406 me.groupBtn.setDisabled(true);
407 }
408 me.store.removeAll();
409 } else {
410 me.addBtn.setDisabled(false);
3b1ca3ff 411 me.removeBtn.baseurl = url + '/';
435cce27
DM
412 if (me.groupBtn) {
413 me.groupBtn.setDisabled(false);
414 }
415 me.store.setProxy({
56a353b9 416 type: 'proxmox',
435cce27
DM
417 url: '/api2/json' + url
418 });
419
420 me.store.load();
421 }
422 },
423
424 moveRule: function(from, to) {
425 var me = this;
426
427 if (!me.base_url) {
428 return;
429 }
430
e7ade592 431 Proxmox.Utils.API2Request({
435cce27
DM
432 url: me.base_url + "/" + from,
433 method: 'PUT',
434 params: { moveto: to },
435 waitMsgTarget: me,
436 failure: function(response, options) {
437 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
438 },
439 callback: function() {
440 me.store.load();
441 }
442 });
443 },
444
445 updateRule: function(rule) {
446 var me = this;
447
448 if (!me.base_url) {
449 return;
450 }
451
452 rule.enable = rule.enable ? 1 : 0;
453
454 var pos = rule.pos;
455 delete rule.pos;
456 delete rule.errors;
457
e7ade592 458 Proxmox.Utils.API2Request({
435cce27
DM
459 url: me.base_url + '/' + pos.toString(),
460 method: 'PUT',
461 params: rule,
462 waitMsgTarget: me,
463 failure: function(response, options) {
464 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
465 },
466 callback: function() {
467 me.store.load();
468 }
469 });
470 },
471
435cce27
DM
472
473 initComponent: function() {
474 /*jslint confusion: true */
475 var me = this;
476
477 if (!me.list_refs_url) {
478 throw "no list_refs_url specified";
479 }
480
f3578e26 481 var store = Ext.create('Ext.data.Store',{
435cce27
DM
482 model: 'pve-fw-rule'
483 });
484
485 var reload = function() {
486 store.load();
487 };
488
489 var sm = Ext.create('Ext.selection.RowModel', {});
490
491 var run_editor = function() {
492 var rec = sm.getSelection()[0];
493 if (!rec) {
494 return;
495 }
496 var type = rec.data.type;
497
498 var editor;
499 if (type === 'in' || type === 'out') {
500 editor = 'PVE.FirewallRuleEdit';
501 } else if (type === 'group') {
502 editor = 'PVE.FirewallGroupRuleEdit';
503 } else {
504 return;
505 }
506
507 var win = Ext.create(editor, {
508 digest: rec.data.digest,
509 allow_iface: me.allow_iface,
510 base_url: me.base_url,
511 list_refs_url: me.list_refs_url,
512 rule_pos: rec.data.pos
513 });
514
515 win.show();
516 win.on('destroy', reload);
517 };
518
5720fafa 519 me.editBtn = Ext.create('Proxmox.button.Button',{
435cce27
DM
520 text: gettext('Edit'),
521 disabled: true,
522 selModel: sm,
523 handler: run_editor
524 });
525
526 me.addBtn = Ext.create('Ext.Button', {
527 text: gettext('Add'),
528 disabled: true,
529 handler: function() {
530 var win = Ext.create('PVE.FirewallRuleEdit', {
531 allow_iface: me.allow_iface,
532 base_url: me.base_url,
533 list_refs_url: me.list_refs_url
534 });
535 win.on('destroy', reload);
536 win.show();
537 }
538 });
539
330020d2
WL
540 var run_copy_editor = function() {
541 var rec = sm.getSelection()[0];
542
543 if (!rec) {
544 return;
545 }
546 var type = rec.data.type;
547
548
549 if (!(type === 'in' || type === 'out')) {
550 return;
551 }
552
553 var win = Ext.create('PVE.FirewallRuleEdit', {
554 allow_iface: me.allow_iface,
555 base_url: me.base_url,
556 list_refs_url: me.list_refs_url,
5eff07f7 557 rec: rec
330020d2
WL
558 });
559
560 win.show();
561 win.on('destroy', reload);
562 };
563
5720fafa 564 me.copyBtn = Ext.create('Proxmox.button.Button',{
330020d2
WL
565 text: gettext('Copy'),
566 selModel: sm,
03375edf
DC
567 enableFn: function(rec) {
568 return (rec.data.type === 'in' || rec.data.type === 'out');
569 },
330020d2 570 disabled: true,
5eff07f7 571 handler: run_copy_editor
330020d2
WL
572 });
573
435cce27
DM
574 if (me.allow_groups) {
575 me.groupBtn = Ext.create('Ext.Button', {
576 text: gettext('Insert') + ': ' +
577 gettext('Security Group'),
578 disabled: true,
579 handler: function() {
580 var win = Ext.create('PVE.FirewallGroupRuleEdit', {
581 allow_iface: me.allow_iface,
582 base_url: me.base_url
583 });
584 win.on('destroy', reload);
585 win.show();
586 }
587 });
588 }
589
3b1ca3ff 590 me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton',{
435cce27 591 selModel: sm,
3b1ca3ff
DC
592 baseurl: me.base_url + '/',
593 confirmMsg: false,
594 getRecordName: function(rec) {
595 var rule = rec.data;
596 return rule.pos.toString() +
597 '?digest=' + encodeURIComponent(rule.digest);
598 },
599 callback: function() {
600 me.store.load();
435cce27
DM
601 }
602 });
603
604 var tbar = me.tbar_prefix ? [ me.tbar_prefix ] : [];
330020d2 605 tbar.push(me.addBtn, me.copyBtn);
435cce27
DM
606 if (me.groupBtn) {
607 tbar.push(me.groupBtn);
608 }
fa94a977 609 tbar.push(me.removeBtn, me.editBtn);
435cce27
DM
610
611 var render_errors = function(name, value, metaData, record) {
612 var errors = record.data.errors;
613 if (errors && errors[name]) {
3ab7e0ec 614 metaData.tdCls = 'proxmox-invalid-row';
435cce27
DM
615 var html = '<p>' + Ext.htmlEncode(errors[name]) + '</p>';
616 metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
617 html.replace(/\"/g,'&quot;') + '"';
618 }
619 return value;
620 };
621
622 var columns = [
623 {
624 // similar to xtype: 'rownumberer',
625 dataIndex: 'pos',
626 resizable: false,
627 width: 23,
628 sortable: false,
629 align: 'right',
630 hideable: false,
631 menuDisabled: true,
632 renderer: function(value, metaData, record, rowIdx, colIdx, store) {
633 metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
634 if (value >= 0) {
635 return value;
636 }
637 return '';
638 }
639 },
640 {
641 xtype: 'checkcolumn',
642 header: gettext('Enable'),
643 dataIndex: 'enable',
644 listeners: {
7a4c3133
EK
645 checkchange: function(column, recordIndex, checked) {
646 var record = me.getStore().getData().items[recordIndex];
435cce27
DM
647 record.commit();
648 var data = {};
7a4c3133 649 Ext.Array.forEach(record.getFields(), function(field) {
435cce27
DM
650 data[field.name] = record.get(field.name);
651 });
652 if (!me.allow_iface || !data.iface) {
653 delete data.iface;
654 }
655 me.updateRule(data);
656 }
657 },
658 width: 50
659 },
660 {
661 header: gettext('Type'),
662 dataIndex: 'type',
663 renderer: function(value, metaData, record) {
664 return render_errors('type', value, metaData, record);
665 },
666 width: 50
667 },
668 {
669 header: gettext('Action'),
670 dataIndex: 'action',
671 renderer: function(value, metaData, record) {
672 return render_errors('action', value, metaData, record);
673 },
674 width: 80
675 },
676 {
677 header: gettext('Macro'),
678 dataIndex: 'macro',
679 renderer: function(value, metaData, record) {
680 return render_errors('macro', value, metaData, record);
681 },
682 width: 80
683 }
684 ];
685
686 if (me.allow_iface) {
687 columns.push({
688 header: gettext('Interface'),
689 dataIndex: 'iface',
690 renderer: function(value, metaData, record) {
691 return render_errors('iface', value, metaData, record);
692 },
693 width: 80
694 });
695 }
696
fa94a977 697 columns.push(
435cce27
DM
698 {
699 header: gettext('Source'),
700 dataIndex: 'source',
701 renderer: function(value, metaData, record) {
702 return render_errors('source', value, metaData, record);
703 },
704 width: 100
705 },
706 {
707 header: gettext('Destination'),
708 dataIndex: 'dest',
709 renderer: function(value, metaData, record) {
710 return render_errors('dest', value, metaData, record);
711 },
712 width: 100
713 },
714 {
715 header: gettext('Protocol'),
716 dataIndex: 'proto',
717 renderer: function(value, metaData, record) {
718 return render_errors('proto', value, metaData, record);
719 },
720 width: 100
721 },
722 {
723 header: gettext('Dest. port'),
724 dataIndex: 'dport',
725 renderer: function(value, metaData, record) {
726 return render_errors('dport', value, metaData, record);
727 },
728 width: 100
729 },
730 {
731 header: gettext('Source port'),
732 dataIndex: 'sport',
733 renderer: function(value, metaData, record) {
734 return render_errors('sport', value, metaData, record);
735 },
736 width: 100
737 },
738 {
739 header: gettext('Comment'),
740 dataIndex: 'comment',
741 flex: 1,
742 renderer: function(value, metaData, record) {
743 return render_errors('comment', Ext.util.Format.htmlEncode(value), metaData, record);
744 }
745 }
fa94a977 746 );
435cce27
DM
747
748 Ext.apply(me, {
749 store: store,
750 selModel: sm,
751 tbar: tbar,
752 viewConfig: {
753 plugins: [
754 {
755 ptype: 'gridviewdragdrop',
756 dragGroup: 'FWRuleDDGroup',
757 dropGroup: 'FWRuleDDGroup'
758 }
759 ],
760 listeners: {
761 beforedrop: function(node, data, dropRec, dropPosition) {
762 if (!dropRec) {
763 return false; // empty view
764 }
765 var moveto = dropRec.get('pos');
766 if (dropPosition === 'after') {
767 moveto++;
768 }
769 var pos = data.records[0].get('pos');
770 me.moveRule(pos, moveto);
771 return 0;
772 },
773 itemdblclick: run_editor
774 }
775 },
776 sortableColumns: false,
777 columns: columns
778 });
779
780 me.callParent();
781
782 if (me.base_url) {
783 me.setBaseUrl(me.base_url); // load
784 }
785 }
786}, function() {
787
788 Ext.define('pve-fw-rule', {
789 extend: 'Ext.data.Model',
790 fields: [ { name: 'enable', type: 'boolean' },
791 'type', 'action', 'macro', 'source', 'dest', 'proto', 'iface',
792 'dport', 'sport', 'comment', 'pos', 'digest', 'errors' ],
793 idProperty: 'pos'
794 });
795
796});