Skip to content

Commit

Permalink
Moved dismissLock logic into ObserverStore case
Browse files Browse the repository at this point in the history
Changed autoClose flag to Bool
Updated Tests
Removed Options from DatabasePasswordInteractor
Login now follows autoClose rules
Login success message added
DatabaseInteractor tests Added
Dispatcher related tests unified into ObserverStore tests
  • Loading branch information
cocojoe committed Jan 16, 2017
1 parent c0706e8 commit 8c75bce
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 274 deletions.
2 changes: 1 addition & 1 deletion Lock/DatabaseForgotPasswordPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class DatabaseForgotPasswordPresenter: Presentable, Loggable {
self.logger.error("Failed with error \(error)")
} else {
let message = "We've just sent you an email to reset your password".i18n(key: "com.auth0.lock.database.forgot.success.message", comment: "forgot password email sent")
if self.options.allow.contains(.Login) || !self.options.autoClose.contains(.ResetPassword) {
if self.options.allow.contains(.Login) || !self.options.autoClose {
self.messagePresenter?.showSuccess(message)
}
guard self.options.allow.contains(.Login) else { return }
Expand Down
4 changes: 1 addition & 3 deletions Lock/DatabasePasswordInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,13 @@ struct DatabasePasswordInteractor: PasswordRecoverable {
var validEmail: Bool { return self.user.validEmail }

let authentication: Authentication
let options: Options
let connections: Connections
let emailValidator: InputValidator = EmailValidator()

init(connections: Connections, authentication: Authentication, user: DatabaseUser, options: Options, dispatcher: Dispatcher) {
init(connections: Connections, authentication: Authentication, user: DatabaseUser, dispatcher: Dispatcher) {
self.authentication = authentication
self.connections = connections
self.user = user
self.options = options
self.dispatcher = dispatcher
}

Expand Down
6 changes: 5 additions & 1 deletion Lock/DatabasePresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class DatabasePresenter: Presentable, Loggable {
button.inProgress = false
guard let error = error else {
self.logger.debug("Logged in!")
let message = "You have logged in successfully.".i18n(key: "com.auth0.lock.database.login.success.message", comment: "User logged in")
if !self.options.autoClose {
self.messagePresenter?.showSuccess(message)
}
return
}
if case DatabaseAuthenticatableError.multifactorRequired = error {
Expand Down Expand Up @@ -162,7 +166,7 @@ class DatabasePresenter: Presentable, Loggable {
if let databaseView = self.databaseView, self.options.allow.contains(.Login) {
self.showLogin(inView: databaseView, identifier: self.creator.identifier)
}
if self.options.allow.contains(.Login) || !self.options.autoClose.contains(.Signup) {
if self.options.allow.contains(.Login) || !self.options.autoClose {
self.messagePresenter?.showSuccess(message)
}
}
Expand Down
2 changes: 1 addition & 1 deletion Lock/Lock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class Lock: NSObject {
var optionsBuilder: OptionBuildable = LockOptions()
var options: Options { return self.optionsBuilder }

var observerStore = ObserverStore(options: LockOptions())
var observerStore = ObserverStore()

var style: Style = Style()

Expand Down
2 changes: 1 addition & 1 deletion Lock/LockOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct LockOptions: OptionBuildable {
var scope: String = "openid"
var parameters: [String : Any] = [:]
var allow: DatabaseMode = [.Login, .Signup, .ResetPassword]
var autoClose: DatabaseMode = [.Login, .Signup, .ResetPassword]
var autoClose: Bool = true
var initialScreen: DatabaseScreen = .login
var usernameStyle: DatabaseIdentifierStyle = [.Username, .Email]
var customSignupFields: [CustomTextField] = []
Expand Down
34 changes: 18 additions & 16 deletions Lock/ObserverStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,38 @@ struct ObserverStore: Dispatcher {
var onCancel: () -> () = { }
var onSignUp: (String, [String: Any]) -> () = { _ in }
var onForgotPassword: (String) -> () = { _ in }
var options: Options
var options: Options = LockOptions()

weak var controller: UIViewController?

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) }
if self.options.autoClose {
closure = dismiss(from: controller?.presentingViewController, completion: { self.onAuth(credentials) })
} else {
closure = { self.onAuth(credentials) }
}
case .error(let error):
dismissLock = false
closure = { self.onFailure(error) }
case .cancel:
dismissLock = true
closure = { self.onCancel() }
closure = dismiss(from: controller?.presentingViewController, completion: { self.onCancel() })
case .signUp(let email, let attributes):
dismissLock = !self.options.allow.contains(.Login) && self.options.autoClose.contains(.Signup)
closure = { self.onSignUp(email, attributes) }
if !self.options.allow.contains(.Login) && self.options.autoClose {
closure = dismiss(from: controller?.presentingViewController, completion: { self.onSignUp(email, attributes) })
} else {
closure = { self.onSignUp(email, attributes) }
}
case .forgotPassword(let email):
dismissLock = !self.options.allow.contains(.Login) && self.options.autoClose.contains(.ResetPassword)
closure = { self.onForgotPassword(email) }
if !self.options.allow.contains(.Login) && self.options.autoClose {
closure = dismiss(from: controller?.presentingViewController, completion: { self.onForgotPassword(email) })
} else {
closure = { self.onForgotPassword(email) }
}
}

Queue.main.async(dismissLock ? dismiss(from: controller?.presentingViewController, completion: closure) : closure)
Queue.main.async(closure)
}

private func dismiss(from controller: UIViewController?, completion: @escaping () -> ()) -> () -> () {
Expand Down
6 changes: 3 additions & 3 deletions Lock/OptionBuildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ public protocol OptionBuildable: Options {
/// What database modes are allowed and must be at least one. By default all modes are allowed.
var allow: DatabaseMode { get set }

/// What database modes can be automatically closed upon success. By default all modes are auto closable.
var autoClose: DatabaseMode { get set }
/// Should Lock close if only mode available. By default is true
var autoClose: Bool { get set }

/// Initial screen displayed by Lock when a database connection is available. By default is Login
var initialScreen: DatabaseScreen { get set }
Expand Down Expand Up @@ -90,7 +90,7 @@ internal extension OptionBuildable {
func validate() -> UnrecoverableError? {
guard !self.allow.isEmpty else { return UnrecoverableError.invalidOptions(cause: "Must allow at least one database mode") }
guard !self.usernameStyle.isEmpty else { return UnrecoverableError.invalidOptions(cause: "Must specify at least one username style") }
guard self.allow.contains(.Login) || self.closable || self.autoClose.contains(self.allow) else { return UnrecoverableError.invalidOptions(cause: "Must enable autoclose for database mode or enable closable") }
guard self.allow.contains(.Login) || self.closable || self.autoClose else { return UnrecoverableError.invalidOptions(cause: "Must enable autoclose or enable closable") }
return nil
}
}
Expand Down
2 changes: 1 addition & 1 deletion Lock/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public protocol Options {
var scope: String { get }
var parameters: [String: Any] { get }
var allow: DatabaseMode { get }
var autoClose: DatabaseMode { get }
var autoClose: Bool { get }
var initialScreen: DatabaseScreen { get }
var usernameStyle: DatabaseIdentifierStyle { get }
var customSignupFields: [CustomTextField] { get }
Expand Down
2 changes: 1 addition & 1 deletion Lock/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ struct Router: Navigable {
exit(withError: UnrecoverableError.clientWithNoConnections)
return nil
}
let interactor = DatabasePasswordInteractor(connections: connections, authentication: self.lock.authentication, user: self.user, options: self.lock.options, dispatcher: lock.observerStore)
let interactor = DatabasePasswordInteractor(connections: connections, authentication: self.lock.authentication, user: self.user, dispatcher: lock.observerStore)
let presenter = DatabaseForgotPasswordPresenter(interactor: interactor, connections: connections, navigator: self, options: self.lock.options)
presenter.customLogger = self.lock.logger
return presenter
Expand Down
144 changes: 0 additions & 144 deletions LockTests/Interactors/DatabaseInteractorSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -566,48 +566,6 @@ class DatabaseInteractorSpec: QuickSpec {
}
}
}

// TODO: Check why it fails only in travis
pending("login dispatch") {

var options: LockOptions!
var auth: Credentials?
var controller: MockLockController!
var presenter: MockController!
var dispatcher: ObserverStore!
var db: DatabaseConnection!

beforeEach {
options = LockOptions()
dispatcher = ObserverStore()
presenter = MockController()
controller = MockLockController(lock: Lock())
presenter.presented = controller
controller.presenting = presenter
dispatcher.controller = controller

auth = nil
options = LockOptions()

dispatcher.onAuth = { credentials in
auth = credentials
}
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: options, dispatcher: dispatcher)
stub(condition: databaseLogin(identifier: email, password: password, connection: connection)) { _ in return Auth0Stubs.authentication() }
}


it("should dispatch on auth event and dismiss lock") {
try! database.update(.email, value: email)
try! database.update(.password(enforcePolicy: false), value: password)
database.login { _ in }
expect(auth?.accessToken).toEventually(equal("token"))
expect(presenter.presented).toEventually(beNil(), timeout: 10)
}

}

}

describe("login OIDC Conformant") {
Expand Down Expand Up @@ -1065,108 +1023,6 @@ class DatabaseInteractorSpec: QuickSpec {
}
}
}

// TODO: Check why it fails only in travis
pending("auto login disabled") {

var options: LockOptions!
var newUserEmail: String?
var controller: MockLockController!
var presenter: MockController!
var dispatcher: ObserverStore!
var db: DatabaseConnection!

beforeEach {
options = LockOptions()
dispatcher = ObserverStore()
presenter = MockController()
controller = MockLockController(lock: Lock())
presenter.presented = controller
controller.presenting = presenter
dispatcher.controller = controller

newUserEmail = nil
options = LockOptions()
options.loginAfterSignup = false

dispatcher.onSignUp = { email, _ in
newUserEmail = email
}
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: options, dispatcher: dispatcher)

stub(condition: databaseSignUp(email: email, username: username, password: password, connection: connection)) { _ in return Auth0Stubs.createdUser(email) }
}

it("should dispatch signup event") {
try! database.update(.email, value: email)
try! database.update(.username, value: username)
try! database.update(.password(enforcePolicy: false), value: password)
database.create { _ in }
expect(newUserEmail).toEventually(equal(email))
expect(presenter.presented).toEventuallyNot(beNil(), timeout: 2)
}

context("auto close disabled") {

it("should dispatch signup event and stay on screen") {
options.autoClose = [.Signup]
database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: options, dispatcher: dispatcher)
try! database.update(.email, value: email)
try! database.update(.username, value: username)
try! database.update(.password(enforcePolicy: false), value: password)
database.create { _ in }
expect(newUserEmail).toEventually(equal(email))
expect(presenter.presented).toEventuallyNot(beNil(), timeout: 2)
}

}

context("no login screen") {

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)
try! database.update(.password(enforcePolicy: false), value: password)
database.create { _ in }
expect(newUserEmail).toEventually(equal(email))
expect(presenter.presented).toEventually(beNil(), timeout: 2)
}

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)
try! database.update(.password(enforcePolicy: false), value: password)
database.create { _ in }
expect(newUserEmail).toEventually(equal(email))
expect(presenter.presented).toEventually(beNil(), timeout: 2)
}

context("auto close disabled") {

it("should dispatch signup event and stay on screen") {
options.allow = .Signup
options.autoClose = []
database = DatabaseInteractor(connection: db, authentication: authentication, user: user, options: options, dispatcher: dispatcher)
try! database.update(.email, value: email)
try! database.update(.username, value: username)
try! database.update(.password(enforcePolicy: false), value: password)
database.create { _ in }
expect(newUserEmail).toEventually(equal(email))
expect(presenter.presented).toEventuallyNot(beNil(), timeout: 2)
}

}

}

}
}

describe("signup OIDC Conformnant") {
Expand Down
Loading

0 comments on commit 8c75bce

Please sign in to comment.