]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/AddTfaRecovery.js
Buttons: add AltText
[proxmox-widget-toolkit.git] / src / window / AddTfaRecovery.js
1 Ext.define('Proxmox.window.AddTfaRecovery', {
2 extend: 'Proxmox.window.Edit',
3 alias: 'widget.pmxAddTfaRecovery',
4 mixins: ['Proxmox.Mixin.CBind'],
5
6 onlineHelp: 'user_mgmt',
7 isCreate: true,
8 isAdd: true,
9 subject: gettext('TFA recovery keys'),
10 width: 512,
11 method: 'POST',
12
13 fixedUser: false,
14
15 url: '/api2/extjs/access/tfa',
16 submitUrl: function(url, values) {
17 let userid = values.userid;
18 delete values.userid;
19 return `${url}/${userid}`;
20 },
21
22 apiCallDone: function(success, response) {
23 if (!success) {
24 return;
25 }
26
27 let values = response
28 .result
29 .data
30 .recovery
31 .map((v, i) => `${i}: ${v}`)
32 .join("\n");
33 Ext.create('Proxmox.window.TfaRecoveryShow', {
34 autoShow: true,
35 userid: this.getViewModel().get('userid'),
36 values,
37 });
38 },
39
40 viewModel: {
41 data: {
42 has_entry: false,
43 userid: null,
44 },
45 },
46
47 controller: {
48 xclass: 'Ext.app.ViewController',
49 hasEntry: async function(userid) {
50 let me = this;
51 let view = me.getView();
52
53 try {
54 await Proxmox.Async.api2({
55 url: `${view.url}/${userid}/recovery`,
56 method: 'GET',
57 });
58 return true;
59 } catch (_response) {
60 return false;
61 }
62 },
63
64 init: function(view) {
65 this.onUseridChange(null, Proxmox.UserName);
66 },
67
68 onUseridChange: async function(field, userid) {
69 let me = this;
70 let vm = me.getViewModel();
71
72 me.userid = userid;
73 vm.set('userid', userid);
74
75 let has_entry = await me.hasEntry(userid);
76 vm.set('has_entry', has_entry);
77 },
78 },
79
80 items: [
81 {
82 xtype: 'pmxDisplayEditField',
83 name: 'userid',
84 cbind: {
85 editable: (get) => !get('fixedUser'),
86 value: () => Proxmox.UserName,
87 },
88 fieldLabel: gettext('User'),
89 editConfig: {
90 xtype: 'pmxUserSelector',
91 allowBlank: false,
92 validator: function(_value) {
93 return !this.up('window').getViewModel().get('has_entry');
94 },
95 },
96 renderer: Ext.String.htmlEncode,
97 listeners: {
98 change: 'onUseridChange',
99 },
100 },
101 {
102 xtype: 'hiddenfield',
103 name: 'type',
104 value: 'recovery',
105 },
106 {
107 xtype: 'displayfield',
108 bind: {
109 hidden: '{!has_entry}',
110 },
111 hidden: true,
112 userCls: 'pmx-hint',
113 value: gettext('User already has recovery keys.'),
114 },
115 {
116 xtype: 'textfield',
117 name: 'password',
118 reference: 'password',
119 fieldLabel: gettext('Verify Password'),
120 inputType: 'password',
121 minLength: 5,
122 allowBlank: false,
123 validateBlank: true,
124 cbind: {
125 hidden: () => Proxmox.UserName === 'root@pam',
126 disabled: () => Proxmox.UserName === 'root@pam',
127 emptyText: () =>
128 Ext.String.format(gettext("Confirm your ({0}) password"), Proxmox.UserName),
129 },
130 },
131 ],
132 });
133
134 Ext.define('Proxmox.window.TfaRecoveryShow', {
135 extend: 'Ext.window.Window',
136 alias: ['widget.pmxTfaRecoveryShow'],
137 mixins: ['Proxmox.Mixin.CBind'],
138
139 width: 600,
140 modal: true,
141 resizable: false,
142 title: gettext('Recovery Keys'),
143 onEsc: Ext.emptyFn,
144
145 items: [
146 {
147 xtype: 'form',
148 layout: 'anchor',
149 bodyPadding: 10,
150 border: false,
151 fieldDefaults: {
152 anchor: '100%',
153 },
154 items: [
155 {
156 xtype: 'textarea',
157 editable: false,
158 inputId: 'token-secret-value',
159 cbind: {
160 value: '{values}',
161 },
162 fieldStyle: {
163 'fontFamily': 'monospace',
164 },
165 height: '160px',
166 },
167 {
168 xtype: 'displayfield',
169 border: false,
170 padding: '5 0 0 0',
171 userCls: 'pmx-hint',
172 value: gettext('Please record recovery keys - they will only be displayed now'),
173 },
174 ],
175 },
176 ],
177 buttons: [
178 {
179 handler: function(b) {
180 document.getElementById('token-secret-value').select();
181 document.execCommand("copy");
182 },
183 iconCls: 'fa fa-clipboard',
184 text: gettext('Copy Recovery Keys'),
185 },
186 {
187 handler: function(b) {
188 let win = this.up('window');
189 win.paperkeys(win.values, win.userid);
190 },
191 iconCls: 'fa fa-print',
192 text: gettext('Print Recovery Keys'),
193 },
194 ],
195 paperkeys: function(keyString, userid) {
196 let me = this;
197
198 let printFrame = document.createElement("iframe");
199 Object.assign(printFrame.style, {
200 position: "fixed",
201 right: "0",
202 bottom: "0",
203 width: "0",
204 height: "0",
205 border: "0",
206 });
207 const host = document.location.host;
208 const title = document.title;
209 const html = `<html><head><script>
210 window.addEventListener('DOMContentLoaded', (ev) => window.print());
211 </script><style>@media print and (max-height: 150mm) {
212 h4, p { margin: 0; font-size: 1em; }
213 }</style></head><body style="padding: 5px;">
214 <h4>Recovery Keys for '${userid}' - ${title} (${host})</h4>
215 <p style="font-size:1.5em;line-height:1.5em;font-family:monospace;
216 white-space:pre-wrap;overflow-wrap:break-word;">
217 ${keyString}
218 </p>
219 </body></html>`;
220
221 printFrame.src = "data:text/html;base64," + btoa(html);
222 document.body.appendChild(printFrame);
223 },
224 });