Skip to content

Commit

Permalink
Launch signup using magic link when account is not found
Browse files Browse the repository at this point in the history
  • Loading branch information
hichamboushaba committed Nov 15, 2024
1 parent b80ceb7 commit c558367
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct WPComEmailLoginView_Previews: PreviewProvider {
static var previews: some View {
WPComEmailLoginView(viewModel: .init(siteURL: "https://example.com",
requiresConnectionOnly: true,
allowAccountCreation: false,
onPasswordUIRequest: { _ in },
onMagicLinkUIRequest: { _ in },
onError: { _ in }))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Combine
import UIKit
import WordPressAuthenticator
import protocol WooFoundation.Analytics
import enum WordPressKit.WordPressAPIError
import struct WordPressKit.WordPressComRestApiEndpointError

/// A protocol used to mock `WordPressComAccountService` for unit tests.
protocol WordPressComAccountServiceProtocol {
Expand All @@ -21,6 +23,7 @@ final class WPComEmailLoginViewModel: ObservableObject {

let termsAttributedString: NSAttributedString

private let allowAccountCreation: Bool
private let accountService: WordPressComAccountServiceProtocol
private let analytics: Analytics
private let onPasswordUIRequest: (String) -> Void
Expand All @@ -31,12 +34,14 @@ final class WPComEmailLoginViewModel: ObservableObject {

init(siteURL: String,
requiresConnectionOnly: Bool,
allowAccountCreation: Bool,
debounceDuration: Double = Constants.fieldDebounceDuration,
accountService: WordPressComAccountServiceProtocol = WordPressComAccountService(),
analytics: Analytics = ServiceLocator.analytics,
onPasswordUIRequest: @escaping (String) -> Void,
onMagicLinkUIRequest: @escaping (String) -> Void,
onError: @escaping (String) -> Void) {
self.allowAccountCreation = allowAccountCreation
self.analytics = analytics
self.accountService = accountService
self.onPasswordUIRequest = onPasswordUIRequest
Expand Down Expand Up @@ -78,8 +83,16 @@ final class WPComEmailLoginViewModel: ObservableObject {
}
await startAuthentication(email: email, isPasswordlessAccount: passwordless)
} catch {
analytics.track(event: .JetpackSetup.loginFlow(step: .emailAddress, failure: error))
onError(error.localizedDescription)
if allowAccountCreation,
let apiError = error as? WordPressAPIError<WordPressComRestApiEndpointError>,
case let .endpointError(endpointError) = apiError,
endpointError.apiErrorCode == Constants.unknownUserErrorCode {
// The user does not exist yet, trigger magic link flow for account creation
await requestAuthenticationLink(email: email, forAccountCreation: true)
} else {
analytics.track(event: .JetpackSetup.loginFlow(step: .emailAddress, failure: error))
onError(error.localizedDescription)
}
}
}

Expand All @@ -93,12 +106,12 @@ final class WPComEmailLoginViewModel: ObservableObject {
}

@MainActor
func requestAuthenticationLink(email: String) async {
func requestAuthenticationLink(email: String, forAccountCreation: Bool = false) async {
do {
try await withCheckedThrowingContinuation { continuation in
accountService.requestAuthenticationLink(for: email,
jetpackLogin: false,
createAccountIfNotFound: false,
createAccountIfNotFound: forAccountCreation,
success: {
continuation.resume()
}, failure: { error in
Expand All @@ -119,6 +132,7 @@ extension WPComEmailLoginViewModel {
static let jetpackTermsURL = "https://jetpack.com/redirect/?source=wpcom-tos&site="
static let jetpackShareDetailsURL = "https://jetpack.com/redirect/?source=jetpack-support-what-data-does-jetpack-sync&site="
static let wpcomErrorCodeKey = "WordPressComRestApiErrorCodeKey"
static let unknownUserErrorCode = "unknown_user"
}

enum Localization {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import UIKit
import Experiments
import Yosemite
import enum Networking.NetworkError
import class Networking.AlamofireNetwork
Expand All @@ -16,6 +17,7 @@ final class JetpackSetupCoordinator {
private var jetpackConnectedEmail: String?
private let stores: StoresManager
private let analytics: Analytics
private let featureFlagService: FeatureFlagService
private let dotcomAuthScheme: String

private var loginNavigationController: LoginNavigationController?
Expand All @@ -24,6 +26,7 @@ final class JetpackSetupCoordinator {
private lazy var emailLoginViewModel: WPComEmailLoginViewModel = {
.init(siteURL: site.url,
requiresConnectionOnly: requiresConnectionOnly,
allowAccountCreation: featureFlagService.isFeatureFlagEnabled(.jetpackSetupWPComAccountCreation),
onPasswordUIRequest: showPasswordUI(email:),
onMagicLinkUIRequest: showMagicLinkUI(email:),
onError: { [weak self] message in
Expand All @@ -40,13 +43,15 @@ final class JetpackSetupCoordinator {
dotcomAuthScheme: String = ApiCredentials.dotcomAuthScheme,
rootViewController: UIViewController,
stores: StoresManager = ServiceLocator.stores,
analytics: Analytics = ServiceLocator.analytics) {
analytics: Analytics = ServiceLocator.analytics,
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService) {
self.site = site
self.dotcomAuthScheme = dotcomAuthScheme
self.requiresConnectionOnly = false // to be updated later after fetching Jetpack status
self.rootViewController = rootViewController
self.stores = stores
self.analytics = analytics
self.featureFlagService = featureFlagService

/// the authenticator needs to be initialized with configs
/// to be used for requesting authentication link and handle login later.
Expand Down

0 comments on commit c558367

Please sign in to comment.