From a70034267b38bab5b19c3e0da567abe26568fdd5 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 5 Nov 2025 16:21:05 +0700 Subject: [PATCH 01/12] Auto authenticate users when logged in with CIAB site --- .../Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift | 2 +- WooCommerce/Classes/Yosemite/DefaultStoresManager.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift b/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift index 3c2212c3a3a..caac43d2e30 100644 --- a/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift +++ b/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift @@ -36,7 +36,7 @@ extension CIABEligibilityChecker: CIABEligibilityCheckerProtocol { // MARK: - Site checks -private extension Site { +public extension Site { var isCIAB: Bool { return isGarden && gardenName == GardenName.commerce.rawValue } diff --git a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift index 138429ac5c0..011c8c2762e 100644 --- a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift +++ b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift @@ -381,7 +381,7 @@ class DefaultStoresManager: StoresManager { /// If the site is self-hosted and user is authenticated with WPCom, /// `AuthenticatedWebView` will attempt to authenticate and redirect to the admin page and fails. /// This should be prevented 💀⛔️ - guard site.isWordPressComStore || isAuthenticatedWithoutWPCom else { + guard site.isCIAB || site.isWordPressComStore || isAuthenticatedWithoutWPCom else { return false } return true From 0c48465b909d95698fbc1f21cf1fa3e16c32e9fe Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 5 Nov 2025 16:21:33 +0700 Subject: [PATCH 02/12] Fix issue showing site name late --- WooCommerce/Classes/Yosemite/DefaultStoresManager.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift index 011c8c2762e..06c10db55ad 100644 --- a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift +++ b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift @@ -786,6 +786,9 @@ private extension DefaultStoresManager { guard case .success(let site) = result else { return } + sessionManager.defaultSite = site + updateAndReloadWidgetInformation(with: siteID) + /// Triggers root endpoint to check if application password is available dispatch(SettingAction.retrieveSiteAPI(siteID: siteID) { [weak self] result in guard let self else { return } @@ -794,9 +797,8 @@ private extension DefaultStoresManager { let updatedSite = site.copy(applicationPasswordAvailable: siteAPI.applicationPasswordAvailable) sessionManager.defaultSite = updatedSite updateAndReloadWidgetInformation(with: siteID) - case .failure: - sessionManager.defaultSite = site - updateAndReloadWidgetInformation(with: siteID) + case .failure(let error): + DDLogError("⛔️ Cannot trigger root endpoint: \(error)") } }) } From 666a0007f9dee9e892608e91f8c466d51066db0e Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 12:23:43 +0700 Subject: [PATCH 03/12] Support authenticate admin page if SSO is enabled --- WooCommerce/Classes/Yosemite/DefaultStoresManager.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift index 06c10db55ad..cd55389f49b 100644 --- a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift +++ b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift @@ -378,10 +378,8 @@ class DefaultStoresManager: StoresManager { } func shouldAuthenticateAdminPage(for site: Site) -> Bool { - /// If the site is self-hosted and user is authenticated with WPCom, - /// `AuthenticatedWebView` will attempt to authenticate and redirect to the admin page and fails. - /// This should be prevented 💀⛔️ - guard site.isCIAB || site.isWordPressComStore || isAuthenticatedWithoutWPCom else { + /// Auto-authentication for web view works if the site has SSO or if user is authenticated with site credentials + guard site.hasSSOEnabled || isAuthenticatedWithoutWPCom else { return false } return true From f51e5c69715469a4fd5704a008f2c635366348d8 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 12:32:57 +0700 Subject: [PATCH 04/12] Auto authenticate admin page when setting up IPP --- .../InPersonPaymentsPluginNotSetup.swift | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift index 169e7e62234..4078da321fe 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift @@ -1,5 +1,6 @@ import SwiftUI import Yosemite +import WooFoundation import struct WooFoundation.ScrollableVStack struct InPersonPaymentsPluginNotSetup: View { @@ -53,7 +54,31 @@ struct InPersonPaymentsPluginNotSetup: View { tappedAnalyticEvent: learnMoreAnalyticEvent)) .padding(.vertical, 8) } - .safariSheet(url: $presentedSetupURL, onDismiss: onRefresh) + .sheet(item: $presentedSetupURL, onDismiss: onRefresh) { url in + setupWebView(url: url) + } + } + + @ViewBuilder + private func setupWebView(url: URL) -> some View { + let stores = ServiceLocator.stores + let site = stores.sessionManager.defaultSite + if let site, stores.shouldAuthenticateAdminPage(for: site) { + NavigationStack { + AuthenticatedWebView(isPresented: .constant(true), url: url) + .navigationTitle(Localization.primaryButton) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button(Localization.doneButton) { + presentedSetupURL = nil + } + } + } + } + } else { + SafariSheetView(url: url) + } } private var setupURL: URL? { @@ -88,6 +113,12 @@ private enum Localization { static let refreshButton = NSLocalizedString( "Refresh", comment: "Button to refresh the state of the in-person payments setup") + + static let doneButton = NSLocalizedString( + "inPersonPaymentsPluginNotSetup.done", + value: "Done", + comment: "Button to dismiss setup in-person payments plugin" + ) } struct InPersonPaymentsPluginNotSetup_Previews: PreviewProvider { From bff6f89301d2430de6c8e432663f43544c9bf0ef Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 12:58:46 +0700 Subject: [PATCH 05/12] Enable authentication for editing tax rates during order creation --- .../InPersonPaymentsPluginNotSetup.swift | 30 +-------------- .../Taxes/NewTaxRateSelectorView.swift | 6 ++- .../AuthenticatedWebView.swift | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift index 4078da321fe..c8e96a1c89e 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift @@ -55,29 +55,7 @@ struct InPersonPaymentsPluginNotSetup: View { .padding(.vertical, 8) } .sheet(item: $presentedSetupURL, onDismiss: onRefresh) { url in - setupWebView(url: url) - } - } - - @ViewBuilder - private func setupWebView(url: URL) -> some View { - let stores = ServiceLocator.stores - let site = stores.sessionManager.defaultSite - if let site, stores.shouldAuthenticateAdminPage(for: site) { - NavigationStack { - AuthenticatedWebView(isPresented: .constant(true), url: url) - .navigationTitle(Localization.primaryButton) - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .confirmationAction) { - Button(Localization.doneButton) { - presentedSetupURL = nil - } - } - } - } - } else { - SafariSheetView(url: url) + AuthenticatableWebView(url: url, title: Localization.primaryButton) } } @@ -113,12 +91,6 @@ private enum Localization { static let refreshButton = NSLocalizedString( "Refresh", comment: "Button to refresh the state of the in-person payments setup") - - static let doneButton = NSLocalizedString( - "inPersonPaymentsPluginNotSetup.done", - value: "Done", - comment: "Button to dismiss setup in-person payments plugin" - ) } struct InPersonPaymentsPluginNotSetup_Previews: PreviewProvider { diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/Taxes/NewTaxRateSelectorView.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/Taxes/NewTaxRateSelectorView.swift index c10a3e4e869..e25c2d2fae0 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/Taxes/NewTaxRateSelectorView.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/Taxes/NewTaxRateSelectorView.swift @@ -113,10 +113,14 @@ struct NewTaxRateSelectorView: View { } } .wooNavigationBarStyle() - .safariSheet(isPresented: $showingWPAdminWebView, url: viewModel.wpAdminTaxSettingsURL, onDismiss: { + .sheet(isPresented: $showingWPAdminWebView, onDismiss: { viewModel.onRefreshAction() onDismissWpAdminWebView() showingWPAdminWebView = false + }, content: { + if let url = viewModel.wpAdminTaxSettingsURL { + AuthenticatableWebView(url: url, title: Localization.editTaxRatesInWpAdminButtonTitle) + } }) } } diff --git a/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/AuthenticatedWebView.swift b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/AuthenticatedWebView.swift index 64d9bf10d9b..fb4b8f55ba9 100644 --- a/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/AuthenticatedWebView.swift +++ b/WooCommerce/Classes/ViewRelated/ReusableViews/SwiftUI Components/AuthenticatedWebView.swift @@ -1,5 +1,6 @@ import SwiftUI import WebKit +import WooFoundation /// A default view model for authenticated web view /// @@ -114,3 +115,40 @@ struct AuthenticatedWebView_Previews: PreviewProvider { } } #endif + +/// A web view that can be authenticated automatically if possible ╮(─▽─)╭ +struct AuthenticatableWebView: View { + let url: URL + var title: String = "" + + @Environment(\.dismiss) var dismiss + + var body: some View { + NavigationStack { + let stores = ServiceLocator.stores + let site = stores.sessionManager.defaultSite + if let site, stores.shouldAuthenticateAdminPage(for: site) { + AuthenticatedWebView(isPresented: .constant(true), url: url) + .navigationTitle(title) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button(Localization.doneButton, action: { dismiss() }) + } + } + } else { + SafariSheetView(url: url) + } + } + } +} + +private extension AuthenticatableWebView { + enum Localization { + static let doneButton = NSLocalizedString( + "authenticatableWebView.done", + value: "Done", + comment: "Button to dismiss a web view" + ) + } +} From c425f7ce7810614b2def298b0db9e5930b4e92c9 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 15:25:29 +0700 Subject: [PATCH 06/12] Use authenticatable web view for custom field --- .../ViewRelated/Custom Fields/CustomFieldsListView.swift | 8 +++++--- .../InPersonPaymentsPluginNotSetup.swift | 1 - .../ViewRelated/HubMenu/HubMenuViewModelTests.swift | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Custom Fields/CustomFieldsListView.swift b/WooCommerce/Classes/ViewRelated/Custom Fields/CustomFieldsListView.swift index 822d1b32f87..23ed0c8e27b 100644 --- a/WooCommerce/Classes/ViewRelated/Custom Fields/CustomFieldsListView.swift +++ b/WooCommerce/Classes/ViewRelated/Custom Fields/CustomFieldsListView.swift @@ -173,7 +173,7 @@ struct CustomFieldsListView: View { }) { CustomFieldRow(title: customField.key, content: customField.value.removedHTMLTags, - contentURL: nil) + contentURL: customField.valueURL) } } .listStyle(.plain) @@ -225,9 +225,11 @@ private struct CustomFieldRow: View { Text(content) .font(.footnote) .foregroundColor(Color(.textLink)) - .safariSheet(url: $displayedURL) + .sheet(item: $displayedURL) { url in + AuthenticatableWebView(url: url) + } .onTapGesture { - switch url.scheme { + switch url.scheme?.lowercased() { case "http", "https": displayedURL = url // Open in `SafariSheet` in app default: diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift index c8e96a1c89e..baa9d10c88c 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift @@ -1,7 +1,6 @@ import SwiftUI import Yosemite import WooFoundation -import struct WooFoundation.ScrollableVStack struct InPersonPaymentsPluginNotSetup: View { let plugin: CardPresentPaymentsPlugin diff --git a/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift index 70a7ffb38ad..8043a4d5e36 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift @@ -479,12 +479,12 @@ final class HubMenuViewModelTests: XCTestCase { } @MainActor - func test_shouldAuthenticateAdminPage_returns_true_when_logged_in_with_wpcom_to_wpcom_site() { + func test_shouldAuthenticateAdminPage_returns_true_when_logged_in_with_wpcom_to_sso_site() { // Given let sampleStoreURL = "https://testshop.com" let sampleAdminURL = "" let sessionManager = SessionManager.makeForTesting(authenticated: true, isWPCom: true) - let site = Site.fake().copy(url: sampleStoreURL, adminURL: sampleAdminURL, isWordPressComStore: true) + let site = Site.fake().copy(url: sampleStoreURL, adminURL: sampleAdminURL, hasSSOEnabled: true) sessionManager.defaultSite = site let stores = MockStoresManager(sessionManager: sessionManager) From bce6adcf6a81b99f98e98d17d061ba48b199fecd Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 15:48:07 +0700 Subject: [PATCH 07/12] Revert redundant changes --- .../Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift | 2 +- .../Onboarding Errors/InPersonPaymentsPluginNotSetup.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift b/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift index caac43d2e30..3c2212c3a3a 100644 --- a/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift +++ b/Modules/Sources/Yosemite/Tools/CIAB/CIABEligibilityChecker.swift @@ -36,7 +36,7 @@ extension CIABEligibilityChecker: CIABEligibilityCheckerProtocol { // MARK: - Site checks -public extension Site { +private extension Site { var isCIAB: Bool { return isGarden && gardenName == GardenName.commerce.rawValue } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift index baa9d10c88c..8e2cf5f2bfb 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/Onboarding Errors/InPersonPaymentsPluginNotSetup.swift @@ -1,6 +1,6 @@ import SwiftUI import Yosemite -import WooFoundation +import struct WooFoundation.ScrollableVStack struct InPersonPaymentsPluginNotSetup: View { let plugin: CardPresentPaymentsPlugin From bb3c1ba9d1cf31a84293509e4a79054d8311ce1d Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 16:11:56 +0700 Subject: [PATCH 08/12] Update release notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 6191fa4834a..608ae7dadc9 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -5,6 +5,7 @@ ----- - [**] We added support for collecting in-person payments (including Tap To Pay) using Stripe Payment Gateway extension in the UK. [https://github.com/woocommerce/woocommerce-ios/pull/16287] - [*] Improve card payments onboarding error handling to show network errors correctly [https://github.com/woocommerce/woocommerce-ios/pull/16304] +- [*] Authenticate the admin page automatically for sites with SSO enabled in custom fields, in-person payment setup, and editing tax rates flows. [https://github.com/woocommerce/woocommerce-ios/pull/16318] 23.6 ----- From a4197febc586650ce0314f6135525ffd1e60acfb Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 16:54:26 +0700 Subject: [PATCH 09/12] Attempt reloading without authentication when provisioning fails --- .../Authentication/AuthenticatedWebViewController.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift b/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift index c00fc5974bd..de161b8015b 100644 --- a/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift +++ b/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift @@ -321,6 +321,10 @@ extension AuthenticatedWebViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { viewModel.didFailProvisionalNavigation(with: error) activityIndicator.stopAnimating() + // attempt reloading without authentication when provisioning fails + if let url = viewModel.initialURL { + webView.load(URLRequest(url: url)) + } } } From 6cc1ad819181daf01e826aa25a48c74f1a17323f Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 18:33:53 +0700 Subject: [PATCH 10/12] Force HTTPS on site URLs to avoid ATS errors --- Modules/Sources/Networking/Model/Site.swift | 11 ++++++----- .../AuthenticatedWebViewController.swift | 4 ---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Modules/Sources/Networking/Model/Site.swift b/Modules/Sources/Networking/Model/Site.swift index 3f84389292b..95896565bc8 100644 --- a/Modules/Sources/Networking/Model/Site.swift +++ b/Modules/Sources/Networking/Model/Site.swift @@ -117,7 +117,7 @@ public struct Site: Decodable, Equatable, Hashable, GeneratedFakeable, Generated let siteID = try siteContainer.decode(Int64.self, forKey: .siteID) let name = try siteContainer.decode(String.self, forKey: .name) let description = try siteContainer.decode(String.self, forKey: .description) - let url = try siteContainer.decode(String.self, forKey: .url) + let url = Self.safeURL(try siteContainer.decode(String.self, forKey: .url)) let capabilitiesContainer = try siteContainer.nestedContainer(keyedBy: CapabilitiesKeys.self, forKey: .capabilities) let isSiteOwner = try capabilitiesContainer.decode(Bool.self, forKey: .isSiteOwner) let isAdmin = try capabilitiesContainer.decode(Bool.self, forKey: .isAdmin) @@ -130,8 +130,8 @@ public struct Site: Decodable, Equatable, Hashable, GeneratedFakeable, Generated let jetpackConnectionActivePlugins = try optionsContainer.decodeIfPresent([String].self, forKey: .jetpackConnectionActivePlugins) ?? [] let timezone = try optionsContainer.decode(String.self, forKey: .timezone) let gmtOffset = try optionsContainer.decode(Double.self, forKey: .gmtOffset) - let adminURL = try optionsContainer.decode(String.self, forKey: .adminURL) - let loginURL = try optionsContainer.decode(String.self, forKey: .loginURL) + let adminURL = Self.safeURL(try optionsContainer.decode(String.self, forKey: .adminURL)) + let loginURL = Self.safeURL(try optionsContainer.decode(String.self, forKey: .loginURL)) let frameNonce = try optionsContainer.decode(String.self, forKey: .frameNonce) let canBlaze = optionsContainer.failsafeDecodeIfPresent(booleanForKey: .canBlaze) ?? false let visibility = optionsContainer.failsafeDecodeIfPresent(SiteVisibility.self, forKey: .visibility) ?? .privateSite @@ -333,7 +333,8 @@ public enum SiteVisibility: Int, Codable, GeneratedFakeable { /// public extension Site { - private var jetpackCanonicalURL: String { + /// Force URL to use HTTPS if possible to avoid App Transport Security errors + private static func safeURL(_ url: String) -> String { guard let originalURL = URL(string: url), originalURL.scheme?.lowercased() == "http" else { @@ -360,7 +361,7 @@ public extension Site { } func toJetpackSite() -> JetpackSite { - JetpackSite(siteID: siteID, siteAddress: jetpackCanonicalURL, applicationPasswordAvailable: applicationPasswordAvailable) + JetpackSite(siteID: siteID, siteAddress: url, applicationPasswordAvailable: applicationPasswordAvailable) } } diff --git a/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift b/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift index de161b8015b..c00fc5974bd 100644 --- a/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift +++ b/WooCommerce/Classes/Authentication/AuthenticatedWebViewController.swift @@ -321,10 +321,6 @@ extension AuthenticatedWebViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { viewModel.didFailProvisionalNavigation(with: error) activityIndicator.stopAnimating() - // attempt reloading without authentication when provisioning fails - if let url = viewModel.initialURL { - webView.load(URLRequest(url: url)) - } } } From bb3ee43413260b03ca04c6a8fcbacebfc88bd5f7 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Thu, 6 Nov 2025 18:44:42 +0700 Subject: [PATCH 11/12] Update site tests --- .../Mapper/SiteListMapperTests.swift | 19 +++++++++++ .../NetworkingTests/Model/SiteTests.swift | 28 --------------- .../NetworkingTests/Responses/sites-http.json | 34 +++++++++++++++++++ .../xcschemes/WooCommerce.xcscheme | 2 +- 4 files changed, 54 insertions(+), 29 deletions(-) delete mode 100644 Modules/Tests/NetworkingTests/Model/SiteTests.swift create mode 100644 Modules/Tests/NetworkingTests/Responses/sites-http.json diff --git a/Modules/Tests/NetworkingTests/Mapper/SiteListMapperTests.swift b/Modules/Tests/NetworkingTests/Mapper/SiteListMapperTests.swift index 38dbb33a420..f77de97bb2d 100644 --- a/Modules/Tests/NetworkingTests/Mapper/SiteListMapperTests.swift +++ b/Modules/Tests/NetworkingTests/Mapper/SiteListMapperTests.swift @@ -37,6 +37,21 @@ final class SiteListMapperTests: XCTestCase { let second = try XCTUnwrap(sites[safe: 1]) XCTAssertFalse(second.hasSSOEnabled) } + + func test_http_urls_are_converted_to_https() throws { + // Given + let sites = mapLoadHTTPSiteListResponse() + + // Then + let site = try XCTUnwrap(sites.first) + XCTAssertTrue(site.url.hasPrefix("https://"), "Site URL should be converted to HTTPS") + XCTAssertTrue(site.adminURL.hasPrefix("https://"), "Admin URL should be converted to HTTPS") + XCTAssertTrue(site.loginURL.hasPrefix("https://"), "Login URL should be converted to HTTPS") + + XCTAssertEqual(site.url, "https://insecure-site.testing.blog") + XCTAssertEqual(site.adminURL, "https://insecure-site.testing.blog/wp-admin/") + XCTAssertEqual(site.loginURL, "https://insecure-site.testing.blog/wp-login.php") + } } private extension SiteListMapperTests { @@ -55,4 +70,8 @@ private extension SiteListMapperTests { func mapLoadMalformedSiteListResponse() -> [Site] { return mapSiteListData(from: "sites-malformed") } + + func mapLoadHTTPSiteListResponse() -> [Site] { + return mapSiteListData(from: "sites-http") + } } diff --git a/Modules/Tests/NetworkingTests/Model/SiteTests.swift b/Modules/Tests/NetworkingTests/Model/SiteTests.swift deleted file mode 100644 index ac2783bfad9..00000000000 --- a/Modules/Tests/NetworkingTests/Model/SiteTests.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation -import Testing -@testable import Networking -@testable import NetworkingCore - -struct SiteTests { - - @Test(arguments: [ - "http://awesomesite.com", - "http://awesomesite.com/", - "http://awesomesite.whatever.com", - "HTTP://awesomesite.com", - "http://192.168.0.12", - "https://awesomesite.com" - ]) - private func forcingHttpsForJetpack(siteAddress: String) { - let site = Site.defaultMock().copy(url: siteAddress) - let jetpack = site.toJetpackSite() - - #expect(jetpack.siteAddress.isHttpsScheme) - } -} - -fileprivate extension String { - var isHttpsScheme: Bool { - return URL(string: self)?.scheme?.lowercased() == "https" - } -} diff --git a/Modules/Tests/NetworkingTests/Responses/sites-http.json b/Modules/Tests/NetworkingTests/Responses/sites-http.json new file mode 100644 index 00000000000..034bbbd810c --- /dev/null +++ b/Modules/Tests/NetworkingTests/Responses/sites-http.json @@ -0,0 +1,34 @@ +{ + "sites": [ + { + "ID": 7777888899990000, + "name": "HTTP Site", + "description": "Testing HTTP to HTTPS conversion", + "URL": "http://insecure-site.testing.blog", + "capabilities": { + "edit_pages": true, + "edit_posts": true, + "manage_options": true, + "own_site": true + }, + "jetpack": true, + "jetpack_connection": true, + "was_ecommerce_trial": false, + "plan": { + "product_id": 1008, + "product_slug": "business-bundle" + }, + "jetpack_modules": [], + "options": { + "timezone": "", + "gmt_offset": 0, + "blog_public": 1, + "login_url": "http://insecure-site.testing.blog/wp-login.php", + "admin_url": "http://insecure-site.testing.blog/wp-admin/", + "is_wpcom_store": true, + "woocommerce_is_active": true, + "frame_nonce": "abc123def4" + } + } + ] +} diff --git a/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme b/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme index 6701467249d..940a73b2942 100644 --- a/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme +++ b/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme @@ -148,7 +148,7 @@ + isEnabled = "YES"> Date: Fri, 7 Nov 2025 09:34:31 +0700 Subject: [PATCH 12/12] Revert unintentional change to the Woo scheme --- .../xcshareddata/xcschemes/WooCommerce.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme b/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme index 940a73b2942..6701467249d 100644 --- a/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme +++ b/WooCommerce/WooCommerce.xcodeproj/xcshareddata/xcschemes/WooCommerce.xcscheme @@ -148,7 +148,7 @@ + isEnabled = "NO">