]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/panel/IPSet.js
ui: ipset: make ip/cidr required
[pve-manager.git] / www / manager6 / panel / IPSet.js
1 Ext.define('pve-fw-ipsets', {
2 extend: 'Ext.data.Model',
3 fields: ['name', 'comment', 'digest'],
4 idProperty: 'name',
5 });
6
7 Ext.define('PVE.IPSetList', {
8 extend: 'Ext.grid.Panel',
9 alias: 'widget.pveIPSetList',
10
11 stateful: true,
12 stateId: 'grid-firewall-ipsetlist',
13
14 ipset_panel: undefined,
15
16 base_url: undefined,
17
18 addBtn: undefined,
19 removeBtn: undefined,
20 editBtn: undefined,
21
22 initComponent: function() {
23 var me = this;
24
25 if (typeof me.ipset_panel === 'undefined') {
26 throw "no rule panel specified";
27 }
28
29 if (typeof me.ipset_panel === 'undefined') {
30 throw "no base_url specified";
31 }
32
33 var store = new Ext.data.Store({
34 model: 'pve-fw-ipsets',
35 proxy: {
36 type: 'proxmox',
37 url: "/api2/json" + me.base_url,
38 },
39 sorters: {
40 property: 'name',
41 direction: 'ASC',
42 },
43 });
44
45 var caps = Ext.state.Manager.get('GuiCap');
46 let canEdit = !!caps.vms['VM.Config.Network'] || !!caps.dc['Sys.Modify'] || !!caps.nodes['Sys.Modify'];
47
48 var sm = Ext.create('Ext.selection.RowModel', {});
49
50 var reload = function() {
51 var oldrec = sm.getSelection()[0];
52 store.load(function(records, operation, success) {
53 if (oldrec) {
54 var rec = store.findRecord('name', oldrec.data.name, 0, false, true, true);
55 if (rec) {
56 sm.select(rec);
57 }
58 }
59 });
60 };
61
62 var run_editor = function() {
63 var rec = sm.getSelection()[0];
64 if (!rec || !canEdit) {
65 return;
66 }
67 var win = Ext.create('Proxmox.window.Edit', {
68 subject: "IPSet '" + rec.data.name + "'",
69 url: me.base_url,
70 method: 'POST',
71 digest: rec.data.digest,
72 items: [
73 {
74 xtype: 'hiddenfield',
75 name: 'rename',
76 value: rec.data.name,
77 },
78 {
79 xtype: 'textfield',
80 name: 'name',
81 value: rec.data.name,
82 fieldLabel: gettext('Name'),
83 allowBlank: false,
84 },
85 {
86 xtype: 'textfield',
87 name: 'comment',
88 value: rec.data.comment,
89 fieldLabel: gettext('Comment'),
90 },
91 ],
92 });
93 win.show();
94 win.on('destroy', reload);
95 };
96
97 me.editBtn = new Proxmox.button.Button({
98 text: gettext('Edit'),
99 disabled: true,
100 enableFn: rec => canEdit,
101 selModel: sm,
102 handler: run_editor,
103 });
104
105 me.addBtn = new Proxmox.button.Button({
106 text: gettext('Create'),
107 handler: function() {
108 sm.deselectAll();
109 var win = Ext.create('Proxmox.window.Edit', {
110 subject: 'IPSet',
111 url: me.base_url,
112 method: 'POST',
113 items: [
114 {
115 xtype: 'textfield',
116 name: 'name',
117 value: '',
118 fieldLabel: gettext('Name'),
119 allowBlank: false,
120 },
121 {
122 xtype: 'textfield',
123 name: 'comment',
124 value: '',
125 fieldLabel: gettext('Comment'),
126 },
127 ],
128 });
129 win.show();
130 win.on('destroy', reload);
131 },
132 });
133
134 me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
135 enableFn: rec => canEdit,
136 selModel: sm,
137 baseurl: me.base_url + '/',
138 callback: reload,
139 });
140
141 Ext.apply(me, {
142 store: store,
143 tbar: ['<b>IPSet:</b>', me.addBtn, me.removeBtn, me.editBtn],
144 selModel: sm,
145 columns: [
146 { header: 'IPSet', dataIndex: 'name', width: '100' },
147 { header: gettext('Comment'), dataIndex: 'comment', renderer: Ext.String.htmlEncode, flex: 1 },
148 ],
149 listeners: {
150 itemdblclick: run_editor,
151 select: function(_, rec) {
152 var url = me.base_url + '/' + rec.data.name;
153 me.ipset_panel.setBaseUrl(url);
154 },
155 deselect: function() {
156 me.ipset_panel.setBaseUrl(undefined);
157 },
158 show: reload,
159 },
160 });
161
162 if (!canEdit) {
163 me.addBtn.setDisabled(true);
164 }
165
166 me.callParent();
167
168 store.load();
169 },
170 });
171
172 Ext.define('PVE.IPSetCidrEdit', {
173 extend: 'Proxmox.window.Edit',
174
175 cidr: undefined,
176
177 initComponent: function() {
178 var me = this;
179
180 me.isCreate = me.cidr === undefined;
181
182
183 if (me.isCreate) {
184 me.url = '/api2/extjs' + me.base_url;
185 me.method = 'POST';
186 } else {
187 me.url = '/api2/extjs' + me.base_url + '/' + me.cidr;
188 me.method = 'PUT';
189 }
190
191 var column1 = [];
192
193 if (me.isCreate) {
194 if (!me.list_refs_url) {
195 throw "no alias_base_url specified";
196 }
197
198 column1.push({
199 xtype: 'pveIPRefSelector',
200 name: 'cidr',
201 ref_type: 'alias',
202 autoSelect: false,
203 editable: true,
204 base_url: me.list_refs_url,
205 value: '',
206 allowBlank: false,
207 fieldLabel: gettext('IP/CIDR'),
208 });
209 } else {
210 column1.push({
211 xtype: 'displayfield',
212 name: 'cidr',
213 value: '',
214 fieldLabel: gettext('IP/CIDR'),
215 });
216 }
217
218 var ipanel = Ext.create('Proxmox.panel.InputPanel', {
219 isCreate: me.isCreate,
220 column1: column1,
221 column2: [
222 {
223 xtype: 'proxmoxcheckbox',
224 name: 'nomatch',
225 checked: false,
226 uncheckedValue: 0,
227 fieldLabel: 'nomatch',
228 },
229 ],
230 columnB: [
231 {
232 xtype: 'textfield',
233 name: 'comment',
234 value: '',
235 fieldLabel: gettext('Comment'),
236 },
237 ],
238 });
239
240 Ext.apply(me, {
241 subject: gettext('IP/CIDR'),
242 items: [ipanel],
243 });
244
245 me.callParent();
246
247 if (!me.isCreate) {
248 me.load({
249 success: function(response, options) {
250 var values = response.result.data;
251 ipanel.setValues(values);
252 },
253 });
254 }
255 },
256 });
257
258 Ext.define('PVE.IPSetGrid', {
259 extend: 'Ext.grid.Panel',
260 alias: 'widget.pveIPSetGrid',
261
262 stateful: true,
263 stateId: 'grid-firewall-ipsets',
264
265 base_url: undefined,
266 list_refs_url: undefined,
267
268 addBtn: undefined,
269 removeBtn: undefined,
270 editBtn: undefined,
271
272 setBaseUrl: function(url) {
273 var me = this;
274
275 me.base_url = url;
276
277 if (url === undefined) {
278 me.addBtn.setDisabled(true);
279 me.store.removeAll();
280 } else {
281 if (me.canEdit) {
282 me.addBtn.setDisabled(false);
283 }
284 me.removeBtn.baseurl = url + '/';
285 me.store.setProxy({
286 type: 'proxmox',
287 url: '/api2/json' + url,
288 });
289
290 me.store.load();
291 }
292 },
293
294 initComponent: function() {
295 var me = this;
296
297 if (!me.list_refs_url) {
298 throw "no1 list_refs_url specified";
299 }
300
301 var store = new Ext.data.Store({
302 model: 'pve-ipset',
303 });
304
305 var reload = function() {
306 store.load();
307 };
308
309 var sm = Ext.create('Ext.selection.RowModel', {});
310
311 me.caps = Ext.state.Manager.get('GuiCap');
312 me.canEdit = !!me.caps.vms['VM.Config.Network'] || !!me.caps.dc['Sys.Modify'] || !!me.caps.nodes['Sys.Modify'];
313
314 var run_editor = function() {
315 var rec = sm.getSelection()[0];
316 if (!rec || !me.canEdit) {
317 return;
318 }
319 var win = Ext.create('PVE.IPSetCidrEdit', {
320 base_url: me.base_url,
321 cidr: rec.data.cidr,
322 });
323 win.show();
324 win.on('destroy', reload);
325 };
326
327 me.editBtn = new Proxmox.button.Button({
328 text: gettext('Edit'),
329 disabled: true,
330 enableFn: rec => me.canEdit,
331 selModel: sm,
332 handler: run_editor,
333 });
334
335 me.addBtn = new Proxmox.button.Button({
336 text: gettext('Add'),
337 disabled: true,
338 enableFn: rec => me.canEdit,
339 handler: function() {
340 if (!me.base_url) {
341 return;
342 }
343 var win = Ext.create('PVE.IPSetCidrEdit', {
344 base_url: me.base_url,
345 list_refs_url: me.list_refs_url,
346 });
347 win.show();
348 win.on('destroy', reload);
349 },
350 });
351
352 me.removeBtn = Ext.create('Proxmox.button.StdRemoveButton', {
353 disabled: true,
354 enableFn: rec => me.canEdit,
355 selModel: sm,
356 baseurl: me.base_url + '/',
357 callback: reload,
358 });
359
360 var render_errors = function(value, metaData, record) {
361 var errors = record.data.errors;
362 if (errors) {
363 var msg = errors.cidr || errors.nomatch;
364 if (msg) {
365 metaData.tdCls = 'proxmox-invalid-row';
366 var html = '<p>' + Ext.htmlEncode(msg) + '</p>';
367 metaData.tdAttr = 'data-qwidth=600 data-qtitle="ERROR" data-qtip="' +
368 html.replace(/"/g, '&quot;') + '"';
369 }
370 }
371 return value;
372 };
373
374 Ext.apply(me, {
375 tbar: ['<b>IP/CIDR:</b>', me.addBtn, me.removeBtn, me.editBtn],
376 store: store,
377 selModel: sm,
378 listeners: {
379 itemdblclick: run_editor,
380 },
381 columns: [
382 {
383 xtype: 'rownumberer',
384 },
385 {
386 header: gettext('IP/CIDR'),
387 dataIndex: 'cidr',
388 width: 150,
389 renderer: function(value, metaData, record) {
390 value = render_errors(value, metaData, record);
391 if (record.data.nomatch) {
392 return '<b>! </b>' + value;
393 }
394 return value;
395 },
396 },
397 {
398 header: gettext('Comment'),
399 dataIndex: 'comment',
400 flex: 1,
401 renderer: function(value) {
402 return Ext.util.Format.htmlEncode(value);
403 },
404 },
405 ],
406 });
407
408 me.callParent();
409
410 if (me.base_url) {
411 me.setBaseUrl(me.base_url); // load
412 }
413 },
414 }, function() {
415 Ext.define('pve-ipset', {
416 extend: 'Ext.data.Model',
417 fields: [{ name: 'nomatch', type: 'boolean' },
418 'cidr', 'comment', 'errors'],
419 idProperty: 'cidr',
420 });
421 });
422
423 Ext.define('PVE.IPSet', {
424 extend: 'Ext.panel.Panel',
425 alias: 'widget.pveIPSet',
426
427 title: 'IPSet',
428
429 onlineHelp: 'pve_firewall_ip_sets',
430
431 list_refs_url: undefined,
432
433 initComponent: function() {
434 var me = this;
435
436 if (!me.list_refs_url) {
437 throw "no list_refs_url specified";
438 }
439
440 var ipset_panel = Ext.createWidget('pveIPSetGrid', {
441 region: 'center',
442 list_refs_url: me.list_refs_url,
443 border: false,
444 });
445
446 var ipset_list = Ext.createWidget('pveIPSetList', {
447 region: 'west',
448 ipset_panel: ipset_panel,
449 base_url: me.base_url,
450 width: '50%',
451 border: false,
452 split: true,
453 });
454
455 Ext.apply(me, {
456 layout: 'border',
457 items: [ipset_list, ipset_panel],
458 listeners: {
459 show: function() {
460 ipset_list.fireEvent('show', ipset_list);
461 },
462 },
463 });
464
465 me.callParent();
466 },
467 });