summaryrefslogtreecommitdiff
path: root/DomainDig/DataResetService.swift
diff options
context:
space:
mode:
Diffstat (limited to 'DomainDig/DataResetService.swift')
-rw-r--r--DomainDig/DataResetService.swift76
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)
+ }
+}