diff options
Diffstat (limited to 'DomainDig/DataResetService.swift')
| -rw-r--r-- | DomainDig/DataResetService.swift | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/DomainDig/DataResetService.swift b/DomainDig/DataResetService.swift new file mode 100644 index 0000000..e993eba --- /dev/null +++ b/DomainDig/DataResetService.swift @@ -0,0 +1,76 @@ +import Foundation +import Security + +enum DataResetService { + enum ResetError: LocalizedError { + case missingBundleIdentifier + + var errorDescription: String? { + switch self { + case .missingBundleIdentifier: + "DomainDig could not determine its local storage identifier." + } + } + } + + static func wipeAllLocalData(viewModel: DomainViewModel) async throws { + let secretReferences = await MainActor.run { + IntegrationService.shared.localSecretReferences() + } + + try await Task.detached(priority: .userInitiated) { + try performPersistentWipe(secretReferences: secretReferences) + }.value + + await LookupRuntime.shared.clearCache() + await LocalNotificationService.shared.clearAllNotifications() + await UsageCreditService.shared.resetForCurrentVersion() + + await MainActor.run { + IntegrationService.shared.resetAfterLocalWipe() + CloudSyncService.shared.resetLocalStateAfterWipe() + PurchaseService.shared.resetCachedStateAfterLocalWipe() + _ = DomainMonitoringScheduler.shared.syncSchedule() + } + + await viewModel.applyLocalDataReset() + } + + private nonisolated static func performPersistentWipe(secretReferences: [String]) throws { + guard let bundleIdentifier = Bundle.main.bundleIdentifier else { + throw ResetError.missingBundleIdentifier + } + + for reference in secretReferences { + deleteIntegrationSecret(reference: reference) + } + + try removeTemporaryFiles() + + let defaults = UserDefaults.standard + defaults.removePersistentDomain(forName: bundleIdentifier) + defaults.synchronize() + } + + private nonisolated static func removeTemporaryFiles() throws { + let tempDirectory = FileManager.default.temporaryDirectory + let urls = try FileManager.default.contentsOfDirectory( + at: tempDirectory, + includingPropertiesForKeys: nil, + options: [.skipsHiddenFiles] + ) + + for url in urls { + try? FileManager.default.removeItem(at: url) + } + } + + private nonisolated static func deleteIntegrationSecret(reference: String) { + let query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrAccount as String: reference + ] + + SecItemDelete(query as CFDictionary) + } +} |
