Files
simplex-chat/apps/ios/Shared/Views/LocalAuth/LocalAuthView.swift
Stanislav Dmitrenko 99a9fb2e1f ios: self destruct improvements (#3640)
* ios: self destruct improvements

* test

* adapted to stopped chat

* wait until ctrl initialization finishes

* Revert "test"

This reverts commit 7c199293cc.

* refactor

* simplify,fix

* refactor2

* refactor3

* comment

* fix

* fix

* comment

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* flip and rename flag

---------

Co-authored-by: Avently <avently@local>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-01-09 21:01:41 +00:00

106 lines
4.4 KiB
Swift

//
// LocalAuthView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 10/04/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct LocalAuthView: View {
@EnvironmentObject var m: ChatModel
var authRequest: LocalAuthRequest
@State private var password = ""
@State private var allowToReact = true
var body: some View {
PasscodeView(passcode: $password, title: authRequest.title ?? "Enter Passcode", reason: authRequest.reason, submitLabel: "Submit",
buttonsEnabled: $allowToReact) {
if let sdPassword = kcSelfDestructPassword.get(), authRequest.selfDestruct && password == sdPassword {
allowToReact = false
deleteStorageAndRestart(sdPassword) { r in
m.laRequest = nil
authRequest.completed(r)
}
return
}
let r: LAResult
if password == authRequest.password {
if authRequest.selfDestruct && kcSelfDestructPassword.get() != nil && !m.chatInitialized {
initChatAndMigrate()
}
r = .success
} else {
r = .failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry"))
}
m.laRequest = nil
authRequest.completed(r)
} cancel: {
m.laRequest = nil
authRequest.completed(.failed(authError: NSLocalizedString("Authentication cancelled", comment: "PIN entry")))
}
}
private func deleteStorageAndRestart(_ password: String, completed: @escaping (LAResult) -> Void) {
Task {
do {
/** Waiting until [initializeChat] finishes */
while (m.ctrlInitInProgress) {
try await Task.sleep(nanoseconds: 50_000000)
}
if m.chatRunning == true {
try await stopChatAsync()
}
if m.chatInitialized {
/**
* The following sequence can bring a user here:
* the user opened the app, entered app passcode, went to background, returned back, entered self-destruct code.
* In this case database should be closed to prevent possible situation when OS can deny database removal command
* */
chatCloseStore()
}
deleteAppDatabaseAndFiles()
// Clear sensitive data on screen just in case app fails to hide its views while new database is created
m.chatId = nil
m.reversedChatItems = []
m.chats = []
m.users = []
_ = kcAppPassword.set(password)
_ = kcSelfDestructPassword.remove()
await NtfManager.shared.removeAllNotifications()
let displayName = UserDefaults.standard.string(forKey: DEFAULT_LA_SELF_DESTRUCT_DISPLAY_NAME)
UserDefaults.standard.removeObject(forKey: DEFAULT_LA_SELF_DESTRUCT)
UserDefaults.standard.removeObject(forKey: DEFAULT_LA_SELF_DESTRUCT_DISPLAY_NAME)
await MainActor.run {
m.chatDbChanged = true
m.chatInitialized = false
}
resetChatCtrl()
try initializeChat(start: true)
m.chatDbChanged = false
AppChatState.shared.set(.active)
if m.currentUser != nil || !m.chatInitialized { return }
var profile: Profile? = nil
if let displayName = displayName, displayName != "" {
profile = Profile(displayName: displayName, fullName: "")
}
m.currentUser = try apiCreateActiveUser(profile, pastTimestamp: true)
onboardingStageDefault.set(.onboardingComplete)
m.onboardingStage = .onboardingComplete
try startChat()
completed(.success)
} catch {
completed(.failed(authError: NSLocalizedString("Incorrect passcode", comment: "PIN entry")))
}
}
}
}
struct LocalAuthView_Previews: PreviewProvider {
static var previews: some View {
LocalAuthView(authRequest: LocalAuthRequest.sample)
}
}