Skip to content

Commit

Permalink
Merge pull request #365 from auth0/feature_login_after_signup
Browse files Browse the repository at this point in the history
Feature to disable log in after sign up
  • Loading branch information
hzalaz authored Jan 10, 2017
2 parents e071e57 + 78a214e commit 43a640d
Show file tree
Hide file tree
Showing 29 changed files with 647 additions and 316 deletions.
14 changes: 4 additions & 10 deletions App/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ViewController: UIViewController {
.classic()
.withOptions {
applyDefaultOptions(&$0)
$0.loginAfterSignup = false
}
.withStyle {
$0.oauth2["slack"] = AuthStyle(
Expand Down Expand Up @@ -175,16 +176,9 @@ class ViewController: UIViewController {
private func showLock(lock: Lock) {
Log.enable(minimumSeverity: LogSeverity.verbose, suppressColors: true)
lock
.on { result in
switch result {
case .success(let credentials):
Log.info?.message("Obtained credentials \(credentials)")
case .failure(let cause):
Log.error?.message("Failed with \(cause)")
default:
Log.debug?.value(result)
}
}
.onAuth { Log.info?.message("Obtained credentials \($0)") }
.onError { Log.error?.message("Failed with \($0)") }
.onCancel { Log.debug?.message("User closed lock") }
.present(from: self)
}
}
Expand Down
12 changes: 12 additions & 0 deletions Lock.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
5B011CDE1E13E16500543F12 /* NotificationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B011CDD1E13E16500543F12 /* NotificationStatus.swift */; };
5B09717C1DC8F229003AA88F /* EnterpriseDomain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B09717B1DC8F229003AA88F /* EnterpriseDomain.swift */; };
5B09717E1DC8F292003AA88F /* EnterpriseActiveAuthInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B09717D1DC8F292003AA88F /* EnterpriseActiveAuthInteractor.swift */; };
5B0971801DC8F5C4003AA88F /* EnterpriseDomainPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B09717F1DC8F5C4003AA88F /* EnterpriseDomainPresenter.swift */; };
Expand All @@ -23,6 +24,8 @@
5BB4A7C11DF9A38E008E8C37 /* DatabaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB4A7C01DF9A38E008E8C37 /* DatabaseView.swift */; };
5BCDE1361DDDF17F00AA2A6C /* EnterpriseActiveAuthPresenterSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BCDE1341DDDF12100AA2A6C /* EnterpriseActiveAuthPresenterSpec.swift */; };
5BCED4C71DD1FEAA00E2CE8A /* EnterpriseDomainPresenterSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BCED4C51DD1FCF200E2CE8A /* EnterpriseDomainPresenterSpec.swift */; };
5F0FCF901E20117E00E3D53B /* ObserverStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F0FCF8F1E20117E00E3D53B /* ObserverStore.swift */; };
5F0FCF921E201CF300E3D53B /* ObserverStoreSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F0FCF911E201CF300E3D53B /* ObserverStoreSpec.swift */; };
5F14565A1D5130E80085DF9C /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F1456591D5130E80085DF9C /* Colors.swift */; };
5F1C498E1D8360AA005B74FC /* Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F1C498D1D8360AA005B74FC /* Style.swift */; };
5F1C49901D8360BF005B74FC /* ConnectionLoadingPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F1C498F1D8360BF005B74FC /* ConnectionLoadingPresenter.swift */; };
Expand Down Expand Up @@ -194,6 +197,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
5B011CDD1E13E16500543F12 /* NotificationStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationStatus.swift; sourceTree = "<group>"; };
5B09717B1DC8F229003AA88F /* EnterpriseDomain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EnterpriseDomain.swift; path = Lock/EnterpriseDomain.swift; sourceTree = SOURCE_ROOT; };
5B09717D1DC8F292003AA88F /* EnterpriseActiveAuthInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EnterpriseActiveAuthInteractor.swift; path = Lock/EnterpriseActiveAuthInteractor.swift; sourceTree = SOURCE_ROOT; };
5B09717F1DC8F5C4003AA88F /* EnterpriseDomainPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EnterpriseDomainPresenter.swift; path = Lock/EnterpriseDomainPresenter.swift; sourceTree = SOURCE_ROOT; };
Expand All @@ -210,6 +214,8 @@
5BB4A7C01DF9A38E008E8C37 /* DatabaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatabaseView.swift; sourceTree = "<group>"; };
5BCDE1341DDDF12100AA2A6C /* EnterpriseActiveAuthPresenterSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterpriseActiveAuthPresenterSpec.swift; sourceTree = "<group>"; };
5BCED4C51DD1FCF200E2CE8A /* EnterpriseDomainPresenterSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterpriseDomainPresenterSpec.swift; sourceTree = "<group>"; };
5F0FCF8F1E20117E00E3D53B /* ObserverStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverStore.swift; sourceTree = "<group>"; };
5F0FCF911E201CF300E3D53B /* ObserverStoreSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverStoreSpec.swift; sourceTree = "<group>"; };
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; };
Expand Down Expand Up @@ -546,11 +552,13 @@
children = (
5FEEE8161DB6AC6C00B4DFED /* PasswordPolicy */,
5F2496B71D665AC500A1C6E2 /* UserAttribute.swift */,
5B011CDD1E13E16500543F12 /* NotificationStatus.swift */,
5FBE5CB71D3D8F030038536D /* User.swift */,
5F57DFC51D4F79DD00C54DA8 /* AuthStyle.swift */,
5F1C498D1D8360AA005B74FC /* Style.swift */,
5F70F1EA1D7909C4004698DA /* Connections */,
5F70F1EB1D7909DC004698DA /* Options */,
5F0FCF8F1E20117E00E3D53B /* ObserverStore.swift */,
);
name = Models;
path = Lock;
Expand All @@ -564,6 +572,7 @@
5FE50DC01D7DED8C00D82290 /* OfflineConnectionsSpec.swift */,
5FEEE8191DB6AF3800B4DFED /* RuleSpec.swift */,
5FEEE81D1DB84BBB00B4DFED /* PasswordPolicySpec.swift */,
5F0FCF911E201CF300E3D53B /* ObserverStoreSpec.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -1004,6 +1013,7 @@
5FBE5CBE1D3E5C7B0038536D /* MultifactorAuthenticatable.swift in Sources */,
5B2981781DD51A460062535C /* InfoBarView.swift in Sources */,
5FBE5CC01D3E5E0A0038536D /* MultifactorInteractor.swift in Sources */,
5F0FCF901E20117E00E3D53B /* ObserverStore.swift in Sources */,
5F50900E1D1DF40400EAA650 /* DatabaseOnlyView.swift in Sources */,
5F70F1E91D7907D5004698DA /* LockOptions.swift in Sources */,
5FC4348A1D1DF82A005188BC /* DatabasePresenter.swift in Sources */,
Expand All @@ -1013,6 +1023,7 @@
5F73CDD41D3073BE00D8D8D1 /* DatabaseForgotPasswordView.swift in Sources */,
5F99AA961D1C4AF400D27842 /* CredentialView.swift in Sources */,
5F1C498E1D8360AA005B74FC /* Style.swift in Sources */,
5B011CDE1E13E16500543F12 /* NotificationStatus.swift in Sources */,
5F73CDDA1D30957900D8D8D1 /* DatabasePasswordInteractor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1030,6 +1041,7 @@
5F92C68D1D50E47100CCE6C0 /* AuthStyleSpec.swift in Sources */,
5F92C68B1D4FE90F00CCE6C0 /* Auth0OAuth2InteractorSpec.swift in Sources */,
5F5090081D1DE7BA00EAA650 /* NetworkStub.swift in Sources */,
5F0FCF921E201CF300E3D53B /* ObserverStoreSpec.swift in Sources */,
5F73CDDC1D309BE900D8D8D1 /* DatabasePasswordInteractorSpec.swift in Sources */,
5F2496AF1D66210500A1C6E2 /* LockViewControllerSpec.swift in Sources */,
5FA250501D48E2A200C544FA /* OptionsSpec.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Lock/Auth0OAuth2Interactor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import Auth0
struct Auth0OAuth2Interactor: OAuth2Authenticatable {

let webAuth: Auth0.WebAuth
let onCredentials: (Credentials) -> ()
let dispatcher: Dispatcher
let options: Options

func login(_ connection: String, callback: @escaping (OAuth2AuthenticatableError?) -> ()) {
Expand All @@ -45,7 +45,7 @@ struct Auth0OAuth2Interactor: OAuth2Authenticatable {
.start { result in
switch result {
case .success(let credentials):
self.onCredentials(credentials)
self.dispatcher.dispatch(result: .auth(credentials))
callback(nil)
case .failure(WebAuthError.userCancelled):
callback(.cancelled)
Expand Down
21 changes: 15 additions & 6 deletions Lock/DatabaseInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl
let credentialAuth: CredentialAuth
let connection: DatabaseConnection
let emailValidator: InputValidator = EmailValidator()
let onAuthentication: (Credentials) -> ()
let dispatcher: Dispatcher
let options: Options
let customFields: [String: CustomTextField]

init(connection: DatabaseConnection, authentication: Authentication, user: DatabaseUser, options: Options, callback: @escaping (Credentials) -> ()) {
init(connection: DatabaseConnection, authentication: Authentication, user: DatabaseUser, options: Options, dispatcher: Dispatcher) {
self.credentialAuth = CredentialAuth(oidc: options.oidcConformant, realm: connection.name, authentication: authentication)
self.connection = connection
self.onAuthentication = callback
self.dispatcher = dispatcher
self.user = user
self.options = options
var fields: [String: CustomTextField] = [:]
Expand Down Expand Up @@ -127,8 +127,17 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl
)
.start {
switch $0 {
case .success:
login.start { self.handle(result: $0, callback: { callback(nil, $0) }) }
case .success(let user):
if self.options.loginAfterSignup {
login.start { self.handle(result: $0, callback: { callback(nil, $0) }) }
} else {
var extra: [String: Any] = [
"verified": user.verified
]
extra["username"] = user.username
self.dispatcher.dispatch(result: .signUp(user.email, extra))
callback(nil, nil)
}
case .failure(let cause as AuthenticationError) where cause.isPasswordNotStrongEnough:
callback(.passwordTooWeak, nil)
case .failure(let cause as AuthenticationError) where cause.isPasswordAlreadyUsed:
Expand Down Expand Up @@ -195,7 +204,7 @@ struct DatabaseInteractor: DatabaseAuthenticatable, DatabaseUserCreator, Loggabl
case .success(let credentials):
self.logger.info("Authenticated user <\(self.identifier)>")
callback(nil)
self.onAuthentication(credentials)
self.dispatcher.dispatch(result: .auth(credentials))
}
}
}
10 changes: 7 additions & 3 deletions Lock/DatabasePresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,20 @@ class DatabasePresenter: Presentable, Loggable {
interactor.create { createError, loginError in
Queue.main.async {
button.inProgress = false

guard createError != nil || loginError != nil else {
self.logger.debug("Logged in!")
if !self.options.loginAfterSignup {
let message = "Thanks for signing up.".i18n(key: "com.auth0.lock.database.signup.success.message", comment: "User signed up")
if let databaseView = self.databaseView {
self.showLogin(inView: databaseView, identifier: self.creator.identifier)
}
self.messagePresenter?.showSuccess(message)
}
return
}
if let error = loginError, case .multifactorRequired = error {
self.navigator.navigate(.multifactor)
return
}

let error: LocalizableError = createError ?? loginError!
form?.needsToUpdateState()
self.messagePresenter?.showError(error)
Expand Down
8 changes: 4 additions & 4 deletions Lock/EnterpriseActiveAuthInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@ struct EnterpriseActiveAuthInteractor: DatabaseAuthenticatable, Loggable {
let passwordValidator: InputValidator = NonEmptyValidator()

let authentication: CredentialAuth
let onAuthentication: (Credentials) -> ()
let dispatcher: Dispatcher
let options: Options
let user: User
let connection: EnterpriseConnection

let identifierAttribute: UserAttribute

init(connection: EnterpriseConnection, authentication: Authentication, user: User, options: Options, callback: @escaping (Credentials) -> ()) {
init(connection: EnterpriseConnection, authentication: Authentication, user: User, options: Options, dispatcher: Dispatcher) {
self.authentication = CredentialAuth(oidc: options.oidcConformant, realm: connection.name, authentication: authentication)
self.connection = connection
self.onAuthentication = callback
self.dispatcher = dispatcher
self.user = user
self.options = options

Expand Down Expand Up @@ -151,7 +151,7 @@ struct EnterpriseActiveAuthInteractor: DatabaseAuthenticatable, Loggable {
case .success(let credentials):
self.logger.info("Authenticated user <\(self.identifier)>")
callback(nil)
self.onAuthentication(credentials)
self.dispatcher.dispatch(result: .auth(credentials))
}
}

Expand Down
59 changes: 44 additions & 15 deletions Lock/Lock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ import Auth0
/// Lock main class to configure and show the native widget
public class Lock: NSObject {

/// Callback used to notify lock authentication outcome
public typealias AuthenticationCallback = (Result) -> ()

static let sharedInstance = Lock()

private(set) var authentication: Authentication
Expand All @@ -40,7 +37,7 @@ public class Lock: NSObject {
var optionsBuilder: OptionBuildable = LockOptions()
var options: Options { return self.optionsBuilder }

var callback: AuthenticationCallback = {_ in }
var observerStore = ObserverStore()

var style: Style = Style()

Expand Down Expand Up @@ -103,7 +100,8 @@ public class Lock: NSObject {
*/
public func present(from controller: UIViewController) {
if let error = self.optionsBuilder.validate() {
self.callback(.failure(error))
self.observerStore.onFailure(error)
// FIXME: Fail violently
} else {
controller.present(self.controller, animated: true, completion: nil)
}
Expand Down Expand Up @@ -179,14 +177,51 @@ public class Lock: NSObject {
}

/**
Register a callback for the outcome of the Authentication
Register a callback to recieve the result of a successful AuthN/AuthZ.
- parameter callback: called on successful AuthN/AuthZ
- returns: Lock itself for chaining
*/
public func onAuth(callback: @escaping (Credentials) -> ()) -> Lock {
self.observerStore.onAuth = callback
return self
}

- parameter callback: callback called when the user is authenticated, lock is dismissed or an unrecoverable error ocurrs
/**
Register a callback to recieve Lock unrecoverable errors
- parameter callback: called on every unrecoverable error
- returns: Lock itself for chaining
*/
public func on(_ callback: @escaping AuthenticationCallback) -> Lock {
self.callback = callback
public func onError(callback: @escaping (Error) -> ()) -> Lock {
self.observerStore.onFailure = callback
return self
}

/**
Register a callback to be notified when the user closes Lock when `closable` option is `true`
- parameter callback: called when the user closes Lock
- returns: Lock itself for chaining
*/
public func onCancel(callback: @escaping () -> ()) -> Lock {
self.observerStore.onCancel = callback
return self
}

/**
Register a callback to be notified when a user signs up when login after signup is disabled.
The callback will yield the new user email and additional attributes like username.
- parameter callback: called when a user signs up
- returns: Lock itself for chaining
*/
public func onSignUp(callback: @escaping (String, [String: Any]) -> ()) -> Lock {
self.observerStore.onSignUp = callback
return self
}

Expand Down Expand Up @@ -224,12 +259,6 @@ struct ConnectionProvider {
var connections: Connections { return local.select(byNames: allowed) }
}

public enum Result {
case success(Credentials)
case failure(Error)
case cancelled
}

public enum UnrecoverableError: Error {
case invalidClientOrDomain
case clientWithNoConnections
Expand Down
1 change: 1 addition & 0 deletions Lock/LockOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct LockOptions: OptionBuildable {
var initialScreen: DatabaseScreen = .login
var usernameStyle: DatabaseIdentifierStyle = [.Username, .Email]
var customSignupFields: [CustomTextField] = []
var loginAfterSignup: Bool = true

// Enterprise
var activeDirectoryEmailAsUsername: Bool = false
Expand Down
8 changes: 6 additions & 2 deletions Lock/LockViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ public class LockViewController: UIViewController {
var current: View?
var keyboard: Bool = false
var routes: Routes = Routes()
var messagePresenter: MessagePresenter!

var anchorConstraint: NSLayoutConstraint?

var messagePresenter: MessagePresenter!
var router: Router!

public required init(lock: Lock) {
super.init(nibName: nil, bundle: nil)
lock.observerStore.controller = self
self.router = Router(lock: lock, controller: self)
}

Expand Down Expand Up @@ -70,7 +72,9 @@ public class LockViewController: UIViewController {
header.translatesAutoresizingMaskIntoConstraints = false

header.showClose = self.router.lock.options.closable
header.onClosePressed = self.router.onDismiss
header.onClosePressed = { [weak self] in
self?.router.lock.observerStore.dispatch(result: .cancel)
}
header.apply(style: style)

self.headerView = header
Expand Down
4 changes: 2 additions & 2 deletions Lock/MessageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class MessageView: UIView {
return self.messageLabel?.text
}
set {
self.messageLabel?.text = newValue
self.messageLabel?.text = newValue?.uppercased()
}
}

Expand Down Expand Up @@ -88,7 +88,7 @@ public class MessageView: UIView {
let messageLabel = UILabel()
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
messageLabel.font = .systemFont(ofSize: 12, weight: UIFontWeightMedium)
messageLabel.font = .systemFont(ofSize: 11, weight: UIFontWeightMedium)
messageLabel.textColor = self.type.textColor

self.addSubview(messageLabel)
Expand Down
Loading

0 comments on commit 43a640d

Please sign in to comment.