1import QtQuick 2.9
2import QtQuick.Controls 2.2
3import QtQuick.Layouts 1.2
4import "slotutils.js" as SlotUtils
5
6StackView {
7    anchors.fill: parent
8    initialItem: noDeviceView
9
10    property int selectedSlot
11    property bool slot1Configured
12    property bool slot2Configured
13
14    property bool locked
15
16    property bool isConfiguringInterfaces: currentItem !== null
17                                           && currentItem.objectName === "interfaces"
18
19    property bool isShowingHomeView: currentItem !== null
20                                     && currentItem.objectName === "homeView"
21
22    function lock() {
23        locked = true
24    }
25
26    function unlock() {
27        locked = false
28    }
29
30    function selectSlot1() {
31        selectedSlot = 1
32    }
33
34    function selectSlot2() {
35        selectedSlot = 2
36    }
37
38    function selectedSlotConfigured() {
39        if (selectedSlot === 1) {
40            return slot1Configured
41        }
42        if (selectedSlot === 2) {
43            return slot2Configured
44        }
45        return false
46    }
47
48    function popToDepth(height) {
49        pop(find(function (item, searchIndex) {
50            return searchIndex === height
51        }))
52    }
53
54    function replaceAtDepth(depth, item, newObjectName) {
55        var itemToReplace = find(function (item, index) {
56            return index === depth
57        })
58        if (itemToReplace) {
59            if (newObjectName) {
60                if (itemToReplace.objectName === newObjectName) {
61                    pop(itemToReplace)
62                } else {
63                    replace(itemToReplace, item)
64                }
65            } else {
66                replace(itemToReplace, item)
67            }
68        } else {
69            push(item)
70        }
71    }
72
73    function home() {
74        if (yubiKey.hasDevice) {
75            var homeViewOnStack = find(function (item) {
76                return item.objectName === 'homeView'
77            })
78            if (homeViewOnStack) {
79                pop(homeViewOnStack)
80            } else {
81                replaceAtDepth(0, homeView, 'homeView')
82            }
83        } else if (yubiKey.nDevices > 1) {
84            replaceAtDepth(0, multipleDevicesView, 'multipleDevicesView')
85        } else {
86            replaceAtDepth(0, noDeviceView, 'noDeviceView')
87        }
88    }
89
90    function configureInterfaces() {
91        var interfaceComponent = yubiKey.supportsNewInterfaces(
92                    ) ? interfaces : legacyInterfaces
93        replaceAtDepth(1, interfaceComponent, 'interfaces')
94    }
95
96    function piv() {
97        replaceAtDepth(1, pivView, 'pivView')
98    }
99
100    function pivCertificates() {
101        replaceAtDepth(2, pivCertificatesView, 'pivCertificatesView')
102    }
103
104    function pivSetupForMacOs() {
105        replaceAtDepth(2, pivSetupForMacOsView, 'pivSetupForMacOs')
106    }
107
108    function pivReset() {
109        replaceAtDepth(2, pivResetView, 'pivResetView')
110    }
111
112    function pivPinManagement() {
113        replaceAtDepth(2, pivPinManagementView, 'pivPinManagementView')
114    }
115
116    function pivChangePin() {
117        replaceAtDepth(3, pivChangePinView, 'pivChangePinView')
118    }
119
120    function pivUnblockPin() {
121        replaceAtDepth(3, pivUnblockPinView, 'pivUnblockPinView')
122    }
123
124    function pivChangePuk() {
125        replaceAtDepth(3, pivChangePukView, 'pivChangePukView')
126    }
127
128    function pivChangeManagementKey() {
129        replaceAtDepth(3, pivChangeManagementKeyView,
130                       'pivChangeManagementKeyView')
131    }
132
133    function pivGetPinOrManagementKey(pinCallback, keyCallback) {
134        if ((yubiKey.piv || {
135
136             }).has_protected_key) {
137            pivPinPopup.getInputAndThen(pinCallback)
138        } else {
139            pivManagementKeyPopup.getInputAndThen(keyCallback)
140        }
141    }
142
143    function fido2() {
144        replaceAtDepth(1, fido2View, 'fido2View')
145    }
146
147    function fido2SetPin() {
148        replaceAtDepth(2, fido2SetPinView, 'fido2SetPinView')
149    }
150
151    function fido2ChangePin() {
152        replaceAtDepth(2, fido2ChangePinView, 'fido2ChangePinView')
153    }
154
155    function fido2Reset() {
156        replaceAtDepth(2, fido2ResetView, 'fido2ResetView')
157    }
158
159    function otp() {
160        replaceAtDepth(1, otpViewComponent, 'otpView')
161    }
162
163    function otpConfirmOverwrite(callback) {
164        confirmationPopup.show(
165                    qsTr("Overwrite?"), qsTr(
166                        "%1 is already configured. Do you want to overwrite the existing configuration?").arg(
167                        SlotUtils.slotNameCapitalized(views.selectedSlot)),
168                    callback)
169    }
170
171    function otpWriteError() {
172        snackbarError.show(
173                    qsTr("Failed to modify %1. Make sure the YubiKey does not have restricted access.").arg(
174                        SlotUtils.slotNameCapitalized(views.selectedSlot)))
175    }
176
177    function otpFailedToConfigureErrorPopup(error) {
178        snackbarError.show(qsTr("Failed to configure %1. %2").arg(
179                               SlotUtils.slotNameCapitalized(
180                                   views.selectedSlot)).arg(snackbarError.getDefaultMessage(error)))
181    }
182
183    function snackbarErrorMessage(error) {
184        snackbarError.showResponseError(error)
185    }
186
187    Component {
188        id: fido2SetPinView
189        Fido2SetPinView {
190        }
191    }
192
193    Component {
194        id: fido2ChangePinView
195        Fido2ChangePinView {
196        }
197    }
198
199    Component {
200        id: homeView
201        HomeView {
202        }
203    }
204
205    Component {
206        id: otpViewComponent
207        OtpView {
208        }
209    }
210
211    Component {
212        id: otpConfigureSlotView
213        OtpConfigureSlotView {
214        }
215    }
216
217    Component {
218        id: otpYubiOtpView
219        OtpYubiOtpView {
220        }
221    }
222
223    Component {
224        id: otpChalRespView
225        OtpChalRespView {
226        }
227    }
228    Component {
229        id: otpOathHotpView
230        OtpOathHotpView {
231        }
232    }
233    Component {
234        id: otpStaticPasswordView
235        OtpStaticPasswordView {
236        }
237    }
238
239    Component {
240        id: fido2View
241        Fido2View {
242        }
243    }
244
245    Component {
246        id: pivView
247
248        PivView {
249        }
250    }
251
252    Component {
253        id: pivCertificatesView
254        PivCertificateView {
255        }
256    }
257
258    Component {
259        id: pivSetupForMacOsView
260        PivSetupForMacOsView {
261        }
262    }
263
264    Component {
265        id: pivPinManagementView
266
267        PivPinManagementView {
268        }
269    }
270
271    Component {
272        id: pivChangePinView
273
274        PivChangePinView {
275        }
276    }
277
278    Component {
279        id: pivUnblockPinView
280
281        PivUnblockPinView {
282        }
283    }
284
285    Component {
286        id: pivChangePukView
287
288        PivChangePukView {
289        }
290    }
291
292    Component {
293        id: pivChangeManagementKeyView
294
295        PivSetManagementKeyView {
296        }
297    }
298
299    Component {
300        id: pivGenerateCertificateWizard
301
302        PivGenerateCertificateWizard {
303        }
304    }
305
306    Component {
307        id: legacyInterfaces
308        LegacyInterfaceView {
309        }
310    }
311
312    Component {
313        id: interfaces
314        InterfaceView {
315        }
316    }
317
318    Component {
319        id: noDeviceView
320        Heading2 {
321            text: qsTr("Insert your YubiKey")
322            verticalAlignment: Text.AlignVCenter
323            horizontalAlignment: Text.AlignHCenter
324        }
325    }
326
327    Component {
328        id: multipleDevicesView
329        Heading2 {
330            text: qsTr("Make sure only one YubiKey is inserted")
331            verticalAlignment: Text.AlignVCenter
332            horizontalAlignment: Text.AlignHCenter
333        }
334    }
335
336    ConfirmationPopup {
337        id: confirmationPopup
338    }
339
340    PivPinPopup {
341        id: pivPinPopup
342    }
343
344    PivManagementKeyPopup {
345        id: pivManagementKeyPopup
346    }
347
348    PivPasswordPopup {
349        id: pivPasswordPopup
350    }
351
352    InterFaceLockCodePopup {
353        id: lockCodePopup
354    }
355
356    SnackBarSuccess {
357        id: snackbarSuccess
358    }
359
360    SnackBarError {
361        id: snackbarError
362    }
363}
364