Sketch out CAPTCHA onboarding view.

pull/2/head
Matthew Chen 6 years ago
parent df12f71b74
commit 58abf76244

@ -485,10 +485,11 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
OnboardingController *onboardingController = [OnboardingController new]; OnboardingController *onboardingController = [OnboardingController new];
[onboardingController
updateWithPhoneNumber:[[OnboardingPhoneNumber alloc] initWithE164:@"+13213214321" userInput:@"3213214321"]];
OnboardingCaptchaViewController *view = OnboardingCaptchaViewController *view =
[[OnboardingCaptchaViewController alloc] initWithOnboardingController:onboardingController]; [[OnboardingCaptchaViewController alloc] initWithOnboardingController:onboardingController];
// OnboardingPermissionsViewController *view =
// [[OnboardingPermissionsViewController alloc] initWithOnboardingController:onboardingController];
OWSNavigationController *navigationController = OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:view]; [[OWSNavigationController alloc] initWithRootViewController:view];
[self presentViewController:navigationController animated:YES completion:nil]; [self presentViewController:navigationController animated:YES completion:nil];

@ -340,8 +340,8 @@ NS_ASSUME_NONNULL_BEGIN
[_requestCodeAgainSpinner startAnimating]; [_requestCodeAgainSpinner startAnimating];
__weak CodeVerificationViewController *weakSelf = self; __weak CodeVerificationViewController *weakSelf = self;
[self.tsAccountManager [self.tsAccountManager rerequestSMSWithCaptchaToken:nil
rerequestSMSWithSuccess:^{ success:^{
OWSLogInfo(@"Successfully requested SMS code"); OWSLogInfo(@"Successfully requested SMS code");
[weakSelf enableServerActions:YES]; [weakSelf enableServerActions:YES];
[weakSelf.requestCodeAgainSpinner stopAnimating]; [weakSelf.requestCodeAgainSpinner stopAnimating];
@ -363,8 +363,8 @@ NS_ASSUME_NONNULL_BEGIN
[_requestCallSpinner startAnimating]; [_requestCallSpinner startAnimating];
__weak CodeVerificationViewController *weakSelf = self; __weak CodeVerificationViewController *weakSelf = self;
[self.tsAccountManager [self.tsAccountManager rerequestVoiceWithCaptchaToken:nil
rerequestVoiceWithSuccess:^{ success:^{
OWSLogInfo(@"Successfully requested voice code"); OWSLogInfo(@"Successfully requested voice code");
[weakSelf enableServerActions:YES]; [weakSelf enableServerActions:YES];

@ -7,6 +7,15 @@ import PromiseKit
@objc @objc
public class OnboardingBaseViewController: OWSViewController { public class OnboardingBaseViewController: OWSViewController {
// MARK: - Dependencies
private var tsAccountManager: TSAccountManager {
return TSAccountManager.sharedInstance()
}
// MARK: -
// Unlike a delegate, we can and should retain a strong reference to the OnboardingController. // Unlike a delegate, we can and should retain a strong reference to the OnboardingController.
let onboardingController: OnboardingController let onboardingController: OnboardingController
@ -82,6 +91,65 @@ public class OnboardingBaseViewController: OWSViewController {
} }
} }
// MARK: - Registration
func tryToRegister(smsVerification: Bool) {
guard let phoneNumber = onboardingController.phoneNumber else {
owsFailDebug("Missing phoneNumber.")
return
}
// We eagerly update this state, regardless of whether or not the
// registration request succeeds.
OnboardingController.setLastRegisteredCountryCode(value: onboardingController.countryState.countryCode)
OnboardingController.setLastRegisteredPhoneNumber(value: phoneNumber.userInput)
let captchaToken = onboardingController.captchaToken
ModalActivityIndicatorViewController.present(fromViewController: self,
canCancel: true) { (modal) in
self.tsAccountManager.register(withPhoneNumber: phoneNumber.e164,
captchaToken: captchaToken,
success: {
DispatchQueue.main.async {
modal.dismiss(completion: {
self.registrationSucceeded()
})
}
}, failure: { (error) in
Logger.error("Error: \(error)")
DispatchQueue.main.async {
modal.dismiss(completion: {
self.registrationFailed(error: error as NSError)
})
}
}, smsVerification: smsVerification)
}
}
private func registrationSucceeded() {
self.onboardingController.onboardingRegistrationSucceeded(viewController: self)
}
private func registrationFailed(error: NSError) {
if error.code == 402 {
Logger.info("Captcha requested.")
self.onboardingController.onboardingDidRequireCaptcha(viewController: self)
return
} else if error.code == 400 {
OWSAlerts.showAlert(title: NSLocalizedString("REGISTRATION_ERROR", comment: ""),
message: NSLocalizedString("REGISTRATION_NON_VALID_NUMBER", comment: ""))
} else {
OWSAlerts.showAlert(title: error.localizedDescription,
message: error.localizedRecoverySuggestion)
}
}
// MARK: - Orientation // MARK: - Orientation
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask { public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

@ -14,7 +14,6 @@ public class OnboardingCaptchaViewController: OnboardingBaseViewController {
super.loadView() super.loadView()
view.backgroundColor = Theme.backgroundColor view.backgroundColor = Theme.backgroundColor
view.backgroundColor = .orange
view.layoutMargins = .zero view.layoutMargins = .zero
// TODO: // TODO:
@ -45,8 +44,8 @@ public class OnboardingCaptchaViewController: OnboardingBaseViewController {
webView.allowsBackForwardNavigationGestures = false webView.allowsBackForwardNavigationGestures = false
webView.customUserAgent = "Signal iOS (+https://signal.org/download)" webView.customUserAgent = "Signal iOS (+https://signal.org/download)"
webView.allowsLinkPreview = false webView.allowsLinkPreview = false
// webView.scrollView.contentInset = .zero webView.scrollView.contentInset = .zero
// webView.layoutMargins = .zero webView.layoutMargins = .zero
let stackView = UIStackView(arrangedSubviews: [ let stackView = UIStackView(arrangedSubviews: [
titleRow, titleRow,
@ -108,46 +107,36 @@ public class OnboardingCaptchaViewController: OnboardingBaseViewController {
loadContent() loadContent()
} }
// MARK: - Events // MARK: -
private func didComplete(url: URL) { private func parseCaptchaAndTryToRegister(url: URL) {
Logger.info("")
guard let captchaToken = parseCaptcha(url: url) else {
owsFailDebug("Could not parse captcha token: \(url)")
// TODO: Alert?
//
// Reload content so user can try again.
loadContent()
return
}
onboardingController.update(captchaToken: captchaToken)
tryToRegister(smsVerification: false)
}
private func parseCaptcha(url: URL) -> String? {
Logger.info("") Logger.info("")
// signalcaptcha://03AF6jDqXgf1PocNNrWRJEENZ9l6RAMIsUoESi2dFKkxTgE2qjdZGVjEW6SZNFQqeRRTgGqOii6zHGG--uLyC1HnhSmRt8wHeKxHcg1hsK4ucTusANIeFXVB8wPPiV7U_0w2jUFVak5clMCvW9_JBfbfzj51_e9sou8DYfwc_R6THuTBTdpSV8Nh0yJalgget-nSukCxh6FPA6hRVbw7lP3r-me1QCykHOfh-V29UVaQ4Fs5upHvwB5rtiViqT_HN8WuGmdIdGcaWxaqy1lQTgFSs2Shdj593wZiXfhJnCWAw9rMn3jSgIZhkFxdXwKOmslQ2E_I8iWkm6 // signalcaptcha://03AF6jDqXgf1PocNNrWRJEENZ9l6RAMIsUoESi2dFKkxTgE2qjdZGVjEW6SZNFQqeRRTgGqOii6zHGG--uLyC1HnhSmRt8wHeKxHcg1hsK4ucTusANIeFXVB8wPPiV7U_0w2jUFVak5clMCvW9_JBfbfzj51_e9sou8DYfwc_R6THuTBTdpSV8Nh0yJalgget-nSukCxh6FPA6hRVbw7lP3r-me1QCykHOfh-V29UVaQ4Fs5upHvwB5rtiViqT_HN8WuGmdIdGcaWxaqy1lQTgFSs2Shdj593wZiXfhJnCWAw9rMn3jSgIZhkFxdXwKOmslQ2E_I8iWkm6
guard let host = url.host, guard let host = url.host,
host.count > 0 else { host.count > 0 else {
owsFailDebug("Missing host.") owsFailDebug("Missing host.")
return return nil
} }
onboardingController. return host
} }
//
// @objc func countryRowTapped(sender: UIGestureRecognizer) {
// guard sender.state == .recognized else {
// return
// }
// showCountryPicker()
// }
//
// @objc func countryCodeTapped(sender: UIGestureRecognizer) {
// guard sender.state == .recognized else {
// return
// }
// showCountryPicker()
// }
//
// @objc func nextPressed() {
// Logger.info("")
//
// parseAndTryToRegister()
// }
//
// // MARK: -
//
// private func registrationSucceeded() {
// self.onboardingController.onboardingPhoneNumberDidComplete(viewController: self)
// }
} }
// MARK: - // MARK: -
@ -164,7 +153,7 @@ extension OnboardingCaptchaViewController: WKNavigationDelegate {
if url.scheme == "signalcaptcha" { if url.scheme == "signalcaptcha" {
decisionHandler(.cancel) decisionHandler(.cancel)
DispatchQueue.main.async { DispatchQueue.main.async {
didComplete(url: url) self.parseCaptchaAndTryToRegister(url: url)
} }
return return
} }
@ -202,8 +191,6 @@ extension OnboardingCaptchaViewController: WKNavigationDelegate {
Logger.verbose("navigation: \(String(describing: navigation)), error: \(error)") Logger.verbose("navigation: \(String(describing: navigation)), error: \(error)")
} }
// public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) { public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
Logger.verbose("") Logger.verbose("")
} }

@ -5,7 +5,7 @@
import UIKit import UIKit
@objc @objc
public class OnboardingState: NSObject { public class OnboardingCountryState: NSObject {
public let countryName: String public let countryName: String
public let callingCode: String public let callingCode: String
public let countryCode: String public let countryCode: String
@ -19,7 +19,7 @@ public class OnboardingState: NSObject {
self.countryCode = countryCode self.countryCode = countryCode
} }
public static var defaultValue: OnboardingState { public static var defaultValue: OnboardingCountryState {
AssertIsOnMainThread() AssertIsOnMainThread()
var countryCode: String = PhoneNumber.defaultCountryCode() var countryCode: String = PhoneNumber.defaultCountryCode()
@ -36,13 +36,35 @@ public class OnboardingState: NSObject {
countryName = countryNameDerived countryName = countryNameDerived
} }
return OnboardingState(countryName: countryName, callingCode: callingCode, countryCode: countryCode) return OnboardingCountryState(countryName: countryName, callingCode: callingCode, countryCode: countryCode)
} }
} }
// MARK: -
@objc
public class OnboardingPhoneNumber: NSObject {
public let e164: String
public let userInput: String
@objc
public init(e164: String,
userInput: String) {
self.e164 = e164
self.userInput = userInput
}
}
// MARK: -
@objc @objc
public class OnboardingController: NSObject { public class OnboardingController: NSObject {
@objc
public override init() {
super.init()
}
// MARK: - Factory Methods // MARK: - Factory Methods
@objc @objc
@ -58,6 +80,8 @@ public class OnboardingController: NSObject {
public func onboardingSplashDidComplete(viewController: UIViewController) { public func onboardingSplashDidComplete(viewController: UIViewController) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.info("")
let view = OnboardingPermissionsViewController(onboardingController: self) let view = OnboardingPermissionsViewController(onboardingController: self)
viewController.navigationController?.pushViewController(view, animated: true) viewController.navigationController?.pushViewController(view, animated: true)
} }
@ -65,12 +89,16 @@ public class OnboardingController: NSObject {
public func onboardingPermissionsWasSkipped(viewController: UIViewController) { public func onboardingPermissionsWasSkipped(viewController: UIViewController) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.info("")
pushPhoneNumberView(viewController: viewController) pushPhoneNumberView(viewController: viewController)
} }
public func onboardingPermissionsDidComplete(viewController: UIViewController) { public func onboardingPermissionsDidComplete(viewController: UIViewController) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.info("")
pushPhoneNumberView(viewController: viewController) pushPhoneNumberView(viewController: viewController)
} }
@ -81,53 +109,64 @@ public class OnboardingController: NSObject {
viewController.navigationController?.pushViewController(view, animated: true) viewController.navigationController?.pushViewController(view, animated: true)
} }
public func onboardingPhoneNumberDidComplete(viewController: UIViewController) { public func onboardingRegistrationSucceeded(viewController: UIViewController) {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.info("")
// CodeVerificationViewController *vc = [CodeVerificationViewController new]; // CodeVerificationViewController *vc = [CodeVerificationViewController new];
// [weakSelf.navigationController pushViewController:vc animated:YES]; // [weakSelf.navigationController pushViewController:vc animated:YES];
} }
public func onboardingPhoneNumberDidRequireCaptcha(viewController: UIViewController) { public func onboardingDidRequireCaptcha(viewController: UIViewController) {
AssertIsOnMainThread() AssertIsOnMainThread()
let view = OnboardingCaptchaViewController(onboardingController: self) Logger.info("")
viewController.navigationController?.pushViewController(view, animated: true)
}
public func onboardingCaptchaDidComplete(viewController: UIViewController, guard let navigationController = viewController.navigationController else {
captchaToken: String) { owsFailDebug("Missing navigationController.")
AssertIsOnMainThread() return
}
self.captchaToken = captchaToken // The service could demand CAPTCHA from the "phone number" view or later
// from the "code verification" view. The "Captcha" view should always appear
// immediately after the "phone number" view.
while navigationController.viewControllers.count > 1 &&
!(navigationController.topViewController is OnboardingPhoneNumberViewController) {
navigationController.popViewController(animated: false)
}
// let view = OnboardingCaptchaViewController(onboardingController: self) let view = OnboardingCaptchaViewController(onboardingController: self)
// viewController.navigationController?.pushViewController(view, animated: true) navigationController.pushViewController(view, animated: true)
} }
// MARK: - State // MARK: - State
public private(set) var state: OnboardingState = .defaultValue public private(set) var countryState: OnboardingCountryState = .defaultValue
private var captchaToken: String public private(set) var phoneNumber: OnboardingPhoneNumber?
public func update(withCountryName countryName: String, callingCode: String, countryCode: String) { public private(set) var captchaToken: String?
@objc
public func update(countryState: OnboardingCountryState) {
AssertIsOnMainThread() AssertIsOnMainThread()
guard countryCode.count > 0 else { self.countryState = countryState
owsFailDebug("Invalid country code.") }
return
} @objc
guard countryName.count > 0 else { public func update(phoneNumber: OnboardingPhoneNumber) {
owsFailDebug("Invalid country name.") AssertIsOnMainThread()
return
} self.phoneNumber = phoneNumber
guard callingCode.count > 0 else { }
owsFailDebug("Invalid calling code.")
return
}
state = OnboardingState(countryName: countryName, callingCode: callingCode, countryCode: countryCode) @objc
public func update(captchaToken: String) {
AssertIsOnMainThread()
self.captchaToken = captchaToken
} }
// MARK: - Debug // MARK: - Debug

@ -165,13 +165,13 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
owsFailDebug("Could not resume re-registration; couldn't parse phoneNumberE164.") owsFailDebug("Could not resume re-registration; couldn't parse phoneNumberE164.")
return return
} }
guard let callingCode = parsedPhoneNumber.getCountryCode() else { guard let callingCodeNumeric = parsedPhoneNumber.getCountryCode() else {
owsFailDebug("Could not resume re-registration; missing callingCode.") owsFailDebug("Could not resume re-registration; missing callingCode.")
return return
} }
let callingCodeText = "\(COUNTRY_CODE_PREFIX)\(callingCode)" let callingCode = "\(COUNTRY_CODE_PREFIX)\(callingCodeNumeric)"
let countryCodes: [String] = let countryCodes: [String] =
PhoneNumberUtil.sharedThreadLocal().countryCodes(fromCallingCode: callingCodeText) PhoneNumberUtil.sharedThreadLocal().countryCodes(fromCallingCode: callingCode)
guard let countryCode = countryCodes.first else { guard let countryCode = countryCodes.first else {
owsFailDebug("Could not resume re-registration; unknown countryCode.") owsFailDebug("Could not resume re-registration; unknown countryCode.")
return return
@ -180,13 +180,28 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
owsFailDebug("Could not resume re-registration; unknown countryName.") owsFailDebug("Could not resume re-registration; unknown countryName.")
return return
} }
if !phoneNumberE164.hasPrefix(callingCodeText) { if !phoneNumberE164.hasPrefix(callingCode) {
owsFailDebug("Could not resume re-registration; non-matching calling code.") owsFailDebug("Could not resume re-registration; non-matching calling code.")
return return
} }
let phoneNumberWithoutCallingCode = phoneNumberE164.substring(from: callingCodeText.count) let phoneNumberWithoutCallingCode = phoneNumberE164.substring(from: callingCode.count)
guard countryCode.count > 0 else {
owsFailDebug("Invalid country code.")
return
}
guard countryName.count > 0 else {
owsFailDebug("Invalid country name.")
return
}
guard callingCode.count > 0 else {
owsFailDebug("Invalid calling code.")
return
}
let countryState = OnboardingCountryState(countryName: countryName, callingCode: callingCode, countryCode: countryCode)
onboardingController.update(countryState: countryState)
onboardingController.update(withCountryName: countryName, callingCode: callingCodeText, countryCode: countryCode)
updateState() updateState()
phoneNumberTextField.text = phoneNumberWithoutCallingCode phoneNumberTextField.text = phoneNumberWithoutCallingCode
@ -198,21 +213,21 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
private var countryName: String { private var countryName: String {
get { get {
return onboardingController.state.countryName return onboardingController.countryState.countryName
} }
} }
private var callingCode: String { private var callingCode: String {
get { get {
AssertIsOnMainThread() AssertIsOnMainThread()
return onboardingController.state.callingCode return onboardingController.countryState.callingCode
} }
} }
private var countryCode: String { private var countryCode: String {
get { get {
AssertIsOnMainThread() AssertIsOnMainThread()
return onboardingController.state.countryCode return onboardingController.countryState.countryCode
} }
} }
@ -297,10 +312,11 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
comment: "Message of alert indicating that users needs to enter a valid phone number to register.")) comment: "Message of alert indicating that users needs to enter a valid phone number to register."))
return return
} }
let parsedPhoneNumber = localNumber.toE164() let e164PhoneNumber = localNumber.toE164()
onboardingController.update(phoneNumber: OnboardingPhoneNumber(e164: e164PhoneNumber, userInput: phoneNumberText))
if UIDevice.current.isIPad { if UIDevice.current.isIPad {
let countryCode = self.countryCode
OWSAlerts.showConfirmationAlert(title: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_TITLE", OWSAlerts.showConfirmationAlert(title: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_TITLE",
comment: "alert title when registering an iPad"), comment: "alert title when registering an iPad"),
message: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BODY", message: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BODY",
@ -308,65 +324,12 @@ public class OnboardingPhoneNumberViewController: OnboardingBaseViewController {
proceedTitle: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BUTTON", proceedTitle: NSLocalizedString("REGISTRATION_IPAD_CONFIRM_BUTTON",
comment: "button text to proceed with registration when on an iPad"), comment: "button text to proceed with registration when on an iPad"),
proceedAction: { (_) in proceedAction: { (_) in
self.tryToRegister(parsedPhoneNumber: parsedPhoneNumber, self.tryToRegister(smsVerification: false)
phoneNumberText: phoneNumberText,
countryCode: countryCode)
}) })
} else { } else {
tryToRegister(parsedPhoneNumber: parsedPhoneNumber, tryToRegister(smsVerification: false)
phoneNumberText: phoneNumberText,
countryCode: countryCode)
} }
} }
private func tryToRegister(parsedPhoneNumber: String,
phoneNumberText: String,
countryCode: String) {
ModalActivityIndicatorViewController.present(fromViewController: self,
canCancel: true) { (modal) in
OnboardingController.setLastRegisteredCountryCode(value: countryCode)
OnboardingController.setLastRegisteredPhoneNumber(value: phoneNumberText)
self.tsAccountManager.register(withPhoneNumber: parsedPhoneNumber,
success: {
DispatchQueue.main.async {
modal.dismiss(completion: {
self.registrationSucceeded()
})
}
}, failure: { (error) in
Logger.error("Error: \(error)")
DispatchQueue.main.async {
modal.dismiss(completion: {
self.registrationFailed(error: error as NSError)
})
}
}, smsVerification: true)
}
}
private func registrationSucceeded() {
self.onboardingController.onboardingPhoneNumberDidComplete(viewController: self)
}
private func registrationFailed(error: NSError) {
if error.code == 402 {
Logger.info("Captcha requested.")
self.onboardingController.onboardingPhoneNumberDidRequireCaptcha(viewController: self)
return
} else if error.code == 400 {
OWSAlerts.showAlert(title: NSLocalizedString("REGISTRATION_ERROR", comment: ""),
message: NSLocalizedString("REGISTRATION_NON_VALID_NUMBER", comment: ""))
} else {
OWSAlerts.showAlert(title: error.localizedDescription,
message: error.localizedRecoverySuggestion)
}
phoneNumberTextField.becomeFirstResponder()
}
} }
// MARK: - // MARK: -
@ -382,7 +345,6 @@ extension OnboardingPhoneNumberViewController: UITextFieldDelegate {
public func textFieldShouldReturn(_ textField: UITextField) -> Bool { public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
parseAndTryToRegister() parseAndTryToRegister()
textField.resignFirstResponder()
return false return false
} }
} }
@ -404,7 +366,10 @@ extension OnboardingPhoneNumberViewController: CountryCodeViewControllerDelegate
return return
} }
onboardingController.update(withCountryName: countryName, callingCode: callingCode, countryCode: countryCode) let countryState = OnboardingCountryState(countryName: countryName, callingCode: callingCode, countryCode: countryCode)
onboardingController.update(countryState: countryState)
updateState() updateState()
// Trigger the formatting logic with a no-op edit. // Trigger the formatting logic with a no-op edit.

@ -448,6 +448,7 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
__weak RegistrationViewController *weakSelf = self; __weak RegistrationViewController *weakSelf = self;
[self.tsAccountManager registerWithPhoneNumber:parsedPhoneNumber [self.tsAccountManager registerWithPhoneNumber:parsedPhoneNumber
captchaToken:nil
success:^{ success:^{
OWSProdInfo([OWSAnalyticsEvents registrationRegisteredPhoneNumber]); OWSProdInfo([OWSAnalyticsEvents registrationRegisteredPhoneNumber]);

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import "RegistrationUtils.h" #import "RegistrationUtils.h"
@ -59,8 +59,8 @@ NS_ASSUME_NONNULL_BEGIN
presentFromViewController:fromViewController presentFromViewController:fromViewController
canCancel:NO canCancel:NO
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) { backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
[self.tsAccountManager [self.tsAccountManager registerWithPhoneNumber:self.tsAccountManager.reregisterationPhoneNumber
registerWithPhoneNumber:self.tsAccountManager.reregisterationPhoneNumber captchaToken:nil
success:^{ success:^{
OWSLogInfo(@"re-registering: send verification code succeeded."); OWSLogInfo(@"re-registering: send verification code succeeded.");

@ -90,13 +90,18 @@ typedef NS_ENUM(NSUInteger, OWSRegistrationState) {
#pragma mark - Register with phone number #pragma mark - Register with phone number
- (void)registerWithPhoneNumber:(NSString *)phoneNumber - (void)registerWithPhoneNumber:(NSString *)phoneNumber
captchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock failure:(void (^)(NSError *error))failureBlock
smsVerification:(BOOL)isSMS; smsVerification:(BOOL)isSMS;
- (void)rerequestSMSWithSuccess:(void (^)(void))successBlock failure:(void (^)(NSError *error))failureBlock; - (void)rerequestSMSWithCaptchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock;
- (void)rerequestVoiceWithSuccess:(void (^)(void))successBlock failure:(void (^)(NSError *error))failureBlock; - (void)rerequestVoiceWithCaptchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock;
- (void)verifyAccountWithCode:(NSString *)verificationCode - (void)verifyAccountWithCode:(NSString *)verificationCode
pin:(nullable NSString *)pin pin:(nullable NSString *)pin

@ -322,6 +322,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
} }
- (void)registerWithPhoneNumber:(NSString *)phoneNumber - (void)registerWithPhoneNumber:(NSString *)phoneNumber
captchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock failure:(void (^)(NSError *error))failureBlock
smsVerification:(BOOL)isSMS smsVerification:(BOOL)isSMS
@ -339,6 +340,7 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
TSRequest *request = TSRequest *request =
[OWSRequestFactory requestVerificationCodeRequestWithPhoneNumber:phoneNumber [OWSRequestFactory requestVerificationCodeRequestWithPhoneNumber:phoneNumber
captchaToken:captchaToken
transport:(isSMS ? TSVerificationTransportSMS transport:(isSMS ? TSVerificationTransportSMS
: TSVerificationTransportVoice)]; : TSVerificationTransportVoice)];
[[TSNetworkManager sharedManager] makeRequest:request [[TSNetworkManager sharedManager] makeRequest:request
@ -357,20 +359,33 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa
}]; }];
} }
- (void)rerequestSMSWithSuccess:(void (^)(void))successBlock failure:(void (^)(NSError *error))failureBlock - (void)rerequestSMSWithCaptchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock
{ {
// TODO: Can we remove phoneNumberAwaitingVerification?
NSString *number = self.phoneNumberAwaitingVerification; NSString *number = self.phoneNumberAwaitingVerification;
OWSAssertDebug(number); OWSAssertDebug(number);
[self registerWithPhoneNumber:number success:successBlock failure:failureBlock smsVerification:YES]; [self registerWithPhoneNumber:number
captchaToken:captchaToken
success:successBlock
failure:failureBlock
smsVerification:YES];
} }
- (void)rerequestVoiceWithSuccess:(void (^)(void))successBlock failure:(void (^)(NSError *error))failureBlock - (void)rerequestVoiceWithCaptchaToken:(nullable NSString *)captchaToken
success:(void (^)(void))successBlock
failure:(void (^)(NSError *error))failureBlock
{ {
NSString *number = self.phoneNumberAwaitingVerification; NSString *number = self.phoneNumberAwaitingVerification;
OWSAssertDebug(number); OWSAssertDebug(number);
[self registerWithPhoneNumber:number success:successBlock failure:failureBlock smsVerification:NO]; [self registerWithPhoneNumber:number
captchaToken:captchaToken
success:successBlock
failure:failureBlock
smsVerification:NO];
} }
- (void)verifyAccountWithCode:(NSString *)verificationCode - (void)verifyAccountWithCode:(NSString *)verificationCode

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -56,6 +56,7 @@ typedef NS_ENUM(NSUInteger, TSVerificationTransport) { TSVerificationTransportVo
+ (TSRequest *)unregisterAccountRequest; + (TSRequest *)unregisterAccountRequest;
+ (TSRequest *)requestVerificationCodeRequestWithPhoneNumber:(NSString *)phoneNumber + (TSRequest *)requestVerificationCodeRequestWithPhoneNumber:(NSString *)phoneNumber
captchaToken:(nullable NSString *)captchaToken
transport:(TSVerificationTransport)transport; transport:(TSVerificationTransport)transport;
+ (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId + (TSRequest *)submitMessageRequestWithRecipient:(NSString *)recipientId

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // Copyright (c) 2019 Open Whisper Systems. All rights reserved.
// //
#import "OWSRequestFactory.h" #import "OWSRequestFactory.h"
@ -235,13 +235,21 @@ NS_ASSUME_NONNULL_BEGIN
} }
+ (TSRequest *)requestVerificationCodeRequestWithPhoneNumber:(NSString *)phoneNumber + (TSRequest *)requestVerificationCodeRequestWithPhoneNumber:(NSString *)phoneNumber
captchaToken:(nullable NSString *)captchaToken
transport:(TSVerificationTransport)transport transport:(TSVerificationTransport)transport
{ {
OWSAssertDebug(phoneNumber.length > 0); OWSAssertDebug(phoneNumber.length > 0);
NSString *path = [NSString stringWithFormat:@"%@/%@/code/%@?client=ios",
NSString *querystring = @"client=ios";
if (captchaToken.length > 0) {
querystring = [NSString stringWithFormat:@"%@&captcha=%@", querystring, captchaToken];
}
NSString *path = [NSString stringWithFormat:@"%@/%@/code/%@?%@",
textSecureAccountsAPI, textSecureAccountsAPI,
[self stringForTransport:transport], [self stringForTransport:transport],
phoneNumber]; phoneNumber,
querystring];
TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}]; TSRequest *request = [TSRequest requestWithUrl:[NSURL URLWithString:path] method:@"GET" parameters:@{}];
request.shouldHaveAuthorizationHeaders = NO; request.shouldHaveAuthorizationHeaders = NO;

Loading…
Cancel
Save