From 9062d497a8af448d9624abf8501284d5e9624bde Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Mon, 21 Nov 2016 21:32:29 +0000 Subject: [PATCH 1/7] Rebase conflict fixes --- Lock/AuthStyle.swift | 8 ++- Lock/CDNLoaderInteractor.swift | 4 +- Lock/ConnectionBuildable.swift | 2 +- Lock/Connections.swift | 2 +- Lock/EnterpriseDomainInteractor.swift | 7 +- Lock/EnterpriseDomainPresenter.swift | 72 +++++++++++++++---- Lock/EnterpriseDomainView.swift | 39 +++++++++- Lock/InfoBarView.swift | 2 +- Lock/OfflineConnections.swift | 4 +- Lock/Router.swift | 11 +-- .../EnterpriseActiveAuthInteractorSpec.swift | 2 +- .../EnterpriseDomainInteractorSpec.swift | 10 +-- .../Presenters/DatabasePresenterSpec.swift | 4 +- .../EnterpriseActiveAuthPresenterSpec.swift | 3 +- .../EnterpriseDomainPresenterSpec.swift | 5 +- LockTests/Router/RouterSpec.swift | 8 +-- 16 files changed, 137 insertions(+), 46 deletions(-) diff --git a/Lock/AuthStyle.swift b/Lock/AuthStyle.swift index 6e7877e94..0f66226d0 100644 --- a/Lock/AuthStyle.swift +++ b/Lock/AuthStyle.swift @@ -26,7 +26,7 @@ import UIKit public class AuthStyle { /// Name that will be used for titles. e.g. 'Login with Auth0' - public let name: String + public var name: String let image: LazyImage let foregroundColor: UIColor let normalColor: UIColor @@ -270,6 +270,8 @@ extension AuthStyle { static func style(forStrategy strategy: String, connectionName: String) -> AuthStyle { switch strategy.lowercaseString { + case "ad", "adfs": + return .Microsoft case "amazon": return .Amazon case "aol": @@ -340,10 +342,12 @@ extension AuthStyle { return .Yammer case "yandex": return .Yandex + case "waad": + return .Google case "weibo": return .Weibo default: return AuthStyle(name: connectionName) } } -} \ No newline at end of file +} diff --git a/Lock/CDNLoaderInteractor.swift b/Lock/CDNLoaderInteractor.swift index 7d8e44ba9..de6a60540 100644 --- a/Lock/CDNLoaderInteractor.swift +++ b/Lock/CDNLoaderInteractor.swift @@ -84,8 +84,8 @@ struct CDNLoaderInteractor: RemoteConnectionLoader, Loggable { } info.enterprise.forEach { strategy in strategy.connections.forEach { connection in - let domain = connection.json["domain_aliases"] as! [String] - connections.enterprise(name: connection.name, domains: domain) + let domains = connection.json["domain_aliases"] as! [String] + connections.enterprise(name: connection.name, domains: domains, style: AuthStyle.style(forStrategy: strategy.name, connectionName: domains.first!)) } } info.oauth2.forEach { strategy in diff --git a/Lock/ConnectionBuildable.swift b/Lock/ConnectionBuildable.swift index 0997d0453..6f97d6c02 100644 --- a/Lock/ConnectionBuildable.swift +++ b/Lock/ConnectionBuildable.swift @@ -62,7 +62,7 @@ public protocol ConnectionBuildable: Connections { - parameter name: name of the connection - parameter domain: array of enterprise domains */ - mutating func enterprise(name name: String, domains: [String]) + mutating func enterprise(name name: String, domains: [String], style: AuthStyle) } public extension ConnectionBuildable { diff --git a/Lock/Connections.swift b/Lock/Connections.swift index 44a00ffe9..6ad126f2e 100644 --- a/Lock/Connections.swift +++ b/Lock/Connections.swift @@ -64,5 +64,5 @@ public struct SocialConnection: OAuth2Connection { public struct EnterpriseConnection : OAuth2Connection { public let name: String public let domains: [String] - public var style: AuthStyle { return AuthStyle(name: self.name) } + public let style: AuthStyle } diff --git a/Lock/EnterpriseDomainInteractor.swift b/Lock/EnterpriseDomainInteractor.swift index 66783e62f..118ce2109 100644 --- a/Lock/EnterpriseDomainInteractor.swift +++ b/Lock/EnterpriseDomainInteractor.swift @@ -36,8 +36,13 @@ struct EnterpriseDomainInteractor: HRDAuthenticatable { init(connections: [EnterpriseConnection], authentication: OAuth2Authenticatable) { self.connections = connections self.authenticator = authentication + + // Single Enterprise, defaulting connection + if self.connections.count == 1 { + self.connection = self.connections.first + } } - + func matchDomain(value: String?) -> EnterpriseConnection? { guard let domain = value?.componentsSeparatedByString("@").last else { return nil } return connections.filter { $0.domains.contains(domain) }.first diff --git a/Lock/EnterpriseDomainPresenter.swift b/Lock/EnterpriseDomainPresenter.swift index 9dc0a3af8..fbf6e9252 100644 --- a/Lock/EnterpriseDomainPresenter.swift +++ b/Lock/EnterpriseDomainPresenter.swift @@ -23,28 +23,48 @@ import Foundation class EnterpriseDomainPresenter: Presentable, Loggable { - + var interactor: EnterpriseDomainInteractor var customLogger: Logger? var user: User var options: Options - + // Social connections var authPresenter: AuthPresenter? - + init(interactor: EnterpriseDomainInteractor, navigator: Navigable, user: User, options: Options) { self.interactor = interactor self.navigator = navigator self.user = user self.options = options } - + var messagePresenter: MessagePresenter? var navigator: Navigable? - + var view: View { let email = self.interactor.validEmail ? self.interactor.email : nil let authCollectionView = self.authPresenter?.newViewToEmbed(withInsets: UIEdgeInsetsMake(0, 0, 0, 0), isLogin: true) + + // Single Enterprise Domain + if let enterpriseButton = EnterpriseButton(forConnections: interactor.connections, customStyle: [:], isLogin: true, onAction: { + if self.authModeSwitch() { return } + + self.interactor.login { error in + Queue.main.async { + if let error = error { + self.messagePresenter?.showError(error) + self.logger.error("Enterprise connection failed: \(error)") + } else { + self.logger.debug("Enterprise authenticator launched") + } + } + + }}) { + let view = EnterpriseDomainView(authButton: enterpriseButton, authCollectionView: authCollectionView) + return view + } + let view = EnterpriseDomainView(email: email, authCollectionView: authCollectionView) let form = view.form @@ -53,7 +73,7 @@ class EnterpriseDomainPresenter: Presentable, Loggable { view.form?.onValueChange = { input in self.messagePresenter?.hideCurrent() view.ssoBar?.hidden = true - + guard case .Email = input.type else { return } do { try self.interactor.updateEmail(input.text) @@ -67,9 +87,9 @@ class EnterpriseDomainPresenter: Presentable, Loggable { input.showError() } } - - let action = { (button: PrimaryButton) in + let action = { (button: PrimaryButton) in + // Check for credential auth if let connection = self.interactor.connection where self.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { guard self.navigator?.navigate(.EnterpriseActiveAuth(connection: connection)) == nil else { return } @@ -90,17 +110,45 @@ class EnterpriseDomainPresenter: Presentable, Loggable { self.logger.debug("Enterprise authenticator launched") } } - + } - + } - + view.primaryButton?.onPress = action view.form?.onReturn = {_ in guard let button = view.primaryButton else { return } action(button) } + return view } - + + func authModeSwitch() -> Bool { + // Check for credential auth + if let connection = self.interactor.connection { + if self.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { + self.navigator?.navigate(.EnterpriseActiveAuth(connection: connection)) + return true + } + } + return false + } + +} + +func EnterpriseButton(forConnections connections: [EnterpriseConnection], customStyle: [String: AuthStyle], isLogin login: Bool, onAction: () -> () ) -> AuthButton? { + guard let connection = connections.first where connections.count == 1 else { return nil } + let style = customStyle[connection.name] ?? connection.style + style.name = connection.domains.first! + let button = AuthButton(size: .Big) + button.title = login ? style.localizedLoginTitle.uppercaseString : style.localizedSignUpTitle.uppercaseString + button.normalColor = style.normalColor + button.highlightedColor = style.highlightedColor + button.titleColor = style.foregroundColor + button.icon = style.image.image(compatibleWithTraits: button.traitCollection) + button.onPress = { _ in + onAction() + } + return button } diff --git a/Lock/EnterpriseDomainView.swift b/Lock/EnterpriseDomainView.swift index fbd0836f7..a211ff560 100644 --- a/Lock/EnterpriseDomainView.swift +++ b/Lock/EnterpriseDomainView.swift @@ -28,8 +28,7 @@ class EnterpriseDomainView: UIView, View { weak var ssoBar: InfoBarView? weak var primaryButton: PrimaryButton? weak var authCollectionView: AuthCollectionView? - - private weak var container: UIStackView? + weak var container: UIStackView? init(email: String?, authCollectionView: AuthCollectionView? = nil) { let primaryButton = PrimaryButton() @@ -92,7 +91,41 @@ class EnterpriseDomainView: UIView, View { domainView.value = email } - + + init(authButton: AuthButton, authCollectionView: AuthCollectionView? = nil) { + let container = UIStackView() + self.container = container + + super.init(frame: CGRectZero) + + self.addSubview(container) + + container.alignment = .Fill + container.axis = .Vertical + container.distribution = .EqualSpacing + container.spacing = 5 + + container.addArrangedSubview(strutView(withHeight: 25)) + if let authCollectionView = authCollectionView { + self.authCollectionView = authCollectionView + container.addArrangedSubview(authCollectionView) + let label = UILabel() + label.text = "or".i18n(key: "com.auth0.lock.database.separator", comment: "Social separator") + label.font = mediumSystemFont(size: 13.75) + label.textColor = UIColor ( red: 0.0, green: 0.0, blue: 0.0, alpha: 0.54 ) + label.textAlignment = .Center + container.addArrangedSubview(label) + } + container.addArrangedSubview(authButton) + container.addArrangedSubview(strutView()) + + constraintEqual(anchor: container.topAnchor, toAnchor: self.topAnchor) + constraintEqual(anchor: container.leftAnchor, toAnchor: self.leftAnchor, constant: 20) + constraintEqual(anchor: container.rightAnchor, toAnchor: self.rightAnchor, constant: -20) + constraintEqual(anchor: container.bottomAnchor, toAnchor: self.bottomAnchor) + container.translatesAutoresizingMaskIntoConstraints = false + } + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } diff --git a/Lock/InfoBarView.swift b/Lock/InfoBarView.swift index 43b8a78e7..9ce77ed73 100644 --- a/Lock/InfoBarView.swift +++ b/Lock/InfoBarView.swift @@ -92,7 +92,7 @@ public class InfoBarView: UIView { } public override func intrinsicContentSize() -> CGSize { - return CGSize(width: 200, height: 35) + return CGSize(width: UIViewNoIntrinsicMetric, height: 35) } diff --git a/Lock/OfflineConnections.swift b/Lock/OfflineConnections.swift index db25bdb6c..9f4dcaa00 100644 --- a/Lock/OfflineConnections.swift +++ b/Lock/OfflineConnections.swift @@ -42,8 +42,8 @@ struct OfflineConnections: ConnectionBuildable { self.oauth2.append(social) } - mutating func enterprise(name name: String, domains: [String]) { - let enterprise = EnterpriseConnection(name: name, domains: domains) + mutating func enterprise(name name: String, domains: [String], style: AuthStyle) { + let enterprise = EnterpriseConnection(name: name, domains: domains, style: style) self.enterprise.append(enterprise) } diff --git a/Lock/Router.swift b/Lock/Router.swift index 2de9a1426..fc7a0c66a 100644 --- a/Lock/Router.swift +++ b/Lock/Router.swift @@ -102,10 +102,13 @@ struct Router: Navigable { if !connections.enterprise.isEmpty { let authInteractor = Auth0OAuth2Interactor(webAuth: self.lock.webAuth, onCredentials: self.onAuthentication, options: self.lock.options) let interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authInteractor) + // Single enterprise in credential auth mode + if let connection = interactor.connection where self.lock.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { + return EnterpriseActiveAuth(connection) + } let presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: self, user: self.user, options: self.lock.options) if !connections.oauth2.isEmpty { - let interactor = Auth0OAuth2Interactor(webAuth: self.lock.webAuth, onCredentials: self.onAuthentication, options: self.lock.options) - presenter.authPresenter = AuthPresenter(connections: connections, interactor: interactor, customStyle: self.lock.style.oauth2) + presenter.authPresenter = AuthPresenter(connections: connections, interactor: authInteractor, customStyle: self.lock.style.oauth2) } return presenter } @@ -141,14 +144,12 @@ struct Router: Navigable { presenter.customLogger = self.lock.logger return presenter } - + func EnterpriseActiveAuth(connection: EnterpriseConnection) -> Presentable? { - let authentication = self.lock.authentication let interactor = EnterpriseActiveAuthInteractor(connection: connection, authentication: authentication, user: self.user, options: self.lock.options, callback: self.onAuthentication) let presenter = EnterpriseActiveAuthPresenter(interactor: interactor) presenter.customLogger = self.lock.logger - return presenter } diff --git a/LockTests/Interactors/EnterpriseActiveAuthInteractorSpec.swift b/LockTests/Interactors/EnterpriseActiveAuthInteractorSpec.swift index 3bc5ceaa6..0012ff427 100644 --- a/LockTests/Interactors/EnterpriseActiveAuthInteractorSpec.swift +++ b/LockTests/Interactors/EnterpriseActiveAuthInteractorSpec.swift @@ -38,7 +38,7 @@ class EnterpriseActiveAuthInteractorSpec: QuickSpec { var connection: EnterpriseConnection! beforeEach { - connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"]) + connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) user = User() options = LockOptions() interactor = EnterpriseActiveAuthInteractor(connection: connection, authentication: authentication, user: user, options: options, callback: {_ in}) diff --git a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift index 17fe5213d..0209a00ac 100644 --- a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift +++ b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift @@ -39,7 +39,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com"]) + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) credentials = nil webAuth = MockWebAuth() @@ -66,7 +66,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: []) + connections.enterprise(name: "TestAD", domains: [], style: AuthStyle(name: "ad")) enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) } @@ -82,7 +82,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com"]) + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) } @@ -116,7 +116,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com","pepe.com"]) + connections.enterprise(name: "TestAD", domains: ["test.com","pepe.com"], style: AuthStyle(name: "ad")) enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) } @@ -142,7 +142,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { error = nil connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com"]) + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) } diff --git a/LockTests/Presenters/DatabasePresenterSpec.swift b/LockTests/Presenters/DatabasePresenterSpec.swift index b414681e8..e38184ad7 100644 --- a/LockTests/Presenters/DatabasePresenterSpec.swift +++ b/LockTests/Presenters/DatabasePresenterSpec.swift @@ -539,7 +539,7 @@ class DatabasePresenterSpec: QuickSpec { beforeEach { connections = OfflineConnections() - connections.enterprise(name: "validAD", domains: ["valid.com"]) + connections.enterprise(name: "validAD", domains: ["valid.com"], style: AuthStyle(name: "ad")) enterpriseInteractor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) presenter.enterpriseInteractor = enterpriseInteractor @@ -632,7 +632,7 @@ class DatabasePresenterSpec: QuickSpec { options.enterpriseConnectionUsingActiveAuth = ["validAD"] connections = OfflineConnections() - connections.enterprise(name: "validAD", domains: ["valid.com"]) + connections.enterprise(name: "validAD", domains: ["valid.com"], style: AuthStyle(name: "ad")) presenter = DatabasePresenter(authenticator: interactor, creator: interactor, connection: DatabaseConnection(name: connection, requiresUsername: true), navigator: navigator, options: options) enterpriseInteractor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) diff --git a/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift b/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift index eca44faaa..7cda28650 100644 --- a/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift @@ -43,8 +43,7 @@ class EnterpriseActiveAuthPresenterSpec: QuickSpec { options = LockOptions() user = User() messagePresenter = MockMessagePresenter() - - connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"]) + connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) interactor = EnterpriseActiveAuthInteractor(connection: connection, authentication: authentication, user: user, options: options, callback: {_ in}) presenter = EnterpriseActiveAuthPresenter(interactor: interactor) presenter.messagePresenter = messagePresenter diff --git a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift index a61a29255..72d011c3c 100644 --- a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift @@ -49,7 +49,8 @@ class EnterpriseDomainPresenterSpec: QuickSpec { options = LockOptions() connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com"]) + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + connections.enterprise(name: "ValidAD", domains: ["validad.com"], style: AuthStyle(name: "adfs")) interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) @@ -147,7 +148,7 @@ class EnterpriseDomainPresenterSpec: QuickSpec { } it("should show yield oauth2 error on failure") { - presenter.interactor.connection = EnterpriseConnection(name: "ad", domains: ["auth0.com"]) + presenter.interactor.connection = EnterpriseConnection(name: "ad", domains: ["auth0.com"], style: AuthStyle(name: "ad")) oauth2.onLogin = { return OAuth2AuthenticatableError.CouldNotAuthenticate } view.primaryButton?.onPress(view.primaryButton!) expect(messagePresenter.error).toEventually(beError(error: OAuth2AuthenticatableError.CouldNotAuthenticate)) diff --git a/LockTests/Router/RouterSpec.swift b/LockTests/Router/RouterSpec.swift index 74291475d..e496f3cd3 100644 --- a/LockTests/Router/RouterSpec.swift +++ b/LockTests/Router/RouterSpec.swift @@ -73,8 +73,8 @@ class RouterSpec: QuickSpec { it("should return root for only enterprise connections") { lock.withConnections { - $0.enterprise(name: "testAD", domains: ["testAD.com"]) - $0.enterprise(name: "validAD", domains: ["validAD.com"]) + $0.enterprise(name: "testAD", domains: ["testAD.com"], style: AuthStyle(name: "ad")) + $0.enterprise(name: "validAD", domains: ["validAD.com"], style: AuthStyle(name: "ad")) } expect(router.root as? EnterpriseDomainPresenter).toNot(beNil()) } @@ -212,7 +212,7 @@ class RouterSpec: QuickSpec { } it("should show enterprise active auth screen") { - router.navigate(.EnterpriseActiveAuth(connection: EnterpriseConnection(name: "testAD", domains: ["testad.com"]))) + router.navigate(.EnterpriseActiveAuth(connection: EnterpriseConnection(name: "testAD", domains: ["testad.com"], style: AuthStyle(name: "ad")))) expect(controller.presentable as? EnterpriseActiveAuthPresenter).toNot(beNil()) } } @@ -292,7 +292,7 @@ class RouterSpec: QuickSpec { } it("EnterpriseActiveAuth should should be equatable with EnterpriseActiveAuth") { - let enterpriseConnection = EnterpriseConnection(name: "TestAD", domains: ["test.com"]) + let enterpriseConnection = EnterpriseConnection(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) let match = Route.EnterpriseActiveAuth(connection: enterpriseConnection) == Route.EnterpriseActiveAuth(connection: enterpriseConnection) expect(match).to(beTrue()) } From 8445929e74ad05931ad74a3477b9c85741907efa Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Mon, 21 Nov 2016 22:47:03 +0000 Subject: [PATCH 2/7] More tests --- Lock/EnterpriseDomainView.swift | 2 ++ Lock/Router.swift | 2 +- .../EnterpriseDomainInteractorSpec.swift | 23 ++++++++++++-- .../EnterpriseDomainPresenterSpec.swift | 11 ++++++- LockTests/Router/RouterSpec.swift | 30 +++++++++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/Lock/EnterpriseDomainView.swift b/Lock/EnterpriseDomainView.swift index a211ff560..7c73d2890 100644 --- a/Lock/EnterpriseDomainView.swift +++ b/Lock/EnterpriseDomainView.swift @@ -29,6 +29,7 @@ class EnterpriseDomainView: UIView, View { weak var primaryButton: PrimaryButton? weak var authCollectionView: AuthCollectionView? weak var container: UIStackView? + weak var authButton: AuthButton? init(email: String?, authCollectionView: AuthCollectionView? = nil) { let primaryButton = PrimaryButton() @@ -99,6 +100,7 @@ class EnterpriseDomainView: UIView, View { super.init(frame: CGRectZero) self.addSubview(container) + self.authButton = authButton container.alignment = .Fill container.axis = .Vertical diff --git a/Lock/Router.swift b/Lock/Router.swift index fc7a0c66a..6929c5c62 100644 --- a/Lock/Router.swift +++ b/Lock/Router.swift @@ -102,7 +102,7 @@ struct Router: Navigable { if !connections.enterprise.isEmpty { let authInteractor = Auth0OAuth2Interactor(webAuth: self.lock.webAuth, onCredentials: self.onAuthentication, options: self.lock.options) let interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authInteractor) - // Single enterprise in credential auth mode + // Single enterprise in active auth mode if let connection = interactor.connection where self.lock.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { return EnterpriseActiveAuth(connection) } diff --git a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift index 0209a00ac..1c09c05c3 100644 --- a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift +++ b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift @@ -40,6 +40,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + connections.enterprise(name: "validAD", domains: ["valid.com"], style: AuthStyle(name: "ad")) credentials = nil webAuth = MockWebAuth() @@ -57,6 +58,25 @@ class EnterpriseDomainInteractorSpec: QuickSpec { it("should have an entperise object") { expect(enterprise).toNot(beNil()) } + + it("connection should be nil") { + expect(enterprise.connection).to(beNil()) + } + + context("connection with single enterprise conection") { + + beforeEach { + connections = OfflineConnections() + connections.enterprise(name: "TestAD", domains: [], style: AuthStyle(name: "ad")) + + enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + } + + it("connection should not default to single connection") { + expect(enterprise.connection).toNot(beNil()) + } + + } } @@ -78,8 +98,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { } context("connection with one domain") { - - + beforeEach { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) diff --git a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift index 72d011c3c..e577df752 100644 --- a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift @@ -58,6 +58,15 @@ class EnterpriseDomainPresenterSpec: QuickSpec { view = presenter.view as! EnterpriseDomainView } + describe("init") { + + it("should have an entperise domain view") { + let view = presenter.view as? EnterpriseDomainView + expect(view).toNot(beNil()) + } + + } + describe("email input validation") { it("should use valid email") { @@ -205,7 +214,7 @@ class EnterpriseDomainPresenterSpec: QuickSpec { let view = presenter.view as? EnterpriseDomainView expect(view?.authCollectionView).to(equal(authPresenter.authView)) } - + it("should init view with not social view") { presenter.authPresenter = nil let view = presenter.view as? EnterpriseDomainView diff --git a/LockTests/Router/RouterSpec.swift b/LockTests/Router/RouterSpec.swift index e496f3cd3..503e61881 100644 --- a/LockTests/Router/RouterSpec.swift +++ b/LockTests/Router/RouterSpec.swift @@ -66,6 +66,29 @@ class RouterSpec: QuickSpec { expect(root?.authPresenter).toNot(beNil()) } + it("should return root for single database connection and social and enterprise") { + lock.withConnections { + $0.database(name: connection, requiresUsername: true) + $0.social(name: "facebook", style: .Facebook) + $0.enterprise(name: "testAD", domains: ["testAD.com"], style: AuthStyle(name: "ad")) + } + let root = router.root as? DatabasePresenter + expect(root).toNot(beNil()) + expect(root?.authPresenter).toNot(beNil()) + expect(root?.enterpriseInteractor).toNot(beNil()) + } + + it("should return root for single enterprise and social") { + lock.withConnections { + $0.social(name: "facebook", style: .Facebook) + $0.enterprise(name: "testAD", domains: ["testAD.com"], style: AuthStyle(name: "ad")) + } + let root = router.root as? EnterpriseDomainPresenter + expect(root).toNot(beNil()) + expect(root?.authPresenter).toNot(beNil()) + } + + it("should return root for only social connections") { lock.withConnections { $0.social(name: "dropbox", style: AuthStyle(name: "Dropbox")) } expect(router.root as? AuthPresenter).toNot(beNil()) @@ -79,6 +102,13 @@ class RouterSpec: QuickSpec { expect(router.root as? EnterpriseDomainPresenter).toNot(beNil()) } + it("should return root for one enterprise with actuve auth") { + lock.withConnections { + $0.enterprise(name: "testAD", domains: ["testAD.com"], style: AuthStyle(name: "ad")) + }.options { $0.enterpriseConnectionUsingActiveAuth = ["testAD"] } + expect(router.root as? EnterpriseActiveAuthPresenter).toNot(beNil()) + } + it("should return root for loading connection from CDN") { expect(router.root as? ConnectionLoadingPresenter).toNot(beNil()) } From 7c759e1be7279147eacdd7e526b0b6ddf9bf3192 Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Tue, 22 Nov 2016 11:59:23 +0000 Subject: [PATCH 3/7] Increased code coverage of EnterpriseDomainPresenter --- .../EnterpriseDomainPresenterSpec.swift | 92 ++++++++++++++++++- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift index e577df752..537ad5fdf 100644 --- a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift @@ -60,11 +60,44 @@ class EnterpriseDomainPresenterSpec: QuickSpec { describe("init") { + it("should have a presenter object") { + expect(presenter).toNot(beNil()) + } + it("should have an entperise domain view") { - let view = presenter.view as? EnterpriseDomainView expect(view).toNot(beNil()) } + it("should have primary button when more than one domain") { + expect(view.primaryButton).toNot(beNil()) + } + + it("should not have auth button") { + expect(view.authButton).to(beNil()) + } + + context("single enterprise connection") { + + beforeEach { + connections = OfflineConnections() + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + + interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) + presenter.messagePresenter = messagePresenter + view = presenter.view as! EnterpriseDomainView + } + + it("should not have primary button") { + expect(view.primaryButton).to(beNil()) + } + + it("should have auth button") { + expect(view.authButton).toNot(beNil()) + } + + } + } describe("email input validation") { @@ -89,7 +122,6 @@ class EnterpriseDomainPresenterSpec: QuickSpec { } - describe("user input") { it("email should update with valid email") { @@ -205,10 +237,60 @@ class EnterpriseDomainPresenterSpec: QuickSpec { } - } + context("single enterprise connection") { - describe("auth buttons") { + beforeEach { + connections = OfflineConnections() + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + + interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) + presenter.messagePresenter = messagePresenter + view = presenter.view as! EnterpriseDomainView + } + it("should show no error on success") { + view.authButton!.onPress(view.authButton!) + expect(messagePresenter.error).toEventually(beNil()) + } + + it("should show yield oauth2 error on failure") { + oauth2.onLogin = { return OAuth2AuthenticatableError.CouldNotAuthenticate } + view.authButton!.onPress(view.authButton!) + expect(messagePresenter.error).toEventually(beError(error: OAuth2AuthenticatableError.CouldNotAuthenticate)) + } + + it("should not navigate to enterprise passwod presenter") { + view.authButton!.onPress(view.authButton!) + expect(navigator.route).toEventually(beNil()) + } + + } + + context("single enterprise connection with auth flag set") { + + beforeEach { + connections = OfflineConnections() + connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + options.enterpriseConnectionUsingActiveAuth.append("TestAD") + + interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) + presenter.messagePresenter = messagePresenter + view = presenter.view as! EnterpriseDomainView + } + + it("should navigate to enterprise passwod presenter") { + view.authButton!.onPress(view.authButton!) + expect(navigator.route).toEventually(equal(Route.EnterpriseActiveAuth(connection: presenter.interactor.connection!))) + } + + } + + } + + describe("auth buttons") { + it("should init view with social view") { presenter.authPresenter = authPresenter let view = presenter.view as? EnterpriseDomainView @@ -224,5 +306,5 @@ class EnterpriseDomainPresenterSpec: QuickSpec { } } -} +} From 0fee01569826f6d34cc210d9ce3d528e510d9fa9 Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Tue, 22 Nov 2016 15:11:37 +0000 Subject: [PATCH 4/7] Renames --- Lock/EnterpriseDomainPresenter.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Lock/EnterpriseDomainPresenter.swift b/Lock/EnterpriseDomainPresenter.swift index fbf6e9252..85b149ca9 100644 --- a/Lock/EnterpriseDomainPresenter.swift +++ b/Lock/EnterpriseDomainPresenter.swift @@ -69,7 +69,6 @@ class EnterpriseDomainPresenter: Presentable, Loggable { let form = view.form view.ssoBar?.hidden = self.interactor.connection == nil - view.form?.onValueChange = { input in self.messagePresenter?.hideCurrent() view.ssoBar?.hidden = true From 3969520568e58e98b9c06cb6f0434cd80182a69f Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Tue, 22 Nov 2016 17:14:16 +0000 Subject: [PATCH 5/7] Credential auth decided in router for single enterprise Removed red auth routing in EDP and tests --- Lock/EnterpriseDomainPresenter.swift | 5 +---- .../EnterpriseDomainPresenterSpec.swift | 20 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/Lock/EnterpriseDomainPresenter.swift b/Lock/EnterpriseDomainPresenter.swift index 85b149ca9..8c8333d26 100644 --- a/Lock/EnterpriseDomainPresenter.swift +++ b/Lock/EnterpriseDomainPresenter.swift @@ -48,8 +48,6 @@ class EnterpriseDomainPresenter: Presentable, Loggable { // Single Enterprise Domain if let enterpriseButton = EnterpriseButton(forConnections: interactor.connections, customStyle: [:], isLogin: true, onAction: { - if self.authModeSwitch() { return } - self.interactor.login { error in Queue.main.async { if let error = error { @@ -88,12 +86,11 @@ class EnterpriseDomainPresenter: Presentable, Loggable { } let action = { (button: PrimaryButton) in - // Check for credential auth if let connection = self.interactor.connection where self.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { guard self.navigator?.navigate(.EnterpriseActiveAuth(connection: connection)) == nil else { return } } - + self.messagePresenter?.hideCurrent() self.logger.info("Enterprise connection started: \(self.interactor.email), \(self.interactor.connection)") let interactor = self.interactor diff --git a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift index 537ad5fdf..ba07aa91e 100644 --- a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift @@ -267,26 +267,6 @@ class EnterpriseDomainPresenterSpec: QuickSpec { } - context("single enterprise connection with auth flag set") { - - beforeEach { - connections = OfflineConnections() - connections.enterprise(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) - options.enterpriseConnectionUsingActiveAuth.append("TestAD") - - interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) - presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) - presenter.messagePresenter = messagePresenter - view = presenter.view as! EnterpriseDomainView - } - - it("should navigate to enterprise passwod presenter") { - view.authButton!.onPress(view.authButton!) - expect(navigator.route).toEventually(equal(Route.EnterpriseActiveAuth(connection: presenter.interactor.connection!))) - } - - } - } describe("auth buttons") { From 5d91c47caea395417b7fe4f05f9bf5cc041d8675 Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Tue, 22 Nov 2016 21:51:39 +0000 Subject: [PATCH 6/7] Removed redundant code --- Lock/EnterpriseDomainPresenter.swift | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Lock/EnterpriseDomainPresenter.swift b/Lock/EnterpriseDomainPresenter.swift index 8c8333d26..ec309095c 100644 --- a/Lock/EnterpriseDomainPresenter.swift +++ b/Lock/EnterpriseDomainPresenter.swift @@ -120,17 +120,6 @@ class EnterpriseDomainPresenter: Presentable, Loggable { return view } - func authModeSwitch() -> Bool { - // Check for credential auth - if let connection = self.interactor.connection { - if self.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { - self.navigator?.navigate(.EnterpriseActiveAuth(connection: connection)) - return true - } - } - return false - } - } func EnterpriseButton(forConnections connections: [EnterpriseConnection], customStyle: [String: AuthStyle], isLogin login: Bool, onAction: () -> () ) -> AuthButton? { From 93057a5ab33189cb9db83bf3fc48aab4ea2dfb5a Mon Sep 17 00:00:00 2001 From: Martin Walsh Date: Thu, 24 Nov 2016 10:27:49 +0000 Subject: [PATCH 7/7] EnterpriseConnection style optional Customised login/signup titles --- Lock/AuthCollectionView.swift | 2 +- Lock/AuthStyle.swift | 10 +++++----- Lock/Connections.swift | 6 ++++++ Lock/EnterpriseDomainPresenter.swift | 3 +-- LockTests/Models/AuthStyleSpec.swift | 6 +++--- .../Presenters/EnterpriseActiveAuthPresenterSpec.swift | 2 +- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Lock/AuthCollectionView.swift b/Lock/AuthCollectionView.swift index ff6122f9f..517721ab5 100644 --- a/Lock/AuthCollectionView.swift +++ b/Lock/AuthCollectionView.swift @@ -145,7 +145,7 @@ func oauth2Buttons(forConnections connections: [OAuth2Connection], customStyle: return connections.map { connection -> AuthButton in let style = customStyle[connection.name] ?? connection.style let button = AuthButton(size: .Big) - button.title = login ? style.localizedLoginTitle.uppercaseString : style.localizedSignUpTitle.uppercaseString + button.title = login ? style.localizedLoginTitle().uppercaseString : style.localizedSignUpTitle().uppercaseString button.normalColor = style.normalColor button.highlightedColor = style.highlightedColor button.titleColor = style.foregroundColor diff --git a/Lock/AuthStyle.swift b/Lock/AuthStyle.swift index 0f66226d0..2e39d68c6 100644 --- a/Lock/AuthStyle.swift +++ b/Lock/AuthStyle.swift @@ -26,20 +26,20 @@ import UIKit public class AuthStyle { /// Name that will be used for titles. e.g. 'Login with Auth0' - public var name: String + let name: String let image: LazyImage let foregroundColor: UIColor let normalColor: UIColor let highlightedColor: UIColor - var localizedLoginTitle: String { + func localizedLoginTitle(title: String? = nil) -> String { let format = "Log in with %@".i18n(key: "com.auth0.lock.strategy.login.title", comment: "Log in action format") - return String(format: format, self.name) + return String(format: format, title ?? self.name) } - var localizedSignUpTitle: String { + func localizedSignUpTitle(title: String? = nil) -> String { let format = "Sign up with %@".i18n(key: "com.auth0.lock.strategy.signup.title", comment: "Sign up action format") - return String(format: format, self.name) + return String(format: format, title ?? self.name) } /** diff --git a/Lock/Connections.swift b/Lock/Connections.swift index 6ad126f2e..338c58ef4 100644 --- a/Lock/Connections.swift +++ b/Lock/Connections.swift @@ -65,4 +65,10 @@ public struct EnterpriseConnection : OAuth2Connection { public let name: String public let domains: [String] public let style: AuthStyle + + init(name: String, domains: [String], style: AuthStyle? = nil) { + self.name = name + self.domains = domains + self.style = style ?? AuthStyle(name: name) + } } diff --git a/Lock/EnterpriseDomainPresenter.swift b/Lock/EnterpriseDomainPresenter.swift index ec309095c..daf73c709 100644 --- a/Lock/EnterpriseDomainPresenter.swift +++ b/Lock/EnterpriseDomainPresenter.swift @@ -125,9 +125,8 @@ class EnterpriseDomainPresenter: Presentable, Loggable { func EnterpriseButton(forConnections connections: [EnterpriseConnection], customStyle: [String: AuthStyle], isLogin login: Bool, onAction: () -> () ) -> AuthButton? { guard let connection = connections.first where connections.count == 1 else { return nil } let style = customStyle[connection.name] ?? connection.style - style.name = connection.domains.first! let button = AuthButton(size: .Big) - button.title = login ? style.localizedLoginTitle.uppercaseString : style.localizedSignUpTitle.uppercaseString + button.title = style.localizedLoginTitle(connection.domains.first).uppercaseString button.normalColor = style.normalColor button.highlightedColor = style.highlightedColor button.titleColor = style.foregroundColor diff --git a/LockTests/Models/AuthStyleSpec.swift b/LockTests/Models/AuthStyleSpec.swift index 1c56234e0..54de7582b 100644 --- a/LockTests/Models/AuthStyleSpec.swift +++ b/LockTests/Models/AuthStyleSpec.swift @@ -102,12 +102,12 @@ class AuthStyleSpec: QuickSpec { it("should provide login title") { let strategy = AuthStyle(name: "facebook") - expect(strategy.localizedLoginTitle) == "Log in with facebook" + expect(strategy.localizedLoginTitle()) == "Log in with facebook" } it("should provide signup title") { let strategy = AuthStyle(name: "facebook") - expect(strategy.localizedSignUpTitle) == "Sign up with facebook" + expect(strategy.localizedSignUpTitle()) == "Sign up with facebook" } } @@ -217,4 +217,4 @@ extension AuthStyle: Equatable, CustomStringConvertible { public func ==(lhs: AuthStyle, rhs: AuthStyle) -> Bool { return lhs.name == rhs.name && lhs.normalColor == rhs.normalColor && lhs.highlightedColor == rhs.highlightedColor && lhs.foregroundColor == rhs.foregroundColor && lhs.image.name == rhs.image.name -} \ No newline at end of file +} diff --git a/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift b/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift index 7cda28650..abb59c5b1 100644 --- a/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseActiveAuthPresenterSpec.swift @@ -43,7 +43,7 @@ class EnterpriseActiveAuthPresenterSpec: QuickSpec { options = LockOptions() user = User() messagePresenter = MockMessagePresenter() - connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"], style: AuthStyle(name: "ad")) + connection = EnterpriseConnection(name: "TestAD", domains: ["test.com"]) interactor = EnterpriseActiveAuthInteractor(connection: connection, authentication: authentication, user: user, options: options, callback: {_ in}) presenter = EnterpriseActiveAuthPresenter(interactor: interactor) presenter.messagePresenter = messagePresenter