diff --git a/Lock.xcodeproj/project.pbxproj b/Lock.xcodeproj/project.pbxproj index 172b4bdce..5dd74572d 100644 --- a/Lock.xcodeproj/project.pbxproj +++ b/Lock.xcodeproj/project.pbxproj @@ -225,7 +225,7 @@ 5BCDE1341DDDF12100AA2A6C /* EnterpriseActiveAuthPresenterSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterpriseActiveAuthPresenterSpec.swift; sourceTree = ""; }; 5BCED4C51DD1FCF200E2CE8A /* EnterpriseDomainPresenterSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterpriseDomainPresenterSpec.swift; sourceTree = ""; }; 5F0FCF8F1E20117E00E3D53B /* ObserverStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverStore.swift; sourceTree = ""; }; - 5F0FCF911E201CF300E3D53B /* ObserverStoreSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverStoreSpec.swift; sourceTree = ""; }; + 5F0FCF911E201CF300E3D53B /* ObserverStoreSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObserverStoreSpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 5F1456591D5130E80085DF9C /* Colors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Colors.swift; path = Lock/Colors.swift; sourceTree = SOURCE_ROOT; }; 5F1C498D1D8360AA005B74FC /* Style.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Style.swift; path = Lock/Style.swift; sourceTree = SOURCE_ROOT; }; 5F1C498F1D8360BF005B74FC /* ConnectionLoadingPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConnectionLoadingPresenter.swift; path = Lock/ConnectionLoadingPresenter.swift; sourceTree = SOURCE_ROOT; }; diff --git a/Lock/Auth0OAuth2Interactor.swift b/Lock/Auth0OAuth2Interactor.swift index 2b938d7ab..385eb2e3d 100644 --- a/Lock/Auth0OAuth2Interactor.swift +++ b/Lock/Auth0OAuth2Interactor.swift @@ -45,7 +45,7 @@ struct Auth0OAuth2Interactor: OAuth2Authenticatable { .start { result in switch result { case .success(let credentials): - self.dispatcher.dispatch(result: .auth(credentials), dismissLock: true) + self.dispatcher.dispatch(result: .auth(credentials)) callback(nil) case .failure(WebAuthError.userCancelled): callback(.cancelled) diff --git a/Lock/DatabaseInteractor.swift b/Lock/DatabaseInteractor.swift index 08e5dd5bd..f2f72a4b4 100644 --- a/Lock/DatabaseInteractor.swift +++ b/Lock/DatabaseInteractor.swift @@ -135,7 +135,7 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl "verified": user.verified ] extra["username"] = user.username - self.dispatcher.dispatch(result: .signUp(user.email, extra), dismissLock: !self.options.allow.contains(.Login) && self.options.autoClose.contains(.Signup)) + self.dispatcher.dispatch(result: .signUp(user.email, extra)) callback(nil, nil) } case .failure(let cause as AuthenticationError) where cause.isPasswordNotStrongEnough: @@ -204,7 +204,7 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl case .success(let credentials): self.logger.info("Authenticated user <\(self.identifier)>") callback(nil) - self.dispatcher.dispatch(result: .auth(credentials), dismissLock: true) + self.dispatcher.dispatch(result: .auth(credentials)) } } } diff --git a/Lock/DatabasePasswordInteractor.swift b/Lock/DatabasePasswordInteractor.swift index 117f64a09..6ea98d3b3 100644 --- a/Lock/DatabasePasswordInteractor.swift +++ b/Lock/DatabasePasswordInteractor.swift @@ -59,7 +59,7 @@ struct DatabasePasswordInteractor: PasswordRecoverable { .resetPassword(email: email, connection: connection) .start { guard case .success = $0 else { return callback(.emailNotSent) } - self.dispatcher.dispatch(result: .forgotPassword(email), dismissLock: !self.options.allow.contains(.Login) && self.options.autoClose.contains(.ResetPassword)) + self.dispatcher.dispatch(result: .forgotPassword(email)) callback(nil) } } diff --git a/Lock/EnterpriseActiveAuthInteractor.swift b/Lock/EnterpriseActiveAuthInteractor.swift index c448d9101..4189c48c4 100644 --- a/Lock/EnterpriseActiveAuthInteractor.swift +++ b/Lock/EnterpriseActiveAuthInteractor.swift @@ -151,7 +151,7 @@ struct EnterpriseActiveAuthInteractor: DatabaseAuthenticatable, Loggable { case .success(let credentials): self.logger.info("Authenticated user <\(self.identifier)>") callback(nil) - self.dispatcher.dispatch(result: .auth(credentials), dismissLock: true) + self.dispatcher.dispatch(result: .auth(credentials)) } } diff --git a/Lock/Lock.swift b/Lock/Lock.swift index 7f0412908..271bc82ea 100644 --- a/Lock/Lock.swift +++ b/Lock/Lock.swift @@ -37,7 +37,7 @@ public class Lock: NSObject { var optionsBuilder: OptionBuildable = LockOptions() var options: Options { return self.optionsBuilder } - var observerStore = ObserverStore() + var observerStore = ObserverStore(options: LockOptions()) var style: Style = Style() @@ -147,6 +147,7 @@ public class Lock: NSObject { var builder: OptionBuildable = self.optionsBuilder closure(&builder) self.optionsBuilder = builder + self.observerStore.options = self.options _ = self.authentication.logging(enabled: self.options.logHttpRequest) _ = self.webAuth.logging(enabled: self.options.logHttpRequest) return self diff --git a/Lock/LockViewController.swift b/Lock/LockViewController.swift index 8bffc3dfb..f31e220b8 100644 --- a/Lock/LockViewController.swift +++ b/Lock/LockViewController.swift @@ -73,7 +73,7 @@ public class LockViewController: UIViewController { header.showClose = self.router.lock.options.closable header.onClosePressed = { [weak self] in - self?.router.lock.observerStore.dispatch(result: .cancel, dismissLock: true) + self?.router.lock.observerStore.dispatch(result: .cancel) } header.apply(style: style) diff --git a/Lock/MultifactorInteractor.swift b/Lock/MultifactorInteractor.swift index 452084c35..e0902240a 100644 --- a/Lock/MultifactorInteractor.swift +++ b/Lock/MultifactorInteractor.swift @@ -86,7 +86,7 @@ struct MultifactorInteractor: MultifactorAuthenticatable { callback(.couldNotLogin) case .success(let credentials): callback(nil) - self.dispatcher.dispatch(result: .auth(credentials), dismissLock: true) + self.dispatcher.dispatch(result: .auth(credentials)) } } } diff --git a/Lock/ObserverStore.swift b/Lock/ObserverStore.swift index 67873e14c..82d40d632 100644 --- a/Lock/ObserverStore.swift +++ b/Lock/ObserverStore.swift @@ -28,23 +28,34 @@ struct ObserverStore: Dispatcher { var onFailure: (Error) -> () = { _ in } var onCancel: () -> () = { } var onSignUp: (String, [String: Any]) -> () = { _ in } - var onForgetPassword: (String) -> () = { _ in } + var onForgotPassword: (String) -> () = { _ in } + var options: Options weak var controller: UIViewController? - func dispatch(result: Result, dismissLock: Bool) { + init(options: Options = LockOptions()) { + self.options = options + } + + func dispatch(result: Result) { + let dismissLock: Bool let closure: () -> () switch result { case .auth(let credentials): + dismissLock = true closure = { self.onAuth(credentials) } case .error(let error): + dismissLock = false closure = { self.onFailure(error) } case .cancel: + dismissLock = true closure = { self.onCancel() } case .signUp(let email, let attributes): + dismissLock = !self.options.allow.contains(.Login) && self.options.autoClose.contains(.Signup) closure = { self.onSignUp(email, attributes) } case .forgotPassword(let email): - closure = { self.onForgetPassword(email) } + dismissLock = !self.options.allow.contains(.Login) && self.options.autoClose.contains(.ResetPassword) + closure = { self.onForgotPassword(email) } } Queue.main.async(dismissLock ? dismiss(from: controller?.presentingViewController, completion: closure) : closure) @@ -65,5 +76,5 @@ enum Result { } protocol Dispatcher { - func dispatch(result: Result, dismissLock: Bool) + func dispatch(result: Result) } diff --git a/LockTests/Interactors/DatabaseInteractorSpec.swift b/LockTests/Interactors/DatabaseInteractorSpec.swift index 109d527b1..f44bd1612 100644 --- a/LockTests/Interactors/DatabaseInteractorSpec.swift +++ b/LockTests/Interactors/DatabaseInteractorSpec.swift @@ -38,13 +38,16 @@ class DatabaseInteractorSpec: QuickSpec { describe("init") { + let options = LockOptions() + let dispatcher = ObserverStore() + it("should build with authentication") { - let database = DatabaseInteractor(connection: DatabaseConnection(name: "db", requiresUsername: true), authentication: authentication, user: User(), options: LockOptions(), dispatcher: ObserverStore()) + let database = DatabaseInteractor(connection: DatabaseConnection(name: "db", requiresUsername: true), authentication: authentication, user: User(), options: options, dispatcher: dispatcher) expect(database).toNot(beNil()) } it("should have authentication object") { - let database = DatabaseInteractor(connection: DatabaseConnection(name: "db", requiresUsername: true), authentication: authentication, user: User(), options: LockOptions(), dispatcher: ObserverStore()) + let database = DatabaseInteractor(connection: DatabaseConnection(name: "db", requiresUsername: true), authentication: authentication, user: User(), options: options, dispatcher: dispatcher) expect(database.credentialAuth.authentication.clientId) == "CLIENT_ID" expect(database.credentialAuth.authentication.url.host) == "samples.auth0.com" expect(database.credentialAuth.oidc) == false @@ -56,12 +59,16 @@ class DatabaseInteractorSpec: QuickSpec { var database: DatabaseInteractor! var user: User! var options: OptionBuildable! + var dispatcher: ObserverStore! beforeEach { + options = LockOptions() + dispatcher = ObserverStore() + Auth0Stubs.failUnknown() user = User() let db = DatabaseConnection(name: connection, requiresUsername: true, usernameValidator: UsernameValidator(withLength: 1...15, characterSet: UsernameValidator.auth0), passwordValidator: PasswordPolicyValidator(policy: .good)) - database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: LockOptions(), dispatcher: ObserverStore()) + database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: options, dispatcher: dispatcher) } describe("updateAttribute") { @@ -561,7 +568,7 @@ class DatabaseInteractorSpec: QuickSpec { } // TODO: Check why it fails only in travis - describe("login dispatch") { + pending("login dispatch") { var options: LockOptions! var auth: Credentials? @@ -1119,6 +1126,7 @@ class DatabaseInteractorSpec: QuickSpec { it("should dispatch signup event and dimiss Lock") { options.allow = .Signup + dispatcher.options = options database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! database.update(.email, value: email) try! database.update(.username, value: username) @@ -1130,6 +1138,7 @@ class DatabaseInteractorSpec: QuickSpec { it("should dispatch signup event and dimiss Lock") { options.allow = [.Signup, .ResetPassword] + dispatcher.options = options database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! database.update(.email, value: email) try! database.update(.username, value: username) diff --git a/LockTests/Interactors/DatabasePasswordInteractorSpec.swift b/LockTests/Interactors/DatabasePasswordInteractorSpec.swift index bce9d8998..d040d5e17 100644 --- a/LockTests/Interactors/DatabasePasswordInteractorSpec.swift +++ b/LockTests/Interactors/DatabasePasswordInteractorSpec.swift @@ -156,6 +156,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { var dispatcher: ObserverStore! beforeEach { + options = LockOptions() dispatcher = ObserverStore() presenter = MockController() controller = MockLockController(lock: Lock()) @@ -164,8 +165,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { dispatcher.controller = controller userEmail = nil - options = LockOptions() - dispatcher.onForgetPassword = { email in + dispatcher.onForgotPassword = { email in userEmail = email } forgot = DatabasePasswordInteractor(connections: connections, authentication: authentication, user: user, options: options, dispatcher: dispatcher) @@ -183,6 +183,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { it("should dispatch forgotPassword event and dismiss lock") { options.allow = .ResetPassword + dispatcher.options = options forgot = DatabasePasswordInteractor(connections: connections, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! forgot.updateEmail(email) @@ -193,6 +194,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { it("should dispatch forgotPassword event and dismiss lock") { options.allow = [.ResetPassword, .Signup] + dispatcher.options = options forgot = DatabasePasswordInteractor(connections: connections, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! forgot.updateEmail(email) @@ -205,6 +207,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { it("should dispatch forgotPassword and stay on screen") { options.autoClose = [] + dispatcher.options = options forgot = DatabasePasswordInteractor(connections: connections, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! forgot.updateEmail(email) @@ -216,6 +219,7 @@ class DatabasePasswordInteractorSpec: QuickSpec { it("should dispatch forgotPassword event and stay on screen") { options.allow = [.ResetPassword] options.autoClose = [] + dispatcher.options = options forgot = DatabasePasswordInteractor(connections: connections, authentication: authentication, user: user, options: options, dispatcher: dispatcher) try! forgot.updateEmail(email) diff --git a/LockTests/Models/ObserverStoreSpec.swift b/LockTests/Models/ObserverStoreSpec.swift index d14e9599e..99652c88d 100644 --- a/LockTests/Models/ObserverStoreSpec.swift +++ b/LockTests/Models/ObserverStoreSpec.swift @@ -49,34 +49,34 @@ class ObserverStoreSpec: QuickSpec { store.onAuth = { credentials = $0 } store.onCancel = { closed = true } store.onSignUp = { newEmail = $0; newAttributes = $1 } - store.onForgetPassword = { newEmail = $0 } + store.onForgotPassword = { newEmail = $0 } dispatcher = store } it("should dispatch errors") { - dispatcher.dispatch(result: .error(UnrecoverableError.invalidClientOrDomain), dismissLock: false) + dispatcher.dispatch(result: .error(UnrecoverableError.invalidClientOrDomain)) expect(error).toEventuallyNot(beNil()) } it("should dispatch credentials") { let value = mockCredentials() - dispatcher.dispatch(result: .auth(value), dismissLock: false) + dispatcher.dispatch(result: .auth(value)) expect(credentials).toEventually(equal(value)) } it("should dispatch when lock is dismissed") { - dispatcher.dispatch(result: .cancel, dismissLock: false) + dispatcher.dispatch(result: .cancel) expect(closed).toEventually(beTrue()) } it("should disptach when user signs up") { - dispatcher.dispatch(result: .signUp(email, ["username": username]), dismissLock: false) + dispatcher.dispatch(result: .signUp(email, ["username": username])) expect(newEmail).toEventually(equal(email)) expect(newAttributes?["username"] as? String).toEventually(equal(username)) } it("should disptach when user requests password") { - dispatcher.dispatch(result: .forgotPassword(email), dismissLock: false) + dispatcher.dispatch(result: .forgotPassword(email)) expect(newEmail).toEventually(equal(email)) } @@ -96,24 +96,24 @@ class ObserverStoreSpec: QuickSpec { it("should dismiss onAuth") { let value = mockCredentials() - dispatcher.dispatch(result: .auth(value), dismissLock: true) + dispatcher.dispatch(result: .auth(value)) expect(presenter.presented).toEventually(beNil(), timeout: 2) } it("should dismiss onCancel") { - dispatcher.dispatch(result: .cancel, dismissLock: true) + dispatcher.dispatch(result: .cancel) expect(presenter.presented).toEventually(beNil(), timeout: 2) } - it("should dismiss onSignUp") { - dispatcher.dispatch(result: .signUp(email, ["username": username]), dismissLock: true) + it("should not dismiss onSignUp") { + dispatcher.dispatch(result: .signUp(email, ["username": username])) expect(newEmail).toEventually(equal(email)) - expect(presenter.presented).toEventually(beNil(), timeout: 2) + expect(presenter.presented).toEventuallyNot(beNil(), timeout: 2) } - it("should dismiss forgotPassword") { - dispatcher.dispatch(result: .forgotPassword(email), dismissLock: true) - expect(presenter.presented).toEventually(beNil(), timeout: 2) + it("should not dismiss forgotPassword") { + dispatcher.dispatch(result: .forgotPassword(email)) + expect(presenter.presented).toEventuallyNot(beNil(), timeout: 2) } } }