From 7e1ae2b369783000981a2198b5f0015cd5f1dc07 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 28 Mar 2023 21:11:00 +1100 Subject: [PATCH 1/4] Replace `GIDGoogleUser` with `SocialService.User` in `case .google` --- .../project.pbxproj | 4 ++ .../Model/LoginFields.swift | 4 +- .../Services/SocialService.swift | 2 +- .../Signin/LoginViewController.swift | 19 ++++++--- .../Unified Auth/GoogleAuthenticator.swift | 13 +++--- .../SingIn/LoginViewControllerTests.swift | 40 +++++++++++++++++++ 6 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift diff --git a/WordPressAuthenticator.xcodeproj/project.pbxproj b/WordPressAuthenticator.xcodeproj/project.pbxproj index 008796e86..9e1f057b8 100644 --- a/WordPressAuthenticator.xcodeproj/project.pbxproj +++ b/WordPressAuthenticator.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 3F86A84229D28473005D20C0 /* SocialUserCreating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84129D28473005D20C0 /* SocialUserCreating.swift */; }; 3F86A84629D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84529D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift */; }; 3F86A84829D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84729D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift */; }; + 3F86A84A29D2A982005D20C0 /* LoginViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84929D2A982005D20C0 /* LoginViewControllerTests.swift */; }; 3F879FD5293A3AB6005C2B48 /* OAuthTokenRequestBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD4293A3AB6005C2B48 /* OAuthTokenRequestBody.swift */; }; 3F879FD7293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD6293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift */; }; 3F879FD9293A48B2005C2B48 /* OAuthTokenResponseBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD8293A48B2005C2B48 /* OAuthTokenResponseBody.swift */; }; @@ -292,6 +293,7 @@ 3F86A84129D28473005D20C0 /* SocialUserCreating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialUserCreating.swift; sourceTree = ""; }; 3F86A84529D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressAuthenticatorDelegateSpy.swift; sourceTree = ""; }; 3F86A84729D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressAuthenticator+TestsUtils.swift"; sourceTree = ""; }; + 3F86A84929D2A982005D20C0 /* LoginViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewControllerTests.swift; sourceTree = ""; }; 3F879FD4293A3AB6005C2B48 /* OAuthTokenRequestBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenRequestBody.swift; sourceTree = ""; }; 3F879FD6293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenRequestBodyTests.swift; sourceTree = ""; }; 3F879FD8293A48B2005C2B48 /* OAuthTokenResponseBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenResponseBody.swift; sourceTree = ""; }; @@ -557,6 +559,7 @@ isa = PBXGroup; children = ( 3F86A83D29D280D7005D20C0 /* AppleAuthenticatorTests.swift */, + 3F86A84929D2A982005D20C0 /* LoginViewControllerTests.swift */, ); path = SingIn; sourceTree = ""; @@ -1569,6 +1572,7 @@ 3FEC44F9293A0F2900EBDECF /* ProofKeyForCodeExchangeTests.swift in Sources */, 3F107B0529A87AF0009B3658 /* CodeVerifier+Fixture.swift in Sources */, CE16177821B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift in Sources */, + 3F86A84A29D2A982005D20C0 /* LoginViewControllerTests.swift in Sources */, 3F86A84829D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift in Sources */, 3F879FF4293A7F46005C2B48 /* GoogleOAuthTokenGetterTests.swift in Sources */, B501C048208FC79C00D1E58F /* LoginFacadeTests.m in Sources */, diff --git a/WordPressAuthenticator/Model/LoginFields.swift b/WordPressAuthenticator/Model/LoginFields.swift index 58ba9acad..ed2919434 100644 --- a/WordPressAuthenticator/Model/LoginFields.swift +++ b/WordPressAuthenticator/Model/LoginFields.swift @@ -152,7 +152,7 @@ public class LoginFieldsMeta: NSObject { @objc public var socialServiceIDToken: String? - var googleUser: GIDGoogleUser? + var googleUser: SocialService.User? var appleUser: SocialService.User? @@ -165,7 +165,7 @@ public class LoginFieldsMeta: NSObject { requiredMultifactor: Bool = false, socialService: SocialServiceName? = nil, socialServiceIDToken: String? = nil, - googleUser: GIDGoogleUser? = nil, + googleUser: SocialService.User? = nil, appleUser: SocialService.User? = nil) { self.emailMagicLinkSource = emailMagicLinkSource self.jetpackLogin = jetpackLogin diff --git a/WordPressAuthenticator/Services/SocialService.swift b/WordPressAuthenticator/Services/SocialService.swift index 74ca480db..aaca9458c 100644 --- a/WordPressAuthenticator/Services/SocialService.swift +++ b/WordPressAuthenticator/Services/SocialService.swift @@ -11,7 +11,7 @@ public enum SocialService { /// Google's Signup Linked Account /// - case google(user: GIDGoogleUser) + case google(user: User) /// Apple's Signup Linked Account /// diff --git a/WordPressAuthenticator/Signin/LoginViewController.swift b/WordPressAuthenticator/Signin/LoginViewController.swift index 60c47dcc3..3fa9465fe 100644 --- a/WordPressAuthenticator/Signin/LoginViewController.swift +++ b/WordPressAuthenticator/Signin/LoginViewController.swift @@ -132,8 +132,8 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { fatalError() } - let service = loginFields.meta.googleUser.flatMap { - return SocialService.google(user: $0) + let service: SocialService? = loginFields.meta.googleUser.map { + SocialService.google(user: $0) } authenticationDelegate.presentSignupEpilogue(in: navigationController, for: credentials, service: service) @@ -425,10 +425,19 @@ extension LoginViewController { /// Updates the LoginFields structure, with the specified Google User + Token + Email. /// func updateLoginFields(googleUser: GIDGoogleUser, googleToken: String, googleEmail: String) { - loginFields.emailAddress = googleEmail - loginFields.username = googleEmail + updateLoginFields( + email: googleEmail, + username: googleEmail, + fullName: googleUser.profile?.name ?? "", + googleToken: googleToken + ) + } + + func updateLoginFields(email: String, username: String, fullName: String, googleToken: String) { + loginFields.emailAddress = email + loginFields.username = email loginFields.meta.socialServiceIDToken = googleToken - loginFields.meta.googleUser = googleUser + loginFields.meta.googleUser = SocialService.User(email: email, fullName: fullName) } // Used by SIWA when logging with with a passwordless, 2FA account. diff --git a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift index 11a3505bc..f74499374 100644 --- a/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift +++ b/WordPressAuthenticator/Unified Auth/GoogleAuthenticator.swift @@ -145,7 +145,7 @@ class GoogleAuthenticator: NSObject { loginFields: loginFields ) - didSignIn(token: token.token.rawValue, email: token.email) + didSignIn(token: token.token.rawValue, email: token.email, fullName: token.name) } catch { failedToSignIn(error: error) } @@ -216,15 +216,13 @@ private extension GoogleAuthenticator { // Get account information guard let user = user, let token = user.authentication.idToken, - let email = user.profile?.email else { + let email = user.profile?.email, + let fullName = user.profile?.name else { failedToSignIn(error: error) return } - // Set `googleUser` here, `didSignIn(token:, email:)` will do the rest. - loginFields.meta.googleUser = user - - didSignIn(token: token, email: email) + didSignIn(token: token, email: email, fullName: fullName) } private func failedToSignIn(error: Error?) { @@ -251,11 +249,12 @@ private extension GoogleAuthenticator { delegate?.googleAuthCancelled() } - private func didSignIn(token: String, email: String) { + private func didSignIn(token: String, email: String, fullName: String) { // Save account information to pass back to delegate later. loginFields.emailAddress = email loginFields.username = email loginFields.meta.socialServiceIDToken = token + loginFields.meta.googleUser = SocialService.User(email: email, fullName: fullName) guard authConfig.enableUnifiedAuth else { // Initiate separate WP login / signup paths. diff --git a/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift b/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift new file mode 100644 index 000000000..193c12fea --- /dev/null +++ b/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift @@ -0,0 +1,40 @@ +@testable import WordPressAuthenticator +import XCTest + +class LoginViewControllerTests: XCTestCase { + + // showSignupEpilogue with loginFields.meta.appleUser set will pass SocialService.apple to + // the delegate + func testShowingSignupEpilogueWithGoogleUser() throws { + WordPressAuthenticator.initializeForTesting() + let delegateSpy = WordPressAuthenticatorDelegateSpy() + WordPressAuthenticator.shared.delegate = delegateSpy + + // This might be unnecessary because delegateSpy should be deallocated once the test method finished. + // Leaving it here, just in case. + addTeardownBlock { + WordPressAuthenticator.shared.delegate = nil + } + + let sut = LoginViewController() + // We need to embed the SUT in a navigation controller because it expects its + // navigationController property to not be nil. + _ = UINavigationController(rootViewController: sut) + + sut.updateLoginFields( + email: "test@email.com", + username: "username", + fullName: "Full Name", + googleToken: "abcd" + ) + + sut.showSignupEpilogue(for: AuthenticatorCredentials()) + + let socialService = try XCTUnwrap(delegateSpy.socialService) + guard case .google(let user) = socialService else { + return XCTFail("Expected Google social service, got \(socialService) instead") + } + XCTAssertEqual(user.fullName, "Full Name") + XCTAssertEqual(user.email, "test@email.com") + } +} From 682c20fb1a716d29a75f6033d7bc3474340c0cac Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 29 Mar 2023 11:15:17 +1100 Subject: [PATCH 2/4] Expose `SocialService.User` convenience computed `var` in `SocialService` --- .../project.pbxproj | 4 ++++ .../Services/SocialService.swift | 7 +++++++ .../Services/SocialServiceTests.swift | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 WordPressAuthenticatorTests/Services/SocialServiceTests.swift diff --git a/WordPressAuthenticator.xcodeproj/project.pbxproj b/WordPressAuthenticator.xcodeproj/project.pbxproj index 9e1f057b8..cb4ade146 100644 --- a/WordPressAuthenticator.xcodeproj/project.pbxproj +++ b/WordPressAuthenticator.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ 3F86A84629D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84529D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift */; }; 3F86A84829D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84729D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift */; }; 3F86A84A29D2A982005D20C0 /* LoginViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84929D2A982005D20C0 /* LoginViewControllerTests.swift */; }; + 3F86A84E29D3B53D005D20C0 /* SocialServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F86A84D29D3B53D005D20C0 /* SocialServiceTests.swift */; }; 3F879FD5293A3AB6005C2B48 /* OAuthTokenRequestBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD4293A3AB6005C2B48 /* OAuthTokenRequestBody.swift */; }; 3F879FD7293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD6293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift */; }; 3F879FD9293A48B2005C2B48 /* OAuthTokenResponseBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F879FD8293A48B2005C2B48 /* OAuthTokenResponseBody.swift */; }; @@ -294,6 +295,7 @@ 3F86A84529D2A306005D20C0 /* WordPressAuthenticatorDelegateSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressAuthenticatorDelegateSpy.swift; sourceTree = ""; }; 3F86A84729D2A42D005D20C0 /* WordPressAuthenticator+TestsUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressAuthenticator+TestsUtils.swift"; sourceTree = ""; }; 3F86A84929D2A982005D20C0 /* LoginViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewControllerTests.swift; sourceTree = ""; }; + 3F86A84D29D3B53D005D20C0 /* SocialServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialServiceTests.swift; sourceTree = ""; }; 3F879FD4293A3AB6005C2B48 /* OAuthTokenRequestBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenRequestBody.swift; sourceTree = ""; }; 3F879FD6293A44F2005C2B48 /* OAuthTokenRequestBodyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenRequestBodyTests.swift; sourceTree = ""; }; 3F879FD8293A48B2005C2B48 /* OAuthTokenResponseBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenResponseBody.swift; sourceTree = ""; }; @@ -717,6 +719,7 @@ isa = PBXGroup; children = ( B501C040208FC52500D1E58F /* LoginFacadeTests.m */, + 3F86A84D29D3B53D005D20C0 /* SocialServiceTests.swift */, ); path = Services; sourceTree = ""; @@ -1549,6 +1552,7 @@ buildActionMask = 2147483647; files = ( 3F4E64782990BBD4000DB555 /* IDTokenTests.swift in Sources */, + 3F86A84E29D3B53D005D20C0 /* SocialServiceTests.swift in Sources */, 3F879FDB293A49AA005C2B48 /* NewGoogleAuthenticatorTests.swift in Sources */, F18DF0E5252500A600D83AFE /* WordPressAuthenticatorTests-Bridging-Header.h in Sources */, 3FE8071529364C410088420C /* Result+ConvenienceInitTests.swift in Sources */, diff --git a/WordPressAuthenticator/Services/SocialService.swift b/WordPressAuthenticator/Services/SocialService.swift index aaca9458c..0cf21de5d 100644 --- a/WordPressAuthenticator/Services/SocialService.swift +++ b/WordPressAuthenticator/Services/SocialService.swift @@ -9,6 +9,13 @@ public enum SocialService { public let fullName: String } + public var user: User { + switch self { + case .google(let user): return user + case .apple(let user): return user + } + } + /// Google's Signup Linked Account /// case google(user: User) diff --git a/WordPressAuthenticatorTests/Services/SocialServiceTests.swift b/WordPressAuthenticatorTests/Services/SocialServiceTests.swift new file mode 100644 index 000000000..85ff0bb96 --- /dev/null +++ b/WordPressAuthenticatorTests/Services/SocialServiceTests.swift @@ -0,0 +1,19 @@ +@testable import WordPressAuthenticator +import XCTest + +class SocialServiceTests: XCTestCase { + + func testSocialServiceUserApple() throws { + let socialService = SocialService.apple(user: .init(email: "test@email.com", fullName: "Full Name")) + + XCTAssertEqual(socialService.user.fullName, "Full Name") + XCTAssertEqual(socialService.user.email, "test@email.com") + } + + func testSocialServiceUserGoogle() throws { + let socialService = SocialService.google(user: .init(email: "email@test.com", fullName: "Name Full")) + + XCTAssertEqual(socialService.user.fullName, "Name Full") + XCTAssertEqual(socialService.user.email, "email@test.com") + } +} From a78ed0deb485f60606fdc3cb93716af34975e0a7 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 29 Mar 2023 22:20:05 +1100 Subject: [PATCH 3/4] Add changelog entry for #764 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa575578..e310b6938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ _None._ ### Breaking Changes - `SocialService` `apple` associated type is now `User` instead of `AppleUser`. [#763] +- `SocialService` `google` associated type is now `User` instead of `GIDGoogleUser`. [#764] ### New Features From 53669e0f1388b8ed1f7b23dfd9e6c662e067dfe5 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Sun, 2 Apr 2023 21:28:48 +1000 Subject: [PATCH 4/4] Remove unused `updateLoginFields` methods from `LoginViewController` --- .../Signin/LoginViewController.swift | 18 ------------------ .../SingIn/LoginViewControllerTests.swift | 7 +------ 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/WordPressAuthenticator/Signin/LoginViewController.swift b/WordPressAuthenticator/Signin/LoginViewController.swift index 3fa9465fe..5beba9d35 100644 --- a/WordPressAuthenticator/Signin/LoginViewController.swift +++ b/WordPressAuthenticator/Signin/LoginViewController.swift @@ -422,24 +422,6 @@ extension LoginViewController { loginFacade.loginToWordPressDotCom(withSocialIDToken: token, service: SocialServiceName.apple.rawValue) } - /// Updates the LoginFields structure, with the specified Google User + Token + Email. - /// - func updateLoginFields(googleUser: GIDGoogleUser, googleToken: String, googleEmail: String) { - updateLoginFields( - email: googleEmail, - username: googleEmail, - fullName: googleUser.profile?.name ?? "", - googleToken: googleToken - ) - } - - func updateLoginFields(email: String, username: String, fullName: String, googleToken: String) { - loginFields.emailAddress = email - loginFields.username = email - loginFields.meta.socialServiceIDToken = googleToken - loginFields.meta.googleUser = SocialService.User(email: email, fullName: fullName) - } - // Used by SIWA when logging with with a passwordless, 2FA account. // func socialNeedsMultifactorCode(forUserID userID: Int, andNonceInfo nonceInfo: SocialLogin2FANonceInfo) { diff --git a/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift b/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift index 193c12fea..23697fe91 100644 --- a/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift +++ b/WordPressAuthenticatorTests/SingIn/LoginViewControllerTests.swift @@ -21,12 +21,7 @@ class LoginViewControllerTests: XCTestCase { // navigationController property to not be nil. _ = UINavigationController(rootViewController: sut) - sut.updateLoginFields( - email: "test@email.com", - username: "username", - fullName: "Full Name", - googleToken: "abcd" - ) + sut.loginFields.meta.googleUser = SocialService.User(email: "test@email.com", fullName: "Full Name") sut.showSignupEpilogue(for: AuthenticatorCredentials())