Skip to content

Commit aa8b3bb

Browse files
authored
Consolidate sign in process in WordPressDotComAuthenticator (#23749)
* Support end-to-end sign-in in WordPressDotComAuthenticator * Use web based sign in for connecting to Jetpack * Use web based sign in flow for logging in to Jetpack site * Update user agent * Move mapping error to error message to extension functions * Update .reauthentication case
1 parent 9a23848 commit aa8b3bb

File tree

13 files changed

+514
-162
lines changed

13 files changed

+514
-162
lines changed

WordPress/Classes/Login/WordPressDotComAuthenticator.swift

Lines changed: 207 additions & 63 deletions
Large diffs are not rendered by default.

WordPress/Classes/Services/AccountService.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ extern NSNotificationName const WPAccountEmailAndDefaultBlogUpdatedNotification;
108108
success:(void (^)(WPAccount * _Nonnull))success
109109
failure:(void (^)(NSError * _Nonnull))failure;
110110

111+
- (NSManagedObjectID *)createOrUpdateAccountWithUserDetails:(RemoteUser *)remoteUser authToken:(NSString *)authToken;
112+
111113
/**
112114
Initializes the WordPress iOS Extensions with the WordPress.com Default Account.
113115
*/

WordPress/Classes/Services/WordPressComSyncService.swift

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import WordPressKit
66
///
77
class WordPressComSyncService {
88

9+
private let coreDataStack: CoreDataStackSwift
10+
11+
init(coreDataStack: CoreDataStackSwift = ContextManager.shared) {
12+
self.coreDataStack = coreDataStack
13+
}
14+
915
/// Syncs account and blog information for the authenticated wpcom user.
1016
///
1117
/// - Parameters:
@@ -15,14 +21,40 @@ class WordPressComSyncService {
1521
/// - onFailure: Closure to be executed upon failure.
1622
///
1723
func syncWPCom(authToken: String, isJetpackLogin: Bool, onSuccess: @escaping (WPAccount) -> Void, onFailure: @escaping (Error) -> Void) {
18-
let accountService = AccountService(coreDataStack: ContextManager.sharedInstance())
24+
let accountService = AccountService(coreDataStack: coreDataStack)
1925
accountService.createOrUpdateAccount(withAuthToken: authToken, success: { account in
2026
self.syncOrAssociateBlogs(account: account, isJetpackLogin: isJetpackLogin, onSuccess: onSuccess, onFailure: onFailure)
2127
}, failure: { error in
2228
onFailure(error)
2329
})
2430
}
2531

32+
@MainActor
33+
func syncWPCom(remoteUser: RemoteUser, authToken: String, isJetpackLogin: Bool) async throws -> TaggedManagedObjectID<WPAccount> {
34+
let accountService = AccountService(coreDataStack: coreDataStack)
35+
let accountID = accountService.createOrUpdateAccount(withUserDetails: remoteUser, authToken: authToken)
36+
37+
return try await withCheckedThrowingContinuation { continuation in
38+
DispatchQueue.main.async {
39+
let account: WPAccount
40+
do {
41+
let object = try self.coreDataStack.mainContext.existingObject(with: accountID)
42+
account = object as! WPAccount
43+
} catch {
44+
continuation.resume(throwing: error)
45+
return
46+
}
47+
48+
self.syncOrAssociateBlogs(
49+
account: account,
50+
isJetpackLogin: isJetpackLogin,
51+
onSuccess: { continuation.resume(returning: .init($0)) },
52+
onFailure: { continuation.resume(throwing: $0) }
53+
)
54+
}
55+
}
56+
}
57+
2658
/// Syncs or associates blogs for the specified account.
2759
///
2860
/// - Parameters:
@@ -47,7 +79,7 @@ class WordPressComSyncService {
4779
}
4880

4981
if isJetpackLogin && !account.isDefaultWordPressComAccount {
50-
let blogService = BlogService(coreDataStack: ContextManager.shared)
82+
let blogService = BlogService(coreDataStack: coreDataStack)
5183
blogService.associateSyncedBlogs(toJetpackAccount: account, success: onSuccessInternal, failure: onFailureInternal)
5284

5385
} else {

WordPress/Classes/System/Root View/SplitViewRootPresenter.swift

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ final class SplitViewRootPresenter: RootViewPresenter {
147147
showMeScreen(completion: nil)
148148
case .signIn:
149149
Task {
150-
await self.signIn()
150+
await WordPressDotComAuthenticator().signIn(from: splitVC, context: .default)
151151
}
152152
}
153153
}
@@ -180,21 +180,6 @@ final class SplitViewRootPresenter: RootViewPresenter {
180180
.showSiteCreationScreen(selection: selection)
181181
}
182182

183-
@MainActor private func signIn() async {
184-
let token: String
185-
do {
186-
token = try await WordPressDotComAuthenticator().authenticate(from: splitVC)
187-
} catch {
188-
return
189-
}
190-
191-
SVProgressHUD.show()
192-
let credentials = WordPressComCredentials(authToken: token, isJetpackLogin: false, multifactor: false)
193-
WordPressAuthenticator.shared.delegate!.sync(credentials: .init(wpcom: credentials)) {
194-
SVProgressHUD.dismiss()
195-
}
196-
}
197-
198183
private func handleCoreDataChanges(_ notification: Foundation.Notification) {
199184
// Automatically switch to a site or show the sign in screen, when the current blog is removed.
200185

WordPress/Classes/System/Root View/WordPressAuthenticatorProtocol.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ extension WordPressAuthenticator: WordPressAuthenticatorProtocol {
1414
}
1515

1616
Task { @MainActor in
17-
await WordPressDotComAuthenticator().signIn(from: navigationController)
17+
let accountID = await WordPressDotComAuthenticator().signIn(from: navigationController, context: .default)
18+
if accountID != nil {
19+
WordPressAppDelegate.shared?.presentDefaultAccountPrimarySite(from: navigationController)
20+
}
1821
}
1922

2023
return true

WordPress/Classes/System/WordPressAppDelegate.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ extension WordPressAppDelegate {
424424
self.authManager = authManager
425425
}
426426

427+
func presentDefaultAccountPrimarySite(from navigationController: UINavigationController) {
428+
self.authManager?.presentDefaultAccountPrimarySite(from: navigationController)
429+
}
430+
427431
func handleWebActivity(_ activity: NSUserActivity) {
428432
// try to handle unauthenticated routes first.
429433
if activity.activityType == NSUserActivityTypeBrowsingWeb,

WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController+SiteActions.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import UIKit
22
import SwiftUI
3-
import WordPressAuthenticator
43

54
extension HomeSiteHeaderViewController {
65

WordPress/Classes/ViewRelated/Jetpack/Install/Webview/JetpackConnectionWebViewController.swift

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class JetpackConnectionWebViewController: UIViewController {
1818
// Sometimes wp-login doesn't redirect to the expected URL, so we're storing
1919
// it and redirecting manually
2020
fileprivate var pendingSiteRedirect: URL?
21-
fileprivate var pendingDotComRedirect: URL?
2221
fileprivate var account: WPAccount?
2322

2423
private var analyticsErrorWasTracked = false
@@ -255,8 +254,18 @@ private extension JetpackConnectionWebViewController {
255254
// There could be no account in some cases where user has connected
256255
// their site to .com account on webView
257256
// without logging into the account in the app
258-
self.startObservingLoginNotifications()
259-
WordPressAuthenticator.showLoginForJustWPCom(from: self, jetpackLogin: true, connectedEmail: self.blog.jetpack?.connectedEmail)
257+
Task { @MainActor in
258+
let email = self.blog.jetpack?.connectedEmail
259+
let accountID = await WordPressDotComAuthenticator().signIn(from: self, context: .jetpackSite(accountEmail: email))
260+
if let accountID {
261+
let account = try ContextManager.shared.mainContext.existingObject(with: accountID)
262+
service.associateSyncedBlogs(
263+
toJetpackAccount: account,
264+
success: success,
265+
failure: failure
266+
)
267+
}
268+
}
260269

261270
return
262271
}
@@ -304,35 +313,14 @@ private extension JetpackConnectionWebViewController {
304313
}
305314

306315
func presentDotComLogin(redirect: URL) {
307-
pendingDotComRedirect = redirect
308-
startObservingLoginNotifications()
309-
310-
WordPressAuthenticator.showLoginForJustWPCom(from: self, jetpackLogin: true, connectedEmail: blog.jetpack?.connectedEmail)
311-
}
312-
313-
func startObservingLoginNotifications() {
314-
NotificationCenter.default.addObserver(self, selector: #selector(self.handleFinishedJetpackLogin), name: .wordpressLoginFinishedJetpackLogin, object: nil)
315-
}
316-
317-
func stopObservingLoginNotifications() {
318-
NotificationCenter.default.removeObserver(self, name: .wordpressLoginFinishedJetpackLogin, object: nil)
319-
}
320316

321-
@objc func handleLoginCancelled() {
322-
stopObservingLoginNotifications()
323-
pendingDotComRedirect = nil
324-
}
317+
Task { @MainActor in
318+
let email = self.blog.jetpack?.connectedEmail
319+
guard let _ = await WordPressDotComAuthenticator().signIn(from: self, context: .jetpackSite(accountEmail: email)) else {
320+
return
321+
}
325322

326-
@objc func handleFinishedJetpackLogin(notification: NSNotification) {
327-
stopObservingLoginNotifications()
328-
defer {
329-
pendingDotComRedirect = nil
330-
}
331-
account = notification.object as? WPAccount
332-
if let redirect = pendingDotComRedirect {
333-
performDotComLogin(redirect: redirect)
334-
} else {
335-
delegate?.jetpackConnectionCompleted()
323+
self.performDotComLogin(redirect: redirect)
336324
}
337325
}
338326

WordPress/Classes/ViewRelated/Jetpack/Login/JetpackLoginViewController.swift

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -89,31 +89,6 @@ class JetpackLoginViewController: UIViewController {
8989
jetpackImage.isHidden = collection.containsTraits(in: UITraitCollection(verticalSizeClass: .compact))
9090
}
9191

92-
fileprivate func observeLoginNotifications(_ observe: Bool) {
93-
if observe {
94-
// Observe `.handleLoginSyncedSites` instead of `WPSigninDidFinishNotification`
95-
// `WPSigninDidFinishNotification` will not be dispatched for Jetpack logins.
96-
// Switch back to `WPSigninDidFinishNotification` when the WPTabViewController
97-
// no longer destroys and recreates its view hierarchy in response to that
98-
// notification.
99-
NotificationCenter.default.addObserver(self, selector: #selector(self.handleFinishedJetpackLogin), name: .wordpressLoginFinishedJetpackLogin, object: nil)
100-
NotificationCenter.default.addObserver(self, selector: #selector(self.handleLoginCancelled), name: .wordpressLoginCancelled, object: nil)
101-
return
102-
}
103-
104-
NotificationCenter.default.removeObserver(self, name: .wordpressLoginFinishedJetpackLogin, object: nil)
105-
NotificationCenter.default.removeObserver(self, name: .wordpressLoginCancelled, object: nil)
106-
}
107-
108-
@objc fileprivate func handleLoginCancelled() {
109-
observeLoginNotifications(false)
110-
}
111-
112-
@objc fileprivate func handleFinishedJetpackLogin() {
113-
observeLoginNotifications(false)
114-
completionBlock?()
115-
}
116-
11792
// MARK: - UI Helpers
11893

11994
func updateMessageAndButton() {
@@ -178,8 +153,15 @@ class JetpackLoginViewController: UIViewController {
178153
}
179154

180155
fileprivate func signIn() {
181-
observeLoginNotifications(true)
182-
WordPressAuthenticator.showLoginForJustWPCom(from: self, jetpackLogin: true, connectedEmail: blog.jetpack?.connectedEmail)
156+
Task { @MainActor [weak self] in
157+
guard let self = self else { return }
158+
159+
let email = self.blog.jetpack?.connectedEmail
160+
let accountID = await WordPressDotComAuthenticator().signIn(from: self, context: .jetpackSite(accountEmail: email))
161+
if accountID != nil {
162+
self.completionBlock?()
163+
}
164+
}
183165
}
184166

185167
fileprivate func trackStat(_ stat: WPAnalyticsStat, blog: Blog? = nil) {

WordPress/Classes/ViewRelated/Me/Me Main/MeViewController.swift

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -524,19 +524,8 @@ class MeViewController: UITableViewController {
524524
/// into a self-hosted site the ability to create a WordPress.com account.
525525
///
526526
fileprivate func promptForLoginOrSignup() {
527-
Task { @MainActor in
528-
let token: String
529-
do {
530-
token = try await WordPressDotComAuthenticator().authenticate(from: self)
531-
} catch {
532-
return
533-
}
534-
535-
SVProgressHUD.show()
536-
let credentials = WordPressComCredentials(authToken: token, isJetpackLogin: false, multifactor: false)
537-
WordPressAuthenticator.shared.delegate!.sync(credentials: .init(wpcom: credentials)) {
538-
SVProgressHUD.dismiss()
539-
}
527+
Task {
528+
await WordPressDotComAuthenticator().signIn(from: self, context: .default)
540529
}
541530
}
542531

0 commit comments

Comments
 (0)