diff --git a/apps/web/src/device-listener/DeviceListenerCurrentDevice.ts b/apps/web/src/device-listener/DeviceListenerCurrentDevice.ts index 11c07ed0fd..f6127c84d9 100644 --- a/apps/web/src/device-listener/DeviceListenerCurrentDevice.ts +++ b/apps/web/src/device-listener/DeviceListenerCurrentDevice.ts @@ -180,64 +180,45 @@ export class DeviceListenerCurrentDevice { const keyBackupDownloadIsOk = !keyBackupUploadActive || backupDisabled || (await crypto.getSessionBackupPrivateKey()) !== null; - const allSystemsReady = - isCurrentDeviceTrusted && - allCrossSigningSecretsCached && - keyBackupUploadIsOk && - recoveryIsOk && - keyBackupDownloadIsOk; + if (!isCurrentDeviceTrusted) { + // The current device is not trusted: prompt the user to verify + await this.failedCheck("verify_this_session", logSpan, "info", "Current device not verified"); + } else if (!allCrossSigningSecretsCached) { + // cross signing ready & device trusted, but we are missing secrets from our local cache. + // prompt the user to enter their recovery key. + const newState = crossSigningStatus.privateKeysInSecretStorage + ? "key_storage_out_of_sync" + : "identity_needs_reset"; - if (allSystemsReady) { + await this.failedCheck( + newState, + logSpan, + "info", + "Some secrets not cached", + crossSigningStatus.privateKeysCachedLocally, + crossSigningStatus.privateKeysInSecretStorage, + ); + } else if (!keyBackupUploadIsOk) { + await this.failedCheck( + "turn_on_key_storage", + logSpan, + "info", + "Key backup upload is unexpectedly turned off", + ); + } else if (!recoveryIsOk) { + if (secretStorageStatus.defaultKeyId === null) { + await this.failedCheck("set_up_recovery", logSpan, "info", "No default 4S key"); + } else { + await this.failedCheck("key_storage_out_of_sync", logSpan, "warn", "4S is missing secrets", { + secretStorageStatus, + }); + } + } else if (!keyBackupDownloadIsOk) { + await this.failedCheck("key_storage_out_of_sync", logSpan, "warn", "Backup key is not cached locally"); + } else { + // Everything is OK - no need to show a toast logSpan.info("No toast needed"); await this.setDeviceState("ok", logSpan); - } else { - // make sure our keys are finished downloading - await crypto.getUserDeviceInfo([this.client.getSafeUserId()]); - - if (!isCurrentDeviceTrusted) { - // the current device is not trusted: prompt the user to verify - logSpan.info("Current device not verified: setting state to VERIFY_THIS_SESSION"); - await this.setDeviceState("verify_this_session", logSpan); - } else if (!allCrossSigningSecretsCached) { - // cross signing ready & device trusted, but we are missing secrets from our local cache. - // prompt the user to enter their recovery key. - logSpan.info( - "Some secrets not cached: setting state to KEY_STORAGE_OUT_OF_SYNC", - crossSigningStatus.privateKeysCachedLocally, - crossSigningStatus.privateKeysInSecretStorage, - ); - await this.setDeviceState( - crossSigningStatus.privateKeysInSecretStorage ? "key_storage_out_of_sync" : "identity_needs_reset", - logSpan, - ); - } else if (!keyBackupUploadIsOk) { - logSpan.info("Key backup upload is unexpectedly turned off: setting state to TURN_ON_KEY_STORAGE"); - await this.setDeviceState("turn_on_key_storage", logSpan); - } else if (!recoveryIsOk) { - if (secretStorageStatus.defaultKeyId === null) { - logSpan.info("No default 4S key: setting state to SET_UP_RECOVERY"); - await this.setDeviceState("set_up_recovery", logSpan); - } else { - logSpan.warn("4S is missing secrets: setting state to KEY_STORAGE_OUT_OF_SYNC", { - secretStorageStatus, - allCrossSigningSecretsCached, - isCurrentDeviceTrusted, - keyBackupDownloadIsOk, - }); - await this.setDeviceState("key_storage_out_of_sync", logSpan); - } - } else if (!keyBackupDownloadIsOk) { - logSpan.warn("Backup key is not cached locally: setting state to KEY_STORAGE_OUT_OF_SYNC", { - secretStorageStatus, - allCrossSigningSecretsCached, - isCurrentDeviceTrusted, - keyBackupDownloadIsOk, - }); - await this.setDeviceState("key_storage_out_of_sync", logSpan); - } else { - // We should not get here - logSpan.error("DeviceListenerCurrentDevice: allSystemsReady was false, but no case matched."); - } } } @@ -250,6 +231,30 @@ export class DeviceListenerCurrentDevice { return this.deviceState; } + /** + * recheck failed - update our local device keys, log a message and set the + * state to display to the user. + */ + private async failedCheck( + newState: DeviceState, + logSpan: LogSpan, + level: "info" | "warn", + message: string, + ...logItems: Array + ): Promise { + // Make sure our keys are finished downloading + await this.client.getCrypto()?.getUserDeviceInfo([this.client.getSafeUserId()]); + + const fullMessage = `${message}: setting state to ${newState.toLowerCase()}`; + if (level === "info") { + logSpan.info(fullMessage, ...logItems); + } else { + logSpan.warn(fullMessage, ...logItems); + } + + await this.setDeviceState(newState, logSpan); + } + /** * Set the state of the device, and perform any actions necessary in * response to the state changing.