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