From 5610685f5cc34fe21e606baf4ac29f66012a29b9 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Mon, 11 Jan 2021 13:54:09 -0800 Subject: [PATCH 01/17] DRY two factor code handling in pasteboard, fix leading zero loss --- .../Extensions/UIPasteboard+Detect.swift | 18 ++++++++++++++++++ .../Signin/Login2FAViewController.swift | 12 +++++------- .../View Related/2FA/TwoFAViewController.swift | 9 +++------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index 7ad6b3acb..579667787 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -25,4 +25,22 @@ extension UIPasteboard { } } } + + /// Detects whether UIPasteboard.general contains a 2FA code. + /// - Parameters: + /// - completion: Called with the 2FA code on success, or failure otherwise + @available(iOS 14.0, *) + func detectTwoFactorCode(completion: (Result) -> Void) { + UIPasteboard.general.detect(patterns: [.number]) { result in + switch result { + case .success(let detections): + if let twoFactorCode = detections.first?.value as? String { + completion(.success(twoFactorCode)) + return + } + } + } + + completion(.failure()); + } } diff --git a/WordPressAuthenticator/Signin/Login2FAViewController.swift b/WordPressAuthenticator/Signin/Login2FAViewController.swift index 8c87b2e78..57e2271fa 100644 --- a/WordPressAuthenticator/Signin/Login2FAViewController.swift +++ b/WordPressAuthenticator/Signin/Login2FAViewController.swift @@ -296,14 +296,12 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } if #available(iOS 14.0, *) { - UIPasteboard.general.detect(patterns: [.number]) { [weak self] result in + UIPasteboard.general.detectTwoFactorCode() { [weak self] result in switch result { - case .success(let detections): - if let pasteString = detections.first?.value as? String { - self?.handle(code: pasteString) - } - case .failure: - break + case .success(let twoFactorCode): + self?.handle(code: twoFactorCode) + case .failure: + break } } } else { diff --git a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift index 47b1fa955..8a3c6ad8b 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift @@ -318,13 +318,10 @@ private extension TwoFAViewController { } if #available(iOS 14.0, *) { - UIPasteboard.general.detect(patterns: [.number]) { [weak self] result in + UIPasteboard.general.detectTwoFactorCode() { [weak self] result in switch result { - case .success(let detections): - if let pasteCode = detections.first?.value as? Int { - let pasteString = String(pasteCode) - self?.handle(code: pasteString, textField: codeField) - } + case .success(let twoFactorCode): + self?.handle(code: twoFactorCode, textField: codeField) case .failure: break } From e38022e4008072a05305242a8a8f2b3c8bcd8961 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Mon, 11 Jan 2021 14:02:49 -0800 Subject: [PATCH 02/17] Fix escaping, failure case handling --- WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index 579667787..e81c54e6b 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -30,7 +30,7 @@ extension UIPasteboard { /// - Parameters: /// - completion: Called with the 2FA code on success, or failure otherwise @available(iOS 14.0, *) - func detectTwoFactorCode(completion: (Result) -> Void) { + func detectTwoFactorCode(completion: @escaping (Result) -> Void) { UIPasteboard.general.detect(patterns: [.number]) { result in switch result { case .success(let detections): @@ -38,9 +38,9 @@ extension UIPasteboard { completion(.success(twoFactorCode)) return } + case .failure(let error): + completion(.failure(error)) } } - - completion(.failure()); } } From 048bc2042170d74c9308d6d8aaf2d5e92fb88563 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Wed, 13 Jan 2021 13:35:43 -0800 Subject: [PATCH 03/17] Correctly handle when pasteboard does not contain 6 decimal digits --- .../Extensions/UIPasteboard+Detect.swift | 38 ++++++++++++++++--- .../Signin/Login2FAViewController.swift | 6 +-- .../2FA/TwoFAViewController.swift | 6 +-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index e81c54e6b..d18e1098b 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -26,20 +26,48 @@ extension UIPasteboard { } } - /// Detects whether UIPasteboard.general contains a 2FA code. + /// Attempts to detect and return a authenticator code from the pasteboard. + /// Expects to run on main thread. /// - Parameters: - /// - completion: Called with the 2FA code on success, or failure otherwise + /// - completion: Called with a six digit authentication code on success @available(iOS 14.0, *) - func detectTwoFactorCode(completion: @escaping (Result) -> Void) { + func detectAuthenticatorCode(completion: @escaping (Result) -> Void) { UIPasteboard.general.detect(patterns: [.number]) { result in switch result { case .success(let detections): - if let twoFactorCode = detections.first?.value as? String { - completion(.success(twoFactorCode)) + guard let firstMatch = detections.first else { + completion(.success("")) return } + guard let matchedNumber = firstMatch.value as? NSNumber else { + completion(.success("")) + return + } + + var authenticationCode = matchedNumber.stringValue + + /// Reject numbers with decimal points or signs in them + let codeCharacterSet = CharacterSet(charactersIn: authenticationCode) + if !codeCharacterSet.isSubset(of: CharacterSet.decimalDigits) { + completion(.success("")) + return + } + + /// We need 6 digits. No more, no less. + if authenticationCode.count > 6 { + completion(.success("")) + return + } + + while authenticationCode.count < 6 { + authenticationCode = "0" + authenticationCode + } + + completion(.success(authenticationCode)) + return case .failure(let error): completion(.failure(error)) + return } } } diff --git a/WordPressAuthenticator/Signin/Login2FAViewController.swift b/WordPressAuthenticator/Signin/Login2FAViewController.swift index 57e2271fa..5aa3f8d4f 100644 --- a/WordPressAuthenticator/Signin/Login2FAViewController.swift +++ b/WordPressAuthenticator/Signin/Login2FAViewController.swift @@ -296,10 +296,10 @@ class Login2FAViewController: LoginViewController, NUXKeyboardResponder, UITextF } if #available(iOS 14.0, *) { - UIPasteboard.general.detectTwoFactorCode() { [weak self] result in + UIPasteboard.general.detectAuthenticatorCode() { [weak self] result in switch result { - case .success(let twoFactorCode): - self?.handle(code: twoFactorCode) + case .success(let authenticatorCode): + self?.handle(code: authenticatorCode) case .failure: break } diff --git a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift index 8a3c6ad8b..8242e6710 100644 --- a/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift +++ b/WordPressAuthenticator/Unified Auth/View Related/2FA/TwoFAViewController.swift @@ -318,10 +318,10 @@ private extension TwoFAViewController { } if #available(iOS 14.0, *) { - UIPasteboard.general.detectTwoFactorCode() { [weak self] result in + UIPasteboard.general.detectAuthenticatorCode() { [weak self] result in switch result { - case .success(let twoFactorCode): - self?.handle(code: twoFactorCode, textField: codeField) + case .success(let authenticatorCode): + self?.handle(code: authenticatorCode, textField: codeField) case .failure: break } From 1b50b263a744bc5a0633bccbd819cd99463de0e4 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Wed, 13 Jan 2021 14:40:03 -0800 Subject: [PATCH 04/17] Add unit tests for auth codes with/without leading zeros --- .../project.pbxproj | 4 ++ .../Extensions/UIPasteboard+Detect.swift | 2 +- .../Authenticator/PasteboardTests.swift | 62 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift diff --git a/WordPressAuthenticator.xcodeproj/project.pbxproj b/WordPressAuthenticator.xcodeproj/project.pbxproj index 773db338e..63b61c7d2 100644 --- a/WordPressAuthenticator.xcodeproj/project.pbxproj +++ b/WordPressAuthenticator.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE74923B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift */; }; 1A21EE9822832BC300C940C6 /* WordPressComOAuthClientFacade+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A21EE9722832BC200C940C6 /* WordPressComOAuthClientFacade+Swift.swift */; }; 1A4095182271AEFC009AA86D /* WPAuthenticator-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4095152271AEFC009AA86D /* WPAuthenticator-Swift.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3108613125AFA4830022F75E /* PasteboardTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3108613025AFA4830022F75E /* PasteboardTests.swift */; }; 3F550D4E23DA429B007E5897 /* AppSelectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */; }; 3F550D5123DA4A9C007E5897 /* LinkMailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */; }; 3F550D5323DA4AC6007E5897 /* URLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5223DA4AC6007E5897 /* URLHandler.swift */; }; @@ -213,6 +214,7 @@ 1A21EE9722832BC200C940C6 /* WordPressComOAuthClientFacade+Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WordPressComOAuthClientFacade+Swift.swift"; sourceTree = ""; }; 1A4095152271AEFC009AA86D /* WPAuthenticator-Swift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WPAuthenticator-Swift.h"; sourceTree = ""; }; 276354F054C34AD36CA32AB6 /* Pods-WordPressAuthenticator.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticator.release-alpha.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticator/Pods-WordPressAuthenticator.release-alpha.xcconfig"; sourceTree = ""; }; + 3108613025AFA4830022F75E /* PasteboardTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardTests.swift; sourceTree = ""; }; 33FEF45B466FF8EAAE5F3923 /* Pods-WordPressAuthenticator.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticator.release.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticator/Pods-WordPressAuthenticator.release.xcconfig"; sourceTree = ""; }; 37AFD4EF492B00CA7AEC11A3 /* Pods-WordPressAuthenticatorTests.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticatorTests.release-alpha.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticatorTests/Pods-WordPressAuthenticatorTests.release-alpha.xcconfig"; sourceTree = ""; }; 3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelectorTests.swift; sourceTree = ""; }; @@ -535,6 +537,7 @@ B501C03D208FC52500D1E58F /* Authenticator */ = { isa = PBXGroup; children = ( + 3108613025AFA4830022F75E /* PasteboardTests.swift */, B501C03E208FC52500D1E58F /* WordPressAuthenticatorTests.swift */, CE16177721B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift */, BA53D64724DFDF97001F1ABF /* WordPressSourceTagTests.swift */, @@ -1362,6 +1365,7 @@ BA53D64B24DFE07D001F1ABF /* WordpressAuthenticatorProvider.swift in Sources */, CE16177821B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift in Sources */, B501C048208FC79C00D1E58F /* LoginFacadeTests.m in Sources */, + 3108613125AFA4830022F75E /* PasteboardTests.swift in Sources */, D85C36F0256E118D00D56E34 /* NavigationToEnterAccountTests.swift in Sources */, D85C36E6256E0DDE00D56E34 /* NavigationToEnterSiteTests.swift in Sources */, D85C3882256E3FEC00D56E34 /* WordPressComSiteInfoTests.swift in Sources */, diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index d18e1098b..76963d71e 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -31,7 +31,7 @@ extension UIPasteboard { /// - Parameters: /// - completion: Called with a six digit authentication code on success @available(iOS 14.0, *) - func detectAuthenticatorCode(completion: @escaping (Result) -> Void) { + public func detectAuthenticatorCode(completion: @escaping (Result) -> Void) { UIPasteboard.general.detect(patterns: [.number]) { result in switch result { case .success(let detections): diff --git a/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift new file mode 100644 index 000000000..5dc55c5a2 --- /dev/null +++ b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift @@ -0,0 +1,62 @@ +// +// PasteboardTests.swift +// WordPressAuthenticatorTests +// +// Created by Allen Snook on 1/13/21. +// Copyright © 2021 Automattic. All rights reserved. +// + +import XCTest + +class PasteboardTests: XCTestCase { + let timeout = TimeInterval(3) + + override class func tearDown() { + super.tearDown() + let pasteboard = UIPasteboard.general + pasteboard.string = "" + } + + func testNominalAuthCode() throws { + guard #available(iOS 14.0, *) else { + throw XCTSkip("Unsupported iOS version") + } + + let expect = expectation(description: "Could read nominal auth code from pasteboard") + let pasteboard = UIPasteboard.general + pasteboard.string = "123456" + + UIPasteboard.general.detectAuthenticatorCode() { result in + switch result { + case .success(let authenticationCode): + XCTAssertEqual(authenticationCode, "123456") + case .failure(_): + XCTAssert(false) + } + expect.fulfill() + } + + waitForExpectations(timeout: timeout, handler: nil) + } + + func testLeadingZeroInAuthCodePreserved() throws { + guard #available(iOS 14.0, *) else { + throw XCTSkip("Unsupported iOS version") + } + + let expect = expectation(description: "Could read leading zero auth code from pasteboard") + let pasteboard = UIPasteboard.general + pasteboard.string = "012345" + + UIPasteboard.general.detectAuthenticatorCode() { result in + switch result { + case .success(let authenticationCode): + XCTAssertEqual(authenticationCode, "012345") + case .failure(_): + XCTAssert(false) + } + expect.fulfill() + } + + waitForExpectations(timeout: timeout, handler: nil) + }} From b98dd241d041d8a225138ae7cac43db8afdcc648 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Tue, 29 Sep 2020 10:33:40 +0800 Subject: [PATCH 05/17] NUXbutton: set spinner's color to `style.disabledTitleColor` when the button is disabled. --- WordPressAuthenticator/NUX/NUXButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator/NUX/NUXButton.swift b/WordPressAuthenticator/NUX/NUXButton.swift index 929d5fb16..cec3635f1 100644 --- a/WordPressAuthenticator/NUX/NUXButton.swift +++ b/WordPressAuthenticator/NUX/NUXButton.swift @@ -12,7 +12,7 @@ import WordPressKit open override var isEnabled: Bool { didSet { if #available(iOS 13, *) { - activityIndicator.color = isEnabled ? style.primaryTitleColor : style.secondaryTitleColor + activityIndicator.color = isEnabled ? style.primaryTitleColor : style.disabledTitleColor } } } From d33b06b281a2cdc5241e7f964b424e8f0d80247e Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Thu, 14 Jan 2021 17:32:47 +0800 Subject: [PATCH 06/17] WordPressAuthenticatorStyle: add a new parameter `disabledButtonActivityIndicatorColor` for the spinner color when the button is disabled. --- .../Authenticator/WordPressAuthenticatorStyles.swift | 5 +++++ WordPressAuthenticator/NUX/NUXButton.swift | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift index 3deb540aa..ff85df1d1 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorStyles.swift @@ -39,6 +39,9 @@ public struct WordPressAuthenticatorStyle { public let disabledTitleColor: UIColor + /// Color of the spinner that is shown when a button is disabled. + public let disabledButtonActivityIndicatorColor: UIColor + /// Style: Text Buttons /// public let textButtonColor: UIColor @@ -109,6 +112,7 @@ public struct WordPressAuthenticatorStyle { primaryTitleColor: UIColor, secondaryTitleColor: UIColor, disabledTitleColor: UIColor, + disabledButtonActivityIndicatorColor: UIColor, textButtonColor: UIColor, textButtonHighlightColor: UIColor, instructionColor: UIColor, @@ -139,6 +143,7 @@ public struct WordPressAuthenticatorStyle { self.primaryTitleColor = primaryTitleColor self.secondaryTitleColor = secondaryTitleColor self.disabledTitleColor = disabledTitleColor + self.disabledButtonActivityIndicatorColor = disabledButtonActivityIndicatorColor self.textButtonColor = textButtonColor self.textButtonHighlightColor = textButtonHighlightColor self.instructionColor = instructionColor diff --git a/WordPressAuthenticator/NUX/NUXButton.swift b/WordPressAuthenticator/NUX/NUXButton.swift index cec3635f1..2f045e87f 100644 --- a/WordPressAuthenticator/NUX/NUXButton.swift +++ b/WordPressAuthenticator/NUX/NUXButton.swift @@ -12,7 +12,7 @@ import WordPressKit open override var isEnabled: Bool { didSet { if #available(iOS 13, *) { - activityIndicator.color = isEnabled ? style.primaryTitleColor : style.disabledTitleColor + activityIndicator.color = isEnabled ? style.primaryTitleColor : style.disabledButtonActivityIndicatorColor } } } From 7ed423b4a82a3f1e16573383f5517be69133d2b8 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Thu, 14 Jan 2021 17:35:04 +0800 Subject: [PATCH 07/17] Bump pod version to 1.33.1-beta.1. --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index e5cd27d7f..ff55fa949 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.33.0" + s.version = "1.33.1-beta.1" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 4315eae3f7f2acd578086e23a458c73730396712 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Thu, 14 Jan 2021 18:12:18 +0800 Subject: [PATCH 08/17] Pass the new style parameter in `WordpressAuthenticatorProvider` for testing. --- .../Mocks/WordpressAuthenticatorProvider.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift b/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift index 44af3dbe7..2ffb69177 100644 --- a/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift +++ b/WordPressAuthenticatorTests/Mocks/WordpressAuthenticatorProvider.swift @@ -32,6 +32,7 @@ public class WordpressAuthenticatorProvider: NSObject { primaryTitleColor: UIColor.random(), secondaryTitleColor: UIColor.random(), disabledTitleColor: UIColor.random(), + disabledButtonActivityIndicatorColor: UIColor.random(), textButtonColor: UIColor.random(), textButtonHighlightColor: UIColor.random(), instructionColor: UIColor.random(), From 30084d93f0ae76012b1337d7d25b2421cf759a06 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 15 Jan 2021 11:54:58 +0800 Subject: [PATCH 09/17] Update pod version to 1.34.0-beta.1 per CR feedback. --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index ff55fa949..a6457a820 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.33.1-beta.1" + s.version = "1.34.0-beta.1" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 6ccee15acc5c6d6c2bf44887449105828aedb4d8 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Mon, 18 Jan 2021 15:47:30 -0800 Subject: [PATCH 10/17] Replace while with String(repeating) props @bjtitus Co-authored-by: Brandon Titus --- WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index 76963d71e..34990bd85 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -59,9 +59,9 @@ extension UIPasteboard { return } - while authenticationCode.count < 6 { - authenticationCode = "0" + authenticationCode - } + let missingDigits = 6 - authenticationCode.count + let paddingZeros = String(repeating: "0", count: missing) + let paddedAuthenticationCode = paddingZeros + authenticationCode completion(.success(authenticationCode)) return From e109be8783aa27c3b3bba97ee45ad559aaee4447 Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Mon, 18 Jan 2021 16:00:47 -0800 Subject: [PATCH 11/17] Avoid mutable state --- .../Extensions/UIPasteboard+Detect.swift | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift index 34990bd85..5665be7b1 100644 --- a/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift +++ b/WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift @@ -29,9 +29,9 @@ extension UIPasteboard { /// Attempts to detect and return a authenticator code from the pasteboard. /// Expects to run on main thread. /// - Parameters: - /// - completion: Called with a six digit authentication code on success + /// - completion: Called with a length digit authentication code on success @available(iOS 14.0, *) - public func detectAuthenticatorCode(completion: @escaping (Result) -> Void) { + public func detectAuthenticatorCode(length: Int = 6, completion: @escaping (Result) -> Void) { UIPasteboard.general.detect(patterns: [.number]) { result in switch result { case .success(let detections): @@ -44,7 +44,7 @@ extension UIPasteboard { return } - var authenticationCode = matchedNumber.stringValue + let authenticationCode = matchedNumber.stringValue /// Reject numbers with decimal points or signs in them let codeCharacterSet = CharacterSet(charactersIn: authenticationCode) @@ -53,17 +53,20 @@ extension UIPasteboard { return } - /// We need 6 digits. No more, no less. - if authenticationCode.count > 6 { + /// We need length digits. No more, no less. + if authenticationCode.count > length { completion(.success("")) return + } else if authenticationCode.count == length { + completion(.success(authenticationCode)) + return } let missingDigits = 6 - authenticationCode.count - let paddingZeros = String(repeating: "0", count: missing) + let paddingZeros = String(repeating: "0", count: missingDigits) let paddedAuthenticationCode = paddingZeros + authenticationCode - completion(.success(authenticationCode)) + completion(.success(paddedAuthenticationCode)) return case .failure(let error): completion(.failure(error)) From c96f997731e9859ef5b96e0a8e5561a4683869ae Mon Sep 17 00:00:00 2001 From: Allen Snook Date: Mon, 18 Jan 2021 16:02:49 -0800 Subject: [PATCH 12/17] Remove automatically generated header --- .../Authenticator/PasteboardTests.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift index 5dc55c5a2..9fbe98560 100644 --- a/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift +++ b/WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift @@ -1,11 +1,3 @@ -// -// PasteboardTests.swift -// WordPressAuthenticatorTests -// -// Created by Allen Snook on 1/13/21. -// Copyright © 2021 Automattic. All rights reserved. -// - import XCTest class PasteboardTests: XCTestCase { From e1661fb38f0f7076daf274cdebb8782a84e01c0b Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Wed, 20 Jan 2021 15:53:09 +0800 Subject: [PATCH 13/17] WordPressAuthenticator: separate login view controller creation to another function `loginUI` so that the caller can determine how to display it. --- .../WordPressAuthenticator.swift | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift index ac170f81f..09d5a580d 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift @@ -156,20 +156,34 @@ import WordPressKit /// - onLoginButtonTapped: Called when the login button on the prologue screen is tapped. /// - onCompletion: Called when the login UI presentation completes. public class func showLogin(from presenter: UIViewController, animated: Bool, showCancel: Bool = false, restrictToWPCom: Bool = false, onLoginButtonTapped: (() -> Void)? = nil, onCompletion: (() -> Void)? = nil) { - defer { - trackOpenedLogin() + guard let loginViewController = loginUI(showCancel: showCancel, restrictToWPCom: restrictToWPCom, onLoginButtonTapped: onLoginButtonTapped) else { + return } + presenter.present(loginViewController, animated: animated, completion: onCompletion) + trackOpenedLogin() + } + /// Returns the view controller for the login flow. + /// The caller is responsible for tracking `.openedLogin` event when displaying the view controller as in `showLogin`. + /// + /// - Parameters: + /// - showCancel: Whether a cancel CTA is shown on the login prologue screen. + /// - restrictToWPCom: Whether only WordPress.com login is enabled. + /// - onLoginButtonTapped: Called when the login button on the prologue screen is tapped. + /// - Returns: The root view controller for the login flow. + public class func loginUI(showCancel: Bool = false, restrictToWPCom: Bool = false, onLoginButtonTapped: (() -> Void)? = nil) -> UIViewController? { let storyboard = Storyboard.login.instance - if let controller = storyboard.instantiateInitialViewController() { - if let childController = controller.children.first as? LoginPrologueViewController { - childController.loginFields.restrictToWPCom = restrictToWPCom - childController.showCancel = showCancel - childController.onLoginButtonTapped = onLoginButtonTapped - } - controller.modalPresentationStyle = .fullScreen - presenter.present(controller, animated: animated, completion: onCompletion) + guard let controller = storyboard.instantiateInitialViewController() else { + assertionFailure("Cannot instantiate login root controller from Storyboard") + return nil + } + if let childController = controller.children.first as? LoginPrologueViewController { + childController.loginFields.restrictToWPCom = restrictToWPCom + childController.showCancel = showCancel + childController.onLoginButtonTapped = onLoginButtonTapped } + controller.modalPresentationStyle = .fullScreen + return controller } /// Used to present the new wpcom-only login flow from the app delegate From a7752cb465791d38c7d56a8c770478064f5dbdc8 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Wed, 20 Jan 2021 15:56:10 +0800 Subject: [PATCH 14/17] Bump pod version. --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index a6457a820..ad62c44cb 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.34.0-beta.1" + s.version = "1.34.0-beta.2" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From f6f23305f0b4df1965d531de09f57f84a332bb51 Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Thu, 21 Jan 2021 13:19:00 +0800 Subject: [PATCH 15/17] Update assertion failure message. --- .../Authenticator/WordPressAuthenticator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift index 09d5a580d..19adecb99 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift @@ -174,7 +174,7 @@ import WordPressKit public class func loginUI(showCancel: Bool = false, restrictToWPCom: Bool = false, onLoginButtonTapped: (() -> Void)? = nil) -> UIViewController? { let storyboard = Storyboard.login.instance guard let controller = storyboard.instantiateInitialViewController() else { - assertionFailure("Cannot instantiate login root controller from Storyboard") + assertionFailure("Cannot instantiate initial login controller from Login.storyboard") return nil } if let childController = controller.children.first as? LoginPrologueViewController { From fc854d51c3600f13e91d859440923ec227cd493c Mon Sep 17 00:00:00 2001 From: Jaclyn Chen Date: Fri, 22 Jan 2021 12:00:49 +0800 Subject: [PATCH 16/17] Bump pod version for https://github.com/wordpress-mobile/WordPressAuthenticator-iOS/pull/564 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index ad62c44cb..14193e995 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.34.0-beta.2" + s.version = "1.34.0-beta.3" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC From 170a8848029ecd93f523d8d69ecd5bf67c1e0d38 Mon Sep 17 00:00:00 2001 From: Olivier Halligon Date: Mon, 25 Jan 2021 17:24:00 +0100 Subject: [PATCH 17/17] Bump version to stable 1.34.0 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index 14193e995..2476df13b 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.34.0-beta.3" + s.version = "1.34.0" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC