Support updated API

This commit is contained in:
Ali 2021-06-22 17:46:03 +04:00
parent 77e55e973c
commit d162be39d5
6 changed files with 123 additions and 53 deletions

View File

@ -952,7 +952,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
switch value {
case .notSet:
break
case let .set(hint, _, _, _):
case let .set(hint, _, _, _, _):
if !hint.isEmpty {
strongSelf.passwordTip = hint
}

View File

@ -26,8 +26,9 @@ private final class TwoStepVerificationUnlockSettingsControllerArguments {
let openResetPendingEmail: () -> Void
let updateEmailCode: (String) -> Void
let openConfirmEmail: () -> Void
let declinePasswordReset: () -> Void
init(updatePasswordText: @escaping (String) -> Void, checkPassword: @escaping () -> Void, openForgotPassword: @escaping () -> Void, openSetupPassword: @escaping () -> Void, openDisablePassword: @escaping () -> Void, openSetupEmail: @escaping () -> Void, openResetPendingEmail: @escaping () -> Void, updateEmailCode: @escaping (String) -> Void, openConfirmEmail: @escaping () -> Void) {
init(updatePasswordText: @escaping (String) -> Void, checkPassword: @escaping () -> Void, openForgotPassword: @escaping () -> Void, openSetupPassword: @escaping () -> Void, openDisablePassword: @escaping () -> Void, openSetupEmail: @escaping () -> Void, openResetPendingEmail: @escaping () -> Void, updateEmailCode: @escaping (String) -> Void, openConfirmEmail: @escaping () -> Void, declinePasswordReset: @escaping () -> Void) {
self.updatePasswordText = updatePasswordText
self.checkPassword = checkPassword
self.openForgotPassword = openForgotPassword
@ -37,6 +38,7 @@ private final class TwoStepVerificationUnlockSettingsControllerArguments {
self.openResetPendingEmail = openResetPendingEmail
self.updateEmailCode = updateEmailCode
self.openConfirmEmail = openConfirmEmail
self.declinePasswordReset = declinePasswordReset
}
}
@ -132,47 +134,51 @@ private enum TwoStepVerificationUnlockSettingsEntry: ItemListNodeEntry {
}, action: {
arguments.checkPassword()
})
case let .passwordEntryInfo(theme, text):
case let .passwordEntryInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { action in
switch action {
case .tap:
arguments.openForgotPassword()
case let .tap(item):
if item == "forgot" {
arguments.openForgotPassword()
} else if item == "declineReset" {
arguments.declinePasswordReset()
}
}
})
case let .passwordSetup(theme, text):
case let .passwordSetup(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openSetupPassword()
})
case let .passwordSetupInfo(theme, text):
case let .passwordSetupInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
case let .changePassword(theme, text):
case let .changePassword(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openSetupPassword()
})
case let .turnPasswordOff(theme, text):
case let .turnPasswordOff(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openDisablePassword()
})
case let .setupRecoveryEmail(theme, text):
case let .setupRecoveryEmail(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openSetupEmail()
})
case let .passwordInfo(theme, text):
case let .passwordInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .pendingEmailConfirmInfo(theme, text):
case let .pendingEmailConfirmInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .pendingEmailConfirmCode(theme, strings, title, text):
case let .pendingEmailConfirmCode(_, _, title, text):
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: ""), text: text, placeholder: title, type: .number, sectionId: self.section, textUpdated: { value in
arguments.updateEmailCode(value)
}, action: {})
case let .pendingEmailInfo(theme, text):
case let .pendingEmailInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { action in
switch action {
case .tap:
arguments.openResetPendingEmail()
}
})
case let .pendingEmailOpenConfirm(theme, text):
case let .pendingEmailOpenConfirm(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openConfirmEmail()
})
@ -204,13 +210,27 @@ private func twoStepVerificationUnlockSettingsControllerEntries(presentationData
entries.append(.passwordSetup(presentationData.theme, presentationData.strings.TwoStepAuth_SetPassword))
entries.append(.passwordSetupInfo(presentationData.theme, presentationData.strings.TwoStepAuth_SetPasswordHelp))
}
case let .set(hint, _, _):
case let .set(hint, _, _, pendingResetTimestamp):
entries.append(.passwordEntry(presentationData.theme, presentationData.strings, presentationData.strings.TwoStepAuth_EnterPasswordPassword, state.passwordText))
if hint.isEmpty {
entries.append(.passwordEntryInfo(presentationData.theme, presentationData.strings.TwoStepAuth_EnterPasswordHelp + "\n\n[" + presentationData.strings.TwoStepAuth_EnterPasswordForgot + "](forgot)"))
var text: String = presentationData.strings.TwoStepAuth_EnterPasswordHint(escapedPlaintextForMarkdown(hint)).0 + "\n\n" + presentationData.strings.TwoStepAuth_EnterPasswordHelp + "\n\n[" + presentationData.strings.TwoStepAuth_EnterPasswordForgot + "](forgot)"
if !hint.isEmpty {
text = presentationData.strings.TwoStepAuth_EnterPasswordHint(escapedPlaintextForMarkdown(hint)).0 + "\n\n" + presentationData.strings.TwoStepAuth_EnterPasswordHelp + "\n\n[" + presentationData.strings.TwoStepAuth_EnterPasswordForgot + "](forgot)"
} else {
entries.append(.passwordEntryInfo(presentationData.theme, presentationData.strings.TwoStepAuth_EnterPasswordHint(escapedPlaintextForMarkdown(hint)).0 + "\n\n" + presentationData.strings.TwoStepAuth_EnterPasswordHelp + "\n\n[" + presentationData.strings.TwoStepAuth_EnterPasswordForgot + "](forgot)"))
text = presentationData.strings.TwoStepAuth_EnterPasswordHelp + "\n\n[" + presentationData.strings.TwoStepAuth_EnterPasswordForgot + "](forgot)"
}
if let pendingResetTimestamp = pendingResetTimestamp {
let remainingSeconds = pendingResetTimestamp - Int32(Date().timeIntervalSince1970)
if remainingSeconds <= 0 {
text.append("\nPassword reset is available")
} else {
text.append("\nPassword reset available in \(remainingSeconds) s")
}
text.append("\n[Cancel reset](declineReset)")
}
entries.append(.passwordEntryInfo(presentationData.theme, text))
}
}
case let .manage(_, emailSet, pendingEmail, _):
@ -240,14 +260,14 @@ struct TwoStepVerificationPendingEmailState: Equatable {
enum TwoStepVerificationAccessConfiguration: Equatable {
case notSet(pendingEmail: TwoStepVerificationPendingEmailState?)
case set(hint: String, hasRecoveryEmail: Bool, hasSecureValues: Bool)
case set(hint: String, hasRecoveryEmail: Bool, hasSecureValues: Bool, pendingResetTimestamp: Int32?)
init(configuration: TwoStepVerificationConfiguration, password: String?) {
switch configuration {
case let .notSet(pendingEmail):
self = .notSet(pendingEmail: pendingEmail.flatMap({ TwoStepVerificationPendingEmailState(password: password, email: $0) }))
case let .set(hint, hasRecoveryEmail, _, hasSecureValues):
self = .set(hint: hint, hasRecoveryEmail: hasRecoveryEmail, hasSecureValues: hasSecureValues)
case let .set(hint, hasRecoveryEmail, _, hasSecureValues, pendingResetTimestamp):
self = .set(hint: hint, hasRecoveryEmail: hasRecoveryEmail, hasSecureValues: hasSecureValues, pendingResetTimestamp: pendingResetTimestamp)
}
}
}
@ -420,7 +440,6 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|> mapToSignal { settings -> Signal<(TwoStepVerificationSettings, TwoStepVerificationPendingEmail?), AuthorizationPasswordVerificationError> in
return twoStepVerificationConfiguration(account: context.account)
|> mapError { _ -> AuthorizationPasswordVerificationError in
return .generic
}
|> map { configuration in
var pendingEmail: TwoStepVerificationPendingEmail?
@ -469,7 +488,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
if let configuration = configuration {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
switch configuration {
case let .set(_, hasRecoveryEmail, _):
case let .set(_, hasRecoveryEmail, _, pendingResetTimestamp):
if hasRecoveryEmail {
updateState { state in
var state = state
@ -506,7 +525,23 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}))
} else {
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.TwoStepAuth_RecoveryUnavailable, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
if true || pendingResetTimestamp == nil {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done, .waitingForReset:
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
case .declined:
break
case let .error(reason):
break
}
})
} else {
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.TwoStepAuth_RecoveryUnavailable, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
}
case .notSet:
break
@ -762,6 +797,13 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
})
}, declinePasswordReset: {
let _ = (declineTwoStepPasswordReset(network: context.account.network)
|> deliverOnMainQueue).start(completed: {
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
})
})
var initialFocusImpl: (() -> Void)?

View File

@ -370,6 +370,7 @@ public struct TwoStepAuthData {
public let unconfirmedEmailPattern: String?
public let secretRandom: Data
public let nextSecurePasswordDerivation: TwoStepSecurePasswordDerivation
public let pendingResetTimestamp: Int32?
}
public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
@ -398,7 +399,7 @@ public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpc
srpSessionData = TwoStepSRPSessionData(id: srpId, B: srpB.makeData())
}
return TwoStepAuthData(nextPasswordDerivation: nextDerivation, currentPasswordDerivation: currentDerivation, srpSessionData: srpSessionData, hasRecovery: hasRecovery, hasSecretValues: hasSecureValues, currentHint: hint, unconfirmedEmailPattern: emailUnconfirmedPattern, secretRandom: secureRandom.makeData(), nextSecurePasswordDerivation: nextSecureDerivation)
return TwoStepAuthData(nextPasswordDerivation: nextDerivation, currentPasswordDerivation: currentDerivation, srpSessionData: srpSessionData, hasRecovery: hasRecovery, hasSecretValues: hasSecureValues, currentHint: hint, unconfirmedEmailPattern: emailUnconfirmedPattern, secretRandom: secureRandom.makeData(), nextSecurePasswordDerivation: nextSecureDerivation, pendingResetTimestamp: pendingResetDate)
}
}
}

View File

@ -374,7 +374,7 @@ public enum PasswordRecoveryError {
}
public func checkPasswordRecoveryCode(network: Network, code: String) -> Signal<Never, PasswordRecoveryError> {
return network.request(Api.functions.auth.checkRecoveryPassword(code: code))
return network.request(Api.functions.auth.checkRecoveryPassword(code: code), automaticFloodWait: false)
|> mapError { error -> PasswordRecoveryError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
@ -416,7 +416,7 @@ public func performPasswordRecovery(accountManager: AccountManager, account: Una
if newSettings != nil {
flags |= 1 << 0
}
return account.network.request(Api.functions.auth.recoverPassword(flags: flags, code: code, newSettings: newSettings))
return account.network.request(Api.functions.auth.recoverPassword(flags: flags, code: code, newSettings: newSettings), automaticFloodWait: false)
|> mapError { error -> PasswordRecoveryError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded

View File

@ -8,7 +8,7 @@ import SyncCore
public enum TwoStepVerificationConfiguration {
case notSet(pendingEmail: TwoStepVerificationPendingEmail?)
case set(hint: String, hasRecoveryEmail: Bool, pendingEmail: TwoStepVerificationPendingEmail?, hasSecureValues: Bool)
case set(hint: String, hasRecoveryEmail: Bool, pendingEmail: TwoStepVerificationPendingEmail?, hasSecureValues: Bool, pendingResetTimestamp: Int32?)
}
public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStepVerificationConfiguration, NoError> {
@ -18,7 +18,7 @@ public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStep
switch result {
case let .password(password):
if password.currentAlgo != nil {
return .set(hint: password.hint ?? "", hasRecoveryEmail: (password.flags & (1 << 0)) != 0, pendingEmail: password.emailUnconfirmedPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: nil) }), hasSecureValues: (password.flags & (1 << 1)) != 0)
return .set(hint: password.hint ?? "", hasRecoveryEmail: (password.flags & (1 << 0)) != 0, pendingEmail: password.emailUnconfirmedPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: nil) }), hasSecureValues: (password.flags & (1 << 1)) != 0, pendingResetTimestamp: password.pendingResetDate)
} else {
return .notSet(pendingEmail: password.emailUnconfirmedPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: nil) }))
}
@ -413,3 +413,53 @@ public func requestTemporaryTwoStepPasswordToken(account: Account, password: Str
}
}
}
public enum RequestTwoStepPasswordResetResult {
public enum ErrorReason {
case generic
case limitExceeded
}
case done
case waitingForReset(resetAtTimestamp: Int32)
case declined
case error(reason: ErrorReason)
}
public func requestTwoStepPasswordReset(network: Network) -> Signal<RequestTwoStepPasswordResetResult, NoError> {
return network.request(Api.functions.account.resetPassword(), automaticFloodWait: false)
|> map { _ -> RequestTwoStepPasswordResetResult in
return .done
}
|> `catch` { error -> Signal<RequestTwoStepPasswordResetResult, NoError> in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .single(.error(reason: .limitExceeded))
} else if error.errorDescription.hasPrefix("RESET_WAIT_") {
if let remainingSeconds = Int32(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "RESET_WAIT_".count)...]) {
let timestamp = Int32(network.globalTime)
return .single(.waitingForReset(resetAtTimestamp: timestamp + remainingSeconds))
} else {
return .single(.error(reason: .generic))
}
} else if error.errorDescription.hasPrefix("RESET_PREVIOUS_WAIT_") {
if let remainingSeconds = Int32(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "RESET_PREVIOUS_WAIT_".count)...]) {
let timestamp = Int32(network.globalTime)
return .single(.waitingForReset(resetAtTimestamp: timestamp + remainingSeconds))
} else {
return .single(.error(reason: .generic))
}
} else if error.errorDescription == "RESET_PREVIOUS_DECLINE" {
return .single(.declined)
} else {
return .single(.error(reason: .generic))
}
}
}
public func declineTwoStepPasswordReset(network: Network) -> Signal<Never, NoError> {
return network.request(Api.functions.account.declinePasswordReset())
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> ignoreValues
}

View File

@ -604,29 +604,6 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
})
strongSelf.setViewControllers(strongSelf.viewControllers + [setupController], animated: true)
}))
/*controller?.inProgress = true
strongSelf.actionDisposable.set((performPasswordRecovery(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, code: code, syncContacts: syncContacts, updatedPassword: .password(password: "123", hint: "", email: nil))
|> deliverOnMainQueue).start(error: { error in
Queue.mainQueue().async {
if let strongSelf = self, let controller = controller {
controller.inProgress = false
let text: String
switch error {
case .limitExceeded:
text = strongSelf.presentationData.strings.LoginPassword_FloodError
case .invalidCode:
text = strongSelf.presentationData.strings.Login_InvalidCodeError
case .expired:
text = strongSelf.presentationData.strings.Login_CodeExpiredError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))*/
}
controller.noAccess = { [weak self, weak controller] in
if let strongSelf = self, let controller = controller {