mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-19 14:36:58 +00:00
Warn user about passport reset.
Also suggest country by phone number in passport.
This commit is contained in:
parent
275ec3e679
commit
ab5f35e952
@ -587,7 +587,7 @@ authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string s
|
||||
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
||||
|
||||
account.noPassword#5ea182f6 new_salt:bytes new_secure_salt:bytes secure_random:bytes email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#d06c5fc3 current_salt:bytes new_salt:bytes new_secure_salt:bytes secure_random:bytes hint:string has_recovery:Bool email_unconfirmed_pattern:string = account.Password;
|
||||
account.password#ca39b447 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true current_salt:bytes new_salt:bytes new_secure_salt:bytes secure_random:bytes hint:string email_unconfirmed_pattern:string = account.Password;
|
||||
|
||||
account.passwordSettings#7bd9c3f1 email:string secure_salt:bytes secure_secret:bytes secure_secret_id:long = account.PasswordSettings;
|
||||
|
||||
|
@ -33,6 +33,7 @@ PasscodeBox::PasscodeBox(
|
||||
const QByteArray &newSalt,
|
||||
const QByteArray &curSalt,
|
||||
bool hasRecovery,
|
||||
bool notEmptyPassport,
|
||||
const QString &hint,
|
||||
const QByteArray &newSecureSecretSalt,
|
||||
bool turningOff)
|
||||
@ -42,6 +43,7 @@ PasscodeBox::PasscodeBox(
|
||||
, _curSalt(curSalt)
|
||||
, _newSecureSecretSalt(newSecureSecretSalt)
|
||||
, _hasRecovery(hasRecovery)
|
||||
, _notEmptyPassport(notEmptyPassport)
|
||||
, _about(st::boxWidth - st::boxPadding.left() * 1.5)
|
||||
, _oldPasscode(this, st::defaultInputField, langFactory(lng_cloud_password_enter_old))
|
||||
, _newPasscode(this, st::defaultInputField, langFactory(curSalt.isEmpty() ? lng_cloud_password_enter_first : lng_cloud_password_enter_new))
|
||||
@ -339,30 +341,31 @@ void PasscodeBox::save(bool force) {
|
||||
void PasscodeBox::clearCloudPassword(const QString &oldPassword) {
|
||||
Expects(!_oldPasscode->isHidden());
|
||||
|
||||
const auto send = [=] {
|
||||
sendClearCloudPassword(oldPassword);
|
||||
};
|
||||
if (_notEmptyPassport) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto confirmed = [=] {
|
||||
send();
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
};
|
||||
*box = getDelegate()->show(Box<ConfirmBox>(
|
||||
lang(lng_cloud_password_passport_losing),
|
||||
lang(lng_continue),
|
||||
confirmed));
|
||||
} else {
|
||||
send();
|
||||
}
|
||||
}
|
||||
|
||||
void PasscodeBox::sendClearCloudPassword(const QString &oldPassword) {
|
||||
const auto passwordUtf = oldPassword.toUtf8();
|
||||
const auto oldPasswordData = (_curSalt + passwordUtf + _curSalt);
|
||||
auto oldPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
hashSha256(oldPasswordData.constData(), oldPasswordData.size(), oldPasswordHash.data());
|
||||
_setRequest = request(MTPaccount_GetPasswordSettings(
|
||||
MTP_bytes(oldPasswordHash)
|
||||
)).done([=](const MTPaccount_PasswordSettings &result) {
|
||||
_setRequest = 0;
|
||||
|
||||
Expects(result.type() == mtpc_account_passwordSettings);
|
||||
const auto &data = result.c_account_passwordSettings();
|
||||
|
||||
if (data.vsecure_secret.v.isEmpty()) {
|
||||
sendClearCloudPassword(oldPasswordHash);
|
||||
return;
|
||||
}
|
||||
warnPassportLoss(oldPasswordHash);
|
||||
}).fail([=](const RPCError &error) {
|
||||
setPasswordFail(error);
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::sendClearCloudPassword(
|
||||
const QByteArray &oldPasswordHash) {
|
||||
const auto newPasswordData = QByteArray();
|
||||
const auto newPasswordHash = QByteArray();
|
||||
const auto hint = QString();
|
||||
@ -389,20 +392,6 @@ void PasscodeBox::sendClearCloudPassword(
|
||||
}).send();
|
||||
}
|
||||
|
||||
void PasscodeBox::warnPassportLoss(const QByteArray &oldPasswordHash) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto sendAndClose = [=] {
|
||||
sendClearCloudPassword(oldPasswordHash);
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
};
|
||||
*box = getDelegate()->show(Box<ConfirmBox>(
|
||||
lang(lng_cloud_password_passport_losing),
|
||||
lang(lng_continue),
|
||||
sendAndClose));
|
||||
}
|
||||
|
||||
void PasscodeBox::setNewCloudPassword(const QString &newPassword) {
|
||||
const auto newPasswordData = (_newSalt + newPassword.toUtf8() + _newSalt);
|
||||
auto newPasswordHash = QByteArray(32, Qt::Uninitialized);
|
||||
@ -611,7 +600,9 @@ void PasscodeBox::recoverExpired() {
|
||||
void PasscodeBox::recover() {
|
||||
if (_pattern == "-") return;
|
||||
|
||||
const auto box = getDelegate()->show(Box<RecoverBox>(_pattern));
|
||||
const auto box = getDelegate()->show(Box<RecoverBox>(
|
||||
_pattern,
|
||||
_notEmptyPassport));
|
||||
connect(box, &RecoverBox::reloadPassword, this, &PasscodeBox::reloadPassword);
|
||||
connect(box, &RecoverBox::recoveryExpired, this, &PasscodeBox::recoverExpired);
|
||||
_replacedBy = box;
|
||||
@ -630,8 +621,12 @@ bool PasscodeBox::recoverStartFail(const RPCError &error) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RecoverBox::RecoverBox(QWidget*, const QString &pattern)
|
||||
RecoverBox::RecoverBox(
|
||||
QWidget*,
|
||||
const QString &pattern,
|
||||
bool notEmptyPassport)
|
||||
: _pattern(st::normalFont->elided(lng_signin_recover_hint(lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
|
||||
, _notEmptyPassport(notEmptyPassport)
|
||||
, _recoverCode(this, st::defaultInputField, langFactory(lng_signin_code)) {
|
||||
}
|
||||
|
||||
@ -684,7 +679,27 @@ void RecoverBox::submit() {
|
||||
return;
|
||||
}
|
||||
|
||||
_submitRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&RecoverBox::codeSubmitDone, true), rpcFail(&RecoverBox::codeSubmitFail));
|
||||
const auto send = base::lambda_guarded(this, [=] {
|
||||
_submitRequest = MTP::send(
|
||||
MTPauth_RecoverPassword(MTP_string(code)),
|
||||
rpcDone(&RecoverBox::codeSubmitDone, true),
|
||||
rpcFail(&RecoverBox::codeSubmitFail));
|
||||
});
|
||||
if (_notEmptyPassport) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto confirmed = [=] {
|
||||
send();
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
};
|
||||
*box = getDelegate()->show(Box<ConfirmBox>(
|
||||
lang(lng_cloud_password_passport_losing),
|
||||
lang(lng_continue),
|
||||
confirmed));
|
||||
} else {
|
||||
send();
|
||||
}
|
||||
}
|
||||
|
||||
void RecoverBox::codeChanged() {
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
const QByteArray &newSalt,
|
||||
const QByteArray &curSalt,
|
||||
bool hasRecovery,
|
||||
bool notEmptyPassport,
|
||||
const QString &hint,
|
||||
const QByteArray &newSecureSecretSalt,
|
||||
bool turningOff = false);
|
||||
@ -73,8 +74,7 @@ private:
|
||||
void resetSecretAndChangePassword(
|
||||
const QByteArray &oldPasswordHash,
|
||||
const QString &newPassword);
|
||||
void sendClearCloudPassword(const QByteArray &oldPasswordHash);
|
||||
void warnPassportLoss(const QByteArray &oldPasswordHash);
|
||||
void sendClearCloudPassword(const QString &oldPassword);
|
||||
|
||||
QString _pattern;
|
||||
|
||||
@ -85,6 +85,7 @@ private:
|
||||
|
||||
QByteArray _newSalt, _curSalt, _newSecureSecretSalt;
|
||||
bool _hasRecovery = false;
|
||||
bool _notEmptyPassport = false;
|
||||
bool _skipEmailWarning = false;
|
||||
|
||||
int _aboutHeight = 0;
|
||||
@ -106,7 +107,7 @@ class RecoverBox : public BoxContent, public RPCSender {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RecoverBox(QWidget*, const QString &pattern);
|
||||
RecoverBox(QWidget*, const QString &pattern, bool notEmptyPassport);
|
||||
|
||||
signals:
|
||||
void reloadPassword();
|
||||
@ -128,6 +129,7 @@ private:
|
||||
mtpRequestId _submitRequest = 0;
|
||||
|
||||
QString _pattern;
|
||||
bool _notEmptyPassport = false;
|
||||
|
||||
object_ptr<Ui::InputField> _recoverCode;
|
||||
|
||||
|
@ -296,8 +296,9 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) {
|
||||
case mtpc_account_password: {
|
||||
auto &d = result.c_account_password();
|
||||
getData()->pwdSalt = qba(d.vcurrent_salt);
|
||||
getData()->hasRecovery = mtpIsTrue(d.vhas_recovery);
|
||||
getData()->hasRecovery = d.is_has_recovery();
|
||||
getData()->pwdHint = qs(d.vhint);
|
||||
getData()->pwdNotEmptyPassport = d.is_has_secure_values();
|
||||
goReplace(new Intro::PwdCheckWidget(parentWidget(), getData()));
|
||||
} break;
|
||||
}
|
||||
@ -314,6 +315,7 @@ void CodeWidget::submit() {
|
||||
getData()->pwdSalt = QByteArray();
|
||||
getData()->hasRecovery = false;
|
||||
getData()->pwdHint = QString();
|
||||
getData()->pwdNotEmptyPassport = false;
|
||||
_sentRequest = MTP::send(MTPauth_SignIn(MTP_string(getData()->phone), MTP_bytes(getData()->phoneHash), MTP_string(_sentCode)), rpcDone(&CodeWidget::codeSubmitDone), rpcFail(&CodeWidget::codeSubmitFail));
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ namespace Intro {
|
||||
PwdCheckWidget::PwdCheckWidget(QWidget *parent, Widget::Data *data) : Step(parent, data)
|
||||
, _salt(getData()->pwdSalt)
|
||||
, _hasRecovery(getData()->hasRecovery)
|
||||
, _notEmptyPassport(getData()->pwdNotEmptyPassport)
|
||||
, _hint(getData()->pwdHint)
|
||||
, _pwdField(this, st::introPassword, langFactory(lng_signin_password))
|
||||
, _pwdHint(this, st::introPasswordHint)
|
||||
@ -276,8 +277,28 @@ void PwdCheckWidget::submit() {
|
||||
_codeField->showError();
|
||||
return;
|
||||
}
|
||||
const auto send = base::lambda_guarded(this, [=] {
|
||||
_sentRequest = MTP::send(
|
||||
MTPauth_RecoverPassword(MTP_string(code)),
|
||||
rpcDone(&PwdCheckWidget::pwdSubmitDone, true),
|
||||
rpcFail(&PwdCheckWidget::codeSubmitFail));
|
||||
});
|
||||
|
||||
_sentRequest = MTP::send(MTPauth_RecoverPassword(MTP_string(code)), rpcDone(&PwdCheckWidget::pwdSubmitDone, true), rpcFail(&PwdCheckWidget::codeSubmitFail));
|
||||
if (_notEmptyPassport) {
|
||||
const auto box = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto confirmed = [=] {
|
||||
send();
|
||||
if (*box) {
|
||||
(*box)->closeBox();
|
||||
}
|
||||
};
|
||||
*box = Ui::show(Box<ConfirmBox>(
|
||||
lang(lng_cloud_password_passport_losing),
|
||||
lang(lng_continue),
|
||||
confirmed));
|
||||
} else {
|
||||
send();
|
||||
}
|
||||
} else {
|
||||
hideError();
|
||||
|
||||
|
@ -55,7 +55,8 @@ private:
|
||||
void stopCheck();
|
||||
|
||||
QByteArray _salt;
|
||||
bool _hasRecovery;
|
||||
bool _hasRecovery = false;
|
||||
bool _notEmptyPassport = false;
|
||||
QString _hint, _emailPattern;
|
||||
|
||||
object_ptr<Ui::PasswordInput> _pwdField;
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
QByteArray pwdSalt;
|
||||
bool hasRecovery = false;
|
||||
QString pwdHint;
|
||||
bool pwdNotEmptyPassport = false;
|
||||
|
||||
TextWithEntities termsText;
|
||||
bool termsPopup = false;
|
||||
|
@ -408,7 +408,9 @@ void FormController::recoverPassword() {
|
||||
|
||||
const auto &data = result.c_auth_passwordRecovery();
|
||||
const auto pattern = qs(data.vemail_pattern);
|
||||
const auto box = _view->show(Box<RecoverBox>(pattern));
|
||||
const auto box = _view->show(Box<RecoverBox>(
|
||||
pattern,
|
||||
_password.notEmptyPassport));
|
||||
box->connect(box, &RecoverBox::reloadPassword, [=] {
|
||||
reloadPassword();
|
||||
});
|
||||
@ -1910,7 +1912,8 @@ bool FormController::applyPassword(const MTPDaccount_noPassword &result) {
|
||||
bool FormController::applyPassword(const MTPDaccount_password &result) {
|
||||
auto settings = PasswordSettings();
|
||||
settings.hint = qs(result.vhint);
|
||||
settings.hasRecovery = mtpIsTrue(result.vhas_recovery);
|
||||
settings.hasRecovery = result.is_has_recovery();
|
||||
settings.notEmptyPassport = result.is_has_secure_values();
|
||||
settings.salt = bytes::make_vector(result.vcurrent_salt.v);
|
||||
settings.unconfirmedPattern = qs(result.vemail_unconfirmed_pattern);
|
||||
settings.newSalt = bytes::make_vector(result.vnew_salt.v);
|
||||
|
@ -182,6 +182,7 @@ struct PasswordSettings {
|
||||
QString unconfirmedPattern;
|
||||
QString confirmedEmail;
|
||||
bool hasRecovery = false;
|
||||
bool notEmptyPassport = false;
|
||||
|
||||
bool operator==(const PasswordSettings &other) const {
|
||||
return (salt == other.salt)
|
||||
|
@ -446,11 +446,13 @@ void PanelController::setupPassword() {
|
||||
newSecureSecretSalt).subspan(settings.newSecureSalt.size()));
|
||||
const auto currentSalt = QByteArray();
|
||||
const auto hasRecovery = false;
|
||||
const auto notEmptyPassport = false;
|
||||
const auto hint = QString();
|
||||
auto box = show(Box<PasscodeBox>(
|
||||
newPasswordSalt,
|
||||
currentSalt,
|
||||
hasRecovery,
|
||||
notEmptyPassport,
|
||||
hint,
|
||||
newSecureSecretSalt));
|
||||
box->connect(box, &PasscodeBox::reloadPassword, _panel.get(), [=] {
|
||||
@ -697,7 +699,7 @@ void PanelController::suggestReset(base::lambda<void()> callback) {
|
||||
Lang::Hard::PassportCorrupted(),
|
||||
Lang::Hard::PassportCorruptedReset(),
|
||||
[=] { resetPassport(callback); },
|
||||
[=] { cancelReset(); })).data()); // #TODO passport no need for confirmation?
|
||||
[=] { cancelReset(); })).data());
|
||||
}
|
||||
|
||||
void PanelController::resetPassport(base::lambda<void()> callback) {
|
||||
|
@ -310,8 +310,12 @@ void CountryRow::errorAnimationCallback() {
|
||||
void CountryRow::chooseCountry() {
|
||||
const auto top = _value.current();
|
||||
const auto name = CountrySelectBox::NameByISO(top);
|
||||
const auto box = _controller->show(Box<CountrySelectBox>(
|
||||
(name.isEmpty() ? Platform::SystemCountry() : top),
|
||||
const auto isoByPhone = CountrySelectBox::ISOByPhone(App::self()->phone());
|
||||
const auto box = _controller->show(Box<CountrySelectBox>(!name.isEmpty()
|
||||
? top
|
||||
: !isoByPhone.isEmpty()
|
||||
? isoByPhone
|
||||
: Platform::SystemCountry(),
|
||||
CountrySelectBox::Type::Countries));
|
||||
connect(box, &CountrySelectBox::countryChosen, this, [=](QString iso) {
|
||||
_value = iso;
|
||||
|
@ -78,6 +78,7 @@ void CloudPasswordState::onEdit() {
|
||||
_newPasswordSalt,
|
||||
_curPasswordSalt,
|
||||
_hasPasswordRecovery,
|
||||
_notEmptyPassport,
|
||||
_curPasswordHint,
|
||||
_newSecureSecretSalt));
|
||||
connect(box, SIGNAL(reloadPassword()), this, SLOT(onReloadPassword()));
|
||||
@ -106,6 +107,7 @@ void CloudPasswordState::onTurnOff() {
|
||||
_newPasswordSalt,
|
||||
_curPasswordSalt,
|
||||
_hasPasswordRecovery,
|
||||
_notEmptyPassport,
|
||||
_curPasswordHint,
|
||||
_newSecureSecretSalt,
|
||||
true));
|
||||
@ -113,13 +115,21 @@ void CloudPasswordState::onTurnOff() {
|
||||
}
|
||||
}
|
||||
|
||||
void CloudPasswordState::onReloadPassword() {
|
||||
if (_reloadRequestId) {
|
||||
return;
|
||||
}
|
||||
_reloadRequestId = MTP::send(MTPaccount_GetPassword(), rpcDone(&CloudPasswordState::getPasswordDone), rpcFail(&CloudPasswordState::getPasswordFail));
|
||||
}
|
||||
|
||||
void CloudPasswordState::onReloadPassword(Qt::ApplicationState state) {
|
||||
if (state == Qt::ApplicationActive) {
|
||||
MTP::send(MTPaccount_GetPassword(), rpcDone(&CloudPasswordState::getPasswordDone));
|
||||
if (!_waitingConfirm.isEmpty() && state == Qt::ApplicationActive) {
|
||||
onReloadPassword();
|
||||
}
|
||||
}
|
||||
|
||||
void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) {
|
||||
_reloadRequestId = 0;
|
||||
_waitingConfirm = QString();
|
||||
|
||||
switch (result.type()) {
|
||||
@ -127,6 +137,7 @@ void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) {
|
||||
auto &d = result.c_account_noPassword();
|
||||
_curPasswordSalt = QByteArray();
|
||||
_hasPasswordRecovery = false;
|
||||
_notEmptyPassport = false;
|
||||
_curPasswordHint = QString();
|
||||
_newPasswordSalt = qba(d.vnew_salt);
|
||||
_newSecureSecretSalt = qba(d.vnew_secure_salt);
|
||||
@ -140,7 +151,8 @@ void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) {
|
||||
case mtpc_account_password: {
|
||||
auto &d = result.c_account_password();
|
||||
_curPasswordSalt = qba(d.vcurrent_salt);
|
||||
_hasPasswordRecovery = mtpIsTrue(d.vhas_recovery);
|
||||
_hasPasswordRecovery = d.is_has_recovery();
|
||||
_notEmptyPassport = d.is_has_secure_values();
|
||||
_curPasswordHint = qs(d.vhint);
|
||||
_newPasswordSalt = qba(d.vnew_salt);
|
||||
_newSecureSecretSalt = qba(d.vnew_secure_salt);
|
||||
@ -166,6 +178,14 @@ void CloudPasswordState::getPasswordDone(const MTPaccount_Password &result) {
|
||||
8);
|
||||
}
|
||||
|
||||
bool CloudPasswordState::getPasswordFail(const RPCError &error) {
|
||||
if (MTP::isDefaultHandledError(error)) {
|
||||
return false;
|
||||
}
|
||||
_reloadRequestId = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloudPasswordState::paintEvent(QPaintEvent *e) {
|
||||
Painter p(this);
|
||||
|
||||
|
@ -50,10 +50,12 @@ protected:
|
||||
private slots:
|
||||
void onEdit();
|
||||
void onTurnOff();
|
||||
void onReloadPassword(Qt::ApplicationState state = Qt::ApplicationActive);
|
||||
void onReloadPassword();
|
||||
void onReloadPassword(Qt::ApplicationState state);
|
||||
|
||||
private:
|
||||
void getPasswordDone(const MTPaccount_Password &result);
|
||||
bool getPasswordFail(const RPCError &error);
|
||||
void offPasswordDone(const MTPBool &result);
|
||||
bool offPasswordFail(const RPCError &error);
|
||||
|
||||
@ -63,9 +65,11 @@ private:
|
||||
QString _waitingConfirm;
|
||||
QByteArray _curPasswordSalt;
|
||||
bool _hasPasswordRecovery = false;
|
||||
bool _notEmptyPassport = false;
|
||||
QString _curPasswordHint;
|
||||
QByteArray _newPasswordSalt;
|
||||
QByteArray _newSecureSecretSalt;
|
||||
mtpRequestId _reloadRequestId = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -219,6 +219,17 @@ QString CountrySelectBox::NameByISO(const QString &iso) {
|
||||
: QString::fromUtf8((*i)->name);
|
||||
}
|
||||
|
||||
QString CountrySelectBox::ISOByPhone(const QString &phone) {
|
||||
if (_countriesByCode.isEmpty()) {
|
||||
initCountries();
|
||||
}
|
||||
const auto code = findValidCode(phone);
|
||||
const auto i = _countriesByCode.find(code);
|
||||
return (i == _countriesByCode.cend())
|
||||
? QString()
|
||||
: QString::fromUtf8((*i)->iso2);
|
||||
}
|
||||
|
||||
void CountrySelectBox::prepare() {
|
||||
setTitle(langFactory(lng_country_select));
|
||||
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
CountrySelectBox(QWidget*, const QString &iso, Type type);
|
||||
|
||||
static QString NameByISO(const QString &iso);
|
||||
static QString ISOByPhone(const QString &phone);
|
||||
|
||||
signals:
|
||||
void countryChosen(const QString &iso);
|
||||
|
Loading…
Reference in New Issue
Block a user