CKKSIncomingQueueEntry.m
1 /* 2 * Copyright (c) 2016 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #if OCTAGON 25 26 #include <AssertMacros.h> 27 28 #import <Foundation/Foundation.h> 29 30 #import "CKKSKeychainView.h" 31 32 #include <utilities/SecDb.h> 33 #include "keychain/securityd/SecDbItem.h" 34 #include "keychain/securityd/SecItemSchema.h" 35 36 #import <CloudKit/CloudKit.h> 37 #import "CKKSIncomingQueueEntry.h" 38 #import "CKKSItemEncrypter.h" 39 #import "CKKSSIV.h" 40 41 @implementation CKKSIncomingQueueEntry 42 43 - (NSString*)description { 44 return [NSString stringWithFormat: @"<%@(%@): %@ %@ (%@)>", 45 NSStringFromClass([self class]), 46 self.item.zoneID.zoneName, 47 self.action, 48 self.item.uuid, 49 self.state]; 50 } 51 52 - (instancetype) initWithCKKSItem:(CKKSItem*) item 53 action:(NSString*) action 54 state:(NSString*) state { 55 if(self = [super init]) { 56 _item = item; 57 _action = action; 58 _state = state; 59 } 60 61 return self; 62 } 63 64 #pragma mark - Property access to underlying CKKSItem 65 66 -(NSString*)uuid { 67 return self.item.uuid; 68 } 69 70 -(void)setUuid:(NSString *)uuid { 71 self.item.uuid = uuid; 72 } 73 74 #pragma mark - Database Operations 75 76 + (instancetype) fromDatabase: (NSString*) uuid zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { 77 return [self fromDatabaseWhere: @{@"UUID": CKKSNilToNSNull(uuid), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} error: error]; 78 } 79 80 + (instancetype) tryFromDatabase: (NSString*) uuid zoneID:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { 81 return [self tryFromDatabaseWhere: @{@"UUID": CKKSNilToNSNull(uuid), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} error: error]; 82 } 83 84 + (NSArray<CKKSIncomingQueueEntry*>*)fetch:(ssize_t)n 85 startingAtUUID:(NSString*)uuid 86 state:(NSString*)state 87 action:(NSString* _Nullable)action 88 zoneID:(CKRecordZoneID*)zoneID 89 error: (NSError * __autoreleasing *) error { 90 NSMutableDictionary* whereDict = [@{@"state": CKKSNilToNSNull(state), @"ckzone":CKKSNilToNSNull(zoneID.zoneName)} mutableCopy]; 91 whereDict[@"action"] = action; 92 if(uuid) { 93 whereDict[@"UUID"] = [CKKSSQLWhereValue op:CKKSSQLWhereComparatorGreaterThan value:uuid]; 94 } 95 return [self fetch:n 96 where:whereDict 97 orderBy:@[@"UUID"] 98 error:error]; 99 } 100 101 102 #pragma mark - CKKSSQLDatabaseObject methods 103 104 + (NSString*)sqlTable { 105 return @"incomingqueue"; 106 } 107 108 + (NSArray<NSString*>*)sqlColumns { 109 return [[CKKSItem sqlColumns] arrayByAddingObjectsFromArray: @[@"action", @"state"]]; 110 } 111 112 - (NSDictionary<NSString*,NSString*>*)whereClauseToFindSelf { 113 return [self.item whereClauseToFindSelf]; 114 } 115 116 - (NSDictionary<NSString*,NSString*>*)sqlValues { 117 NSMutableDictionary* values = [[self.item sqlValues] mutableCopy]; 118 values[@"action"] = self.action; 119 values[@"state"] = self.state; 120 return values; 121 } 122 123 124 + (instancetype)fromDatabaseRow:(NSDictionary<NSString *, CKKSSQLResult*>*) row { 125 return [[CKKSIncomingQueueEntry alloc] initWithCKKSItem: [CKKSItem fromDatabaseRow: row] 126 action:row[@"action"].asString 127 state:row[@"state"].asString]; 128 } 129 130 + (NSDictionary<NSString*,NSNumber*>*)countsByStateInZone:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { 131 NSMutableDictionary* results = [[NSMutableDictionary alloc] init]; 132 133 [CKKSSQLDatabaseObject queryDatabaseTable: [[self class] sqlTable] 134 where: @{@"ckzone": CKKSNilToNSNull(zoneID.zoneName)} 135 columns: @[@"state", @"count(rowid)"] 136 groupBy: @[@"state"] 137 orderBy:nil 138 limit: -1 139 processRow: ^(NSDictionary<NSString*, CKKSSQLResult*>* row) { 140 results[row[@"state"].asString] = row[@"count(rowid)"].asNSNumberInteger; 141 } 142 error: error]; 143 return results; 144 } 145 146 + (NSInteger)countByState:(CKKSItemState *)state zone:(CKRecordZoneID*)zoneID error: (NSError * __autoreleasing *) error { 147 __block NSInteger result = -1; 148 149 [CKKSSQLDatabaseObject queryDatabaseTable: [[self class] sqlTable] 150 where: @{@"ckzone": CKKSNilToNSNull(zoneID.zoneName), @"state": state } 151 columns: @[@"count(*)"] 152 groupBy: nil 153 orderBy: nil 154 limit: -1 155 processRow: ^(NSDictionary<NSString*, CKKSSQLResult*>* row) { 156 result = row[@"count(*)"].asNSInteger; 157 } 158 error: error]; 159 return result; 160 } 161 162 @end 163 164 #endif