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