tdesktop/Telegram/SourceFiles/passport/passport_form_controller.h

277 lines
6.6 KiB
C
Raw Normal View History

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "mtproto/sender.h"
#include "base/weak_ptr.h"
class BoxContent;
namespace Storage {
struct UploadSecureDone;
struct UploadSecureProgress;
} // namespace Storage
namespace Window {
class Controller;
} // namespace Window
namespace Passport {
struct FormRequest {
FormRequest(
UserId botId,
2018-03-27 13:00:13 +00:00
const QString &scope,
const QString &callbackUrl,
const QString &publicKey);
UserId botId;
2018-03-27 13:00:13 +00:00
QString scope;
QString callbackUrl;
QString publicKey;
};
struct IdentityData;
struct FileKey {
uint64 id = 0;
int32 dcId = 0;
inline bool operator==(const FileKey &other) const {
return (id == other.id) && (dcId == other.dcId);
}
inline bool operator!=(const FileKey &other) const {
return !(*this == other);
}
inline bool operator<(const FileKey &other) const {
return (id < other.id) || ((id == other.id) && (dcId < other.dcId));
}
inline bool operator>(const FileKey &other) const {
return (other < *this);
}
inline bool operator<=(const FileKey &other) const {
return !(other < *this);
}
inline bool operator>=(const FileKey &other) const {
return !(*this < other);
}
};
struct ScanInfo {
FileKey key;
QString status;
QImage thumb;
};
class FormController : private MTP::Sender, public base::has_weak_ptr {
public:
FormController(
not_null<Window::Controller*> controller,
const FormRequest &request);
void show();
void submitPassword(const QString &password);
rpl::producer<QString> passwordError() const;
QString passwordHint() const;
2018-03-29 14:44:34 +00:00
void uploadScan(int valueIndex, QByteArray &&content);
void deleteScan(int valueIndex, int fileIndex);
rpl::producer<> secretReadyEvents() const;
QString defaultEmail() const;
QString defaultPhoneNumber() const;
rpl::producer<ScanInfo> scanUpdated() const;
void fillRows(
base::lambda<void(
QString title,
QString description,
bool ready)> callback);
2018-03-29 14:44:34 +00:00
void editValue(int index);
2018-03-29 14:44:34 +00:00
void saveValueIdentity(int index, const IdentityData &data);
~FormController();
private:
2018-03-29 14:44:34 +00:00
struct UploadScanData {
~UploadScanData();
FullMsgId fullId;
uint64 fileId = 0;
int partsCount = 0;
QByteArray md5checksum;
bytes::vector hash;
bytes::vector bytes;
int offset = 0;
};
struct File {
uint64 id = 0;
uint64 accessHash = 0;
int32 size = 0;
int32 dcId = 0;
2018-03-29 14:44:34 +00:00
TimeId date = 0;
bytes::vector hash;
bytes::vector secret;
bytes::vector encryptedSecret;
int downloadOffset = 0;
QImage image;
};
struct EditFile {
EditFile(
const File &fields,
2018-03-29 14:44:34 +00:00
std::unique_ptr<UploadScanData> &&uploadData);
File fields;
2018-03-29 14:44:34 +00:00
std::unique_ptr<UploadScanData> uploadData;
bool deleted = false;
};
2018-03-27 13:00:13 +00:00
struct Verification {
TimeId date;
};
2018-03-29 14:44:34 +00:00
struct ValueData {
QByteArray original;
std::map<QString, QString> parsed;
bytes::vector hash;
bytes::vector secret;
bytes::vector encryptedSecret;
};
struct Value {
enum class Type {
Identity,
Address,
Phone,
Email,
};
2018-03-27 13:00:13 +00:00
2018-03-29 14:44:34 +00:00
explicit Value(Type type);
Value(Value &&other) = default;
Value &operator=(Value &&other) = default;
Type type;
2018-03-29 14:44:34 +00:00
ValueData data;
2018-03-27 13:00:13 +00:00
std::vector<File> files;
std::vector<EditFile> filesInEdit;
2018-03-29 14:44:34 +00:00
bytes::vector consistencyHash;
2018-03-27 13:00:13 +00:00
base::optional<Verification> verification;
};
struct Form {
2018-03-29 14:44:34 +00:00
std::vector<Value> rows;
};
struct PasswordSettings {
2018-03-27 13:00:13 +00:00
bytes::vector salt;
bytes::vector newSalt;
bytes::vector newSecureSalt;
QString hint;
QString unconfirmedPattern;
2018-03-27 13:00:13 +00:00
QString confirmedEmail;
bool hasRecovery = false;
};
2018-03-27 13:00:13 +00:00
EditFile *findEditFile(const FullMsgId &fullId);
EditFile *findEditFile(const FileKey &key);
2018-03-29 14:44:34 +00:00
std::pair<Value*, File*> findFile(const FileKey &key);
void requestForm();
void requestPassword();
void formDone(const MTPaccount_AuthorizationForm &result);
void formFail(const RPCError &error);
void parseForm(const MTPaccount_AuthorizationForm &result);
void showForm();
2018-03-29 14:44:34 +00:00
Value parseValue(const MTPSecureValue &value) const;
2018-03-27 13:00:13 +00:00
template <typename DataType>
2018-03-29 14:44:34 +00:00
Value parseEncryptedValue(
Value::Type type,
2018-03-27 13:00:13 +00:00
const DataType &data) const;
template <typename DataType>
2018-03-29 14:44:34 +00:00
Value parsePlainTextValue(
Value::Type type,
const QByteArray &text,
2018-03-27 13:00:13 +00:00
const DataType &data) const;
Verification parseVerified(const MTPSecureValueVerified &data) const;
std::vector<File> parseFiles(
const QVector<MTPSecureFile> &data,
const std::vector<EditFile> &editData = {}) const;
2018-03-29 14:44:34 +00:00
void fillDownloadedFile(
File &destination,
const std::vector<EditFile> &source) const;
void passwordDone(const MTPaccount_Password &result);
void passwordFail(const RPCError &error);
void parsePassword(const MTPDaccount_noPassword &settings);
void parsePassword(const MTPDaccount_password &settings);
2018-03-27 13:00:13 +00:00
bytes::vector passwordHashForAuth(bytes::const_span password) const;
void validateSecureSecret(
bytes::const_span salt,
bytes::const_span encryptedSecret,
bytes::const_span password);
2018-03-29 14:44:34 +00:00
void decryptValues();
void decryptValue(Value &value);
bool validateValueSecrets(Value &value);
void resetValue(Value &value);
2018-03-29 14:44:34 +00:00
IdentityData valueDataIdentity(const Value &value) const;
std::vector<ScanInfo> valueFilesIdentity(const Value &value) const;
2018-03-27 13:00:13 +00:00
void saveIdentity(int index);
void loadFiles(std::vector<File> &files);
void fileLoadDone(FileKey key, const QByteArray &bytes);
void fileLoadProgress(FileKey key, int offset);
void fileLoadFail(FileKey key);
2018-03-27 13:00:13 +00:00
void generateSecret(bytes::const_span password);
void subscribeToUploader();
void encryptScan(
2018-03-29 14:44:34 +00:00
int valueIndex,
int fileIndex,
QByteArray &&content);
2018-03-29 14:44:34 +00:00
void uploadEncryptedScan(
int valueIndex,
int fileIndex,
UploadScanData &&data);
void scanUploadDone(const Storage::UploadSecureDone &data);
void scanUploadProgress(const Storage::UploadSecureProgress &data);
void scanUploadFail(const FullMsgId &fullId);
ScanInfo collectScanInfo(const EditFile &file) const;
not_null<Window::Controller*> _controller;
FormRequest _request;
UserData *_bot = nullptr;
mtpRequestId _formRequestId = 0;
mtpRequestId _passwordRequestId = 0;
mtpRequestId _passwordCheckRequestId = 0;
PasswordSettings _password;
Form _form;
std::map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
rpl::event_stream<ScanInfo> _scanUpdated;
bytes::vector _secret;
2018-03-29 14:44:34 +00:00
uint64 _secretId = 0;
std::vector<base::lambda<void()>> _secretCallbacks;
mtpRequestId _saveSecretRequestId = 0;
rpl::event_stream<> _secretReady;
rpl::event_stream<QString> _passwordError;
QPointer<BoxContent> _editBox;
rpl::lifetime _uploaderSubscriptions;
};
} // namespace Passport