diff --git a/Lock/Podfile b/Lock/Podfile index 2a821cbf7..27078a12f 100644 --- a/Lock/Podfile +++ b/Lock/Podfile @@ -5,7 +5,6 @@ platform :ios, '8.0' def pod_with_warnings pod 'libextobjc', :inhibit_warnings => true #Ignore warnings for this lib pod 'BDBOAuth1Manager', :inhibit_warnings => true #Ignore warnings for this lib - pod 'Facebook-iOS-SDK', :inhibit_warnings => true #Ignore warnings for this lib pod 'ISO8601DateFormatter', :inhibit_warnings => true #Ignore warnings for this lib end @@ -15,7 +14,7 @@ target 'Lock', :exclusive => true do pod 'Lock/SMS', :path => '../' pod 'Lock/ReactiveCore', :path => '../' pod 'Lock/1Password', :path => '../' - pod 'Lock-Facebook', '~> 1.0' + pod 'Lock-Facebook', '~> 2.0' pod 'Lock-Twitter', '~> 1.0' pod 'Lock-GooglePlus', '~> 1.0' diff --git a/Lock/Podfile.lock b/Lock/Podfile.lock index 7833f61ec..88503dfc0 100644 --- a/Lock/Podfile.lock +++ b/Lock/Podfile.lock @@ -39,8 +39,17 @@ PODS: - CocoaLumberjack/Extensions (2.0.0): - CocoaLumberjack/Default - Expecta (1.0.0) - - Facebook-iOS-SDK (3.23.2): - - Bolts (~> 1.0) + - FBSDKCoreKit (4.1.0): + - Bolts (~> 1.1) + - FBSDKCoreKit/arc (= 4.1.0) + - FBSDKCoreKit/no-arc (= 4.1.0) + - FBSDKCoreKit/arc (4.1.0): + - Bolts (~> 1.1) + - FBSDKCoreKit/no-arc (4.1.0): + - Bolts (~> 1.1) + - FBSDKCoreKit/arc + - FBSDKLoginKit (4.1.0): + - FBSDKCoreKit - googleplus-ios-sdk (1.7.1) - ISO8601DateFormatter (0.7) - JWTDecode (0.2.1) @@ -84,8 +93,10 @@ PODS: - libextobjc (~> 0.4) - Lock/Core (= 1.12.1) - Lock/UI (= 1.12.1) - - Lock-Facebook (1.0.0): - - Facebook-iOS-SDK (~> 3.15) + - Lock-Facebook (2.0.1): + - CocoaLumberjack (~> 2.0) + - FBSDKCoreKit (~> 4.0) + - FBSDKLoginKit (~> 4.0) - Lock/Core (~> 1.11) - Lock-GooglePlus (1.0.1): - googleplus-ios-sdk (~> 1.7.1) @@ -152,12 +163,11 @@ PODS: DEPENDENCIES: - BDBOAuth1Manager - Expecta - - Facebook-iOS-SDK - ISO8601DateFormatter - JWTDecode - libextobjc - Lock (from `../`) - - Lock-Facebook (~> 1.0) + - Lock-Facebook (~> 2.0) - Lock-GooglePlus (~> 1.0) - Lock-Twitter (~> 1.0) - Lock/1Password (from `../`) @@ -181,13 +191,14 @@ SPEC CHECKSUMS: Bolts: aac24961496d504aa56fc267cde95162a71bac39 CocoaLumberjack: a6f77d987d65dc7ba86b0f84db7d0b9084f77bcb Expecta: 32604574add2c46a36f8d2f716b6c5736eb75024 - Facebook-iOS-SDK: cd87f0b2f0c1d9574b44e8fa2baacc275524bac3 + FBSDKCoreKit: 469ed167195f860dbd2b4c4bbaa33d2e90598db9 + FBSDKLoginKit: ff6224762732e3698f30942e4544321b8c7a23e6 googleplus-ios-sdk: 065d9135061a5f84c07656a68ced48336408fe35 ISO8601DateFormatter: ab926648eebe497f4d167c0fd083992f959f1274 JWTDecode: bff190dc06ff9ee7a3a244c454dc8ef05962c994 libextobjc: a650fc1bf489a3d3a9bc2e621efa3e1006fc5471 Lock: ea007a23242b55f95433b848f9223e297165739d - Lock-Facebook: fc83349f48dee2d41fe8a36013502fe64a0d77fc + Lock-Facebook: 02c315b7d15d6fed20c7a2ea8a5e5e27c072483a Lock-GooglePlus: 38ea73da70d3dd3d210dfb7716b5aeed5aaabca6 Lock-Twitter: 61168e95f6614535167621794cbada2d6606d4c5 LUKeychainAccess: 6479edb12cf06e11ff3336f796959eedbc58f714 diff --git a/Lock/Tests/A0IdentityProviderAuthenticatorSpec.m b/Lock/Tests/A0IdentityProviderAuthenticatorSpec.m index c14af37b1..22c1ea5e2 100644 --- a/Lock/Tests/A0IdentityProviderAuthenticatorSpec.m +++ b/Lock/Tests/A0IdentityProviderAuthenticatorSpec.m @@ -26,6 +26,7 @@ #import "A0Strategy.h" #import "A0Errors.h" #import "A0WebAuthenticator.h" +#import "A0Lock.h" #define HC_SHORTHAND #import @@ -48,9 +49,11 @@ @interface A0IdentityProviderAuthenticator (TestAPI) describe(@"A0SocialAuthenticator", ^{ __block A0IdentityProviderAuthenticator *authenticator; + __block A0Lock *lock; beforeEach(^{ - authenticator = [[A0IdentityProviderAuthenticator alloc] init]; + lock = mock(A0Lock.class); + authenticator = [[A0IdentityProviderAuthenticator alloc] initWithLock:lock]; }); describe(@"provider registration", ^{ diff --git a/Lock/Tests/A0LockConfigurationSpec.m b/Lock/Tests/A0LockConfigurationSpec.m index d71f82f9f..39bde639a 100644 --- a/Lock/Tests/A0LockConfigurationSpec.m +++ b/Lock/Tests/A0LockConfigurationSpec.m @@ -244,6 +244,67 @@ }); }); + + describe(@"disable Sign Up & Reset Password", ^{ + + __block A0LockConfiguration *configuration; + + before(^{ + NSData *jsonData = [NSData dataWithContentsOfFile:[[NSBundle bundleForClass:self.class] pathForResource:@"AppInfo" ofType:@"json"]]; + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; + application = [[A0Application alloc] initWithJSONDictionary:json]; + configuration = [[A0LockConfiguration alloc] initWithApplication:application filter:@[]]; + }); + + context(@"when enabled in connection", ^{ + + beforeEach(^{ + configuration.defaultDatabaseConnectionName = @"Username-PasswordAuthentication"; + }); + + it(@"should disable Sign Up", ^{ + expect([configuration shouldDisableSignUp:YES]).to.beTruthy(); + }); + + it(@"should not disable Sign Up", ^{ + expect([configuration shouldDisableSignUp:NO]).to.beFalsy(); + }); + + it(@"should disable Reset Password", ^{ + expect([configuration shouldDisableResetPassword:YES]).to.beTruthy(); + }); + + it(@"should not disable Reset Password", ^{ + expect([configuration shouldDisableResetPassword:NO]).to.beFalsy(); + }); + + }); + + context(@"when disabled in connection", ^{ + + beforeEach(^{ + configuration.defaultDatabaseConnectionName = @"LoginOnly"; + }); + + it(@"should disable Sign Up", ^{ + expect([configuration shouldDisableSignUp:YES]).to.beTruthy(); + }); + + it(@"should not disable Sign Up", ^{ + expect([configuration shouldDisableSignUp:NO]).to.beTruthy(); + }); + + it(@"should disable Reset Password", ^{ + expect([configuration shouldDisableResetPassword:YES]).to.beTruthy(); + }); + + it(@"should not disable Reset Password", ^{ + expect([configuration shouldDisableResetPassword:NO]).to.beTruthy(); + }); + + }); + + }); }); SpecEnd diff --git a/Lock/Tests/AppInfo.json b/Lock/Tests/AppInfo.json index ce14fdba5..ce9b03210 100644 --- a/Lock/Tests/AppInfo.json +++ b/Lock/Tests/AppInfo.json @@ -22,6 +22,13 @@ "showSignup": true, "showForgot": true, "requires_username": false + }, { + "name": "LoginOnly", + "forgot_password_url": "https://login.auth0.com/lo/forgot?wtrealm=urn:auth0:samples:LoginOnly", + "signup_url": "https://login.auth0.com/lo/signup?wtrealm=urn:auth0:samples:LoginOnly", + "showSignup": false, + "showForgot": false, + "requires_username": false }] }, { "name": "ad", diff --git a/Pod/Assets/TouchID/A0TouchIDRegisterViewController.xib b/Pod/Assets/TouchID/A0TouchIDRegisterViewController.xib index a7af7b51d..fbc36ed3d 100644 --- a/Pod/Assets/TouchID/A0TouchIDRegisterViewController.xib +++ b/Pod/Assets/TouchID/A0TouchIDRegisterViewController.xib @@ -1,7 +1,7 @@ - + - + diff --git a/Pod/Classes/Provider/A0IdentityProviderAuthenticator.m b/Pod/Classes/Provider/A0IdentityProviderAuthenticator.m index 422889802..8b2283095 100644 --- a/Pod/Classes/Provider/A0IdentityProviderAuthenticator.m +++ b/Pod/Classes/Provider/A0IdentityProviderAuthenticator.m @@ -49,24 +49,17 @@ + (A0IdentityProviderAuthenticator *)sharedInstance { } - (instancetype)initWithLock:(A0Lock *)lock { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated" - self = [self init]; -#pragma GCC diagnostic pop + self = [super init]; if (self) { + _registeredAuthenticators = [@{} mutableCopy]; + _useWebAsDefault = YES; _clientProvider = lock; } return self; } - (id)init { - self = [super init]; - if (self) { - _registeredAuthenticators = [@{} mutableCopy]; - _useWebAsDefault = YES; - _clientProvider = nil; - } - return self; + return [self initWithLock:nil]; } - (void)registerAuthenticationProviders:(NSArray *)authenticationProviders { diff --git a/Pod/Classes/TouchID/A0TouchIDRegisterViewController.m b/Pod/Classes/TouchID/A0TouchIDRegisterViewController.m index cd2d3a8e7..92d5e0ea6 100644 --- a/Pod/Classes/TouchID/A0TouchIDRegisterViewController.m +++ b/Pod/Classes/TouchID/A0TouchIDRegisterViewController.m @@ -76,8 +76,6 @@ - (void)viewDidLoad { - (A0DatabaseLoginViewController *)buildLogin { @weakify(self); A0DatabaseLoginViewController *controller = [[A0DatabaseLoginViewController alloc] init]; - controller.showSignUp = YES; - controller.showResetPassword = YES; controller.parameters = self.parameters; controller.onLoginBlock = self.onRegisterBlock; controller.lock = self.lock; diff --git a/Pod/Classes/UI/A0LockConfiguration.h b/Pod/Classes/UI/A0LockConfiguration.h index e33d858e2..d264482fa 100644 --- a/Pod/Classes/UI/A0LockConfiguration.h +++ b/Pod/Classes/UI/A0LockConfiguration.h @@ -42,4 +42,8 @@ - (A0Connection *)defaultActiveDirectoryConnection; +- (BOOL)shouldDisableSignUp:(BOOL)disableSignUp; + +- (BOOL)shouldDisableResetPassword:(BOOL)disableResetPassword; + @end diff --git a/Pod/Classes/UI/A0LockConfiguration.m b/Pod/Classes/UI/A0LockConfiguration.m index af4567383..0809200e9 100644 --- a/Pod/Classes/UI/A0LockConfiguration.m +++ b/Pod/Classes/UI/A0LockConfiguration.m @@ -111,4 +111,15 @@ - (NSArray *)selectFromArray:(NSArray *)array passingTest:(BOOL(^)(id element))t }]; return [NSArray arrayWithArray:result]; } + +- (BOOL)shouldDisableSignUp:(BOOL)disableSignUp { + A0Connection *database = self.defaultDatabaseConnection; + return ![database[A0ConnectionShowSignUp] boolValue] || disableSignUp; +} + +- (BOOL)shouldDisableResetPassword:(BOOL)disableResetPassword { + A0Connection *database = self.defaultDatabaseConnection; + return ![database[A0ConnectionShowForgot] boolValue] || disableResetPassword; +} + @end diff --git a/Pod/Classes/UI/A0LockViewController.h b/Pod/Classes/UI/A0LockViewController.h index bfa5fe7e9..36e2f5be2 100644 --- a/Pod/Classes/UI/A0LockViewController.h +++ b/Pod/Classes/UI/A0LockViewController.h @@ -51,6 +51,10 @@ typedef void(^A0AuthenticationBlock)(A0UserProfile *profile, A0Token *token); */ - (instancetype)init __attribute__((deprecated)); +///------------------------------------------------ +/// @name Callbacks +///------------------------------------------------ + /** Block that is called on successful authentication. It has two parameters profile and token, which will be non-nil unless login is disabled after signup. */ @@ -61,6 +65,10 @@ typedef void(^A0AuthenticationBlock)(A0UserProfile *profile, A0Token *token); */ @property (copy, nonatomic) void(^onUserDismissBlock)(); +///------------------------------------------------ +/// @name UI customization +///------------------------------------------------ + /** Enable the username to be treated as an email (and validated as one too) in all Auth0 screens. Default is YES */ @@ -71,6 +79,25 @@ typedef void(^A0AuthenticationBlock)(A0UserProfile *profile, A0Token *token); */ @property (assign, nonatomic) BOOL closable; +/** + View that will appear in the bottom of Signup screen. It should be used to show Terms & Conditions of your app. + */ +@property (strong, nonatomic) UIView *signUpDisclaimerView; + +/** + * Hides the Sign Up button. By default is `false`. + */ +@property (assign, nonatomic) BOOL disableSignUp; + +/** + * Hides the Reset Password button. By default is `false`. + */ +@property (assign, nonatomic) BOOL disableResetPassword; + +///------------------------------------------------ +/// @name Authentication options +///------------------------------------------------ + /** After a successful Signup, `A0AuthenticationViewController` will attempt to login the user if this property is YES otherwise will call onAuthenticationBlock with both parameters nil. Default value is YES */ @@ -83,11 +110,6 @@ typedef void(^A0AuthenticationBlock)(A0UserProfile *profile, A0Token *token); */ @property (assign, nonatomic) BOOL defaultADUsernameFromEmailPrefix; -/** - View that will appear in the bottom of Signup screen. It should be used to show Terms & Conditions of your app. - */ -@property (strong, nonatomic) UIView *signUpDisclaimerView; - /** * When authenticating with a social connection, it will use an embedded webView instead of Safari. Default is NO. */ @@ -99,6 +121,10 @@ typedef void(^A0AuthenticationBlock)(A0UserProfile *profile, A0Token *token); */ @property (strong, nonatomic) A0AuthParameters *authenticationParameters; +///------------------------------------------------ +/// @name Connection filtering +///------------------------------------------------ + /** * List of connections to be used by Lock. * It can be used to filter connections already enabled in Auth0 dashboard. If a connection is not enabled in the dashboard it will be ignored. diff --git a/Pod/Classes/UI/A0LockViewController.m b/Pod/Classes/UI/A0LockViewController.m index e48b7166a..16f29e0e9 100644 --- a/Pod/Classes/UI/A0LockViewController.m +++ b/Pod/Classes/UI/A0LockViewController.m @@ -200,8 +200,6 @@ - (void)layoutRootController { if ((hasDB && hasSocial) || (hasSocial && hasEnterprise && !hasAD)) { A0FullLoginViewController *controller = [self newFullLoginViewController:onAuthSuccessBlock]; controller.config = self.configuration; - controller.showResetPassword = [database[A0ConnectionShowForgot] boolValue]; - controller.showSignUp = [database[A0ConnectionShowSignUp] boolValue]; controller.domainMatcher = [[A0SimpleConnectionDomainMatcher alloc] initWithStrategies:self.configuration.enterpriseStrategies]; controller.forceUsername = !self.usesEmail; controller.defaultConnection = database; @@ -209,8 +207,6 @@ - (void)layoutRootController { } if ((hasDB & !hasSocial) || (hasEnterprise && !hasDB && !hasSocial && !hasAD)) { A0DatabaseLoginViewController *controller = [self newDatabaseLoginViewController:onAuthSuccessBlock];; - controller.showResetPassword = [database[A0ConnectionShowForgot] boolValue]; - controller.showSignUp = [database[A0ConnectionShowSignUp] boolValue]; controller.domainMatcher = [[A0SimpleConnectionDomainMatcher alloc] initWithStrategies:self.configuration.enterpriseStrategies]; controller.forceUsername = !self.usesEmail; controller.defaultConnection = database ?: ad; @@ -270,16 +266,22 @@ - (A0FullLoginViewController *)newFullLoginViewController:(void(^)(A0UserProfile [self displayController:controller]; }; [self.navigationView removeAll]; - [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"SIGN UP") actionBlock:^{ - @strongify(self); - A0SignUpViewController *controller = [self newSignUpViewControllerWithSuccess:success]; - [self displayController:controller]; - }]; - [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"RESET PASSWORD") actionBlock:^{ - @strongify(self); - A0ChangePasswordViewController *controller = [self newChangePasswordViewController]; - [self displayController:controller]; - }]; + BOOL showResetPassword = ![self.configuration shouldDisableResetPassword:self.disableResetPassword]; + BOOL showSignUp = ![self.configuration shouldDisableSignUp:self.disableSignUp]; + if (showSignUp) { + [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"SIGN UP") actionBlock:^{ + @strongify(self); + A0SignUpViewController *controller = [self newSignUpViewControllerWithSuccess:success]; + [self displayController:controller]; + }]; + } + if (showResetPassword) { + [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"RESET PASSWORD") actionBlock:^{ + @strongify(self); + A0ChangePasswordViewController *controller = [self newChangePasswordViewController]; + [self displayController:controller]; + }]; + } return controller; } @@ -302,16 +304,22 @@ - (A0DatabaseLoginViewController *)newDatabaseLoginViewController:(void(^)(A0Use [self displayController:controller]; }; [self.navigationView removeAll]; - [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"SIGN UP") actionBlock:^{ - @strongify(self); - A0SignUpViewController *controller = [self newSignUpViewControllerWithSuccess:success]; - [self displayController:controller]; - }]; - [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"RESET PASSWORD") actionBlock:^{ - @strongify(self); - A0ChangePasswordViewController *controller = [self newChangePasswordViewController]; - [self displayController:controller]; - }]; + BOOL showResetPassword = ![self.configuration shouldDisableResetPassword:self.disableResetPassword]; + BOOL showSignUp = ![self.configuration shouldDisableSignUp:self.disableSignUp]; + if (showSignUp) { + [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"SIGN UP") actionBlock:^{ + @strongify(self); + A0SignUpViewController *controller = [self newSignUpViewControllerWithSuccess:success]; + [self displayController:controller]; + }]; + } + if (showResetPassword) { + [self.navigationView addButtonWithLocalizedTitle:A0LocalizedString(@"RESET PASSWORD") actionBlock:^{ + @strongify(self); + A0ChangePasswordViewController *controller = [self newChangePasswordViewController]; + [self displayController:controller]; + }]; + } return controller; } diff --git a/Pod/Classes/UI/Private/A0DatabaseLoginViewController.h b/Pod/Classes/UI/Private/A0DatabaseLoginViewController.h index 28c44aeaa..8b5eb8877 100644 --- a/Pod/Classes/UI/Private/A0DatabaseLoginViewController.h +++ b/Pod/Classes/UI/Private/A0DatabaseLoginViewController.h @@ -33,8 +33,6 @@ @property (copy, nonatomic) A0AuthParameters *parameters; @property (strong, nonatomic) A0Connection *defaultConnection; -@property (assign, nonatomic) BOOL showSignUp; -@property (assign, nonatomic) BOOL showResetPassword; @property (copy, nonatomic) NSString *defaultUsername; @property (copy, nonatomic) void(^onLoginBlock)(A0UserProfile *profile, A0Token *token); diff --git a/Pod/Classes/UI/Private/A0DatabaseLoginViewController.m b/Pod/Classes/UI/Private/A0DatabaseLoginViewController.m index d949f4401..e9a9765ad 100644 --- a/Pod/Classes/UI/Private/A0DatabaseLoginViewController.m +++ b/Pod/Classes/UI/Private/A0DatabaseLoginViewController.m @@ -81,8 +81,6 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = A0LocalizedString(@"Login"); - self.showSignUp = YES; - self.showResetPassword = YES; } return self; } @@ -98,8 +96,6 @@ - (void)viewDidLoad { [theme configureTextField:self.passwordField.textField]; BOOL requiresUsername = [self.defaultConnection[A0ConnectionRequiresUsername] boolValue]; - self.signUpButton.hidden = !self.showSignUp; - self.forgotPasswordButton.hidden = !self.showResetPassword; [self.userField.textField addTarget:self action:@selector(matchDomainInTextField:) forControlEvents:UIControlEventEditingChanged]; self.singleSignOnIcon.image = [self.singleSignOnIcon.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; if (self.defaultConnection) {