diff --git a/VENTouchLock/VENTouchLock.h b/VENTouchLock/VENTouchLock.h index 642ee90..f88ccce 100644 --- a/VENTouchLock/VENTouchLock.h +++ b/VENTouchLock/VENTouchLock.h @@ -37,6 +37,22 @@ typedef NS_ENUM(NSUInteger, VENTouchLockTouchIDResponse) { passcodeAttemptLimit:(NSUInteger)attemptLimit splashViewControllerClass:(Class)splashViewControllerClass; +/** + Set the defaults. This method should be called at launch. Access group is needed for keychain sharing. + @param service The keychain service for which to set and return a passcode + @param account The keychain account for which to set and return a passcode + @param accessGroup The keychain access group for which to set and return a shared passcode + @param splashViewControllerClass The class of the custom splash view controller. This class should be a subclass of VENTouchLockSplashViewController and any of its custom initialization must be in its init function + @param reason The default message displayed on the TouchID prompt + */ +- (void)setKeychainService:(NSString *)service + keychainAccount:(NSString *)account + keychainAccessGroup:(NSString *)accessGroup + touchIDReason:(NSString *)reason + passcodeAttemptLimit:(NSUInteger)attemptLimit + splashViewControllerClass:(Class)splashViewControllerClass; + + /** Returns YES if a passcode exists, and NO otherwise. */ diff --git a/VENTouchLock/VENTouchLock.m b/VENTouchLock/VENTouchLock.m index a6272e8..74ae5bc 100644 --- a/VENTouchLock/VENTouchLock.m +++ b/VENTouchLock/VENTouchLock.m @@ -10,6 +10,7 @@ @interface VENTouchLock () @property (copy, nonatomic) NSString *keychainService; @property (copy, nonatomic) NSString *keychainAccount; +@property (copy, nonatomic) NSString *keychainAccessGroup; @property (copy, nonatomic) NSString *touchIDReason; @property (assign, nonatomic) NSUInteger passcodeAttemptLimit; @property (assign, nonatomic) Class splashViewControllerClass; @@ -62,6 +63,20 @@ - (void)setKeychainService:(NSString *)service self.splashViewControllerClass = splashViewControllerClass; } +- (void)setKeychainService:(NSString *)service + keychainAccount:(NSString *)account + keychainAccessGroup:(NSString *)accessGroup + touchIDReason:(NSString *)reason + passcodeAttemptLimit:(NSUInteger)attemptLimit + splashViewControllerClass:(Class)splashViewControllerClass { + + [self setKeychainService:service + keychainAccount:account + touchIDReason:reason + passcodeAttemptLimit:attemptLimit + splashViewControllerClass:splashViewControllerClass]; + self.keychainAccessGroup = accessGroup; +} #pragma mark - Keychain Methods @@ -70,11 +85,14 @@ - (BOOL)isPasscodeSet return !![self currentPasscode]; } -- (NSString *)currentPasscode -{ - NSString *service = self.keychainService; - NSString *account = self.keychainAccount; - return [SSKeychain passwordForService:service account:account]; +- (NSString *)currentPasscode { + + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = self.keychainService; + query.account = self.keychainAccount; + query.accessGroup = self.keychainAccessGroup; + [query fetch:nil]; + return query.password; } - (BOOL)isPasscodeValid:(NSString *)passcode @@ -84,9 +102,12 @@ - (BOOL)isPasscodeValid:(NSString *)passcode - (void)setPasscode:(NSString *)passcode { - NSString *service = self.keychainService; - NSString *account = self.keychainAccount; - [SSKeychain setPassword:passcode forService:service account:account]; + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = self.keychainService; + query.account = self.keychainAccount; + query.accessGroup = self.keychainAccessGroup; + query.password = passcode; + [query save:nil]; } - (void)deletePasscode @@ -95,9 +116,11 @@ - (void)deletePasscode [VENTouchLockEnterPasscodeViewController resetPasscodeAttemptHistory]; [[NSUserDefaults standardUserDefaults] synchronize]; - NSString *service = self.keychainService; - NSString *account = self.keychainAccount; - [SSKeychain deletePasswordForService:service account:account]; + SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; + query.service = self.keychainService; + query.account = self.keychainAccount; + query.accessGroup = self.keychainAccessGroup; + [query deleteItem:nil]; } diff --git a/VENTouchLockTests/VENTouchLockSpec.m b/VENTouchLockTests/VENTouchLockSpec.m index 9616d50..7d30c34 100644 --- a/VENTouchLockTests/VENTouchLockSpec.m +++ b/VENTouchLockTests/VENTouchLockSpec.m @@ -97,4 +97,64 @@ }); -SpecEnd \ No newline at end of file +SpecEnd + +SpecBegin(VENTouchLockAccessGroup) + +beforeAll(^{ + [[VENTouchLock sharedInstance] setKeychainService:@"keychainService" + keychainAccount:@"keychainAccount" + keychainAccessGroup:@"keychainAccessGroupAccount" + touchIDReason:@"touchIDReason" + passcodeAttemptLimit:0 + splashViewControllerClass:NULL]; +}); + +beforeEach(^{ + [[VENTouchLock sharedInstance] deletePasscode]; +}); + +describe(@"setPasscode:", ^{ + + it(@"should register a passcode with VENTouchLock", ^{ + VENTouchLock *touchLock = [VENTouchLock sharedInstance]; + expect([touchLock isPasscodeSet]).to.equal(NO); + expect([touchLock currentPasscode]).to.beNil(); + + [[VENTouchLock sharedInstance] setPasscode:@"testPasscode"]; + + expect([touchLock isPasscodeSet]).to.equal(YES); + expect([touchLock currentPasscode]).to.equal(@"testPasscode"); + }); + +}); + +describe(@"isPasscodeValid", ^{ + + it(@"should return YES if the parameter sent is equal to the set passcode and NO otherwise", ^{ + VENTouchLock *touchLock = [VENTouchLock sharedInstance]; + [touchLock setPasscode:@"testPasscode"]; + expect([touchLock isPasscodeValid:@"testPasscode"]).to.equal(YES); + expect([touchLock isPasscodeValid:@"wrongPasscode"]).to.equal(NO); + }); + +}); + +describe(@"deletePasscode", ^{ + + it(@"should register a passcode with VENTouchLock", ^{ + VENTouchLock *touchLock = [VENTouchLock sharedInstance]; + + [[VENTouchLock sharedInstance] setPasscode:@"testPasscode"]; + expect([touchLock isPasscodeSet]).to.equal(YES); + expect([touchLock currentPasscode]).to.equal(@"testPasscode"); + + [touchLock deletePasscode]; + + expect([touchLock isPasscodeSet]).to.equal(NO); + expect([touchLock currentPasscode]).to.beNil(); + }); + +}); + +SpecEnd