Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d16b5cb
Merge pull request #559 from wordpress-mobile/release/1.33.0
oguzkocer Jan 11, 2021
5610685
DRY two factor code handling in pasteboard, fix leading zero loss
allendav Jan 11, 2021
e38022e
Fix escaping, failure case handling
allendav Jan 11, 2021
048bc20
Correctly handle when pasteboard does not contain 6 decimal digits
allendav Jan 13, 2021
1b50b26
Add unit tests for auth codes with/without leading zeros
allendav Jan 13, 2021
b98dd24
NUXbutton: set spinner's color to `style.disabledTitleColor` when the…
jaclync Sep 29, 2020
d33b06b
WordPressAuthenticatorStyle: add a new parameter `disabledButtonActiv…
jaclync Jan 14, 2021
7ed423b
Bump pod version to 1.33.1-beta.1.
jaclync Jan 14, 2021
4315eae
Pass the new style parameter in `WordpressAuthenticatorProvider` for …
jaclync Jan 14, 2021
30084d9
Update pod version to 1.34.0-beta.1 per CR feedback.
jaclync Jan 15, 2021
8e91f82
Merge pull request #562 from wordpress-mobile/wcios-2716/color-updates
jaclync Jan 15, 2021
6ccee15
Replace while with String(repeating) props @bjtitus
allendav Jan 18, 2021
e109be8
Avoid mutable state
allendav Jan 19, 2021
c96f997
Remove automatically generated header
allendav Jan 19, 2021
e1661fb
WordPressAuthenticator: separate login view controller creation to an…
jaclync Jan 20, 2021
a7752cb
Bump pod version.
jaclync Jan 20, 2021
f6f2330
Update assertion failure message.
jaclync Jan 21, 2021
135f66a
Merge pull request #561 from wordpress-mobile/fix/557-leading-zero-2fa
allendav Jan 21, 2021
0eef99d
Merge pull request #564 from wordpress-mobile/wcios-3107/login-ui
jaclync Jan 22, 2021
fc854d5
Bump pod version for https://github.com/wordpress-mobile/WordPressAut…
jaclync Jan 22, 2021
cc79aca
Merge pull request #566 from wordpress-mobile/bump-pod-version
jaclync Jan 22, 2021
170a884
Bump version to stable 1.34.0
AliSoftware Jan 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion WordPressAuthenticator.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "WordPressAuthenticator"
s.version = "1.33.0"
s.version = "1.34.0"
s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps."

s.description = <<-DESC
Expand Down
4 changes: 4 additions & 0 deletions WordPressAuthenticator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -213,6 +214,7 @@
1A21EE9722832BC200C940C6 /* WordPressComOAuthClientFacade+Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WordPressComOAuthClientFacade+Swift.swift"; sourceTree = "<group>"; };
1A4095152271AEFC009AA86D /* WPAuthenticator-Swift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "WPAuthenticator-Swift.h"; sourceTree = "<group>"; };
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 = "<group>"; };
3108613025AFA4830022F75E /* PasteboardTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardTests.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelectorTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -535,6 +537,7 @@
B501C03D208FC52500D1E58F /* Authenticator */ = {
isa = PBXGroup;
children = (
3108613025AFA4830022F75E /* PasteboardTests.swift */,
B501C03E208FC52500D1E58F /* WordPressAuthenticatorTests.swift */,
CE16177721B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift */,
BA53D64724DFDF97001F1ABF /* WordPressSourceTagTests.swift */,
Expand Down Expand Up @@ -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 */,
Expand Down
34 changes: 24 additions & 10 deletions WordPressAuthenticator/Authenticator/WordPressAuthenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 initial login controller from Login.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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -109,6 +112,7 @@ public struct WordPressAuthenticatorStyle {
primaryTitleColor: UIColor,
secondaryTitleColor: UIColor,
disabledTitleColor: UIColor,
disabledButtonActivityIndicatorColor: UIColor,
textButtonColor: UIColor,
textButtonHighlightColor: UIColor,
instructionColor: UIColor,
Expand Down Expand Up @@ -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
Expand Down
49 changes: 49 additions & 0 deletions WordPressAuthenticator/Extensions/UIPasteboard+Detect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,53 @@ extension UIPasteboard {
}
}
}

/// Attempts to detect and return a authenticator code from the pasteboard.
/// Expects to run on main thread.
/// - Parameters:
/// - completion: Called with a length digit authentication code on success
@available(iOS 14.0, *)
public func detectAuthenticatorCode(length: Int = 6, completion: @escaping (Result<String, Error>) -> Void) {
UIPasteboard.general.detect(patterns: [.number]) { result in
switch result {
case .success(let detections):
guard let firstMatch = detections.first else {
completion(.success(""))
return
}
guard let matchedNumber = firstMatch.value as? NSNumber else {
completion(.success(""))
return
}

let 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 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: missingDigits)
let paddedAuthenticationCode = paddingZeros + authenticationCode

completion(.success(paddedAuthenticationCode))
return
case .failure(let error):
completion(.failure(error))
return
}
}
}
}
2 changes: 1 addition & 1 deletion WordPressAuthenticator/NUX/NUXButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.disabledButtonActivityIndicatorColor
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions WordPressAuthenticator/Signin/Login2FAViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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.detectAuthenticatorCode() { [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 authenticatorCode):
self?.handle(code: authenticatorCode)
case .failure:
break
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,10 @@ private extension TwoFAViewController {
}

if #available(iOS 14.0, *) {
UIPasteboard.general.detect(patterns: [.number]) { [weak self] result in
UIPasteboard.general.detectAuthenticatorCode() { [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 authenticatorCode):
self?.handle(code: authenticatorCode, textField: codeField)
case .failure:
break
}
Expand Down
54 changes: 54 additions & 0 deletions WordPressAuthenticatorTests/Authenticator/PasteboardTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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)
}}
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down