Stop passport authorization with confirm.

This commit is contained in:
John Preston 2018-04-13 22:14:14 +04:00
parent 1064208be9
commit 6de3112c8a
11 changed files with 100 additions and 38 deletions

View File

@ -1594,6 +1594,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_delete_email_sure" = "Are you sure you want to delete your email?"; "lng_passport_delete_email_sure" = "Are you sure you want to delete your email?";
"lng_passport_delete_phone" = "Delete phone number"; "lng_passport_delete_phone" = "Delete phone number";
"lng_passport_delete_phone_sure" = "Are you sure you want to delete your phone number?"; "lng_passport_delete_phone_sure" = "Are you sure you want to delete your phone number?";
"lng_passport_success" = "Authorization successfull!";
"lng_passport_stop_sure" = "Are you sure you want to stop this authorization?";
"lng_passport_stop" = "Stop";
// Wnd specific // Wnd specific

View File

@ -335,7 +335,7 @@ bytes::vector DecryptValueSecret(
return DecryptSecretBytes(encrypted, bytesForEncryptionKey); return DecryptSecretBytes(encrypted, bytesForEncryptionKey);
} }
uint64 CountSecureSecretHash(bytes::const_span secret) { uint64 CountSecureSecretId(bytes::const_span secret) {
const auto full = openssl::Sha256(secret); const auto full = openssl::Sha256(secret);
return *reinterpret_cast<const uint64*>(full.data()); return *reinterpret_cast<const uint64*>(full.data());
} }

View File

@ -54,7 +54,7 @@ bytes::vector DecryptValueSecret(
bytes::const_span secret, bytes::const_span secret,
bytes::const_span valueHash); bytes::const_span valueHash);
uint64 CountSecureSecretHash(bytes::const_span secret); uint64 CountSecureSecretId(bytes::const_span secret);
bytes::vector EncryptCredentialsSecret( bytes::vector EncryptCredentialsSecret(
bytes::const_span secret, bytes::const_span secret,

View File

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "ui/toast/toast.h"
#include "auth_session.h" #include "auth_session.h"
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
@ -77,7 +78,7 @@ MTPSecureValueType ConvertType(Value::Type type) {
}; };
QJsonObject GetJSONFromMap( QJsonObject GetJSONFromMap(
const std::map<QString, bytes::const_span> &map) { const std::map<QString, bytes::const_span> &map) {
auto result = QJsonObject(); auto result = QJsonObject();
for (const auto &[key, value] : map) { for (const auto &[key, value] : map) {
const auto raw = QByteArray::fromRawData( const auto raw = QByteArray::fromRawData(
@ -92,7 +93,7 @@ QJsonObject GetJSONFromFile(const File &file) {
return GetJSONFromMap({ return GetJSONFromMap({
{ "file_hash", file.hash }, { "file_hash", file.hash },
{ "secret", file.secret } { "secret", file.secret }
}); });
} }
FormRequest PreprocessRequest(const FormRequest &request) { FormRequest PreprocessRequest(const FormRequest &request) {
@ -125,26 +126,26 @@ FormRequest::FormRequest(
const QString &callbackUrl, const QString &callbackUrl,
const QString &publicKey, const QString &publicKey,
const QString &payload) const QString &payload)
: botId(botId) : botId(botId)
, scope(scope) , scope(scope)
, callbackUrl(callbackUrl) , callbackUrl(callbackUrl)
, publicKey(publicKey) , publicKey(publicKey)
, payload(payload) { , payload(payload) {
} }
EditFile::EditFile( EditFile::EditFile(
not_null<const Value*> value, not_null<const Value*> value,
const File &fields, const File &fields,
std::unique_ptr<UploadScanData> &&uploadData) std::unique_ptr<UploadScanData> &&uploadData)
: value(value) : value(value)
, fields(std::move(fields)) , fields(std::move(fields))
, uploadData(std::move(uploadData)) , uploadData(std::move(uploadData))
, guard(std::make_shared<bool>(true)) { , guard(std::make_shared<bool>(true)) {
} }
UploadScanDataPointer::UploadScanDataPointer( UploadScanDataPointer::UploadScanDataPointer(
std::unique_ptr<UploadScanData> &&value) std::unique_ptr<UploadScanData> &&value)
: _value(std::move(value)) { : _value(std::move(value)) {
} }
UploadScanDataPointer::UploadScanDataPointer( UploadScanDataPointer::UploadScanDataPointer(
@ -183,9 +184,9 @@ Value::Value(Type type) : type(type) {
FormController::FormController( FormController::FormController(
not_null<Window::Controller*> controller, not_null<Window::Controller*> controller,
const FormRequest &request) const FormRequest &request)
: _controller(controller) : _controller(controller)
, _request(PreprocessRequest(request)) , _request(PreprocessRequest(request))
, _view(std::make_unique<PanelController>(this)) { , _view(std::make_unique<PanelController>(this)) {
} }
void FormController::show() { void FormController::show() {
@ -202,7 +203,7 @@ QString FormController::privacyPolicyUrl() const {
} }
bytes::vector FormController::passwordHashForAuth( bytes::vector FormController::passwordHashForAuth(
bytes::const_span password) const { bytes::const_span password) const {
return openssl::Sha256(bytes::concatenate( return openssl::Sha256(bytes::concatenate(
_password.salt, _password.salt,
password, password,
@ -213,14 +214,14 @@ auto FormController::prepareFinalData() -> FinalData {
auto hashes = QVector<MTPSecureValueHash>(); auto hashes = QVector<MTPSecureValueHash>();
auto secureData = QJsonObject(); auto secureData = QJsonObject();
const auto addValueToJSON = [&]( const auto addValueToJSON = [&](
const QString &key, const QString &key,
not_null<const Value*> value) { not_null<const Value*> value) {
auto object = QJsonObject(); auto object = QJsonObject();
if (!value->data.parsed.fields.empty()) { if (!value->data.parsed.fields.empty()) {
object.insert("data", GetJSONFromMap({ object.insert("data", GetJSONFromMap({
{ "data_hash", value->data.hash }, { "data_hash", value->data.hash },
{ "secret", value->data.secret } { "secret", value->data.secret }
})); }));
} }
if (!value->scans.empty()) { if (!value->scans.empty()) {
auto files = QJsonArray(); auto files = QJsonArray();
@ -277,7 +278,7 @@ auto FormController::prepareFinalData() -> FinalData {
} }
bool FormController::submit() { bool FormController::submit() {
if (_submitRequestId) { if (_submitRequestId || _submitSuccess|| _cancelled) {
return true; return true;
} }
@ -301,11 +302,17 @@ bool FormController::submit() {
MTP_bytes(credentialsEncryptedData.hash), MTP_bytes(credentialsEncryptedData.hash),
MTP_bytes(credentialsEncryptedSecret)) MTP_bytes(credentialsEncryptedSecret))
)).done([=](const MTPBool &result) { )).done([=](const MTPBool &result) {
const auto url = qthelp::url_append_query( _submitRequestId = 0;
_request.callbackUrl, _submitSuccess = true;
"tg_passport=success");
UrlClickHandler::doOpen(url); _view->showToast(lang(lng_passport_success));
App::CallDelayed(
Ui::Toast::DefaultDuration + st::toastFadeOutDuration,
this,
[=] { cancel(); });
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_submitRequestId = 0;
_view->show(Box<InformBox>( _view->show(Box<InformBox>(
"Failed sending data :(\n" + error.type())); "Failed sending data :(\n" + error.type()));
}).send(); }).send();
@ -333,7 +340,8 @@ void FormController::submitPassword(const QString &password) {
validateSecureSecret( validateSecureSecret(
bytes::make_span(data.vsecure_salt.v), bytes::make_span(data.vsecure_salt.v),
bytes::make_span(data.vsecure_secret.v), bytes::make_span(data.vsecure_secret.v),
bytes::make_span(passwordBytes)); bytes::make_span(passwordBytes),
data.vsecure_secret_id.v);
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_passwordCheckRequestId = 0; _passwordCheckRequestId = 0;
if (MTP::isFloodError(error)) { if (MTP::isFloodError(error)) {
@ -349,7 +357,8 @@ void FormController::submitPassword(const QString &password) {
void FormController::validateSecureSecret( void FormController::validateSecureSecret(
bytes::const_span salt, bytes::const_span salt,
bytes::const_span encryptedSecret, bytes::const_span encryptedSecret,
bytes::const_span password) { bytes::const_span password,
uint64 serverSecretId) {
if (!salt.empty() && !encryptedSecret.empty()) { if (!salt.empty() && !encryptedSecret.empty()) {
_secret = DecryptSecureSecret(salt, encryptedSecret, password); _secret = DecryptSecureSecret(salt, encryptedSecret, password);
if (_secret.empty()) { if (_secret.empty()) {
@ -361,8 +370,18 @@ void FormController::validateSecureSecret(
resetValue(value); resetValue(value);
} }
} }
} else if (CountSecureSecretId(_secret) != serverSecretId) {
_secret.clear();
_secretId = 0;
LOG(("API Error: Wrong secure secret id. "
"Forgetting all files and data :("));
for (auto &[type, value] : _form.values) {
if (!value.data.original.isEmpty()) {
resetValue(value);
}
}
} else { } else {
_secretId = CountSecureSecretHash(_secret); _secretId = serverSecretId;
decryptValues(); decryptValues();
} }
} }
@ -1327,7 +1346,7 @@ void FormController::generateSecret(bytes::const_span password) {
_password.newSecureSalt, _password.newSecureSalt,
randomSaltPart); randomSaltPart);
auto secureSecretId = CountSecureSecretHash(secret); auto secureSecretId = CountSecureSecretId(secret);
auto encryptedSecret = EncryptSecureSecret( auto encryptedSecret = EncryptSecureSecret(
newSecureSaltFull, newSecureSaltFull,
secret, secret,
@ -1642,9 +1661,27 @@ void FormController::parsePassword(const MTPDaccount_password &result) {
} }
void FormController::cancel() { void FormController::cancel() {
if (!_submitSuccess) {
_view->show(Box<ConfirmBox>(
lang(lng_passport_stop_sure),
lang(lng_passport_stop),
[=] { cancelSure(); }));
} else {
cancelSure();
}
}
void FormController::cancelSure() {
if (!_cancelled) { if (!_cancelled) {
_cancelled = true; _cancelled = true;
crl::on_main(this, [=] {
const auto url = qthelp::url_append_query(
_request.callbackUrl,
_submitSuccess ? "tg_passport=success" : "tg_passport=cancel");
UrlClickHandler::doOpen(url);
const auto timeout = _view->closeGetDuration();
App::CallDelayed(timeout, this, [=] {
_controller->clearPassportForm(); _controller->clearPassportForm();
}); });
} }

View File

@ -287,7 +287,8 @@ private:
void validateSecureSecret( void validateSecureSecret(
bytes::const_span salt, bytes::const_span salt,
bytes::const_span encryptedSecret, bytes::const_span encryptedSecret,
bytes::const_span password); bytes::const_span password,
uint64 serverSecretId);
void decryptValues(); void decryptValues();
void decryptValue(Value &value); void decryptValue(Value &value);
bool validateValueSecrets(Value &value); bool validateValueSecrets(Value &value);
@ -344,6 +345,8 @@ private:
const MTPInputSecureValue &data); const MTPInputSecureValue &data);
FinalData prepareFinalData(); FinalData prepareFinalData();
void cancelSure();
not_null<Window::Controller*> _controller; not_null<Window::Controller*> _controller;
FormRequest _request; FormRequest _request;
UserData *_bot = nullptr; UserData *_bot = nullptr;
@ -369,6 +372,7 @@ private:
rpl::event_stream<> _secretReady; rpl::event_stream<> _secretReady;
rpl::event_stream<QString> _passwordError; rpl::event_stream<QString> _passwordError;
mtpRequestId _submitRequestId = 0; mtpRequestId _submitRequestId = 0;
bool _submitSuccess = false;
rpl::lifetime _uploaderSubscriptions; rpl::lifetime _uploaderSubscriptions;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View File

@ -103,6 +103,11 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
case Scope::Type::Identity: case Scope::Type::Identity:
case Scope::Type::Address: { case Scope::Type::Address: {
auto list = QStringList(); auto list = QStringList();
const auto pushListValue = [&](const QString &value) {
if (const auto trimmed = value.trimmed(); !trimmed.isEmpty()) {
list.push_back(trimmed);
}
};
const auto &fields = scope.fields->data.parsed.fields; const auto &fields = scope.fields->data.parsed.fields;
const auto document = [&]() -> const Value* { const auto document = [&]() -> const Value* {
for (const auto &document : scope.documents) { for (const auto &document : scope.documents) {
@ -113,7 +118,7 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
return nullptr; return nullptr;
}(); }();
if (document && scope.documents.size() > 1) { if (document && scope.documents.size() > 1) {
list.push_back([&] { pushListValue([&] {
switch (document->type) { switch (document->type) {
case Value::Type::Passport: case Value::Type::Passport:
return lang(lng_passport_identity_passport); return lang(lng_passport_identity_passport);
@ -145,7 +150,7 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
} else if (row.validate && !row.validate(i->second)) { } else if (row.validate && !row.validate(i->second)) {
return QString(); return QString();
} }
list.push_back(format ? format(i->second) : i->second); pushListValue(format ? format(i->second) : i->second);
} else if (!document) { } else if (!document) {
return QString(); return QString();
} else { } else {
@ -155,7 +160,7 @@ QString ComputeScopeRowReadyString(const Scope &scope) {
} else if (row.validate && !row.validate(i->second)) { } else if (row.validate && !row.validate(i->second)) {
return QString(); return QString();
} }
list.push_back(i->second); pushListValue(i->second);
} }
} }
return list.join(", "); return list.join(", ");

View File

@ -48,6 +48,8 @@ public:
virtual void showBox(object_ptr<BoxContent> box) = 0; virtual void showBox(object_ptr<BoxContent> box) = 0;
virtual void showToast(const QString &text) = 0; virtual void showToast(const QString &text) = 0;
virtual int closeGetDuration() = 0;
virtual ~ViewController() { virtual ~ViewController() {
} }

View File

@ -53,7 +53,7 @@ void Panel::initControls() {
}, lifetime()); }, lifetime());
_close->addClickHandler([=] { _close->addClickHandler([=] {
hideAndDestroy(); _controller->cancelAuth();
}); });
_back->toggledValue( _back->toggledValue(
@ -206,11 +206,13 @@ void Panel::destroyDelayed() {
_controller->cancelAuth(); _controller->cancelAuth();
} }
void Panel::hideAndDestroy() { int Panel::hideAndDestroyGetDuration() {
toggleOpacityAnimation(false); toggleOpacityAnimation(false);
if (_animationCache.isNull()) { if (_animationCache.isNull()) {
destroyDelayed(); destroyDelayed();
return 0;
} }
return st::callPanelDuration;
} }
void Panel::showAskPassword() { void Panel::showAskPassword() {

View File

@ -33,7 +33,7 @@ public:
Panel(not_null<PanelController*> controller); Panel(not_null<PanelController*> controller);
void showAndActivate(); void showAndActivate();
void hideAndDestroy(); int hideAndDestroyGetDuration();
void showAskPassword(); void showAskPassword();
void showNoPassword(); void showNoPassword();

View File

@ -975,6 +975,13 @@ void PanelController::cancelEditScope() {
} }
} }
int PanelController::closeGetDuration() {
if (_panel) {
return _panel->hideAndDestroyGetDuration();
}
return 0;
}
void PanelController::cancelAuth() { void PanelController::cancelAuth() {
_form->cancel(); _form->cancel();
} }

View File

@ -97,6 +97,8 @@ public:
void showBox(object_ptr<BoxContent> box) override; void showBox(object_ptr<BoxContent> box) override;
void showToast(const QString &text) override; void showToast(const QString &text) override;
int closeGetDuration() override;
void cancelAuth(); void cancelAuth();
rpl::lifetime &lifetime(); rpl::lifetime &lifetime();