From b128b3bf131a9ca5f47774e1e076059c95b91a49 Mon Sep 17 00:00:00 2001 From: Davide Date: Thu, 7 Nov 2024 12:43:24 +0100 Subject: [PATCH] Erase shared profiles from iCloud correctly (#827) Do not delete CloudKit zone. Instead, delete Core Data entities and let sync do the rest. It's also a "more standard" approach. Deleting the zone right after the entities legitimately makes deletion ineffective, because it probably spoils sync. --- .../AppDataProfiles/CDProfileRepositoryV3.swift | 4 ++++ .../Views/Settings/SettingsSectionGroup.swift | 4 ---- .../Business/InMemoryProfileRepository.swift | 5 +++++ .../CommonLibrary/Business/NEProfileRepository.swift | 4 ++++ .../CommonLibrary/Business/ProfileManager.swift | 2 +- .../CommonLibrary/Business/ProfileRepository.swift | 2 ++ .../CommonUtils/Business/CoreDataRepository.swift | 12 +++++++----- .../Sources/CommonUtils/Business/Repository.swift | 2 +- 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift b/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift index 43881547..504892e5 100644 --- a/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift +++ b/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift @@ -120,4 +120,8 @@ extension CoreDataRepository: ProfileRepository where T == Profile { public func removeProfiles(withIds profileIds: [Profile.ID]) async throws { try await removeEntities(withIds: profileIds) } + + public func removeAllProfiles() async throws { + try await removeEntities(withIds: nil) + } } diff --git a/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsSectionGroup.swift b/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsSectionGroup.swift index 7f0c357b..88be554c 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsSectionGroup.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsSectionGroup.swift @@ -88,10 +88,6 @@ private extension SettingsSectionGroup { do { pp_log(.app, .info, "Erase CloudKit profiles...") try await profileManager.eraseRemotelySharedProfiles() - - let containerId = BundleConfiguration.mainString(for: .cloudKitId) - pp_log(.app, .info, "Erase CloudKit store with identifier \(containerId)...") - try await Utils.eraseCloudKitStore(fromContainerWithId: containerId) } catch { pp_log(.app, .error, "Unable to erase CloudKit store: \(error)") } diff --git a/Passepartout/Library/Sources/CommonLibrary/Business/InMemoryProfileRepository.swift b/Passepartout/Library/Sources/CommonLibrary/Business/InMemoryProfileRepository.swift index 621d3111..e65e39f9 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Business/InMemoryProfileRepository.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Business/InMemoryProfileRepository.swift @@ -60,4 +60,9 @@ public final class InMemoryProfileRepository: ProfileRepository { !ids.contains($0.id) } } + + public func removeAllProfiles() async throws { + pp_log(.App.profiles, .info, "Remove all profiles") + profiles = [] + } } diff --git a/Passepartout/Library/Sources/CommonLibrary/Business/NEProfileRepository.swift b/Passepartout/Library/Sources/CommonLibrary/Business/NEProfileRepository.swift index e976c19e..b2dc1e51 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Business/NEProfileRepository.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Business/NEProfileRepository.swift @@ -85,6 +85,10 @@ public final class NEProfileRepository: ProfileRepository { removedIds.insert(id) } } + + public func removeAllProfiles() async throws { + try await removeProfiles(withIds: profilesSubject.value.map(\.id)) + } } private extension NEProfileRepository { diff --git a/Passepartout/Library/Sources/CommonLibrary/Business/ProfileManager.swift b/Passepartout/Library/Sources/CommonLibrary/Business/ProfileManager.swift index cc39d1c2..ee4e695d 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Business/ProfileManager.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Business/ProfileManager.swift @@ -226,7 +226,7 @@ extension ProfileManager { public func eraseRemotelySharedProfiles() async throws { pp_log(.App.profiles, .notice, "Erase remotely shared profiles...") - try await remoteRepository?.removeProfiles(withIds: Array(allRemoteProfiles.keys)) + try await remoteRepository?.removeAllProfiles() } } diff --git a/Passepartout/Library/Sources/CommonLibrary/Business/ProfileRepository.swift b/Passepartout/Library/Sources/CommonLibrary/Business/ProfileRepository.swift index 99d56913..c7cacbcf 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Business/ProfileRepository.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Business/ProfileRepository.swift @@ -33,4 +33,6 @@ public protocol ProfileRepository { func saveProfile(_ profile: Profile) async throws func removeProfiles(withIds profileIds: [Profile.ID]) async throws + + func removeAllProfiles() async throws } diff --git a/Passepartout/Library/Sources/CommonUtils/Business/CoreDataRepository.swift b/Passepartout/Library/Sources/CommonUtils/Business/CoreDataRepository.swift index e37c3169..3c5eed68 100644 --- a/Passepartout/Library/Sources/CommonUtils/Business/CoreDataRepository.swift +++ b/Passepartout/Library/Sources/CommonUtils/Business/CoreDataRepository.swift @@ -139,16 +139,18 @@ public actor CoreDataRepository: NSObject, } } - public func removeEntities(withIds ids: [UUID]) async throws { + public func removeEntities(withIds ids: [UUID]?) async throws { try await context.perform { [weak self] in guard let self else { return } let request = newFetchRequest() - request.predicate = NSPredicate( - format: "any uuid in %@", - ids - ) + if let ids { + request.predicate = NSPredicate( + format: "any uuid in %@", + ids + ) + } do { let existing = try context.fetch(request) existing.forEach(context.delete) diff --git a/Passepartout/Library/Sources/CommonUtils/Business/Repository.swift b/Passepartout/Library/Sources/CommonUtils/Business/Repository.swift index 022fa4ca..7aff34bb 100644 --- a/Passepartout/Library/Sources/CommonUtils/Business/Repository.swift +++ b/Passepartout/Library/Sources/CommonUtils/Business/Repository.swift @@ -56,5 +56,5 @@ public protocol Repository { func saveEntities(_ entities: [Entity]) async throws - func removeEntities(withIds ids: [UUID]) async throws + func removeEntities(withIds ids: [UUID]?) async throws }