Change all e164 references in reg coordinator to E164 type
This commit is contained in:
parent
6640819e46
commit
a31fb00368
@ -44,7 +44,7 @@ public protocol RegistrationCoordinator {
|
||||
/// An e164 may already be known (e.g. re-registration); this call cements that
|
||||
/// e164. Until this is called, the e164 will not actually be used for registration.
|
||||
/// This gives the user a chance to change it before any automatic steps are taken.
|
||||
func submitE164(_ e164: String) -> Guarantee<RegistrationStep>
|
||||
func submitE164(_ e164: E164) -> Guarantee<RegistrationStep>
|
||||
|
||||
/// Request an SMS code be sent, returning the next step to take.
|
||||
/// If requesting a code is disallowed for any reason, the next step will be the same current
|
||||
|
||||
@ -17,7 +17,7 @@ extension RegistrationCoordinatorImpl {
|
||||
}
|
||||
|
||||
static func makeKBSAuthCheckRequest(
|
||||
e164: String,
|
||||
e164: E164,
|
||||
candidateCredentials: [KBSAuthCredential],
|
||||
signalService: OWSSignalServiceProtocol,
|
||||
schedulers: Schedulers
|
||||
@ -64,7 +64,7 @@ extension RegistrationCoordinatorImpl {
|
||||
|
||||
static func makeCreateAccountRequest(
|
||||
_ method: RegistrationRequestFactory.VerificationMethod,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
authPassword: String,
|
||||
accountAttributes: AccountAttributes,
|
||||
skipDeviceTransfer: Bool,
|
||||
@ -167,7 +167,7 @@ extension RegistrationCoordinatorImpl {
|
||||
|
||||
static func makeChangeNumberRequest(
|
||||
_ method: RegistrationRequestFactory.VerificationMethod,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
reglockToken: String?,
|
||||
authPassword: String,
|
||||
signalService: OWSSignalServiceProtocol,
|
||||
|
||||
@ -150,7 +150,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
public func submitE164(_ e164: String) -> Guarantee<RegistrationStep> {
|
||||
public func submitE164(_ e164: E164) -> Guarantee<RegistrationStep> {
|
||||
// TODO[Registration] do some validation on the e164 format?
|
||||
// maybe we trust the view controller to do that.
|
||||
db.write { tx in
|
||||
@ -494,7 +494,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
/// The e164 the user has entered for this attempt at registration.
|
||||
/// Initially the e164 in the UI may be pre-populated (e.g. in re-reg)
|
||||
/// but this value is not set until the user accepts it or enters their own value.
|
||||
var e164: String?
|
||||
var e164: E164?
|
||||
|
||||
/// How many times the user has tried making guesses against the PIN
|
||||
/// we have locally? This happens when we have a local KBS master key
|
||||
@ -950,7 +950,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
|
||||
private func registerForRegRecoveryPwPath(
|
||||
regRecoveryPw: String,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
pinFromUser: String,
|
||||
retriesLeft: Int = Constants.networkErrorRetries
|
||||
) -> Guarantee<RegistrationStep> {
|
||||
@ -971,7 +971,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
private func handleCreateAccountResponseFromRegRecoveryPassword(
|
||||
_ response: AccountResponse,
|
||||
regRecoveryPw: String,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
pinFromUser: String,
|
||||
retriesLeft: Int
|
||||
) -> Guarantee<RegistrationStep> {
|
||||
@ -1177,7 +1177,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
|
||||
private func makeKBSAuthCredentialCheckRequest(
|
||||
kbsAuthCredentialCandidates: [KBSAuthCredential],
|
||||
e164: String,
|
||||
e164: E164,
|
||||
retriesLeft: Int = Constants.networkErrorRetries
|
||||
) -> Guarantee<RegistrationStep> {
|
||||
return Service.makeKBSAuthCheckRequest(
|
||||
@ -1201,7 +1201,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
private func handleKBSAuthCredentialCheckResponse(
|
||||
_ response: Service.KBSAuthCheckResponse,
|
||||
kbsAuthCredentialCandidates: [KBSAuthCredential],
|
||||
e164: String,
|
||||
e164: E164,
|
||||
retriesLeft: Int
|
||||
) -> Guarantee<RegistrationStep> {
|
||||
var matchedCredential: KBSAuthCredential?
|
||||
@ -1502,7 +1502,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
}
|
||||
|
||||
private func startSession(
|
||||
e164: String,
|
||||
e164: E164,
|
||||
retriesLeft: Int = Constants.networkErrorRetries
|
||||
) -> Guarantee<RegistrationStep> {
|
||||
return deps.pushRegistrationManager.requestPushToken()
|
||||
@ -2482,7 +2482,7 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
|
||||
private func makeRegisterOrChangeNumberRequest(
|
||||
_ method: RegistrationRequestFactory.VerificationMethod,
|
||||
e164: String
|
||||
e164: E164
|
||||
) -> Guarantee<AccountResponse> {
|
||||
switch mode {
|
||||
case .registering, .reRegistering:
|
||||
@ -2504,12 +2504,12 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
schedulers: schedulers
|
||||
)
|
||||
|
||||
case .changingNumber(_, let oldAuthPassword):
|
||||
case .changingNumber(let state):
|
||||
return Service.makeChangeNumberRequest(
|
||||
method,
|
||||
e164: e164,
|
||||
reglockToken: inMemoryState.reglockToken,
|
||||
authPassword: oldAuthPassword,
|
||||
authPassword: state.oldAuthToken,
|
||||
signalService: deps.signalService,
|
||||
schedulers: schedulers
|
||||
)
|
||||
@ -2587,8 +2587,8 @@ public class RegistrationCoordinatorImpl: RegistrationCoordinator {
|
||||
return .initialRegistration(previouslyEnteredE164: persistedState.e164)
|
||||
case .reRegistering(let e164):
|
||||
return .reregistration(e164: e164)
|
||||
case .changingNumber(let oldE164, _):
|
||||
return .changingPhoneNumber(oldE164: oldE164)
|
||||
case .changingNumber(let state):
|
||||
return .changingPhoneNumber(oldE164: state.oldE164)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,15 @@ import Foundation
|
||||
|
||||
public enum RegistrationMode: Codable, Equatable {
|
||||
case registering
|
||||
case reRegistering(e164: String)
|
||||
case changingNumber(oldE164: String, oldAuthToken: String)
|
||||
case reRegistering(e164: E164)
|
||||
case changingNumber(ChangeNumberParams)
|
||||
|
||||
public struct ChangeNumberParams: Codable, Equatable {
|
||||
public let oldE164: E164
|
||||
public let oldAuthToken: String
|
||||
public let localAci: UUID
|
||||
public let localAccountId: String
|
||||
public let localDeviceId: UInt32
|
||||
public let localUserAllDeviceIds: [UInt32]
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ extension RegistrationNavigationController: RegistrationPermissionsPresenter {
|
||||
|
||||
extension RegistrationNavigationController: RegistrationPhoneNumberPresenter {
|
||||
|
||||
func goToNextStep(withE164 e164: String) {
|
||||
func goToNextStep(withE164 e164: E164) {
|
||||
pushNextController(coordinator.submitE164(e164))
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ class RegistrationPhoneNumberInputView: UIStackView {
|
||||
|
||||
public var nationalNumber: String { nationalNumberView.text?.asciiDigitsOnly ?? "" }
|
||||
|
||||
public var e164: String {
|
||||
public var e164: E164? {
|
||||
return RegistrationPhoneNumber(
|
||||
countryState: countryState,
|
||||
nationalNumber: nationalNumber
|
||||
|
||||
@ -10,7 +10,7 @@ import SignalMessaging
|
||||
// MARK: - RegistrationPhoneNumberValidationError
|
||||
|
||||
public enum RegistrationPhoneNumberValidationError: Equatable {
|
||||
case invalidNumber(invalidE164: String)
|
||||
case invalidNumber(invalidE164: E164)
|
||||
case rateLimited(expiration: Date)
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@ public struct RegistrationPhoneNumberState: Equatable {
|
||||
public enum RegistrationPhoneNumberMode: Equatable {
|
||||
/// previouslyEnteredE164 is if the user entered a number, quit, and came back.
|
||||
/// Will be used to pre-populate the entry field.
|
||||
case initialRegistration(previouslyEnteredE164: String?)
|
||||
case reregistration(e164: String)
|
||||
case changingPhoneNumber(oldE164: String)
|
||||
case initialRegistration(previouslyEnteredE164: E164?)
|
||||
case reregistration(e164: E164)
|
||||
case changingPhoneNumber(oldE164: E164)
|
||||
}
|
||||
|
||||
let mode: RegistrationPhoneNumberMode
|
||||
@ -32,7 +32,7 @@ public struct RegistrationPhoneNumberState: Equatable {
|
||||
// MARK: - RegistrationPhoneNumberPresenter
|
||||
|
||||
protocol RegistrationPhoneNumberPresenter: AnyObject {
|
||||
func goToNextStep(withE164: String)
|
||||
func goToNextStep(withE164: E164)
|
||||
}
|
||||
|
||||
// MARK: - RegistrationPhoneNumberViewController
|
||||
@ -101,7 +101,7 @@ class RegistrationPhoneNumberViewController: OWSViewController {
|
||||
private var nowTimer: Timer?
|
||||
|
||||
private var nationalNumber: String { phoneNumberInput.nationalNumber }
|
||||
private var e164: String { phoneNumberInput.e164 }
|
||||
private var e164: E164? { phoneNumberInput.e164 }
|
||||
|
||||
private var localValidationError: RegistrationPhoneNumberValidationError? {
|
||||
didSet { render() }
|
||||
@ -121,7 +121,7 @@ class RegistrationPhoneNumberViewController: OWSViewController {
|
||||
}
|
||||
|
||||
private var canSubmit: Bool {
|
||||
guard !nationalNumber.isEmpty, e164.isStructurallyValidE164 else {
|
||||
guard !nationalNumber.isEmpty, let e164 else {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ class RegistrationPhoneNumberViewController: OWSViewController {
|
||||
"ONBOARDING_PHONE_NUMBER_VALIDATION_WARNING",
|
||||
comment: "Label indicating that the phone number is invalid in the 'onboarding phone number' view."
|
||||
)
|
||||
showInvalidPhoneNumberAlertIfNecessary(for: invalidE164)
|
||||
showInvalidPhoneNumberAlertIfNecessary(for: invalidE164.stringValue)
|
||||
case let .rateLimited(expiration):
|
||||
validationWarningLabel.alpha = expiration > now ? 1 : 0
|
||||
let rateLimitFormat = OWSLocalizedString(
|
||||
@ -367,10 +367,12 @@ class RegistrationPhoneNumberViewController: OWSViewController {
|
||||
|
||||
phoneNumberInput.resignFirstResponder()
|
||||
|
||||
let e164 = self.e164
|
||||
guard let e164 = self.e164 else {
|
||||
return
|
||||
}
|
||||
|
||||
guard
|
||||
let phoneNumber = PhoneNumber(fromE164: e164),
|
||||
let phoneNumber = PhoneNumber(fromE164: e164.stringValue),
|
||||
PhoneNumberValidator().isValidForRegistration(phoneNumber: phoneNumber)
|
||||
else {
|
||||
localValidationError = .invalidNumber(invalidE164: e164)
|
||||
@ -380,7 +382,7 @@ class RegistrationPhoneNumberViewController: OWSViewController {
|
||||
|
||||
presentActionSheet(.forRegistrationVerificationConfirmation(
|
||||
mode: .sms,
|
||||
e164: e164,
|
||||
e164: e164.stringValue,
|
||||
didConfirm: { [weak self] in self?.presenter?.goToNextStep(withE164: e164) },
|
||||
didRequestEdit: { [weak self] in self?.phoneNumberInput.becomeFirstResponder() }
|
||||
))
|
||||
|
||||
@ -20,7 +20,7 @@ public enum RegistrationVerificationValidationError: Equatable {
|
||||
// MARK: - RegistrationVerificationState
|
||||
|
||||
public struct RegistrationVerificationState: Equatable {
|
||||
let e164: String
|
||||
let e164: E164
|
||||
let nextSMSDate: Date?
|
||||
let nextCallDate: Date?
|
||||
// TODO[Registration]: use this state to render a countdown.
|
||||
@ -123,7 +123,7 @@ class RegistrationVerificationViewController: OWSViewController {
|
||||
"ONBOARDING_VERIFICATION_TITLE_DEFAULT_FORMAT",
|
||||
comment: "Format for the title of the 'onboarding verification' view. Embeds {{the user's phone number}}."
|
||||
)
|
||||
let text = String(format: format, state.e164.e164FormattedAsPhoneNumberWithoutBreaks)
|
||||
let text = String(format: format, state.e164.stringValue.e164FormattedAsPhoneNumberWithoutBreaks)
|
||||
|
||||
let result = UILabel.explanationLabelForRegistration(text: text)
|
||||
result.accessibilityIdentifier = "registration.verification.explanationLabel"
|
||||
@ -300,7 +300,7 @@ class RegistrationVerificationViewController: OWSViewController {
|
||||
|
||||
presentActionSheet(.forRegistrationVerificationConfirmation(
|
||||
mode: .sms,
|
||||
e164: state.e164,
|
||||
e164: state.e164.stringValue,
|
||||
didConfirm: { [weak self] in self?.presenter?.requestSMSCode() },
|
||||
didRequestEdit: { [weak self] in self?.presenter?.returnToPhoneNumberEntry() }
|
||||
))
|
||||
@ -314,7 +314,7 @@ class RegistrationVerificationViewController: OWSViewController {
|
||||
|
||||
presentActionSheet(.forRegistrationVerificationConfirmation(
|
||||
mode: .voice,
|
||||
e164: state.e164,
|
||||
e164: state.e164.stringValue,
|
||||
didConfirm: { [weak self] in self?.presenter?.requestVoiceCode() },
|
||||
didRequestEdit: { [weak self] in self?.presenter?.returnToPhoneNumberEntry() }
|
||||
))
|
||||
|
||||
@ -20,7 +20,9 @@ public extension RegistrationUtils {
|
||||
}
|
||||
|
||||
guard tsAccountManager.resetForReregistration(),
|
||||
let phoneNumber = Self.tsAccountManager.reregistrationPhoneNumber()?.nilIfEmpty else {
|
||||
let phoneNumber = Self.tsAccountManager.reregistrationPhoneNumber()?.nilIfEmpty,
|
||||
let e164 = E164(phoneNumber)
|
||||
else {
|
||||
owsFailDebug("could not reset for re-registration.")
|
||||
return
|
||||
}
|
||||
@ -30,51 +32,12 @@ public extension RegistrationUtils {
|
||||
Self.preferences.unsetRecordedAPNSTokens()
|
||||
|
||||
if FeatureFlags.useNewRegistrationFlow {
|
||||
showReRegistration(e164: phoneNumber)
|
||||
showReRegistration(e164: e164)
|
||||
} else {
|
||||
showLegacyReRegistration(fromViewController: fromViewController, e164: phoneNumber)
|
||||
}
|
||||
}
|
||||
|
||||
private static func showReRegistration(e164: String) {
|
||||
let dependencies = RegistrationCoordinatorImpl.Dependencies(
|
||||
accountManager: RegistrationCoordinatorImpl.Wrappers.AccountManager(Self.accountManager),
|
||||
appExpiry: RegistrationCoordinatorImpl.Wrappers.AppExpiry(Self.appExpiry),
|
||||
contactsManager: RegistrationCoordinatorImpl.Wrappers.ContactsManager(Self.contactsManagerImpl),
|
||||
contactsStore: RegistrationCoordinatorImpl.Wrappers.ContactsStore(),
|
||||
dateProvider: { Date() },
|
||||
db: DependenciesBridge.shared.db,
|
||||
experienceManager: RegistrationCoordinatorImpl.Wrappers.ExperienceManager(),
|
||||
kbs: DependenciesBridge.shared.keyBackupService,
|
||||
kbsAuthCredentialStore: DependenciesBridge.shared.kbsCredentialStorage,
|
||||
keyValueStoreFactory: DependenciesBridge.shared.keyValueStoreFactory,
|
||||
ows2FAManager: RegistrationCoordinatorImpl.Wrappers.OWS2FAManager(Self.ows2FAManager),
|
||||
preKeyManager: RegistrationCoordinatorImpl.Wrappers.PreKeyManager(),
|
||||
profileManager: RegistrationCoordinatorImpl.Wrappers.ProfileManager(Self.profileManager),
|
||||
pushRegistrationManager: RegistrationCoordinatorImpl.Wrappers.PushRegistrationManager(Self.pushRegistrationManager),
|
||||
receiptManager: RegistrationCoordinatorImpl.Wrappers.ReceiptManager(Self.receiptManager),
|
||||
remoteConfig: RegistrationCoordinatorImpl.Wrappers.RemoteConfig(),
|
||||
schedulers: DependenciesBridge.shared.schedulers,
|
||||
sessionManager: DependenciesBridge.shared.registrationSessionManager,
|
||||
signalService: Self.signalService,
|
||||
storageServiceManager: Self.storageServiceManager,
|
||||
tsAccountManager: RegistrationCoordinatorImpl.Wrappers.TSAccountManager(Self.tsAccountManager),
|
||||
udManager: RegistrationCoordinatorImpl.Wrappers.UDManager(Self.udManager)
|
||||
)
|
||||
|
||||
let desiredMode = RegistrationMode.reRegistering(e164: e164)
|
||||
let coordinator = databaseStorage.read {
|
||||
return RegistrationCoordinatorImpl.forDesiredMode(
|
||||
desiredMode,
|
||||
dependencies: dependencies,
|
||||
transaction: $0.asV2Read
|
||||
)
|
||||
}
|
||||
let navController = RegistrationNavigationController(coordinator: coordinator)
|
||||
let window: UIWindow = CurrentAppContext().mainWindow!
|
||||
window.rootViewController = navController
|
||||
}
|
||||
|
||||
private static func showLegacyReRegistration(fromViewController: UIViewController, e164: String) {
|
||||
ModalActivityIndicatorViewController.present(
|
||||
fromViewController: fromViewController,
|
||||
@ -154,3 +117,45 @@ public extension RegistrationUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RegistrationUtils {
|
||||
|
||||
fileprivate static func showReRegistration(e164: E164) {
|
||||
let dependencies = RegistrationCoordinatorImpl.Dependencies(
|
||||
accountManager: RegistrationCoordinatorImpl.Wrappers.AccountManager(Self.accountManager),
|
||||
appExpiry: RegistrationCoordinatorImpl.Wrappers.AppExpiry(Self.appExpiry),
|
||||
contactsManager: RegistrationCoordinatorImpl.Wrappers.ContactsManager(Self.contactsManagerImpl),
|
||||
contactsStore: RegistrationCoordinatorImpl.Wrappers.ContactsStore(),
|
||||
dateProvider: { Date() },
|
||||
db: DependenciesBridge.shared.db,
|
||||
experienceManager: RegistrationCoordinatorImpl.Wrappers.ExperienceManager(),
|
||||
kbs: DependenciesBridge.shared.keyBackupService,
|
||||
kbsAuthCredentialStore: DependenciesBridge.shared.kbsCredentialStorage,
|
||||
keyValueStoreFactory: DependenciesBridge.shared.keyValueStoreFactory,
|
||||
ows2FAManager: RegistrationCoordinatorImpl.Wrappers.OWS2FAManager(Self.ows2FAManager),
|
||||
preKeyManager: RegistrationCoordinatorImpl.Wrappers.PreKeyManager(),
|
||||
profileManager: RegistrationCoordinatorImpl.Wrappers.ProfileManager(Self.profileManager),
|
||||
pushRegistrationManager: RegistrationCoordinatorImpl.Wrappers.PushRegistrationManager(Self.pushRegistrationManager),
|
||||
receiptManager: RegistrationCoordinatorImpl.Wrappers.ReceiptManager(Self.receiptManager),
|
||||
remoteConfig: RegistrationCoordinatorImpl.Wrappers.RemoteConfig(),
|
||||
schedulers: DependenciesBridge.shared.schedulers,
|
||||
sessionManager: DependenciesBridge.shared.registrationSessionManager,
|
||||
signalService: Self.signalService,
|
||||
storageServiceManager: Self.storageServiceManager,
|
||||
tsAccountManager: RegistrationCoordinatorImpl.Wrappers.TSAccountManager(Self.tsAccountManager),
|
||||
udManager: RegistrationCoordinatorImpl.Wrappers.UDManager(Self.udManager)
|
||||
)
|
||||
|
||||
let desiredMode = RegistrationMode.reRegistering(e164: e164)
|
||||
let coordinator = databaseStorage.read {
|
||||
return RegistrationCoordinatorImpl.forDesiredMode(
|
||||
desiredMode,
|
||||
dependencies: dependencies,
|
||||
transaction: $0.asV2Read
|
||||
)
|
||||
}
|
||||
let navController = RegistrationNavigationController(coordinator: coordinator)
|
||||
let window: UIWindow = CurrentAppContext().mainWindow!
|
||||
window.rootViewController = navController
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,14 +196,14 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(coordinator.nextStep().value, .phoneNumberEntry(Stubs.phoneNumberEntryState()))
|
||||
|
||||
// Give it a phone number, which should show the PIN entry step.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue).value
|
||||
var nextStep = coordinator.submitE164(Stubs.e164).value
|
||||
// Now it should ask for the PIN to confirm the user knows it.
|
||||
XCTAssertEqual(nextStep, .pinEntry(Stubs.pinEntryStateForRegRecoveryPath()))
|
||||
|
||||
// Give it the pin code, which should make it try and register.
|
||||
let expectedRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -321,7 +321,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(coordinator.nextStep().value, .phoneNumberEntry(Stubs.phoneNumberEntryState()))
|
||||
|
||||
// Give it a phone number, which should show the PIN entry step.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue).value
|
||||
var nextStep = coordinator.submitE164(Stubs.e164).value
|
||||
// Now it should ask for the PIN to confirm the user knows it.
|
||||
XCTAssertEqual(nextStep, .pinEntry(Stubs.pinEntryStateForRegRecoveryPath()))
|
||||
|
||||
@ -332,7 +332,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
// Give it the right pin code, which should make it try and register.
|
||||
let expectedRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -429,7 +429,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(coordinator.nextStep().value, .phoneNumberEntry(Stubs.phoneNumberEntryState()))
|
||||
|
||||
// Give it a phone number, which should show the PIN entry step.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
// Now it should ask for the PIN to confirm the user knows it.
|
||||
XCTAssertEqual(nextStep.value, .pinEntry(Stubs.pinEntryStateForRegRecoveryPath()))
|
||||
|
||||
@ -442,7 +442,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
|
||||
let expectedRecoveryPwRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -529,7 +529,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(coordinator.nextStep().value, .phoneNumberEntry(Stubs.phoneNumberEntryState()))
|
||||
|
||||
// Give it a phone number, which should show the PIN entry step.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
// Now it should ask for the PIN to confirm the user knows it.
|
||||
XCTAssertEqual(nextStep.value, .pinEntry(Stubs.pinEntryStateForRegRecoveryPath()))
|
||||
|
||||
@ -542,7 +542,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
|
||||
let expectedRecoveryPwRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -631,7 +631,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(coordinator.nextStep().value, .phoneNumberEntry(Stubs.phoneNumberEntryState()))
|
||||
|
||||
// Give it a phone number, which should show the PIN entry step.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
// Now it should ask for the PIN to confirm the user knows it.
|
||||
XCTAssertEqual(nextStep.value, .pinEntry(Stubs.pinEntryStateForRegRecoveryPath()))
|
||||
|
||||
@ -644,7 +644,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
|
||||
let expectedRecoveryPwRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -662,7 +662,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
// Resolve with success at t=3
|
||||
let expectedRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -772,7 +772,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
// Give it a phone number, which should cause it to check the auth credentials.
|
||||
// Match the main auth credential.
|
||||
let expectedKBSCheckRequest = RegistrationRequestFactory.kbsAuthCredentialCheckRequest(
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
credentials: credentialCandidates
|
||||
)
|
||||
mockURLSession.addResponse(TSRequestOWSURLSessionMock.Response(
|
||||
@ -786,7 +786,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
])
|
||||
))
|
||||
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue).value
|
||||
let nextStep = coordinator.submitE164(Stubs.e164).value
|
||||
|
||||
// At this point, we should be asking for PIN entry so we can use the credential
|
||||
// to recover the KBS master key.
|
||||
@ -832,7 +832,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
var authPassword: String!
|
||||
let expectedRegRecoveryPwRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .recoveryPassword(Stubs.regRecoveryPw),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -925,11 +925,11 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
scheduler.adjustTime(to: 0)
|
||||
|
||||
// Give it a phone number, which should cause it to check the auth credentials.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// Don't give back any matches at t=2, which means we will want to create a session as a fallback.
|
||||
let expectedKBSCheckRequest = RegistrationRequestFactory.kbsAuthCredentialCheckRequest(
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
credentials: credentialCandidates
|
||||
)
|
||||
mockURLSession.addResponse(
|
||||
@ -1005,7 +1005,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.submitCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1026,7 +1026,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
scheduler.run(atTime: 6) {
|
||||
let expectedRequest = RegistrationRequestFactory.createAccountRequest(
|
||||
verificationMethod: .sessionId(Stubs.sessionId),
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
authPassword: "", // Doesn't matter for request generation.
|
||||
accountAttributes: Stubs.accountAttributes(),
|
||||
skipDeviceTransfer: true
|
||||
@ -1126,7 +1126,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
public func testSessionPath_invalidE164() {
|
||||
setUpSessionPath()
|
||||
|
||||
let badE164 = "555555555555"
|
||||
let badE164 = E164("+15555555555")!
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(badE164)
|
||||
@ -1159,7 +1159,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
let retryTimeInterval: TimeInterval = 5
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, reject with a rate limit.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
@ -1176,7 +1176,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(
|
||||
Stubs.phoneNumberEntryState(
|
||||
previouslyEnteredE164: Stubs.e164.stringValue,
|
||||
previouslyEnteredE164: Stubs.e164,
|
||||
withValidationErrorFor: .retryAfter(retryTimeInterval)
|
||||
)
|
||||
)
|
||||
@ -1187,13 +1187,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
setUpSessionPath()
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session, but with SMS code rate limiting already.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 10,
|
||||
nextCall: 0,
|
||||
@ -1214,7 +1214,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(
|
||||
Stubs.phoneNumberEntryState(
|
||||
previouslyEnteredE164: Stubs.e164.stringValue,
|
||||
previouslyEnteredE164: Stubs.e164,
|
||||
withValidationErrorFor: .retryAfter(10)
|
||||
)
|
||||
)
|
||||
@ -1225,7 +1225,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
setUpSessionPath()
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// We'll ask for a push challenge, though we won't resolve it in this test.
|
||||
self.pushRegistrationManagerMock.receivePreAuthChallengeTokenMock = {
|
||||
@ -1236,7 +1236,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1256,7 +1256,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 10,
|
||||
nextCall: 0,
|
||||
@ -1278,7 +1278,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(
|
||||
Stubs.phoneNumberEntryState(
|
||||
previouslyEnteredE164: Stubs.e164.stringValue,
|
||||
previouslyEnteredE164: Stubs.e164,
|
||||
withValidationErrorFor: .retryAfter(10)
|
||||
)
|
||||
)
|
||||
@ -1289,13 +1289,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
setUpSessionPath()
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session with a captcha challenge.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1324,7 +1324,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1346,7 +1346,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1379,7 +1379,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1402,7 +1402,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: secondCodeDate,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1440,7 +1440,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// Prepare to provide the challenge token.
|
||||
let (challengeTokenPromise, challengeTokenFuture) = Guarantee<String>.pending()
|
||||
@ -1453,7 +1453,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1474,7 +1474,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1490,7 +1490,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1513,7 +1513,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1535,7 +1535,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1575,7 +1575,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// Prepare to provide the challenge token.
|
||||
let (challengeTokenPromise, challengeTokenFuture) = Guarantee<String>.pending()
|
||||
@ -1588,7 +1588,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1626,7 +1626,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// We'll never provide a challenge token and will just leave it around forever.
|
||||
let (challengeTokenPromise, _) = Guarantee<String>.pending()
|
||||
@ -1639,7 +1639,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1666,7 +1666,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// We'll ask for a push challenge, though we don't need to resolve it in this test.
|
||||
self.pushRegistrationManagerMock.receivePreAuthChallengeTokenMock = {
|
||||
@ -1678,7 +1678,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1695,7 +1695,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(scheduler.currentTime, 2)
|
||||
XCTAssertEqual(
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(Stubs.phoneNumberEntryState(previouslyEnteredE164: Stubs.e164.stringValue))
|
||||
.phoneNumberEntry(Stubs.phoneNumberEntryState(previouslyEnteredE164: Stubs.e164))
|
||||
)
|
||||
XCTAssertNil(sessionManager.latestChallengeFulfillment)
|
||||
}
|
||||
@ -1715,13 +1715,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session with multiple challenges.
|
||||
sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1739,7 +1739,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1754,7 +1754,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1795,7 +1795,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// Prepare to provide the challenge token.
|
||||
let (challengeTokenPromise, challengeTokenFuture) = Guarantee<String>.pending()
|
||||
@ -1808,7 +1808,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1848,13 +1848,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session with multiple challenges.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1877,13 +1877,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
setUpSessionPath()
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session with a captcha challenge and an unknown challenge.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1914,7 +1914,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.fulfillChallengeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1943,7 +1943,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.submitCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .rejectedArgument(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -1975,7 +1975,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.submitCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2004,7 +2004,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 7,
|
||||
nextCall: 0,
|
||||
@ -2036,7 +2036,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 6,
|
||||
nextCall: 0.1,
|
||||
@ -2056,7 +2056,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 5,
|
||||
nextCall: 4,
|
||||
@ -2092,7 +2092,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.submitCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .disallowed(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2118,7 +2118,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(Stubs.phoneNumberEntryState(
|
||||
previouslyEnteredE164: Stubs.e164.stringValue
|
||||
previouslyEnteredE164: Stubs.e164
|
||||
))
|
||||
)
|
||||
}
|
||||
@ -2131,7 +2131,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.submitCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .retryAfterTimeout(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2157,7 +2157,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(
|
||||
nextStep.value,
|
||||
.phoneNumberEntry(Stubs.phoneNumberEntryState(
|
||||
previouslyEnteredE164: Stubs.e164.stringValue
|
||||
previouslyEnteredE164: Stubs.e164
|
||||
))
|
||||
)
|
||||
}
|
||||
@ -2166,13 +2166,13 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
setUpSessionPath()
|
||||
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
var nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
var nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// At t=2, give back a session thats ready to go.
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2197,7 +2197,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2236,7 +2236,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
XCTAssertEqual(nextStep.value, .showErrorSheet(.sessionInvalidated))
|
||||
nextStep = coordinator.nextStep()
|
||||
scheduler.runUntilIdle()
|
||||
XCTAssertEqual(nextStep.value, .phoneNumberEntry(Stubs.phoneNumberEntryState(previouslyEnteredE164: Stubs.e164.stringValue)))
|
||||
XCTAssertEqual(nextStep.value, .phoneNumberEntry(Stubs.phoneNumberEntryState(previouslyEnteredE164: Stubs.e164)))
|
||||
}
|
||||
|
||||
// MARK: - Profile Setup Path
|
||||
@ -2299,7 +2299,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
|
||||
preservingSchedulerState {
|
||||
// Give it a phone number, which should cause it to start a session.
|
||||
let nextStep = coordinator.submitE164(Stubs.e164.stringValue)
|
||||
let nextStep = coordinator.submitE164(Stubs.e164)
|
||||
|
||||
// We'll ask for a push challenge, though we won't resolve it.
|
||||
self.pushRegistrationManagerMock.receivePreAuthChallengeTokenMock = {
|
||||
@ -2310,7 +2310,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.beginSessionResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2330,7 +2330,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
self.sessionManager.requestCodeResponse = self.scheduler.guarantee(
|
||||
resolvingWith: .success(RegistrationSession(
|
||||
id: Stubs.sessionId,
|
||||
e164: Stubs.e164.stringValue,
|
||||
e164: Stubs.e164,
|
||||
receivedDate: self.date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2439,7 +2439,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
static func session(hasSentVerificationCode: Bool) -> RegistrationSession {
|
||||
return RegistrationSession(
|
||||
id: UUID().uuidString,
|
||||
e164: e164.stringValue,
|
||||
e164: e164,
|
||||
receivedDate: date,
|
||||
nextSMS: 0,
|
||||
nextCall: 0,
|
||||
@ -2470,7 +2470,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
static func phoneNumberEntryState(
|
||||
previouslyEnteredE164: String? = nil,
|
||||
previouslyEnteredE164: E164? = nil,
|
||||
withValidationErrorFor response: Registration.BeginSessionResponse = .success(Stubs.session(hasSentVerificationCode: false))
|
||||
) -> RegistrationPhoneNumberState {
|
||||
let validationError: RegistrationPhoneNumberValidationError?
|
||||
@ -2478,7 +2478,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
case .success:
|
||||
validationError = nil
|
||||
case .invalidArgument:
|
||||
validationError = .invalidNumber(invalidE164: previouslyEnteredE164 ?? Stubs.e164.stringValue)
|
||||
validationError = .invalidNumber(invalidE164: previouslyEnteredE164 ?? Stubs.e164)
|
||||
case .retryAfter(let timeInterval):
|
||||
validationError = .rateLimited(expiration: self.date.addingTimeInterval(timeInterval))
|
||||
case .networkFailure, .genericError:
|
||||
@ -2494,7 +2494,7 @@ public class RegistrationCoordinatorTest: XCTestCase {
|
||||
}
|
||||
|
||||
static func verificationCodeEntryState(
|
||||
e164: String = Stubs.e164.stringValue,
|
||||
e164: E164 = Stubs.e164,
|
||||
nextSMS: TimeInterval? = 0,
|
||||
nextCall: TimeInterval? = 0,
|
||||
nextVerificationAttempt: TimeInterval = 0,
|
||||
|
||||
@ -20,7 +20,7 @@ public class RegistrationSessionManagerMock: RegistrationSessionManager {
|
||||
public var beginSessionResponse: Guarantee<Registration.BeginSessionResponse>?
|
||||
public var didBeginOrRestoreSession = false
|
||||
|
||||
public func beginOrRestoreSession(e164: String, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse> {
|
||||
public func beginOrRestoreSession(e164: E164, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse> {
|
||||
didBeginOrRestoreSession = true
|
||||
return beginSessionResponse!
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ public struct RegistrationSession: Codable, Equatable {
|
||||
public let id: String
|
||||
|
||||
/// The phone number (in e164 format) this session was created for.
|
||||
public let e164: String
|
||||
public let e164: E164
|
||||
|
||||
/// The date at which we received this session metadata from the server.
|
||||
/// All durations should be measured against this date.
|
||||
|
||||
@ -13,7 +13,7 @@ public protocol RegistrationSessionManager {
|
||||
|
||||
/// Begins a new session, first attempting to restore any existing valid session for the same number.
|
||||
/// See `Registration.BeginSessionResponse` for possible responses, including errors.
|
||||
func beginOrRestoreSession(e164: String, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse>
|
||||
func beginOrRestoreSession(e164: E164, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse>
|
||||
|
||||
/// Fulfill a challenge for the session (e.g. a captcha).
|
||||
/// See `Registration.UpdateSessionResponse` for possible responses, including errors.
|
||||
|
||||
@ -35,7 +35,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
return restoreSession(forE164: nil)
|
||||
}
|
||||
|
||||
public func beginOrRestoreSession(e164: String, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse> {
|
||||
public func beginOrRestoreSession(e164: E164, apnsToken: String?) -> Guarantee<Registration.BeginSessionResponse> {
|
||||
// Verify the session is still valid.
|
||||
return restoreSession(forE164: e164)
|
||||
.then(on: schedulers.sync) { [weak self, db, schedulers] restoredSession in
|
||||
@ -167,7 +167,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
|
||||
// TODO: make this and other methods resilient to transient network failures by adding
|
||||
// basic retrying logic.
|
||||
private func restoreSession(forE164 e164: String?) -> Guarantee<RegistrationSession?> {
|
||||
private func restoreSession(forE164 e164: E164?) -> Guarantee<RegistrationSession?> {
|
||||
guard let existingSession = db.read(block: { self.getPersistedSession($0) }) else {
|
||||
return .value(nil)
|
||||
}
|
||||
@ -195,7 +195,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
// MARK: Begin Session
|
||||
|
||||
private func makeBeginSessionRequest(
|
||||
e164: String,
|
||||
e164: E164,
|
||||
apnsToken: String?,
|
||||
mcc: String?,
|
||||
mnc: String?
|
||||
@ -216,7 +216,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
}
|
||||
|
||||
private func handleBeginSessionResponse(
|
||||
forE164 e164: String,
|
||||
forE164 e164: E164,
|
||||
statusCode: Int,
|
||||
retryAfterHeader: String?,
|
||||
bodyData: Data?
|
||||
@ -515,7 +515,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
|
||||
private func registrationSession(
|
||||
fromResponseBody bodyData: Data?,
|
||||
e164: String
|
||||
e164: E164
|
||||
) -> RegistrationSession? {
|
||||
guard let bodyData else {
|
||||
Logger.warn("Got empty registration session response")
|
||||
@ -560,8 +560,8 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
|
||||
private func makeRequest<ResponseType>(
|
||||
_ request: TSRequest,
|
||||
e164: String,
|
||||
handler: @escaping (_ e164: String, _ statusCode: Int, _ retryAfterHeader: String?, _ bodyData: Data?) -> ResponseType,
|
||||
e164: E164,
|
||||
handler: @escaping (_ e164: E164, _ statusCode: Int, _ retryAfterHeader: String?, _ bodyData: Data?) -> ResponseType,
|
||||
fallbackError: ResponseType,
|
||||
networkFailureError: ResponseType
|
||||
) -> Guarantee<ResponseType> {
|
||||
@ -611,7 +611,7 @@ public class RegistrationSessionManagerImpl: RegistrationSessionManager {
|
||||
fileprivate extension RegistrationServiceResponses.RegistrationSession {
|
||||
|
||||
func toLocalSession(
|
||||
forE164 e164: String,
|
||||
forE164 e164: E164,
|
||||
receivedAt: Date
|
||||
) -> RegistrationSession {
|
||||
let mappedChallenges = requestedInformation.compactMap(\.asLocalChallenge)
|
||||
|
||||
@ -11,13 +11,11 @@ public enum RegistrationRequestFactory {
|
||||
|
||||
/// See `RegistrationServiceResponses.BeginSessionResponseCodes` for possible responses.
|
||||
public static func beginSessionRequest(
|
||||
e164: String,
|
||||
e164: E164,
|
||||
pushToken: String?,
|
||||
mcc: String?,
|
||||
mnc: String?
|
||||
) -> TSRequest {
|
||||
owsAssertDebug(!e164.isEmpty)
|
||||
|
||||
let urlPathComponents = URLPathComponents(
|
||||
["v1", "verification", "session"]
|
||||
)
|
||||
@ -26,7 +24,7 @@ public enum RegistrationRequestFactory {
|
||||
let url = urlComponents.url!
|
||||
|
||||
var parameters: [String: Any] = [
|
||||
"number": e164
|
||||
"number": e164.stringValue
|
||||
]
|
||||
if let pushToken {
|
||||
owsAssertDebug(!pushToken.isEmpty)
|
||||
@ -170,7 +168,7 @@ public enum RegistrationRequestFactory {
|
||||
// MARK: - KBS Auth Check
|
||||
|
||||
public static func kbsAuthCredentialCheckRequest(
|
||||
e164: String,
|
||||
e164: E164,
|
||||
credentials: [KBSAuthCredential]
|
||||
) -> TSRequest {
|
||||
owsAssertDebug(!credentials.isEmpty)
|
||||
@ -216,7 +214,7 @@ public enum RegistrationRequestFactory {
|
||||
/// response indicating that the client should prompt the user to transfer data from an existing device.
|
||||
public static func createAccountRequest(
|
||||
verificationMethod: VerificationMethod,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
authPassword: String,
|
||||
accountAttributes: AccountAttributes,
|
||||
skipDeviceTransfer: Bool
|
||||
@ -246,7 +244,7 @@ public enum RegistrationRequestFactory {
|
||||
result.shouldHaveAuthorizationHeaders = true
|
||||
result.addValue("OWI", forHTTPHeaderField: "X-Signal-Agent")
|
||||
// As odd as this is, it is to spec.
|
||||
result.authUsername = e164
|
||||
result.authUsername = e164.stringValue
|
||||
result.authPassword = authPassword
|
||||
return result
|
||||
}
|
||||
@ -262,7 +260,7 @@ public enum RegistrationRequestFactory {
|
||||
/// kbs master key.
|
||||
public static func changeNumberRequest(
|
||||
verificationMethod: VerificationMethod,
|
||||
e164: String,
|
||||
e164: E164,
|
||||
reglockToken: String?
|
||||
) -> TSRequest {
|
||||
let urlPathComponents = URLPathComponents(
|
||||
@ -273,7 +271,7 @@ public enum RegistrationRequestFactory {
|
||||
let url = urlComponents.url!
|
||||
|
||||
var parameters: [String: Any] = [
|
||||
"number": e164
|
||||
"number": e164.stringValue
|
||||
]
|
||||
switch verificationMethod {
|
||||
case .sessionId(let sessionId):
|
||||
|
||||
@ -165,7 +165,7 @@ public class RegistrationSessionManagerTest: XCTestCase {
|
||||
}
|
||||
|
||||
public func testBeginOrRestoreSession() throws {
|
||||
let e164 = "+17875550100"
|
||||
let e164 = E164("+17875550100")!
|
||||
let apnsToken = "1234"
|
||||
let beginSessionRequest = RegistrationRequestFactory.beginSessionRequest(
|
||||
e164: e164,
|
||||
@ -301,7 +301,7 @@ public class RegistrationSessionManagerTest: XCTestCase {
|
||||
XCTAssertEqual(savedSession, responseSession)
|
||||
|
||||
// If we try and request with a different e164 it should also get a new session and wipe the old one.
|
||||
let newE164 = "+17875550101"
|
||||
let newE164 = E164("+17875550101")!
|
||||
responseBody = stubWireSession()
|
||||
responseSession = sessionConverter(responseBody, e164: newE164)
|
||||
|
||||
@ -542,7 +542,7 @@ public class RegistrationSessionManagerTest: XCTestCase {
|
||||
private func stubSession() -> RegistrationSession {
|
||||
return RegistrationSession(
|
||||
id: UUID().uuidString,
|
||||
e164: "+17875550100", // For our purposes, can be fixed.
|
||||
e164: E164("+17875550100")!, // For our purposes, can be fixed.
|
||||
receivedDate: date,
|
||||
nextSMS: 1,
|
||||
nextCall: 1,
|
||||
@ -572,7 +572,7 @@ public class RegistrationSessionManagerTest: XCTestCase {
|
||||
// Keep this independent of the production code converter for an extra layer of durability.
|
||||
private func sessionConverter(
|
||||
_ wireSession: RegistrationServiceResponses.RegistrationSession,
|
||||
e164: String = "+17875550100"
|
||||
e164: E164 = E164("+17875550100")!
|
||||
) -> RegistrationSession {
|
||||
let requestedInformation: [RegistrationSession.Challenge] = wireSession.requestedInformation.compactMap {
|
||||
switch $0 {
|
||||
|
||||
@ -93,26 +93,24 @@ public struct RegistrationCountryState: Equatable, Dependencies {
|
||||
public struct RegistrationPhoneNumber {
|
||||
public let countryState: RegistrationCountryState
|
||||
public let nationalNumber: String
|
||||
public let e164: String
|
||||
public let e164: E164?
|
||||
|
||||
public init(countryState: RegistrationCountryState, nationalNumber: String) {
|
||||
self.countryState = countryState
|
||||
self.nationalNumber = nationalNumber
|
||||
|
||||
self.e164 = "\(countryState.callingCode)\(nationalNumber)"
|
||||
self.e164 = E164("\(countryState.callingCode)\(nationalNumber)")
|
||||
}
|
||||
|
||||
public init?(e164: String) {
|
||||
self.e164 = e164
|
||||
|
||||
public init?(e164: E164) {
|
||||
guard
|
||||
let countryState = RegistrationCountryState.countryState(forE164: e164),
|
||||
let nationalNumber = PhoneNumber(fromE164: e164)?.nationalNumber
|
||||
let countryState = RegistrationCountryState.countryState(forE164: e164.stringValue),
|
||||
let nationalNumber = PhoneNumber(fromE164: e164.stringValue)?.nationalNumber
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
self.countryState = countryState
|
||||
self.nationalNumber = nationalNumber
|
||||
self.e164 = e164
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user