mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Ask for a new password when recovering by email.
This commit is contained in:
parent
5a882d1fdc
commit
c3595f2e31
9 changed files with 256 additions and 143 deletions
|
@ -189,21 +189,33 @@ PasscodeBox::PasscodeBox(
|
|||
|
||||
PasscodeBox::PasscodeBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<MTP::Instance*> mtp,
|
||||
Main::Session *session,
|
||||
const CloudFields &fields)
|
||||
: _session(session)
|
||||
, _api(&_session->mtp())
|
||||
, _api(mtp)
|
||||
, _turningOff(fields.turningOff)
|
||||
, _cloudPwd(true)
|
||||
, _cloudFields(fields)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, tr::lng_cloud_password_enter_old())
|
||||
, _newPasscode(this, st::defaultInputField, fields.curRequest ? tr::lng_cloud_password_enter_new() : tr::lng_cloud_password_enter_first())
|
||||
, _newPasscode(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
(fields.curRequest
|
||||
? tr::lng_cloud_password_enter_new()
|
||||
: tr::lng_cloud_password_enter_first()))
|
||||
, _reenterPasscode(this, st::defaultInputField, tr::lng_cloud_password_confirm_new())
|
||||
, _passwordHint(this, st::defaultInputField, fields.curRequest ? tr::lng_cloud_password_change_hint() : tr::lng_cloud_password_hint())
|
||||
, _passwordHint(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
(fields.curRequest
|
||||
? tr::lng_cloud_password_change_hint()
|
||||
: tr::lng_cloud_password_hint()))
|
||||
, _recoverEmail(this, st::defaultInputField, tr::lng_cloud_password_email())
|
||||
, _recover(this, tr::lng_signin_recover(tr::now))
|
||||
, _showRecoverLink(_cloudFields.hasRecovery || !_cloudFields.pendingResetDate) {
|
||||
Expects(session != nullptr || !fields.fromRecoveryCode.isEmpty());
|
||||
Expects(!_turningOff || _cloudFields.curRequest);
|
||||
|
||||
if (!_cloudFields.hint.isEmpty()) {
|
||||
|
@ -213,6 +225,13 @@ PasscodeBox::PasscodeBox(
|
|||
}
|
||||
}
|
||||
|
||||
PasscodeBox::PasscodeBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
const CloudFields &fields)
|
||||
: PasscodeBox(nullptr, &session->mtp(), session, fields) {
|
||||
}
|
||||
|
||||
rpl::producer<QByteArray> PasscodeBox::newPasswordSet() const {
|
||||
return _newPasswordSet.events();
|
||||
}
|
||||
|
@ -225,6 +244,10 @@ rpl::producer<> PasscodeBox::clearUnconfirmedPassword() const {
|
|||
return _clearUnconfirmedPassword.events();
|
||||
}
|
||||
|
||||
rpl::producer<MTPauth_Authorization> PasscodeBox::newAuthorization() const {
|
||||
return _newAuthorization.events();
|
||||
}
|
||||
|
||||
bool PasscodeBox::currentlyHave() const {
|
||||
return _cloudPwd
|
||||
? (!!_cloudFields.curRequest)
|
||||
|
@ -272,9 +295,11 @@ void PasscodeBox::prepare() {
|
|||
} else {
|
||||
_oldPasscode->hide();
|
||||
setTitle(_cloudPwd
|
||||
? tr::lng_cloud_password_create()
|
||||
? (_cloudFields.fromRecoveryCode.isEmpty()
|
||||
? tr::lng_cloud_password_create()
|
||||
: tr::lng_cloud_password_change())
|
||||
: tr::lng_passcode_create());
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + (_cloudPwd ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) : st::passcodePadding.bottom()));
|
||||
setDimensions(st::boxWidth, st::passcodePadding.top() + _newPasscode->height() + st::passcodeLittleSkip + _reenterPasscode->height() + st::passcodeSkip + (_cloudPwd ? _passwordHint->height() + st::passcodeLittleSkip : 0) + st::passcodeAboutSkip + _aboutHeight + ((_cloudPwd && _cloudFields.fromRecoveryCode.isEmpty()) ? (st::passcodeLittleSkip + _recoverEmail->height() + st::passcodeSkip) : st::passcodePadding.bottom()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,7 +326,10 @@ void PasscodeBox::prepare() {
|
|||
_newPasscode->setVisible(!onlyCheck);
|
||||
_reenterPasscode->setVisible(!onlyCheck);
|
||||
_passwordHint->setVisible(!onlyCheck && _cloudPwd);
|
||||
_recoverEmail->setVisible(!onlyCheck && _cloudPwd && !has);
|
||||
_recoverEmail->setVisible(!onlyCheck
|
||||
&& _cloudPwd
|
||||
&& !has
|
||||
&& _cloudFields.fromRecoveryCode.isEmpty());
|
||||
}
|
||||
|
||||
void PasscodeBox::submit() {
|
||||
|
@ -400,21 +428,42 @@ void PasscodeBox::setInnerFocus() {
|
|||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::recoverPasswordDone(
|
||||
const QByteArray &newPasswordBytes,
|
||||
const MTPauth_Authorization &result) {
|
||||
if (_replacedBy) {
|
||||
_replacedBy->closeBox();
|
||||
}
|
||||
_setRequest = 0;
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
_newAuthorization.fire_copy(result);
|
||||
_newPasswordSet.fire_copy(newPasswordBytes);
|
||||
if (weak) {
|
||||
getDelegate()->show(Box<InformBox>(
|
||||
tr::lng_cloud_password_updated(tr::now)));
|
||||
if (weak) {
|
||||
closeBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::setPasswordDone(const QByteArray &newPasswordBytes) {
|
||||
if (_replacedBy) {
|
||||
_replacedBy->closeBox();
|
||||
}
|
||||
_setRequest = 0;
|
||||
_newPasswordSet.fire_copy(newPasswordBytes);
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
const auto text = _reenterPasscode->isHidden()
|
||||
? tr::lng_cloud_password_removed(tr::now)
|
||||
: _oldPasscode->isHidden()
|
||||
? tr::lng_cloud_password_was_set(tr::now)
|
||||
: tr::lng_cloud_password_updated(tr::now);
|
||||
getDelegate()->show(Box<InformBox>(text));
|
||||
_newPasswordSet.fire_copy(newPasswordBytes);
|
||||
if (weak) {
|
||||
closeBox();
|
||||
const auto text = _reenterPasscode->isHidden()
|
||||
? tr::lng_cloud_password_removed(tr::now)
|
||||
: _oldPasscode->isHidden()
|
||||
? tr::lng_cloud_password_was_set(tr::now)
|
||||
: tr::lng_cloud_password_updated(tr::now);
|
||||
getDelegate()->show(Box<InformBox>(text));
|
||||
if (weak) {
|
||||
closeBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,25 +848,40 @@ void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
|||
}
|
||||
const auto hint = _passwordHint->getLastText();
|
||||
const auto email = _recoverEmail->getLastText().trimmed();
|
||||
const auto flags = MTPDaccount_passwordInputSettings::Flag::f_new_algo
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_new_password_hash
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_hint
|
||||
| MTPDaccount_passwordInputSettings::Flag::f_email;
|
||||
using Flag = MTPDaccount_passwordInputSettings::Flag;
|
||||
const auto flags = Flag::f_new_algo
|
||||
| Flag::f_new_password_hash
|
||||
| Flag::f_hint
|
||||
| (_cloudFields.fromRecoveryCode.isEmpty() ? Flag::f_email : Flag(0));
|
||||
_checkPasswordCallback = nullptr;
|
||||
_setRequest = _api.request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_inputCheckPasswordEmpty(),
|
||||
MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.newAlgo),
|
||||
MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
MTPSecureSecretSettings())
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone(newPasswordBytes);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
setPasswordFail(newPasswordBytes, email, error);
|
||||
}).handleFloodErrors().send();
|
||||
|
||||
const auto settings = MTP_account_passwordInputSettings(
|
||||
MTP_flags(flags),
|
||||
Core::PrepareCloudPasswordAlgo(_cloudFields.newAlgo),
|
||||
MTP_bytes(newPasswordHash.modpow),
|
||||
MTP_string(hint),
|
||||
MTP_string(email),
|
||||
MTPSecureSecretSettings());
|
||||
if (_cloudFields.fromRecoveryCode.isEmpty()) {
|
||||
_setRequest = _api.request(MTPaccount_UpdatePasswordSettings(
|
||||
MTP_inputCheckPasswordEmpty(),
|
||||
settings
|
||||
)).done([=](const MTPBool &result) {
|
||||
setPasswordDone(newPasswordBytes);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
setPasswordFail(newPasswordBytes, email, error);
|
||||
}).handleFloodErrors().send();
|
||||
} else {
|
||||
_setRequest = _api.request(MTPauth_RecoverPassword(
|
||||
MTP_flags(MTPauth_RecoverPassword::Flag::f_new_settings),
|
||||
MTP_string(_cloudFields.fromRecoveryCode),
|
||||
settings
|
||||
)).done([=](const MTPauth_Authorization &result) {
|
||||
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
setPasswordFail(newPasswordBytes, email, error);
|
||||
}).handleFloodErrors().send();
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::changeCloudPassword(
|
||||
|
@ -1005,6 +1069,7 @@ void PasscodeBox::emailChanged() {
|
|||
|
||||
void PasscodeBox::recoverByEmail() {
|
||||
if (!_cloudFields.hasRecovery) {
|
||||
Assert(_session != nullptr);
|
||||
const auto session = _session;
|
||||
const auto confirmBox = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto reset = crl::guard(this, [=] {
|
||||
|
@ -1036,19 +1101,19 @@ void PasscodeBox::recoverExpired() {
|
|||
}
|
||||
|
||||
void PasscodeBox::recover() {
|
||||
if (_pattern == "-") return;
|
||||
if (_pattern == "-" || !_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
const auto box = getDelegate()->show(Box<RecoverBox>(
|
||||
&_api.instance(),
|
||||
_session,
|
||||
_pattern,
|
||||
_cloudFields.notEmptyPassport,
|
||||
_cloudFields.pendingResetDate != 0,
|
||||
_cloudFields,
|
||||
[weak] { if (weak) { weak->closeBox(); } }));
|
||||
|
||||
box->passwordCleared(
|
||||
) | rpl::map_to(
|
||||
QByteArray()
|
||||
box->newPasswordSet(
|
||||
) | rpl::start_to_stream(_newPasswordSet, lifetime());
|
||||
|
||||
box->recoveryExpired(
|
||||
|
@ -1071,18 +1136,19 @@ void PasscodeBox::recoverStartFail(const MTP::Error &error) {
|
|||
|
||||
RecoverBox::RecoverBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<MTP::Instance*> mtp,
|
||||
Main::Session *session,
|
||||
const QString &pattern,
|
||||
bool notEmptyPassport,
|
||||
bool hasPendingReset,
|
||||
const PasscodeBox::CloudFields &fields,
|
||||
Fn<void()> closeParent)
|
||||
: _api(&session->mtp())
|
||||
: _session(session)
|
||||
, _api(mtp)
|
||||
, _pattern(st::normalFont->elided(tr::lng_signin_recover_hint(tr::now, lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
||||
, _notEmptyPassport(notEmptyPassport)
|
||||
, _cloudFields(fields)
|
||||
, _recoverCode(this, st::defaultInputField, tr::lng_signin_code())
|
||||
, _noEmailAccess(this, tr::lng_signin_try_password(tr::now))
|
||||
, _closeParent(std::move(closeParent)) {
|
||||
if (hasPendingReset) {
|
||||
if (_cloudFields.pendingResetDate != 0 || !session) {
|
||||
_noEmailAccess.destroy();
|
||||
} else {
|
||||
_noEmailAccess->setClickedCallback([=] {
|
||||
|
@ -1106,8 +1172,8 @@ RecoverBox::RecoverBox(
|
|||
}
|
||||
}
|
||||
|
||||
rpl::producer<> RecoverBox::passwordCleared() const {
|
||||
return _passwordCleared.events();
|
||||
rpl::producer<QByteArray> RecoverBox::newPasswordSet() const {
|
||||
return _newPasswordSet.events();
|
||||
}
|
||||
|
||||
rpl::producer<> RecoverBox::recoveryExpired() const {
|
||||
|
@ -1173,17 +1239,15 @@ void RecoverBox::submit() {
|
|||
}
|
||||
|
||||
const auto send = crl::guard(this, [=] {
|
||||
_submitRequest = _api.request(MTPauth_RecoverPassword(
|
||||
MTP_flags(0),
|
||||
MTP_string(code),
|
||||
MTPaccount_PasswordInputSettings()
|
||||
)).done([=](const MTPauth_Authorization &result) {
|
||||
codeSubmitDone(result);
|
||||
_submitRequest = _api.request(MTPauth_CheckRecoveryPassword(
|
||||
MTP_string(code)
|
||||
)).done([=](const MTPBool &result) {
|
||||
checkSubmitDone(code, result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
codeSubmitFail(error);
|
||||
checkSubmitFail(error);
|
||||
}).handleFloodErrors().send();
|
||||
});
|
||||
if (_notEmptyPassport) {
|
||||
if (_cloudFields.notEmptyPassport) {
|
||||
const auto confirmed = [=](Fn<void()> &&close) {
|
||||
send();
|
||||
close();
|
||||
|
@ -1209,16 +1273,38 @@ void RecoverBox::codeChanged() {
|
|||
setError(QString());
|
||||
}
|
||||
|
||||
void RecoverBox::codeSubmitDone(const MTPauth_Authorization &result) {
|
||||
void RecoverBox::checkSubmitDone(const QString &code, const MTPBool &result) {
|
||||
_submitRequest = 0;
|
||||
|
||||
_passwordCleared.fire({});
|
||||
getDelegate()->show(
|
||||
Box<InformBox>(tr::lng_cloud_password_removed(tr::now)),
|
||||
Ui::LayerOption::CloseOther);
|
||||
auto fields = _cloudFields;
|
||||
fields.fromRecoveryCode = code;
|
||||
fields.hasRecovery = false;
|
||||
// we could've been turning off, no need to force new password then
|
||||
// like if (_cloudFields.turningOff) { just RecoverPassword else Check }
|
||||
fields.turningOff = ???
|
||||
fields.curRequest = {};
|
||||
auto box = Box<PasscodeBox>(_session, fields);
|
||||
|
||||
box->boxClosing(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
if (const auto onstack = _closeParent) {
|
||||
onstack();
|
||||
}
|
||||
if (weak) {
|
||||
weak->closeBox();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
box->newPasswordSet(
|
||||
) | rpl::start_with_next([=](QByteArray &&password) {
|
||||
_newPasswordSet.fire(std::move(password));
|
||||
}, lifetime());
|
||||
|
||||
getDelegate()->show(std::move(box));
|
||||
}
|
||||
|
||||
void RecoverBox::codeSubmitFail(const MTP::Error &error) {
|
||||
void RecoverBox::checkSubmitFail(const MTP::Error &error) {
|
||||
if (MTP::IsFloodError(error)) {
|
||||
_submitRequest = 0;
|
||||
setError(tr::lng_flood_error(tr::now));
|
||||
|
@ -1229,7 +1315,7 @@ void RecoverBox::codeSubmitFail(const MTP::Error &error) {
|
|||
|
||||
const QString &err = error.type();
|
||||
if (err == qstr("PASSWORD_EMPTY")) {
|
||||
_passwordCleared.fire({});
|
||||
_newPasswordSet.fire(QByteArray());
|
||||
getDelegate()->show(
|
||||
Box<InformBox>(tr::lng_cloud_password_removed(tr::now)),
|
||||
Ui::LayerOption::CloseOther);
|
||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mtproto/sender.h"
|
||||
#include "core/core_cloud_password.h"
|
||||
|
||||
namespace MTP {
|
||||
class Instance;
|
||||
} // namespace MTP
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
@ -35,6 +39,7 @@ public:
|
|||
Core::CloudPasswordCheckRequest curRequest;
|
||||
Core::CloudPasswordAlgo newAlgo;
|
||||
bool hasRecovery = false;
|
||||
QString fromRecoveryCode;
|
||||
bool notEmptyPassport = false;
|
||||
QString hint;
|
||||
Core::SecureSecretAlgo newSecureSecretAlgo;
|
||||
|
@ -47,6 +52,11 @@ public:
|
|||
std::optional<QString> customDescription;
|
||||
rpl::producer<QString> customSubmitButton;
|
||||
};
|
||||
PasscodeBox(
|
||||
QWidget*,
|
||||
not_null<MTP::Instance*> mtp,
|
||||
Main::Session *session,
|
||||
const CloudFields &fields);
|
||||
PasscodeBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
|
@ -56,6 +66,8 @@ public:
|
|||
rpl::producer<> passwordReloadNeeded() const;
|
||||
rpl::producer<> clearUnconfirmedPassword() const;
|
||||
|
||||
rpl::producer<MTPauth_Authorization> newAuthorization() const;
|
||||
|
||||
bool handleCustomCheckError(const MTP::Error &error);
|
||||
bool handleCustomCheckError(const QString &type);
|
||||
|
||||
|
@ -83,6 +95,9 @@ private:
|
|||
bool onlyCheckCurrent() const;
|
||||
|
||||
void setPasswordDone(const QByteArray &newPasswordBytes);
|
||||
void recoverPasswordDone(
|
||||
const QByteArray &newPasswordBytes,
|
||||
const MTPauth_Authorization &result);
|
||||
void setPasswordFail(const MTP::Error &error);
|
||||
void setPasswordFail(const QString &type);
|
||||
void setPasswordFail(
|
||||
|
@ -132,7 +147,7 @@ private:
|
|||
void passwordChecked();
|
||||
void serverError();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
Main::Session *_session = nullptr;
|
||||
MTP::Sender _api;
|
||||
|
||||
QString _pattern;
|
||||
|
@ -163,6 +178,7 @@ private:
|
|||
QString _oldError, _newError, _emailError;
|
||||
|
||||
rpl::event_stream<QByteArray> _newPasswordSet;
|
||||
rpl::event_stream<MTPauth_Authorization> _newAuthorization;
|
||||
rpl::event_stream<> _passwordReloadNeeded;
|
||||
rpl::event_stream<> _clearUnconfirmedPassword;
|
||||
|
||||
|
@ -172,14 +188,14 @@ class RecoverBox final : public Ui::BoxContent {
|
|||
public:
|
||||
RecoverBox(
|
||||
QWidget*,
|
||||
not_null<Main::Session*> session,
|
||||
not_null<MTP::Instance*> mtp,
|
||||
Main::Session *session,
|
||||
const QString &pattern,
|
||||
bool notEmptyPassport,
|
||||
bool hasPendingReset,
|
||||
const PasscodeBox::CloudFields &fields,
|
||||
Fn<void()> closeParent = nullptr);
|
||||
|
||||
rpl::producer<> passwordCleared() const;
|
||||
rpl::producer<> recoveryExpired() const;
|
||||
[[nodiscard]] rpl::producer<QByteArray> newPasswordSet() const;
|
||||
[[nodiscard]] rpl::producer<> recoveryExpired() const;
|
||||
|
||||
//void reloadPassword();
|
||||
//void recoveryExpired();
|
||||
|
@ -194,15 +210,17 @@ protected:
|
|||
private:
|
||||
void submit();
|
||||
void codeChanged();
|
||||
void codeSubmitDone(const MTPauth_Authorization &result);
|
||||
void codeSubmitFail(const MTP::Error &error);
|
||||
void checkSubmitDone(const QString &code, const MTPBool &result);
|
||||
void checkSubmitFail(const MTP::Error &error);
|
||||
void setError(const QString &error);
|
||||
|
||||
Main::Session *_session = nullptr;
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _submitRequest = 0;
|
||||
|
||||
QString _pattern;
|
||||
bool _notEmptyPassport = false;
|
||||
|
||||
PasscodeBox::CloudFields _cloudFields;
|
||||
|
||||
object_ptr<Ui::InputField> _recoverCode;
|
||||
object_ptr<Ui::LinkButton> _noEmailAccess;
|
||||
|
@ -210,7 +228,7 @@ private:
|
|||
|
||||
QString _error;
|
||||
|
||||
rpl::event_stream<> _passwordCleared;
|
||||
rpl::event_stream<QByteArray> _newPasswordSet;
|
||||
rpl::event_stream<> _recoveryExpired;
|
||||
|
||||
};
|
||||
|
|
|
@ -341,12 +341,12 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) {
|
|||
stopCheck();
|
||||
_sentRequest = 0;
|
||||
const auto &d = result.c_account_password();
|
||||
getData()->pwdRequest = Core::ParseCloudPasswordCheckRequest(d);
|
||||
getData()->pwdState = Core::ParseCloudPasswordState(d);
|
||||
if (!d.vcurrent_algo() || !d.vsrp_id() || !d.vsrp_B()) {
|
||||
LOG(("API Error: No current password received on login."));
|
||||
_code->setFocus();
|
||||
return;
|
||||
} else if (!getData()->pwdRequest) {
|
||||
} else if (!getData()->pwdState.request) {
|
||||
const auto callback = [=](Fn<void()> &&close) {
|
||||
Core::UpdateApplication();
|
||||
close();
|
||||
|
@ -357,9 +357,6 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) {
|
|||
callback));
|
||||
return;
|
||||
}
|
||||
getData()->hasRecovery = d.is_has_recovery();
|
||||
getData()->pwdHint = qs(d.vhint().value_or_empty());
|
||||
getData()->pwdNotEmptyPassport = d.is_has_secure_values();
|
||||
goReplace<PasswordCheckWidget>(Animate::Forward);
|
||||
}
|
||||
|
||||
|
@ -381,10 +378,7 @@ void CodeWidget::submit() {
|
|||
_checkRequestTimer.callEach(1000);
|
||||
|
||||
_sentCode = text;
|
||||
getData()->pwdRequest = Core::CloudPasswordCheckRequest();
|
||||
getData()->hasRecovery = false;
|
||||
getData()->pwdHint = QString();
|
||||
getData()->pwdNotEmptyPassport = false;
|
||||
getData()->pwdState = Core::CloudPasswordState();
|
||||
_sentRequest = api().request(MTPauth_SignIn(
|
||||
MTP_string(getData()->phone),
|
||||
MTP_bytes(getData()->phoneHash),
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/file_utilities.h"
|
||||
#include "core/core_cloud_password.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "boxes/passcode_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "intro/intro_signup.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
@ -29,16 +30,13 @@ PasswordCheckWidget::PasswordCheckWidget(
|
|||
not_null<Main::Account*> account,
|
||||
not_null<Data*> data)
|
||||
: Step(parent, account, data)
|
||||
, _request(getData()->pwdRequest)
|
||||
, _hasRecovery(getData()->hasRecovery)
|
||||
, _notEmptyPassport(getData()->pwdNotEmptyPassport)
|
||||
, _hint(getData()->pwdHint)
|
||||
, _passwordState(getData()->pwdState)
|
||||
, _pwdField(this, st::introPassword, tr::lng_signin_password())
|
||||
, _pwdHint(this, st::introPasswordHint)
|
||||
, _codeField(this, st::introPassword, tr::lng_signin_code())
|
||||
, _toRecover(this, tr::lng_signin_recover(tr::now))
|
||||
, _toPassword(this, tr::lng_signin_try_password(tr::now)) {
|
||||
Expects(!!_request);
|
||||
Expects(!!_passwordState.request);
|
||||
|
||||
Lang::Updated(
|
||||
) | rpl::start_with_next([=] {
|
||||
|
@ -53,11 +51,13 @@ PasswordCheckWidget::PasswordCheckWidget(
|
|||
setTitleText(tr::lng_signin_title());
|
||||
updateDescriptionText();
|
||||
|
||||
if (_hint.isEmpty()) {
|
||||
if (_passwordState.hint.isEmpty()) {
|
||||
_pwdHint->hide();
|
||||
} else {
|
||||
_pwdHint->setText(
|
||||
tr::lng_signin_hint(tr::now, lt_password_hint, _hint));
|
||||
_pwdHint->setText(tr::lng_signin_hint(
|
||||
tr::now,
|
||||
lt_password_hint,
|
||||
_passwordState.hint));
|
||||
}
|
||||
_codeField->hide();
|
||||
_toPassword->hide();
|
||||
|
@ -73,9 +73,11 @@ void PasswordCheckWidget::refreshLang() {
|
|||
_toPassword->setText(
|
||||
tr::lng_signin_try_password(tr::now));
|
||||
}
|
||||
if (!_hint.isEmpty()) {
|
||||
_pwdHint->setText(
|
||||
tr::lng_signin_hint(tr::now, lt_password_hint, _hint));
|
||||
if (!_passwordState.hint.isEmpty()) {
|
||||
_pwdHint->setText(tr::lng_signin_hint(
|
||||
tr::now,
|
||||
lt_password_hint,
|
||||
_passwordState.hint));
|
||||
}
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ void PasswordCheckWidget::handleSrpIdInvalid() {
|
|||
const auto now = crl::now();
|
||||
if (_lastSrpIdInvalidTime > 0
|
||||
&& now - _lastSrpIdInvalidTime < Core::kHandleSrpIdInvalidTimeout) {
|
||||
_request.id = 0;
|
||||
_passwordState.request.id = 0;
|
||||
showError(rpl::single(Lang::Hard::ServerError()));
|
||||
} else {
|
||||
_lastSrpIdInvalidTime = now;
|
||||
|
@ -176,7 +178,7 @@ void PasswordCheckWidget::handleSrpIdInvalid() {
|
|||
}
|
||||
|
||||
void PasswordCheckWidget::checkPasswordHash() {
|
||||
if (_request.id) {
|
||||
if (_passwordState.request.id) {
|
||||
passwordChecked();
|
||||
} else {
|
||||
requestPasswordData();
|
||||
|
@ -190,12 +192,8 @@ void PasswordCheckWidget::requestPasswordData() {
|
|||
).done([=](const MTPaccount_Password &result) {
|
||||
_sentRequest = 0;
|
||||
result.match([&](const MTPDaccount_password &data) {
|
||||
auto request = Core::ParseCloudPasswordCheckRequest(data);
|
||||
if (request && request.id) {
|
||||
_request = std::move(request);
|
||||
} else {
|
||||
// Maybe the password was removed? Just submit it once again.
|
||||
}
|
||||
openssl::AddRandomSeed(bytes::make_span(data.vsecure_random().v));
|
||||
_passwordState = Core::ParseCloudPasswordState(data);
|
||||
passwordChecked();
|
||||
});
|
||||
}).send();
|
||||
|
@ -203,12 +201,12 @@ void PasswordCheckWidget::requestPasswordData() {
|
|||
|
||||
void PasswordCheckWidget::passwordChecked() {
|
||||
const auto check = Core::ComputeCloudPasswordCheck(
|
||||
_request,
|
||||
_passwordState.request,
|
||||
_passwordHash);
|
||||
if (!check) {
|
||||
return serverError();
|
||||
}
|
||||
_request.id = 0;
|
||||
_passwordState.request.id = 0;
|
||||
_sentRequest = api().request(
|
||||
MTPauth_CheckPassword(check.result)
|
||||
).done([=](const MTPauth_Authorization &result) {
|
||||
|
@ -222,6 +220,23 @@ void PasswordCheckWidget::serverError() {
|
|||
showError(rpl::single(Lang::Hard::ServerError()));
|
||||
}
|
||||
|
||||
void PasswordCheckWidget::codeSubmitDone(
|
||||
const QString &code,
|
||||
const MTPBool &result) {
|
||||
auto fields = PasscodeBox::CloudFields::From(_passwordState);
|
||||
fields.fromRecoveryCode = code;
|
||||
fields.hasRecovery = false;
|
||||
fields.curRequest = {};
|
||||
auto box = Box<PasscodeBox>(&api().instance(), nullptr, fields);
|
||||
|
||||
box->newAuthorization(
|
||||
) | rpl::start_with_next([=](const MTPauth_Authorization &result) {
|
||||
pwdSubmitDone(true, result);
|
||||
}, lifetime());
|
||||
|
||||
Ui::show(std::move(box));
|
||||
}
|
||||
|
||||
void PasswordCheckWidget::codeSubmitFail(const MTP::Error &error) {
|
||||
if (MTP::IsFloodError(error)) {
|
||||
showError(tr::lng_flood_error());
|
||||
|
@ -269,7 +284,7 @@ void PasswordCheckWidget::recoverStartFail(const MTP::Error &error) {
|
|||
}
|
||||
|
||||
void PasswordCheckWidget::toRecover() {
|
||||
if (_hasRecovery) {
|
||||
if (_passwordState.hasRecovery) {
|
||||
if (_sentRequest) {
|
||||
api().request(base::take(_sentRequest)).cancel();
|
||||
}
|
||||
|
@ -339,18 +354,16 @@ void PasswordCheckWidget::submit() {
|
|||
return;
|
||||
}
|
||||
const auto send = crl::guard(this, [=] {
|
||||
_sentRequest = api().request(MTPauth_RecoverPassword(
|
||||
MTP_flags(0),
|
||||
MTP_string(code),
|
||||
MTPaccount_PasswordInputSettings()
|
||||
)).done([=](const MTPauth_Authorization &result) {
|
||||
pwdSubmitDone(true, result);
|
||||
_sentRequest = api().request(MTPauth_CheckRecoveryPassword(
|
||||
MTP_string(code)
|
||||
)).done([=](const MTPBool &result) {
|
||||
codeSubmitDone(code, result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
codeSubmitFail(error);
|
||||
}).handleFloodErrors().send();
|
||||
});
|
||||
|
||||
if (_notEmptyPassport) {
|
||||
if (_passwordState.notEmptyPassport) {
|
||||
const auto confirmed = [=](Fn<void()> &&close) {
|
||||
send();
|
||||
close();
|
||||
|
@ -367,7 +380,7 @@ void PasswordCheckWidget::submit() {
|
|||
|
||||
const auto password = _pwdField->getLastText().toUtf8();
|
||||
_passwordHash = Core::ComputeCloudPasswordHash(
|
||||
_request.algo,
|
||||
_passwordState.request.algo,
|
||||
bytes::make_span(password));
|
||||
checkPasswordHash();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ private:
|
|||
|
||||
void pwdSubmitDone(bool recover, const MTPauth_Authorization &result);
|
||||
void pwdSubmitFail(const MTP::Error &error);
|
||||
void codeSubmitDone(const QString &code, const MTPBool &result);
|
||||
void codeSubmitFail(const MTP::Error &error);
|
||||
void recoverStartFail(const MTP::Error &error);
|
||||
|
||||
|
@ -62,12 +63,10 @@ private:
|
|||
void passwordChecked();
|
||||
void serverError();
|
||||
|
||||
Core::CloudPasswordCheckRequest _request;
|
||||
Core::CloudPasswordState _passwordState;
|
||||
crl::time _lastSrpIdInvalidTime = 0;
|
||||
bytes::vector _passwordHash;
|
||||
bool _hasRecovery = false;
|
||||
bool _notEmptyPassport = false;
|
||||
QString _hint, _emailPattern;
|
||||
QString _emailPattern;
|
||||
|
||||
object_ptr<Ui::PasswordInput> _pwdField;
|
||||
object_ptr<Ui::FlatLabel> _pwdHint;
|
||||
|
|
|
@ -391,13 +391,12 @@ void QrWidget::sendCheckPasswordRequest() {
|
|||
_requestId = api().request(MTPaccount_GetPassword(
|
||||
)).done([=](const MTPaccount_Password &result) {
|
||||
result.match([&](const MTPDaccount_password &data) {
|
||||
getData()->pwdRequest = Core::ParseCloudPasswordCheckRequest(
|
||||
data);
|
||||
getData()->pwdState = Core::ParseCloudPasswordState(data);
|
||||
if (!data.vcurrent_algo() || !data.vsrp_id() || !data.vsrp_B()) {
|
||||
LOG(("API Error: No current password received on login."));
|
||||
goReplace<QrWidget>(Animate::Forward);
|
||||
return;
|
||||
} else if (!getData()->pwdRequest) {
|
||||
} else if (!getData()->pwdState.request) {
|
||||
const auto callback = [=](Fn<void()> &&close) {
|
||||
Core::UpdateApplication();
|
||||
close();
|
||||
|
@ -408,9 +407,6 @@ void QrWidget::sendCheckPasswordRequest() {
|
|||
callback));
|
||||
return;
|
||||
}
|
||||
getData()->hasRecovery = data.is_has_recovery();
|
||||
getData()->pwdHint = qs(data.vhint().value_or_empty());
|
||||
getData()->pwdNotEmptyPassport = data.is_has_secure_values();
|
||||
goReplace<PasswordCheckWidget>(Animate::Forward);
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
|
|
|
@ -56,10 +56,7 @@ struct Data {
|
|||
int codeLength = 5;
|
||||
bool codeByTelegram = false;
|
||||
|
||||
Core::CloudPasswordCheckRequest pwdRequest;
|
||||
bool hasRecovery = false;
|
||||
QString pwdHint;
|
||||
bool pwdNotEmptyPassport = false;
|
||||
Core::CloudPasswordState pwdState;
|
||||
|
||||
Window::TermsLock termsLock;
|
||||
|
||||
|
|
|
@ -1000,15 +1000,25 @@ void FormController::recoverPassword() {
|
|||
|
||||
const auto &data = result.c_auth_passwordRecovery();
|
||||
const auto pattern = qs(data.vemail_pattern());
|
||||
auto fields = PasscodeBox::CloudFields{
|
||||
.newAlgo = _password.newAlgo,
|
||||
.hasRecovery = _password.hasRecovery,
|
||||
.newSecureSecretAlgo = _password.newSecureAlgo,
|
||||
.pendingResetDate = _password.pendingResetDate,
|
||||
};
|
||||
const auto box = _view->show(Box<RecoverBox>(
|
||||
&_controller->session().mtp(),
|
||||
&_controller->session(),
|
||||
pattern,
|
||||
_password.notEmptyPassport,
|
||||
_password.pendingResetDate != 0));
|
||||
fields));
|
||||
|
||||
box->passwordCleared(
|
||||
) | rpl::start_with_next([=] {
|
||||
reloadPassword();
|
||||
box->newPasswordSet(
|
||||
) | rpl::start_with_next([=](const QByteArray &password) {
|
||||
if (password.isEmpty()) {
|
||||
reloadPassword();
|
||||
} else {
|
||||
reloadAndSubmitPassword(password);
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
box->recoveryExpired(
|
||||
|
|
|
@ -684,23 +684,23 @@ void PanelController::setupPassword() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto fields = PasscodeBox::CloudFields();
|
||||
fields.newAlgo = settings.newAlgo;
|
||||
fields.newSecureSecretAlgo = settings.newSecureAlgo;
|
||||
auto fields = PasscodeBox::CloudFields{
|
||||
.newAlgo = settings.newAlgo,
|
||||
.hasRecovery = settings.hasRecovery,
|
||||
.newSecureSecretAlgo = settings.newSecureAlgo,
|
||||
.pendingResetDate = settings.pendingResetDate,
|
||||
};
|
||||
auto box = show(Box<PasscodeBox>(&_form->window()->session(), fields));
|
||||
box->newPasswordSet(
|
||||
) | rpl::filter([=](const QByteArray &password) {
|
||||
return !password.isEmpty();
|
||||
}) | rpl::start_with_next([=](const QByteArray &password) {
|
||||
_form->reloadAndSubmitPassword(password);
|
||||
) | rpl::start_with_next([=](const QByteArray &password) {
|
||||
if (password.isEmpty()) {
|
||||
_form->reloadPassword();
|
||||
} else {
|
||||
_form->reloadAndSubmitPassword(password);
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
rpl::merge(
|
||||
box->passwordReloadNeeded(),
|
||||
box->newPasswordSet(
|
||||
) | rpl::filter([=](const QByteArray &password) {
|
||||
return password.isEmpty();
|
||||
}) | rpl::to_empty
|
||||
box->passwordReloadNeeded(
|
||||
) | rpl::start_with_next([=] {
|
||||
_form->reloadPassword();
|
||||
}, box->lifetime());
|
||||
|
|
Loading…
Add table
Reference in a new issue