/ keychain / ckks / CKKSDeleteCKZoneOperation.m
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