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