diff --git a/Podfile b/Podfile index ce44697cf..33e731c73 100644 --- a/Podfile +++ b/Podfile @@ -12,7 +12,7 @@ def wordpress_authenticator_pods ## pod 'Gridicons', '~> 0.15' pod 'WordPressUI', '~> 1.3' - pod 'WordPressKit', '~> 4.5.0-beta.1' + pod 'WordPressKit', '~> 4.5.0-beta.2' pod 'WordPressShared', '~> 1.8' ## Third party libraries diff --git a/Podfile.lock b/Podfile.lock index 83d1b3cf2..50e7bcc97 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -44,7 +44,7 @@ PODS: - Specta (1.0.7) - SVProgressHUD (2.2.5) - UIDeviceIdentifier (1.1.4) - - WordPressKit (4.5.0-beta.1): + - WordPressKit (4.5.0-beta.2): - Alamofire (~> 4.7.3) - CocoaLumberjack (~> 3.4) - NSObject-SafeExpectations (= 0.0.3) @@ -71,7 +71,7 @@ DEPENDENCIES: - OHHTTPStubs/Swift (= 8.0.0) - Specta (= 1.0.7) - SVProgressHUD (= 2.2.5) - - WordPressKit (~> 4.5.0-beta.1) + - WordPressKit (~> 4.5.0-beta.2) - WordPressShared (~> 1.8) - WordPressUI (~> 1.3) @@ -117,11 +117,11 @@ SPEC CHECKSUMS: Specta: 3e1bd89c3517421982dc4d1c992503e48bd5fe66 SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6 UIDeviceIdentifier: 8f8a24b257a4d978c8d40ad1e7355b944ffbfa8c - WordPressKit: bfb5e77a32e66b19ee304bdffd5b7128a7fe4ede + WordPressKit: 6fb3101e9542398c895517d64ac435d3a4e83e25 WordPressShared: 34f7a1386d28d7e4650c1a225c554ee024401ca3 WordPressUI: 0ea6df25bf6e63f0619376fa23870177cb37646f wpxmlrpc: 6ba55c773cfa27083ae4a2173e69b19f46da98e2 -PODFILE CHECKSUM: e2a10fcbbc81f9e30af60797f89b8315a6819211 +PODFILE CHECKSUM: 066779a8741fbd6f8205a5d3469e19c8c80682b7 COCOAPODS: 1.6.1 diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 81b57b7e6..5730ef8de 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.8.0-beta.6" + s.version = "1.8.0-beta.7" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC @@ -39,6 +39,6 @@ Pod::Spec.new do |s| s.dependency 'Gridicons', '~> 0.15' s.dependency 'GoogleSignIn', '~> 4.4' s.dependency 'WordPressUI', '~> 1.3' - s.dependency 'WordPressKit', '~> 4.5.0-beta.1' + s.dependency 'WordPressKit', '~> 4.5.0-beta.2' s.dependency 'WordPressShared', '~> 1.8' end diff --git a/WordPressAuthenticator/Model/LoginFields.swift b/WordPressAuthenticator/Model/LoginFields.swift index d373ca0c2..c269723bf 100644 --- a/WordPressAuthenticator/Model/LoginFields.swift +++ b/WordPressAuthenticator/Model/LoginFields.swift @@ -116,4 +116,6 @@ public class LoginFieldsMeta: NSObject { @objc public var socialServiceIDToken: String? var googleUser: GIDGoogleUser? + + var appleUser: AppleUser? } diff --git a/WordPressAuthenticator/Services/SocialService.swift b/WordPressAuthenticator/Services/SocialService.swift index ff9c1ebde..fee855eae 100644 --- a/WordPressAuthenticator/Services/SocialService.swift +++ b/WordPressAuthenticator/Services/SocialService.swift @@ -7,4 +7,14 @@ public enum SocialService { /// Google's Signup Linked Account /// case google(user: GIDGoogleUser) + + /// Apple's Signup Linked Account + /// + case apple(user: AppleUser) +} + +// Struct to contain information relevant to an Apple ID account. +public struct AppleUser { + public var email: String + public var fullName: String } diff --git a/WordPressAuthenticator/Services/WordPressComAccountService.swift b/WordPressAuthenticator/Services/WordPressComAccountService.swift index 5996f28a5..470724ed8 100644 --- a/WordPressAuthenticator/Services/WordPressComAccountService.swift +++ b/WordPressAuthenticator/Services/WordPressComAccountService.swift @@ -21,7 +21,12 @@ class WordPressComAccountService { /// Connects a WordPress.com account with the specified Social Service. /// - func connect(wpcomAuthToken: String, serviceName: SocialServiceName, serviceToken: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { + func connect(wpcomAuthToken: String, + serviceName: SocialServiceName, + serviceToken: String, + connectParameters: [String:AnyObject]? = nil, + success: @escaping () -> Void, + failure: @escaping (Error) -> Void) { let loggedAPI = WordPressComRestApi(oAuthToken: wpcomAuthToken, userAgent: configuration.userAgent, baseUrlString: configuration.wpcomAPIBaseURL) @@ -29,6 +34,7 @@ class WordPressComAccountService { remote.connectToSocialService(serviceName, serviceIDToken: serviceToken, + connectParameters: connectParameters, oAuthClientID: configuration.wpcomClientId, oAuthClientSecret: configuration.wpcomSecret, success: success, diff --git a/WordPressAuthenticator/Signin/AppleAuthenticator.swift b/WordPressAuthenticator/Signin/AppleAuthenticator.swift index 2f4bfbf4e..4db4d0875 100644 --- a/WordPressAuthenticator/Signin/AppleAuthenticator.swift +++ b/WordPressAuthenticator/Signin/AppleAuthenticator.swift @@ -1,5 +1,6 @@ import Foundation import AuthenticationServices +import WordPressKit #if XCODE11 @@ -10,10 +11,19 @@ class AppleAuthenticator: NSObject { static var sharedInstance: AppleAuthenticator = AppleAuthenticator() private override init() {} private var showFromViewController: UIViewController? + private let loginFields = LoginFields() + private var authenticationDelegate: WordPressAuthenticatorDelegate { + guard let delegate = WordPressAuthenticator.shared.delegate else { + fatalError() + } + return delegate + } + // MARK: - Start Authentication func showFrom(viewController: UIViewController) { + loginFields.meta.socialService = SocialServiceName.apple showFromViewController = viewController requestAuthorization() } @@ -47,17 +57,54 @@ private extension AppleAuthenticator { return } + let token = identityToken.base64EncodedString() + let name = fullName(from: appleCredentials.fullName) + + updateLoginFields(email: email, fullName: name, token: token) + let service = SignupService() - service.createWPComUserWithApple(token: identityToken.base64EncodedString(), - email: email, - fullName: fullName(from: appleCredentials.fullName), + service.createWPComUserWithApple(token: token, email: email, fullName: name, success: { [weak self] accountCreated, wpcomUsername, wpcomToken in - NSLog("Apple Authenticator: createWPComUserWithApple success. accountCreated: ", accountCreated) + + let wpcom = WordPressComCredentials(authToken: wpcomToken, isJetpackLogin: false, multifactor: false, siteURL: self?.loginFields.siteAddress ?? "") + let credentials = AuthenticatorCredentials(wpcom: wpcom) + + // New Account + if accountCreated { + self?.authenticationDelegate.createdWordPressComAccount(username: wpcomUsername, authToken: wpcomToken) + self?.signupSuccessful(with: credentials) + return + } + // TODO: handle Existing Account. + }, failure: { [weak self] error in - DDLogError("Apple Authenticator: createWPComUserWithApple failure. error: \(error)") + self?.signupFailed(with: error) }) } + func signupSuccessful(with credentials: AuthenticatorCredentials) { + WordPressAuthenticator.track(.createdAccount, properties: ["source": "apple"]) + WordPressAuthenticator.track(.signupSocialSuccess) + showSignupEpilogue(for: credentials) + } + + func showSignupEpilogue(for credentials: AuthenticatorCredentials) { + guard let navigationController = showFromViewController?.navigationController else { + fatalError() + } + + let service = loginFields.meta.appleUser.flatMap { + return SocialService.apple(user: $0) + } + + authenticationDelegate.presentSignupEpilogue(in: navigationController, for: credentials, service: service) + } + + func signupFailed(with error: Error) { + WPAnalytics.track(.signupSocialFailure) + DDLogError("Apple Authenticator: signup failed. error: \(error)") + } + // MARK: - Helpers func fullName(from components: PersonNameComponents?) -> String { @@ -66,6 +113,13 @@ private extension AppleAuthenticator { } return PersonNameComponentsFormatter().string(from: name) } + + func updateLoginFields(email: String, fullName: String, token: String) { + loginFields.emailAddress = email + loginFields.username = email + loginFields.meta.socialServiceIDToken = token + loginFields.meta.appleUser = AppleUser(email: email, fullName: fullName) + } } diff --git a/WordPressAuthenticator/Signin/LoginViewController.swift b/WordPressAuthenticator/Signin/LoginViewController.swift index e9a3f68e1..db7950ef9 100644 --- a/WordPressAuthenticator/Signin/LoginViewController.swift +++ b/WordPressAuthenticator/Signin/LoginViewController.swift @@ -262,22 +262,34 @@ extension LoginViewController { guard let serviceName = loginFields.meta.socialService, let serviceToken = loginFields.meta.socialServiceIDToken else { return } - - linkSocialService(serviceName: serviceName, serviceToken: serviceToken, wpcomAuthToken: wpcomAuthToken) + + let appleConnectParameters:[String:AnyObject]? = { + if let appleUser = loginFields.meta.appleUser { + return AccountServiceRemoteREST.appleSignInParameters(email: appleUser.email, fullName: appleUser.fullName) + } + return nil + }() + + linkSocialService(serviceName: serviceName, + serviceToken: serviceToken, + wpcomAuthToken: wpcomAuthToken, + appleConnectParameters: appleConnectParameters) } /// Links the current WordPress Account to a Social Service. /// - func linkSocialService(serviceName: SocialServiceName, serviceToken: String, wpcomAuthToken: String) { - guard serviceName == .google else { - DDLogError("Error: Unsupported Social Service") - return - } - + func linkSocialService(serviceName: SocialServiceName, + serviceToken: String, + wpcomAuthToken: String, + appleConnectParameters: [String:AnyObject]? = nil) { let service = WordPressComAccountService() - service.connect(wpcomAuthToken: wpcomAuthToken, serviceName: serviceName, serviceToken: serviceToken, success: { - WordPressAuthenticator.track(.loginSocialConnectSuccess) - WordPressAuthenticator.track(.loginSocialSuccess) + service.connect(wpcomAuthToken: wpcomAuthToken, + serviceName: serviceName, + serviceToken: serviceToken, + connectParameters: appleConnectParameters, + success: { + WordPressAuthenticator.track(.loginSocialConnectSuccess) + WordPressAuthenticator.track(.loginSocialSuccess) }, failure: { error in DDLogError("Social Link Error: \(error)") WordPressAuthenticator.track(.loginSocialConnectFailure, error: error)