Skip to content

Commit

Permalink
Push all interactor event errors through dispatcher
Browse files Browse the repository at this point in the history
Updated Tests
  • Loading branch information
cocojoe committed Jan 17, 2017
1 parent 7a5d87f commit cc20121
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 11 deletions.
4 changes: 3 additions & 1 deletion Lock/Auth0OAuth2Interactor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ struct Auth0OAuth2Interactor: OAuth2Authenticatable {
.start { result in
switch result {
case .success(let credentials):
self.dispatcher.dispatch(result: .auth(credentials))
callback(nil)
self.dispatcher.dispatch(result: .auth(credentials))
case .failure(WebAuthError.userCancelled):
callback(.cancelled)
self.dispatcher.dispatch(result: .error(WebAuthError.userCancelled))
case .failure:
callback(.couldNotAuthenticate)
self.dispatcher.dispatch(result: .error(OAuth2AuthenticatableError.couldNotAuthenticate))
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions Lock/ConnectionLoadingPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ class ConnectionLoadingPresenter: Presentable, Loggable {
}
#endif
return Queue.main.async {
self.dispatcher.dispatch(result: .error(error!, {
self.navigator.navigate(.unrecoverableError(error: error!))
}))
self.navigator.navigate(.unrecoverableError(error: error!))
self.dispatcher.dispatch(result: .error(error!))
}
}
guard let connections = connections, !connections.isEmpty else {
Expand Down
18 changes: 15 additions & 3 deletions Lock/DatabaseInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,22 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl
}
case .failure(let cause as AuthenticationError) where cause.isPasswordNotStrongEnough:
callback(.passwordTooWeak, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.passwordTooWeak))
case .failure(let cause as AuthenticationError) where cause.isPasswordAlreadyUsed:
callback(.passwordAlreadyUsed, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.passwordAlreadyUsed))
case .failure(let cause as AuthenticationError) where cause.code == "invalid_password" && cause.value("name") == "PasswordDictionaryError":
callback(.passwordTooCommon, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.passwordTooCommon))
case .failure(let cause as AuthenticationError) where cause.code == "invalid_password" && cause.value("name") == "PasswordNoUserInfoError":
callback(.passwordHasUserInfo, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.passwordHasUserInfo))
case .failure(let cause as AuthenticationError) where cause.code == "invalid_password":
callback(.passwordInvalid, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.passwordInvalid))
case .failure:
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.couldNotCreateUser, {
callback(.couldNotCreateUser, nil)
}))
callback(.couldNotCreateUser, nil)
self.dispatcher.dispatch(result: .error(DatabaseUserCreatorError.couldNotCreateUser))
}
}
}
Expand Down Expand Up @@ -182,27 +186,35 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl
case .failure(let cause as AuthenticationError) where cause.isMultifactorRequired || cause.isMultifactorEnrollRequired:
self.logger.error("Multifactor is required for user <\(self.identifier)>")
callback(.multifactorRequired)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.multifactorRequired))
case .failure(let cause as AuthenticationError) where cause.isTooManyAttempts:
self.logger.error("Blocked user <\(self.identifier)> for too many login attempts")
callback(.tooManyAttempts)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.tooManyAttempts))
case .failure(let cause as AuthenticationError) where cause.isInvalidCredentials:
self.logger.error("Invalid credentials of user <\(self.identifier)>")
callback(.invalidEmailPassword)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.invalidEmailPassword))
case .failure(let cause as AuthenticationError) where cause.isMultifactorCodeInvalid:
self.logger.error("Multifactor code is invalid for user <\(self.identifier)>")
callback(.multifactorInvalid)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.multifactorInvalid))
case .failure(let cause as AuthenticationError) where cause.isRuleError && cause.description.lowercased() == "user is blocked":
self.logger.error("Blocked user <\(self.identifier)>")
callback(.userBlocked)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.userBlocked))
case .failure(let cause as AuthenticationError) where cause.code == "password_change_required":
self.logger.error("Change password required for user <\(self.identifier)>")
callback(.passwordChangeRequired)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.passwordChangeRequired))
case .failure(let cause as AuthenticationError) where cause.code == "password_leaked":
self.logger.error("The password of user <\(self.identifier)> was leaked")
callback(.passwordLeaked)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.passwordLeaked))
case .failure(let cause):
self.logger.error("Failed login of user <\(self.identifier)> with error \(cause)")
callback(.couldNotLogin)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.couldNotLogin))
case .success(let credentials):
self.logger.info("Authenticated user <\(self.identifier)>")
callback(nil)
Expand Down
5 changes: 2 additions & 3 deletions Lock/DatabasePasswordInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ struct DatabasePasswordInteractor: PasswordRecoverable {
let authentication: Authentication
let connections: Connections
let emailValidator: InputValidator = EmailValidator()
let dispatcher: Dispatcher

init(connections: Connections, authentication: Authentication, user: DatabaseUser, dispatcher: Dispatcher) {
self.authentication = authentication
Expand All @@ -57,11 +56,11 @@ struct DatabasePasswordInteractor: PasswordRecoverable {
self.authentication
.resetPassword(email: email, connection: connection)
.start {
guard case .success = $0 else { return callback(.emailNotSent) }
self.dispatcher.dispatch(result: .forgotPassword(email))
guard case .success = $0 else {
callback(.emailNotSent)
return self.dispatcher.dispatch(result: .error(PasswordRecoverableError.emailNotSent))
}
self.dispatcher.dispatch(result: .forgotPassword(email))
callback(nil)
}
}
Expand Down
8 changes: 8 additions & 0 deletions Lock/EnterpriseActiveAuthInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,27 +127,35 @@ struct EnterpriseActiveAuthInteractor: DatabaseAuthenticatable, Loggable {
case .failure(let cause as AuthenticationError) where cause.isMultifactorRequired || cause.isMultifactorEnrollRequired:
self.logger.error("Multifactor is required for user <\(self.identifier)>")
callback(.multifactorRequired)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.multifactorRequired))
case .failure(let cause as AuthenticationError) where cause.isTooManyAttempts:
self.logger.error("Blocked user <\(self.identifier)> for too many login attempts")
callback(.tooManyAttempts)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.tooManyAttempts))
case .failure(let cause as AuthenticationError) where cause.isInvalidCredentials:
self.logger.error("Invalid credentials of user <\(self.identifier)>")
callback(.invalidEmailPassword)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.invalidEmailPassword))
case .failure(let cause as AuthenticationError) where cause.isMultifactorCodeInvalid:
self.logger.error("Multifactor code is invalid for user <\(self.identifier)>")
callback(.multifactorInvalid)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.multifactorInvalid))
case .failure(let cause as AuthenticationError) where cause.isRuleError && cause.description.lowercased() == "user is blocked":
self.logger.error("Blocked user <\(self.identifier)>")
callback(.userBlocked)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.userBlocked))
case .failure(let cause as AuthenticationError) where cause.code == "password_change_required":
self.logger.error("Change password required for user <\(self.identifier)>")
callback(.passwordChangeRequired)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.passwordChangeRequired))
case .failure(let cause as AuthenticationError) where cause.code == "password_leaked":
self.logger.error("The password of user <\(self.identifier)> was leaked")
callback(.passwordLeaked)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.passwordLeaked))
case .failure(let cause):
self.logger.error("Failed login of user <\(self.identifier)> with error \(cause)")
callback(.couldNotLogin)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.couldNotLogin))
case .success(let credentials):
self.logger.info("Authenticated user <\(self.identifier)>")
callback(nil)
Expand Down
2 changes: 2 additions & 0 deletions Lock/MultifactorInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ struct MultifactorInteractor: MultifactorAuthenticatable {
switch result {
case .failure(let cause as AuthenticationError) where cause.isMultifactorCodeInvalid:
callback(.multifactorInvalid)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.multifactorInvalid))
case .failure:
callback(.couldNotLogin)
self.dispatcher.dispatch(result: .error(DatabaseAuthenticatableError.couldNotLogin))
case .success(let credentials):
callback(nil)
self.dispatcher.dispatch(result: .auth(credentials))
Expand Down
4 changes: 3 additions & 1 deletion LockTests/Presenters/ConnectionLoadingPresenterSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ class ConnectionLoadingPresenterSpec: QuickSpec {
var messagePresenter: MockMessagePresenter!
var navigator: MockNavigator!
var options: OptionBuildable!
var dispatcher: Dispatcher!

beforeEach {
options = LockOptions()
messagePresenter = MockMessagePresenter()
interactor = MockConnectionsLoader()
navigator = MockNavigator()
presenter = ConnectionLoadingPresenter(loader: interactor, navigator: navigator, options: options)
dispatcher = ObserverStore()
presenter = ConnectionLoadingPresenter(loader: interactor, navigator: navigator, dispatcher: dispatcher, options: options)
presenter.messagePresenter = messagePresenter
}

Expand Down

0 comments on commit cc20121

Please sign in to comment.