passport_form_controller.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "mtproto/sender.h"
  9. #include "base/timer.h"
  10. #include "base/weak_ptr.h"
  11. #include "core/core_cloud_password.h"
  12. class mtpFileLoader;
  13. namespace Storage {
  14. struct UploadSecureDone;
  15. struct UploadSecureProgress;
  16. } // namespace Storage
  17. namespace Window {
  18. class SessionController;
  19. } // namespace Window
  20. namespace Main {
  21. class Session;
  22. } // namespace Main
  23. namespace Ui {
  24. class SentCodeCall;
  25. } // namespace Ui
  26. namespace Passport {
  27. struct EditDocumentCountry;
  28. struct SavedCredentials {
  29. bytes::vector hashForAuth;
  30. bytes::vector hashForSecret;
  31. uint64 secretId = 0;
  32. };
  33. QString NonceNameByScope(const QString &scope);
  34. class ViewController;
  35. struct FormRequest {
  36. FormRequest(
  37. UserId botId,
  38. const QString &scope,
  39. const QString &callbackUrl,
  40. const QString &publicKey,
  41. const QString &nonce);
  42. UserId botId;
  43. QString scope;
  44. QString callbackUrl;
  45. QString publicKey;
  46. QString nonce;
  47. };
  48. class LoadStatus final {
  49. public:
  50. enum class Status {
  51. Done,
  52. InProgress,
  53. Failed,
  54. };
  55. LoadStatus() = default;
  56. void set(Status status, int offset = 0) {
  57. if (!offset) {
  58. offset = _offset;
  59. }
  60. _offset = (status == Status::InProgress) ? offset : 0;
  61. _status = status;
  62. }
  63. int offset() const {
  64. return _offset;
  65. }
  66. Status status() const {
  67. return _status;
  68. }
  69. private:
  70. int _offset = 0;
  71. Status _status = Status::Done;
  72. };
  73. struct UploadScanData {
  74. FullMsgId fullId;
  75. uint64 fileId = 0;
  76. int partsCount = 0;
  77. QByteArray md5checksum;
  78. bytes::vector hash;
  79. bytes::vector bytes;
  80. LoadStatus status;
  81. };
  82. class UploadScanDataPointer {
  83. public:
  84. UploadScanDataPointer(
  85. not_null<Main::Session*> session,
  86. std::unique_ptr<UploadScanData> &&value);
  87. UploadScanDataPointer(UploadScanDataPointer &&other);
  88. UploadScanDataPointer &operator=(UploadScanDataPointer &&other);
  89. ~UploadScanDataPointer();
  90. UploadScanData *get() const;
  91. operator UploadScanData*() const;
  92. explicit operator bool() const;
  93. UploadScanData *operator->() const;
  94. private:
  95. not_null<Main::Session*> _session;
  96. std::unique_ptr<UploadScanData> _value;
  97. };
  98. struct Value;
  99. enum class FileType {
  100. Scan,
  101. Translation,
  102. FrontSide,
  103. ReverseSide,
  104. Selfie,
  105. };
  106. struct File {
  107. uint64 id = 0;
  108. uint64 accessHash = 0;
  109. int32 size = 0;
  110. int32 dcId = 0;
  111. TimeId date = 0;
  112. bytes::vector hash;
  113. bytes::vector secret;
  114. bytes::vector encryptedSecret;
  115. LoadStatus downloadStatus;
  116. QImage image;
  117. QString error;
  118. };
  119. struct EditFile {
  120. EditFile(
  121. not_null<Main::Session*> session,
  122. not_null<const Value*> value,
  123. FileType type,
  124. const File &fields,
  125. std::unique_ptr<UploadScanData> &&uploadData);
  126. not_null<const Value*> value;
  127. FileType type;
  128. File fields;
  129. UploadScanDataPointer uploadData;
  130. std::shared_ptr<bool> guard;
  131. bool deleted = false;
  132. };
  133. struct ValueField {
  134. QString text;
  135. QString error;
  136. };
  137. struct ValueMap {
  138. std::map<QString, ValueField> fields;
  139. };
  140. struct ValueData {
  141. QByteArray original;
  142. bytes::vector secret;
  143. ValueMap parsed;
  144. bytes::vector hash;
  145. bytes::vector encryptedSecret;
  146. ValueMap parsedInEdit;
  147. bytes::vector hashInEdit;
  148. bytes::vector encryptedSecretInEdit;
  149. };
  150. struct Verification {
  151. mtpRequestId requestId = 0;
  152. QString phoneCodeHash;
  153. int codeLength = 0;
  154. QString fragmentUrl;
  155. std::unique_ptr<Ui::SentCodeCall> call;
  156. QString error;
  157. };
  158. struct Form;
  159. struct Value {
  160. enum class Type {
  161. PersonalDetails,
  162. Passport,
  163. DriverLicense,
  164. IdentityCard,
  165. InternalPassport,
  166. Address,
  167. UtilityBill,
  168. BankStatement,
  169. RentalAgreement,
  170. PassportRegistration,
  171. TemporaryRegistration,
  172. Phone,
  173. Email,
  174. };
  175. explicit Value(Type type);
  176. Value(Value &&other) = default;
  177. // Some data is not parsed from server-provided values.
  178. // It should be preserved through re-parsing (for example when saving).
  179. // So we hide "operator=(Value&&)" in private and instead provide this.
  180. void fillDataFrom(Value &&other);
  181. bool requiresSpecialScan(FileType type) const;
  182. bool requiresScan(FileType type) const;
  183. bool scansAreFilled() const;
  184. void saveInEdit(not_null<Main::Session*> session);
  185. void clearEditData();
  186. bool uploadingScan() const;
  187. bool saving() const;
  188. static constexpr auto kNothingFilled = 0x100;
  189. static constexpr auto kNoTranslationFilled = 0x10;
  190. static constexpr auto kNoSelfieFilled = 0x001;
  191. int whatNotFilled() const;
  192. std::vector<File> &files(FileType type);
  193. const std::vector<File> &files(FileType type) const;
  194. QString &fileMissingError(FileType type);
  195. const QString &fileMissingError(FileType type) const;
  196. std::vector<EditFile> &filesInEdit(FileType type);
  197. const std::vector<EditFile> &filesInEdit(FileType type) const;
  198. EditFile &fileInEdit(FileType type, std::optional<int> fileIndex);
  199. const EditFile &fileInEdit(
  200. FileType type,
  201. std::optional<int> fileIndex) const;
  202. std::vector<EditFile> takeAllFilesInEdit();
  203. Type type;
  204. ValueData data;
  205. std::map<FileType, File> specialScans;
  206. QString error;
  207. std::map<FileType, EditFile> specialScansInEdit;
  208. Verification verification;
  209. bytes::vector submitHash;
  210. bool selfieRequired = false;
  211. bool translationRequired = false;
  212. bool nativeNames = false;
  213. int editScreens = 0;
  214. mtpRequestId saveRequestId = 0;
  215. private:
  216. Value &operator=(Value &&other) = default;
  217. std::vector<File> _scans;
  218. std::vector<File> _translations;
  219. std::vector<EditFile> _scansInEdit;
  220. std::vector<EditFile> _translationsInEdit;
  221. QString _scanMissingError;
  222. QString _translationMissingError;
  223. };
  224. bool ValueChanged(not_null<const Value*> value, const ValueMap &data);
  225. struct RequestedValue {
  226. explicit RequestedValue(Value::Type type);
  227. Value::Type type;
  228. bool selfieRequired = false;
  229. bool translationRequired = false;
  230. bool nativeNames = false;
  231. };
  232. struct RequestedRow {
  233. std::vector<RequestedValue> values;
  234. };
  235. struct Form {
  236. using Request = std::vector<std::vector<Value::Type>>;
  237. std::map<Value::Type, Value> values;
  238. Request request;
  239. QString privacyPolicyUrl;
  240. QVector<MTPSecureValueError> pendingErrors;
  241. };
  242. struct PasswordSettings {
  243. Core::CloudPasswordCheckRequest request;
  244. Core::CloudPasswordAlgo newAlgo;
  245. Core::SecureSecretAlgo newSecureAlgo;
  246. QString hint;
  247. QString unconfirmedPattern;
  248. QString confirmedEmail;
  249. bool hasRecovery = false;
  250. bool notEmptyPassport = false;
  251. bool unknownAlgo = false;
  252. TimeId pendingResetDate = 0;
  253. bool operator==(const PasswordSettings &other) const {
  254. return (request == other.request)
  255. // newAlgo and newSecureAlgo are always different, because they have
  256. // different random parts added on the client to the server salts.
  257. // && (newAlgo == other.newAlgo)
  258. // && (newSecureAlgo == other.newSecureAlgo)
  259. && ((v::is_null(newAlgo) && v::is_null(other.newAlgo))
  260. || (!v::is_null(newAlgo) && !v::is_null(other.newAlgo)))
  261. && ((v::is_null(newSecureAlgo) && v::is_null(other.newSecureAlgo))
  262. || (!v::is_null(newSecureAlgo)
  263. && !v::is_null(other.newSecureAlgo)))
  264. && (hint == other.hint)
  265. && (unconfirmedPattern == other.unconfirmedPattern)
  266. && (confirmedEmail == other.confirmedEmail)
  267. && (hasRecovery == other.hasRecovery)
  268. && (unknownAlgo == other.unknownAlgo)
  269. && (pendingResetDate == other.pendingResetDate);
  270. }
  271. bool operator!=(const PasswordSettings &other) const {
  272. return !(*this == other);
  273. }
  274. };
  275. struct FileKey {
  276. uint64 id = 0;
  277. inline bool operator==(const FileKey &other) const {
  278. return (id == other.id);
  279. }
  280. inline bool operator!=(const FileKey &other) const {
  281. return !(*this == other);
  282. }
  283. inline bool operator<(const FileKey &other) const {
  284. return (id < other.id);
  285. }
  286. inline bool operator>(const FileKey &other) const {
  287. return (other < *this);
  288. }
  289. inline bool operator<=(const FileKey &other) const {
  290. return !(other < *this);
  291. }
  292. inline bool operator>=(const FileKey &other) const {
  293. return !(*this < other);
  294. }
  295. };
  296. class FormController : public base::has_weak_ptr {
  297. public:
  298. FormController(
  299. not_null<Window::SessionController*> controller,
  300. const FormRequest &request);
  301. [[nodiscard]] not_null<Window::SessionController*> window() const {
  302. return _controller;
  303. }
  304. [[nodiscard]] Main::Session &session() const;
  305. void show();
  306. UserData *bot() const;
  307. QString privacyPolicyUrl() const;
  308. std::vector<not_null<const Value*>> submitGetErrors();
  309. void submitPassword(const QByteArray &password);
  310. void recoverPassword();
  311. rpl::producer<QString> passwordError() const;
  312. const PasswordSettings &passwordSettings() const;
  313. void reloadPassword();
  314. void reloadAndSubmitPassword(const QByteArray &password);
  315. void cancelPassword();
  316. bool canAddScan(not_null<const Value*> value, FileType type) const;
  317. void uploadScan(
  318. not_null<const Value*> value,
  319. FileType type,
  320. QByteArray &&content);
  321. void deleteScan(
  322. not_null<const Value*> value,
  323. FileType type,
  324. std::optional<int> fileIndex);
  325. void restoreScan(
  326. not_null<const Value*> value,
  327. FileType type,
  328. std::optional<int> fileIndex);
  329. rpl::producer<> secretReadyEvents() const;
  330. QString defaultEmail() const;
  331. QString defaultPhoneNumber() const;
  332. rpl::producer<not_null<const EditFile*>> scanUpdated() const;
  333. rpl::producer<not_null<const Value*>> valueSaveFinished() const;
  334. rpl::producer<not_null<const Value*>> verificationNeeded() const;
  335. rpl::producer<not_null<const Value*>> verificationUpdate() const;
  336. void verify(not_null<const Value*> value, const QString &code);
  337. const Form &form() const;
  338. void startValueEdit(not_null<const Value*> value);
  339. void cancelValueEdit(not_null<const Value*> value);
  340. void cancelValueVerification(not_null<const Value*> value);
  341. void saveValueEdit(not_null<const Value*> value, ValueMap &&data);
  342. void deleteValueEdit(not_null<const Value*> value);
  343. void cancel();
  344. void cancelSure();
  345. [[nodiscard]] rpl::producer<EditDocumentCountry> preferredLanguage(
  346. const QString &countryCode);
  347. rpl::lifetime &lifetime();
  348. ~FormController();
  349. private:
  350. using PasswordCheckCallback = Fn<void(
  351. const Core::CloudPasswordResult &check)>;
  352. struct FinalData {
  353. QVector<MTPSecureValueHash> hashes;
  354. QByteArray credentials;
  355. std::vector<not_null<const Value*>> errors;
  356. };
  357. template <typename Condition>
  358. EditFile *findEditFileByCondition(Condition &&condition);
  359. EditFile *findEditFile(const FullMsgId &fullId);
  360. EditFile *findEditFile(const FileKey &key);
  361. std::pair<Value*, File*> findFile(const FileKey &key);
  362. not_null<Value*> findValue(not_null<const Value*> value);
  363. void requestForm();
  364. void requestPassword();
  365. void formDone(const MTPaccount_AuthorizationForm &result);
  366. void formFail(const QString &error);
  367. bool parseForm(const MTPaccount_AuthorizationForm &result);
  368. void showForm();
  369. Value parseValue(
  370. const MTPSecureValue &value,
  371. const std::vector<EditFile> &editData = {}) const;
  372. std::vector<File> parseFiles(
  373. const QVector<MTPSecureFile> &data,
  374. const std::vector<EditFile> &editData) const;
  375. std::optional<File> parseFile(
  376. const MTPSecureFile &data,
  377. const std::vector<EditFile> &editData) const;
  378. void fillDownloadedFile(
  379. File &destination,
  380. const std::vector<EditFile> &source) const;
  381. bool handleAppUpdateError(const QString &error);
  382. void submitPassword(
  383. const Core::CloudPasswordResult &check,
  384. const QByteArray &password,
  385. bool submitSaved);
  386. void checkPasswordHash(
  387. mtpRequestId &guard,
  388. bytes::vector hash,
  389. PasswordCheckCallback callback);
  390. bool handleSrpIdInvalid(mtpRequestId &guard);
  391. void requestPasswordData(mtpRequestId &guard);
  392. void passwordChecked();
  393. void passwordServerError();
  394. void passwordDone(const MTPaccount_Password &result);
  395. bool applyPassword(const MTPDaccount_password &settings);
  396. bool applyPassword(PasswordSettings &&settings);
  397. bytes::vector passwordHashForAuth(bytes::const_span password) const;
  398. void checkSavedPasswordSettings(const SavedCredentials &credentials);
  399. void checkSavedPasswordSettings(
  400. const Core::CloudPasswordResult &check,
  401. const SavedCredentials &credentials);
  402. void validateSecureSecret(
  403. bytes::const_span encryptedSecret,
  404. bytes::const_span passwordHashForSecret,
  405. bytes::const_span passwordBytes,
  406. uint64 serverSecretId);
  407. void decryptValues();
  408. void decryptValue(Value &value) const;
  409. bool validateValueSecrets(Value &value) const;
  410. void resetValue(Value &value) const;
  411. void fillErrors();
  412. void fillNativeFromFallback();
  413. void loadFile(File &file);
  414. void fileLoadDone(FileKey key, const QByteArray &bytes);
  415. void fileLoadProgress(FileKey key, int offset);
  416. void fileLoadFail(FileKey key);
  417. void generateSecret(bytes::const_span password);
  418. void saveSecret(
  419. const Core::CloudPasswordResult &check,
  420. const SavedCredentials &saved,
  421. const bytes::vector &secret);
  422. void subscribeToUploader();
  423. void encryptFile(
  424. EditFile &file,
  425. QByteArray &&content,
  426. Fn<void(UploadScanData &&result)> callback);
  427. void prepareFile(
  428. EditFile &file,
  429. const QByteArray &content);
  430. void uploadEncryptedFile(
  431. EditFile &file,
  432. UploadScanData &&data);
  433. void scanUploadDone(const Storage::UploadSecureDone &data);
  434. void scanUploadProgress(const Storage::UploadSecureProgress &data);
  435. void scanUploadFail(const FullMsgId &fullId);
  436. void scanDeleteRestore(
  437. not_null<const Value*> value,
  438. FileType type,
  439. std::optional<int> fileIndex,
  440. bool deleted);
  441. QString getPhoneFromValue(not_null<const Value*> value) const;
  442. QString getEmailFromValue(not_null<const Value*> value) const;
  443. QString getPlainTextFromValue(not_null<const Value*> value) const;
  444. void startPhoneVerification(not_null<Value*> value);
  445. void startEmailVerification(not_null<Value*> value);
  446. void valueSaveShowError(not_null<Value*> value, const MTP::Error &error);
  447. void valueSaveFailed(not_null<Value*> value);
  448. void requestPhoneCall(not_null<Value*> value);
  449. void verificationError(
  450. not_null<Value*> value,
  451. const QString &text);
  452. void valueEditFailed(not_null<Value*> value);
  453. void clearValueEdit(not_null<Value*> value);
  454. void clearValueVerification(not_null<Value*> value);
  455. bool isEncryptedValue(Value::Type type) const;
  456. void saveEncryptedValue(not_null<Value*> value);
  457. void savePlainTextValue(not_null<Value*> value);
  458. void sendSaveRequest(
  459. not_null<Value*> value,
  460. const MTPInputSecureValue &data);
  461. FinalData prepareFinalData();
  462. void suggestReset(bytes::vector password);
  463. void resetSecret(
  464. const Core::CloudPasswordResult &check,
  465. const bytes::vector &password);
  466. void suggestRestart();
  467. void cancelAbort();
  468. void shortPollEmailConfirmation();
  469. not_null<Window::SessionController*> _controller;
  470. MTP::Sender _api;
  471. FormRequest _request;
  472. UserData *_bot = nullptr;
  473. mtpRequestId _formRequestId = 0;
  474. mtpRequestId _passwordRequestId = 0;
  475. mtpRequestId _passwordCheckRequestId = 0;
  476. PasswordSettings _password;
  477. crl::time _lastSrpIdInvalidTime = 0;
  478. bytes::vector _passwordCheckHash;
  479. PasswordCheckCallback _passwordCheckCallback;
  480. QByteArray _savedPasswordValue;
  481. Form _form;
  482. bool _cancelled = false;
  483. mtpRequestId _recoverRequestId = 0;
  484. base::flat_map<FileKey, std::unique_ptr<mtpFileLoader>> _fileLoaders;
  485. struct {
  486. int32 hash = 0;
  487. std::map<QString, QString> languagesByCountryCode;
  488. } _passportConfig;
  489. rpl::event_stream<not_null<const EditFile*>> _scanUpdated;
  490. rpl::event_stream<not_null<const Value*>> _valueSaveFinished;
  491. rpl::event_stream<not_null<const Value*>> _verificationNeeded;
  492. rpl::event_stream<not_null<const Value*>> _verificationUpdate;
  493. bytes::vector _secret;
  494. uint64 _secretId = 0;
  495. std::vector<Fn<void()>> _secretCallbacks;
  496. mtpRequestId _saveSecretRequestId = 0;
  497. rpl::event_stream<> _secretReady;
  498. rpl::event_stream<QString> _passwordError;
  499. mtpRequestId _submitRequestId = 0;
  500. bool _submitSuccess = false;
  501. bool _suggestingRestart = false;
  502. QString _serviceErrorText;
  503. base::Timer _shortPollTimer;
  504. rpl::lifetime _uploaderSubscriptions;
  505. rpl::lifetime _lifetime;
  506. std::unique_ptr<ViewController> _view;
  507. };
  508. } // namespace Passport