]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSDeleteCKZoneOperation.m
Security-59754.41.1.tar.gz
[apple/security.git] / keychain / ckks / CKKSDeleteCKZoneOperation.m
1
2
3 #if OCTAGON
4
5 #import <CloudKit/CloudKit.h>
6 #import <CloudKit/CloudKit_Private.h>
7
8 #import "keychain/ckks/CKKSDeleteCKZoneOperation.h"
9 #import "keychain/ckks/CKKSZoneStateEntry.h"
10 #import "keychain/categories/NSError+UsefulConstructors.h"
11 #import "keychain/ot/ObjCImprovements.h"
12 #import "keychain/ot/OTDefines.h"
13
14 @implementation CKKSDeleteCKZoneOperation
15 @synthesize nextState = _nextState;
16 @synthesize intendedState = _intendedState;
17
18 - (instancetype)initWithDependencies:(CKKSOperationDependencies*)dependencies
19 intendedState:(OctagonState*)intendedState
20 errorState:(OctagonState*)errorState
21 {
22 if(self = [super init]) {
23 _deps = dependencies;
24
25 _intendedState = intendedState;
26 _nextState = errorState;
27 }
28 return self;
29 }
30
31 - (void)groupStart
32 {
33
34 ckksnotice("ckkszone", self.deps.zoneID, "Deleting CloudKit zone '%@'", self.deps.zoneID);
35 CKKSZoneModifyOperations* zoneOps = [self.deps.zoneModifier deleteZone:self.deps.zoneID];
36
37
38 WEAKIFY(self);
39
40 CKKSResultOperation* handleModificationsOperation = [CKKSResultOperation named:@"handle-modification" withBlock:^{
41 STRONGIFY(self);
42
43 bool fatalError = false;
44
45 NSError* operationError = zoneOps.zoneModificationOperation.error;
46 bool removed = [zoneOps.deletedRecordZoneIDs containsObject:self.deps.zoneID];
47
48 if(!removed && operationError) {
49 // Okay, but if this error is either 'ZoneNotFound' or 'UserDeletedZone', that's fine by us: the zone is deleted.
50 NSDictionary* partialErrors = operationError.userInfo[CKPartialErrorsByItemIDKey];
51 if([operationError.domain isEqualToString:CKErrorDomain] && operationError.code == CKErrorPartialFailure && partialErrors) {
52 for(CKRecordZoneID* errorZoneID in partialErrors.allKeys) {
53 NSError* errorZone = partialErrors[errorZoneID];
54
55 if(errorZone && [errorZone.domain isEqualToString:CKErrorDomain] &&
56 (errorZone.code == CKErrorZoneNotFound || errorZone.code == CKErrorUserDeletedZone)) {
57 ckksnotice("ckkszone", self.deps.zoneID, "Attempted to delete zone %@, but it's already missing. This is okay: %@", errorZoneID, errorZone);
58 } else {
59 fatalError = true;
60 }
61 }
62
63 } else {
64 fatalError = true;
65 }
66
67 ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed with error: %@", self.deps.zoneID, operationError);
68
69 if(fatalError) {
70 // Early-exit
71 self.error = operationError;
72 return;
73 }
74 }
75
76 ckksnotice("ckkszone", self.deps.zoneID, "deletion of record zone %@ completed successfully", self.deps.zoneID);
77
78 [self.deps.databaseProvider dispatchSyncWithSQLTransaction:^CKKSDatabaseTransactionResult{
79 NSError* error = nil;
80 CKKSZoneStateEntry* ckse = [CKKSZoneStateEntry state:self.deps.zoneID.zoneName];
81 ckse.ckzonecreated = NO;
82 ckse.ckzonesubscribed = NO;
83
84 [ckse saveToDatabase:&error];
85 if(error) {
86 ckkserror("ckks", self.deps.zoneID, "couldn't save zone creation status for %@: %@", self.deps.zoneID, error);
87 }
88
89 self.nextState = self.intendedState;
90 return CKKSDatabaseTransactionCommit;
91 }];
92 }];
93
94 [handleModificationsOperation addNullableDependency:zoneOps.zoneModificationOperation];
95 [handleModificationsOperation addNullableDependency:zoneOps.zoneSubscriptionOperation];
96 [self runBeforeGroupFinished:handleModificationsOperation];
97 }
98
99 @end
100
101 #endif // OCTAGON