| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- /*
- 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/timer.h"
- #include "base/weak_ptr.h"
- #include "core/core_cloud_password.h"
- class mtpFileLoader;
- namespace Storage {
- struct UploadSecureDone;
- struct UploadSecureProgress;
- } // namespace Storage
- namespace Window {
- class SessionController;
- } // namespace Window
- namespace Main {
- class Session;
- } // namespace Main
- namespace Ui {
- class SentCodeCall;
- } // namespace Ui
- namespace Passport {
- struct EditDocumentCountry;
- struct SavedCredentials {
- bytes::vector hashForAuth;
- bytes::vector hashForSecret;
- uint64 secretId = 0;
- };
- QString NonceNameByScope(const QString &scope);
- class ViewController;
- struct FormRequest {
- FormRequest(
- UserId botId,
- const QString &scope,
- const QString &callbackUrl,
- const QString &publicKey,
- const QString &nonce);
- UserId botId;
- QString scope;
- QString callbackUrl;
- QString publicKey;
- QString nonce;
- };
- class LoadStatus final {
- public:
- enum class Status {
- Done,
- InProgress,
- Failed,
- };
- LoadStatus() = default;
- void set(Status status, int offset = 0) {
- if (!offset) {
- offset = _offset;
- }
- _offset = (status == Status::InProgress) ? offset : 0;
- _status = status;
- }
- int offset() const {
- return _offset;
- }
- Status status() const {
- return _status;
- }
- private:
- int _offset = 0;
- Status _status = Status::Done;
- };
- struct UploadScanData {
- FullMsgId fullId;
- uint64 fileId = 0;
- int partsCount = 0;
- QByteArray md5checksum;
- bytes::vector hash;
- bytes::vector bytes;
- LoadStatus status;
- };
- class UploadScanDataPointer {
- public:
- UploadScanDataPointer(
- not_null<Main::Session*> session,
- std::unique_ptr<UploadScanData> &&value);
- UploadScanDataPointer(UploadScanDataPointer &&other);
- UploadScanDataPointer &operator=(UploadScanDataPointer &&other);
- ~UploadScanDataPointer();
- UploadScanData *get() const;
- operator UploadScanData*() const;
- explicit operator bool() const;
- UploadScanData *operator->() const;
- private:
- not_null<Main::Session*> _session;
- std::unique_ptr<UploadScanData> _value;
- };
- struct Value;
- enum class FileType {
- Scan,
- Translation,
- FrontSide,
- ReverseSide,
- Selfie,
- };
- struct File {
- uint64 id = 0;
- uint64 accessHash = 0;
- int32 size = 0;
- int32 dcId = 0;
- TimeId date = 0;
- bytes::vector hash;
- bytes::vector secret;
- bytes::vector encryptedSecret;
- LoadStatus downloadStatus;
- QImage image;
- QString error;
- };
- struct EditFile {
- EditFile(
- not_null<Main::Session*> session,
- not_null<const Value*> value,
- FileType type,
- const File &fields,
- std::unique_ptr<UploadScanData> &&uploadData);
- not_null<const Value*> value;
- FileType type;
- File fields;
- UploadScanDataPointer uploadData;
- std::shared_ptr<bool> guard;
- bool deleted = false;
- };
- struct ValueField {
- QString text;
- QString error;
- };
- struct ValueMap {
- std::map<QString, ValueField> fields;
- };
- struct ValueData {
- QByteArray original;
- bytes::vector secret;
- ValueMap parsed;
- bytes::vector hash;
- bytes::vector encryptedSecret;
- ValueMap parsedInEdit;
- bytes::vector hashInEdit;
- bytes::vector encryptedSecretInEdit;
- };
- struct Verification {
- mtpRequestId requestId = 0;
- QString phoneCodeHash;
- int codeLength = 0;
- QString fragmentUrl;
- std::unique_ptr<Ui::SentCodeCall> call;
- QString error;
- };
- struct Form;
- struct Value {
- enum class Type {
- PersonalDetails,
- Passport,
- DriverLicense,
- IdentityCard,
- InternalPassport,
- Address,
- UtilityBill,
- BankStatement,
- RentalAgreement,
- PassportRegistration,
- TemporaryRegistration,
- Phone,
- Email,
- };
- explicit Value(Type type);
- Value(Value &&other) = default;
- // Some data is not parsed from server-provided values.
- // It should be preserved through re-parsing (for example when saving).
- // So we hide "operator=(Value&&)" in private and instead provide this.
- void fillDataFrom(Value &&other);
- bool requiresSpecialScan(FileType type) const;
- bool requiresScan(FileType type) const;
- bool scansAreFilled() const;
- void saveInEdit(not_null<Main::Session*> session);
- void clearEditData();
- bool uploadingScan() const;
- bool saving() const;
- static constexpr auto kNothingFilled = 0x100;
- static constexpr auto kNoTranslationFilled = 0x10;
- static constexpr auto kNoSelfieFilled = 0x001;
- int whatNotFilled() const;
- std::vector<File> &files(FileType type);
- const std::vector<File> &files(FileType type) const;
- QString &fileMissingError(FileType type);
- const QString &fileMissingError(FileType type) const;
- std::vector<EditFile> &filesInEdit(FileType type);
- const std::vector<EditFile> &filesInEdit(FileType type) const;
- EditFile &fileInEdit(FileType type, std::optional<int> fileIndex);
- const EditFile &fileInEdit(
- FileType type,
- std::optional<int> fileIndex) const;
- std::vector<EditFile> takeAllFilesInEdit();
- Type type;
- ValueData data;
- std::map<FileType, File> specialScans;
- QString error;
- std::map<FileType, EditFile> specialScansInEdit;
- Verification verification;
- bytes::vector submitHash;
- bool selfieRequired = false;
- bool translationRequired = false;
- bool nativeNames = false;
- int editScreens = 0;
- mtpRequestId saveRequestId = 0;
- private:
- Value &operator=(Value &&other) = default;
- std::vector<File> _scans;
- std::vector<File> _translations;
- std::vector<EditFile> _scansInEdit;
- std::vector<EditFile> _translationsInEdit;
- QString _scanMissingError;
- QString _translationMissingError;
- };
- bool ValueChanged(not_null<const Value*> value, const ValueMap &data);
- struct RequestedValue {
- explicit RequestedValue(Value::Type type);
- Value::Type type;
- bool selfieRequired = false;
- bool translationRequired = false;
- bool nativeNames = false;
- };
- struct RequestedRow {
- std::vector<RequestedValue> values;
- };
- struct Form {
- using Request = std::vector<std::vector<Value::Type>>;
- std::map<Value::Type, Value> values;
- Request request;
- QString privacyPolicyUrl;
- QVector<MTPSecureValueError> pendingErrors;
- };
- struct PasswordSettings {
- Core::CloudPasswordCheckRequest request;
- Core::CloudPasswordAlgo newAlgo;
- Core::SecureSecretAlgo newSecureAlgo;
- QString hint;
- QString unconfirmedPattern;
- QString confirmedEmail;
- bool hasRecovery = false;
- bool notEmptyPassport = false;
- bool unknownAlgo = false;
- TimeId pendingResetDate = 0;
- bool operator==(const PasswordSettings &other) const {
- return (request == other.request)
- // newAlgo and newSecureAlgo are always different, because they have
- // different random parts added on the client to the server salts.
- // && (newAlgo == other.newAlgo)
- // && (newSecureAlgo == other.newSecureAlgo)
- && ((v::is_null(newAlgo) && v::is_null(other.newAlgo))
- || (!v::is_null(newAlgo) && !v::is_null(other.newAlgo)))
- && ((v::is_null(newSecureAlgo) && v::is_null(other.newSecureAlgo))
- || (!v::is_null(newSecureAlgo)
- && !v::is_null(other.newSecureAlgo)))
- && (hint == other.hint)
- && (unconfirmedPattern == other.unconfirmedPattern)
- && (confirmedEmail == other.confirmedEmail)
- && (hasRecovery == other.hasRecovery)
- && (unknownAlgo == other.unknownAlgo)
- && (pendingResetDate == other.pendingResetDate);
- }
- bool operator!=(const PasswordSettings &other) const {
- return !(*this == other);
- }
- };
- struct FileKey {
- uint64 id = 0;
- inline bool operator==(const FileKey &other) const {
- return (id == other.id);
- }
- inline bool operator!=(const FileKey &other) const {
- return !(*this == other);
- }
- inline bool operator<(const FileKey &other) const {
- return (id < other.id);
- }
- 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);
- }
- };
- class FormController : public base::has_weak_ptr {
- public:
- FormController(
- not_null<Window::SessionController*> controller,
- const FormRequest &request);
- [[nodiscard]] not_null<Window::SessionController*> window() const {
- return _controller;
- }
- [[nodiscard]] Main::Session &session() const;
- void show();
- UserData *bot() const;
- QString privacyPolicyUrl() const;
- std::vector<not_null<const Value*>> submitGetErrors();
- void submitPassword(const QByteArray &password);
- void recoverPassword();
- rpl::producer<QString> passwordError() const;
- const PasswordSettings &passwordSettings() const;
- void reloadPassword();
- void reloadAndSubmitPassword(const QByteArray &password);
- void cancelPassword();
- bool canAddScan(not_null<const Value*> value, FileType type) const;
- void uploadScan(
- not_null<const Value*> value,
- FileType type,
- QByteArray &&content);
- void deleteScan(
- not_null<const Value*> value,
- FileType type,
- std::optional<int> fileIndex);
- void restoreScan(
- not_null<const Value*> value,
- FileType type,
- std::optional<int> fileIndex);
- rpl::producer<> secretReadyEvents() const;
- QString defaultEmail() const;
- QString defaultPhoneNumber() const;
- rpl::producer<not_null<const EditFile*>> scanUpdated() const;
- rpl::producer<not_null<const Value*>> valueSaveFinished() const;
- rpl::producer<not_null<const Value*>> verificationNeeded() const;
- rpl::producer<not_null<const Value*>> verificationUpdate() const;
- void verify(not_null<const Value*> value, const QString &code);
- const Form &form() const;
- void startValueEdit(not_null<const Value*> value);
- void cancelValueEdit(not_null<const Value*> value);
- void cancelValueVerification(not_null<const Value*> value);
- void saveValueEdit(not_null<const Value*> value, ValueMap &&data);
- void deleteValueEdit(not_null<const Value*> value);
- void cancel();
- void cancelSure();
- [[nodiscard]] rpl::producer<EditDocumentCountry> preferredLanguage(
- const QString &countryCode);
- rpl::lifetime &lifetime();
- ~FormController();
- private:
- using PasswordCheckCallback = Fn<void(
- const Core::CloudPasswordResult &check)>;
- struct FinalData {
- QVector<MTPSecureValueHash> hashes;
- QByteArray credentials;
- std::vector<not_null<const Value*>> errors;
- };
- template <typename Condition>
- EditFile *findEditFileByCondition(Condition &&condition);
- EditFile *findEditFile(const FullMsgId &fullId);
- EditFile *findEditFile(const FileKey &key);
- std::pair<Value*, File*> findFile(const FileKey &key);
- not_null<Value*> findValue(not_null<const Value*> value);
- void requestForm();
- void requestPassword();
- void formDone(const MTPaccount_AuthorizationForm &result);
- void formFail(const QString &error);
- bool parseForm(const MTPaccount_AuthorizationForm &result);
- void showForm();
- Value parseValue(
- const MTPSecureValue &value,
- const std::vector<EditFile> &editData = {}) const;
- std::vector<File> parseFiles(
- const QVector<MTPSecureFile> &data,
- const std::vector<EditFile> &editData) const;
- std::optional<File> parseFile(
- const MTPSecureFile &data,
- const std::vector<EditFile> &editData) const;
- void fillDownloadedFile(
- File &destination,
- const std::vector<EditFile> &source) const;
- bool handleAppUpdateError(const QString &error);
- void submitPassword(
- const Core::CloudPasswordResult &check,
- const QByteArray &password,
- bool submitSaved);
- void checkPasswordHash(
- mtpRequestId &guard,
- bytes::vector hash,
- PasswordCheckCallback callback);
- bool handleSrpIdInvalid(mtpRequestId &guard);
- void requestPasswordData(mtpRequestId &guard);
- void passwordChecked();
- void passwordServerError();
- void passwordDone(const MTPaccount_Password &result);
- bool applyPassword(const MTPDaccount_password &settings);
- bool applyPassword(PasswordSettings &&settings);
- bytes::vector passwordHashForAuth(bytes::const_span password) const;
- void checkSavedPasswordSettings(const SavedCredentials &credentials);
- void checkSavedPasswordSettings(
- const Core::CloudPasswordResult &check,
- const SavedCredentials &credentials);
- void validateSecureSecret(
- bytes::const_span encryptedSecret,
- bytes::const_span passwordHashForSecret,
- bytes::const_span passwordBytes,
- uint64 serverSecretId);
- void decryptValues();
- void decryptValue(Value &value) const;
- bool validateValueSecrets(Value &value) const;
- void resetValue(Value &value) const;
- void fillErrors();
- void fillNativeFromFallback();
- void loadFile(File &file);
- void fileLoadDone(FileKey key, const QByteArray &bytes);
- void fileLoadProgress(FileKey key, int offset);
- void fileLoadFail(FileKey key);
- void generateSecret(bytes::const_span password);
- void saveSecret(
- const Core::CloudPasswordResult &check,
- const SavedCredentials &saved,
- const bytes::vector &secret);
- void subscribeToUploader();
- void encryptFile(
- EditFile &file,
- QByteArray &&content,
- Fn<void(UploadScanData &&result)> callback);
- void prepareFile(
- EditFile &file,
- const QByteArray &content);
- void uploadEncryptedFile(
- EditFile &file,
- UploadScanData &&data);
- void scanUploadDone(const Storage::UploadSecureDone &data);
- void scanUploadProgress(const Storage::UploadSecureProgress &data);
- void scanUploadFail(const FullMsgId &fullId);
- void scanDeleteRestore(
- not_null<const Value*> value,
- FileType type,
- std::optional<int> fileIndex,
- bool deleted);
- QString getPhoneFromValue(not_null<const Value*> value) const;
- QString getEmailFromValue(not_null<const Value*> value) const;
- QString getPlainTextFromValue(not_null<const Value*> value) const;
- void startPhoneVerification(not_null<Value*> value);
- void startEmailVerification(not_null<Value*> value);
- void valueSaveShowError(not_null<Value*> value, const MTP::Error &error);
- void valueSaveFailed(not_null<Value*> value);
- void requestPhoneCall(not_null<Value*> value);
- void verificationError(
- not_null<Value*> value,
- const QString &text);
- void valueEditFailed(not_null<Value*> value);
- void clearValueEdit(not_null<Value*> value);
- void clearValueVerification(not_null<Value*> value);
- bool isEncryptedValue(Value::Type type) const;
- void saveEncryptedValue(not_null<Value*> value);
- void savePlainTextValue(not_null<Value*> value);
- void sendSaveRequest(
- not_null<Value*> value,
- const MTPInputSecureValue &data);
- FinalData prepareFinalData();
- void suggestReset(bytes::vector password);
- void resetSecret(
- const Core::CloudPasswordResult &check,
- const bytes::vector &password);
- void suggestRestart();
- void cancelAbort();
- void shortPollEmailConfirmation();
- not_null<Window::SessionController*> _controller;
- MTP::Sender _api;
- FormRequest _request;
- UserData *_bot = nullptr;
- mtpRequestId _formRequestId = 0;
- mtpRequestId _passwordRequestId = 0;
- mtpRequestId _passwordCheckRequestId = 0;
- PasswordSettings _password;
- crl::time _lastSrpIdInvalidTime = 0;
- bytes::vector _passwordCheckHash;
- PasswordCheckCallback _passwordCheckCallback;
- QByteArray _savedPasswordValue;
- Form _form;
- bool _cancelled = false;
- mtpRequestId _recoverRequestId = 0;
- base::flat_map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
- struct {
- int32 hash = 0;
- std::map<QString, QString> languagesByCountryCode;
- } _passportConfig;
- rpl::event_stream<not_null<const EditFile*>> _scanUpdated;
- rpl::event_stream<not_null<const Value*>> _valueSaveFinished;
- rpl::event_stream<not_null<const Value*>> _verificationNeeded;
- rpl::event_stream<not_null<const Value*>> _verificationUpdate;
- bytes::vector _secret;
- uint64 _secretId = 0;
- std::vector<Fn<void()>> _secretCallbacks;
- mtpRequestId _saveSecretRequestId = 0;
- rpl::event_stream<> _secretReady;
- rpl::event_stream<QString> _passwordError;
- mtpRequestId _submitRequestId = 0;
- bool _submitSuccess = false;
- bool _suggestingRestart = false;
- QString _serviceErrorText;
- base::Timer _shortPollTimer;
- rpl::lifetime _uploaderSubscriptions;
- rpl::lifetime _lifetime;
- std::unique_ptr<ViewController> _view;
- };
- } // namespace Passport
|