]>
Commit | Line | Data |
---|---|---|
64176447 WB |
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 | }); |