]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/node/Certificates.js
ui: node certificate: make panel only vertical scrollable
[pve-manager.git] / www / manager6 / node / Certificates.js
CommitLineData
c287e233
DC
1Ext.define('PVE.node.CertificateView', {
2 extend: 'Ext.container.Container',
3 xtype: 'pveCertificatesView',
4
16dedd0f
DC
5 onlineHelp: 'sysadmin_certificate_management',
6
8058410f 7 mixins: ['Proxmox.Mixin.CBind'],
d3d48736 8 scrollable: 'y',
c287e233
DC
9
10 items: [
11 {
12 xtype: 'pveCertView',
13 border: 0,
14 cbind: {
f6710aac
TL
15 nodename: '{nodename}',
16 },
c287e233
DC
17 },
18 {
19 xtype: 'pveACMEView',
20 border: 0,
21 cbind: {
f6710aac
TL
22 nodename: '{nodename}',
23 },
24 },
25 ],
c287e233
DC
26
27});
28
29Ext.define('PVE.node.CertificateViewer', {
30 extend: 'Proxmox.window.Edit',
31
32 title: gettext('Certificate'),
33
34 fieldDefaults: {
f6710aac 35 labelWidth: 120,
c287e233
DC
36 },
37 width: 800,
38 resizable: true,
39
40 items: [
41 {
42 xtype: 'displayfield',
43 fieldLabel: gettext('Name'),
f6710aac 44 name: 'filename',
c287e233
DC
45 },
46 {
47 xtype: 'displayfield',
48 fieldLabel: gettext('Fingerprint'),
f6710aac 49 name: 'fingerprint',
c287e233
DC
50 },
51 {
52 xtype: 'displayfield',
53 fieldLabel: gettext('Issuer'),
f6710aac 54 name: 'issuer',
c287e233
DC
55 },
56 {
57 xtype: 'displayfield',
58 fieldLabel: gettext('Subject'),
f6710aac 59 name: 'subject',
c287e233 60 },
e81645f5
AA
61 {
62 xtype: 'displayfield',
63 fieldLabel: gettext('Public Key Type'),
f6710aac 64 name: 'public-key-type',
e81645f5
AA
65 },
66 {
67 xtype: 'displayfield',
68 fieldLabel: gettext('Public Key Size'),
f6710aac 69 name: 'public-key-bits',
e81645f5 70 },
c287e233
DC
71 {
72 xtype: 'displayfield',
73 fieldLabel: gettext('Valid Since'),
74 renderer: Proxmox.Utils.render_timestamp,
f6710aac 75 name: 'notbefore',
c287e233
DC
76 },
77 {
78 xtype: 'displayfield',
79 fieldLabel: gettext('Expires'),
80 renderer: Proxmox.Utils.render_timestamp,
f6710aac 81 name: 'notafter',
c287e233
DC
82 },
83 {
84 xtype: 'displayfield',
85 fieldLabel: gettext('Subject Alternative Names'),
86 name: 'san',
f6710aac 87 renderer: PVE.Utils.render_san,
c287e233
DC
88 },
89 {
90 xtype: 'textarea',
91 editable: false,
92 grow: true,
93 growMax: 200,
94 fieldLabel: gettext('Certificate'),
f6710aac
TL
95 name: 'pem',
96 },
c287e233
DC
97 ],
98
99 initComponent: function() {
48bbb009 100 let me = this;
c287e233
DC
101
102 if (!me.cert) {
103 throw "no cert given";
104 }
c287e233
DC
105 if (!me.nodename) {
106 throw "no nodename given";
107 }
108
48bbb009 109 me.url = `/nodes/${me.nodename}/certificates/info`;
c287e233
DC
110 me.callParent();
111
112 // hide OK/Reset button, because we just want to show data
113 me.down('toolbar[dock=bottom]').setVisible(false);
114
115 me.load({
116 success: function(response) {
117 if (Ext.isArray(response.result.data)) {
48bbb009 118 for (const item of response.result.data) {
c287e233
DC
119 if (item.filename === me.cert) {
120 me.setValues(item);
48bbb009 121 return;
c287e233 122 }
48bbb009 123 }
c287e233 124 }
f6710aac 125 },
c287e233 126 });
f6710aac 127 },
c287e233
DC
128});
129
130Ext.define('PVE.node.CertUpload', {
131 extend: 'Proxmox.window.Edit',
132 xtype: 'pveCertUpload',
133
134 title: gettext('Upload Custom Certificate'),
135 resizable: false,
136 isCreate: true,
137 submitText: gettext('Upload'),
138 method: 'POST',
139 width: 600,
140
141 apiCallDone: function(success, response, options) {
142 if (!success) {
143 return;
144 }
48bbb009 145 let txt = gettext('API server will be restarted to use new certificates, please reload web-interface!');
c287e233 146 Ext.getBody().mask(txt, ['pve-static-mask']);
48bbb009 147 Ext.defer(() => window.location.reload(true), 10000); // reload after 10 seconds automatically
c287e233
DC
148 },
149
150 items: [
151 {
152 fieldLabel: gettext('Private Key (Optional)'),
153 labelAlign: 'top',
154 emptyText: gettext('No change'),
155 name: 'key',
f6710aac 156 xtype: 'textarea',
c287e233
DC
157 },
158 {
159 xtype: 'filebutton',
160 text: gettext('From File'),
161 listeners: {
162 change: function(btn, e, value) {
48bbb009
TL
163 let form = this.up('form');
164 for (const file of e.event.target.files) {
3491bd18 165 PVE.Utils.loadFile(file, res => form.down('field[name=key]').setValue(res));
48bbb009 166 }
c287e233 167 btn.reset();
f6710aac
TL
168 },
169 },
c287e233
DC
170 },
171 {
172 xtype: 'box',
f6710aac 173 autoEl: 'hr',
c287e233
DC
174 },
175 {
176 fieldLabel: gettext('Certificate Chain'),
177 labelAlign: 'top',
178 allowBlank: false,
179 name: 'certificates',
f6710aac 180 xtype: 'textarea',
c287e233
DC
181 },
182 {
183 xtype: 'filebutton',
184 text: gettext('From File'),
185 listeners: {
186 change: function(btn, e, value) {
48bbb009
TL
187 let form = this.up('form');
188 for (const file of e.event.target.files) {
3491bd18 189 PVE.Utils.loadFile(file, res => form.down('field[name=certificates]').setValue(res));
48bbb009 190 }
c287e233 191 btn.reset();
f6710aac
TL
192 },
193 },
c287e233
DC
194 },
195 {
196 xtype: 'hidden',
197 name: 'restart',
f6710aac 198 value: '1',
c287e233
DC
199 },
200 {
201 xtype: 'hidden',
202 name: 'force',
f6710aac
TL
203 value: '1',
204 },
c287e233
DC
205 ],
206
207 initComponent: function() {
48bbb009 208 let me = this;
c287e233
DC
209 if (!me.nodename) {
210 throw "no nodename given";
211 }
48bbb009 212 me.url = `/nodes/${me.nodename}/certificates/custom`;
c287e233
DC
213
214 me.callParent();
f6710aac 215 },
c287e233
DC
216});
217
218Ext.define('pve-certificate', {
219 extend: 'Ext.data.Model',
8058410f 220 fields: ['filename', 'fingerprint', 'issuer', 'notafter', 'notbefore', 'subject', 'san', 'public-key-bits', 'public-key-type'],
f6710aac 221 idProperty: 'filename',
c287e233
DC
222});
223
224Ext.define('PVE.node.Certificates', {
225 extend: 'Ext.grid.Panel',
226 xtype: 'pveCertView',
227
228 tbar: [
229 {
230 xtype: 'button',
231 text: gettext('Upload Custom Certificate'),
232 handler: function() {
48bbb009
TL
233 let view = this.up('grid');
234 Ext.create('PVE.node.CertUpload', {
235 nodename: view.nodename,
236 listeners: {
237 destroy: () => view.reload(),
238 },
239 autoShow: true,
c287e233 240 });
f6710aac 241 },
c287e233
DC
242 },
243 {
028e4cd3 244 xtype: 'proxmoxStdRemoveButton',
c287e233
DC
245 itemId: 'deletebtn',
246 text: gettext('Delete Custom Certificate'),
028e4cd3
TL
247 dangerous: true,
248 selModel: false,
249 getUrl: function(rec) {
250 let view = this.up('grid');
251 return `/nodes/${view.nodename}/certificates/custom?restart=1`;
252 },
253 confirmMsg: gettext('Delete custom certificate and switch to generated one?'),
254 callback: function(options, success, response) {
255 if (success) {
256 let txt = gettext('API server will be restarted to use new certificates, please reload web-interface!');
257 Ext.getBody().mask(txt, ['pve-static-mask']);
258 // reload after 10 seconds automatically
259 Ext.defer(() => window.location.reload(true), 10000);
260 }
f6710aac 261 },
c287e233
DC
262 },
263 '-',
264 {
265 xtype: 'proxmoxButton',
266 itemId: 'viewbtn',
267 disabled: true,
268 text: gettext('View Certificate'),
269 handler: function() {
48bbb009 270 this.up('grid').viewCertificate();
f6710aac
TL
271 },
272 },
c287e233
DC
273 ],
274
275 columns: [
276 {
277 header: gettext('File'),
278 width: 150,
f6710aac 279 dataIndex: 'filename',
c287e233
DC
280 },
281 {
282 header: gettext('Issuer'),
283 flex: 1,
f6710aac 284 dataIndex: 'issuer',
c287e233
DC
285 },
286 {
287 header: gettext('Subject'),
288 flex: 1,
f6710aac 289 dataIndex: 'subject',
c287e233 290 },
e81645f5
AA
291 {
292 header: gettext('Public Key Alogrithm'),
293 flex: 1,
294 dataIndex: 'public-key-type',
f6710aac 295 hidden: true,
e81645f5
AA
296 },
297 {
298 header: gettext('Public Key Size'),
299 flex: 1,
300 dataIndex: 'public-key-bits',
f6710aac 301 hidden: true,
e81645f5 302 },
c287e233
DC
303 {
304 header: gettext('Valid Since'),
305 width: 150,
306 dataIndex: 'notbefore',
f6710aac 307 renderer: Proxmox.Utils.render_timestamp,
c287e233
DC
308 },
309 {
310 header: gettext('Expires'),
311 width: 150,
312 dataIndex: 'notafter',
f6710aac 313 renderer: Proxmox.Utils.render_timestamp,
c287e233
DC
314 },
315 {
316 header: gettext('Subject Alternative Names'),
317 flex: 1,
318 dataIndex: 'san',
f6710aac 319 renderer: PVE.Utils.render_san,
c287e233
DC
320 },
321 {
322 header: gettext('Fingerprint'),
323 dataIndex: 'fingerprint',
f6710aac 324 hidden: true,
c287e233
DC
325 },
326 {
327 header: gettext('PEM'),
328 dataIndex: 'pem',
f6710aac
TL
329 hidden: true,
330 },
c287e233
DC
331 ],
332
333 reload: function() {
48bbb009 334 this.rstore.load();
c287e233
DC
335 },
336
48bbb009
TL
337 viewCertificate: function() {
338 let me = this;
339 let selection = me.getSelection();
c287e233
DC
340 if (!selection || selection.length < 1) {
341 return;
342 }
343 var win = Ext.create('PVE.node.CertificateViewer', {
344 cert: selection[0].data.filename,
8058410f 345 nodename: me.nodename,
c287e233
DC
346 });
347 win.show();
348 },
349
350 listeners: {
48bbb009 351 itemdblclick: 'viewCertificate',
c287e233
DC
352 },
353
354 initComponent: function() {
355 var me = this;
356
357 if (!me.nodename) {
358 throw "no nodename given";
359 }
360
361 me.rstore = Ext.create('Proxmox.data.UpdateStore', {
362 storeid: 'certs-' + me.nodename,
363 model: 'pve-certificate',
364 proxy: {
365 type: 'proxmox',
f6710aac
TL
366 url: '/api2/json/nodes/' + me.nodename + '/certificates/info',
367 },
c287e233
DC
368 });
369
370 me.store = {
371 type: 'diff',
f6710aac 372 rstore: me.rstore,
c287e233
DC
373 };
374
375 me.callParent();
376
48bbb009 377 me.mon(me.rstore, 'load', store => me.down('#deletebtn').setDisabled(!store.getById('pveproxy-ssl.pem')));
c287e233 378 me.rstore.startUpdate();
1f249769 379 me.on('destroy', me.rstore.stopUpdate, me.rstore);
f6710aac 380 },
c287e233 381});