summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp651
1 files changed, 436 insertions, 215 deletions
diff --git a/protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp b/protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp
index aaf91b0357..39ba1f2afe 100644
--- a/protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp
+++ b/protocols/Telegram/tdlib/td/td/telegram/AuthManager.cpp
@@ -1,5 +1,5 @@
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -9,37 +9,280 @@
#include "td/telegram/AttachMenuManager.h"
#include "td/telegram/AuthManager.hpp"
#include "td/telegram/ConfigManager.h"
-#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogFilterManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
+#include "td/telegram/logevent/LogEventHelper.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/NetQueryDispatcher.h"
#include "td/telegram/NewPasswordState.h"
#include "td/telegram/NotificationManager.h"
+#include "td/telegram/OnlineManager.h"
#include "td/telegram/OptionManager.h"
#include "td/telegram/PasswordManager.h"
+#include "td/telegram/PromoDataManager.h"
+#include "td/telegram/ReactionManager.h"
+#include "td/telegram/SendCodeHelper.hpp"
#include "td/telegram/StateManager.h"
#include "td/telegram/StickersManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
+#include "td/telegram/telegram_api.h"
+#include "td/telegram/TermsOfService.hpp"
+#include "td/telegram/TermsOfServiceManager.h"
#include "td/telegram/ThemeManager.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/UpdatesManager.h"
+#include "td/telegram/UserManager.h"
+#include "td/telegram/Version.h"
#include "td/utils/base64.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Promise.h"
-#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
+#include "td/utils/SliceBuilder.h"
#include "td/utils/Time.h"
+#include "td/utils/tl_helpers.h"
namespace td {
+struct AuthManager::DbState {
+ State state_;
+ int32 api_id_;
+ string api_hash_;
+ double expires_at_;
+
+ // WaitEmailAddress and WaitEmailCode
+ bool allow_apple_id_ = false;
+ bool allow_google_id_ = false;
+
+ // WaitEmailCode
+ string email_address_;
+ SentEmailCode email_code_info_;
+ int32 reset_available_period_ = -1;
+ int32 reset_pending_date_ = -1;
+
+ // WaitEmailAddress, WaitEmailCode, WaitCode and WaitRegistration
+ SendCodeHelper send_code_helper_;
+
+ // WaitQrCodeConfirmation
+ vector<UserId> other_user_ids_;
+ string login_token_;
+ double login_token_expires_at_ = 0;
+
+ // WaitPassword
+ WaitPasswordState wait_password_state_;
+
+ // WaitRegistration
+ TermsOfService terms_of_service_;
+
+ DbState() = default;
+
+ static DbState wait_email_address(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id,
+ SendCodeHelper send_code_helper) {
+ DbState state(State::WaitEmailAddress, api_id, std::move(api_hash));
+ state.send_code_helper_ = std::move(send_code_helper);
+ state.allow_apple_id_ = allow_apple_id;
+ state.allow_google_id_ = allow_google_id;
+ return state;
+ }
+
+ static DbState wait_email_code(int32 api_id, string api_hash, bool allow_apple_id, bool allow_google_id,
+ string email_address, SentEmailCode email_code_info, int32 reset_available_period,
+ int32 reset_pending_date, SendCodeHelper send_code_helper) {
+ DbState state(State::WaitEmailCode, api_id, std::move(api_hash));
+ state.send_code_helper_ = std::move(send_code_helper);
+ state.allow_apple_id_ = allow_apple_id;
+ state.allow_google_id_ = allow_google_id;
+ state.email_address_ = std::move(email_address);
+ state.email_code_info_ = std::move(email_code_info);
+ state.reset_available_period_ = reset_available_period;
+ state.reset_pending_date_ = reset_pending_date;
+ return state;
+ }
+
+ static DbState wait_code(int32 api_id, string api_hash, SendCodeHelper send_code_helper) {
+ DbState state(State::WaitCode, api_id, std::move(api_hash));
+ state.send_code_helper_ = std::move(send_code_helper);
+ return state;
+ }
+
+ static DbState wait_qr_code_confirmation(int32 api_id, string api_hash, vector<UserId> other_user_ids,
+ string login_token, double login_token_expires_at) {
+ DbState state(State::WaitQrCodeConfirmation, api_id, std::move(api_hash));
+ state.other_user_ids_ = std::move(other_user_ids);
+ state.login_token_ = std::move(login_token);
+ state.login_token_expires_at_ = login_token_expires_at;
+ return state;
+ }
+
+ static DbState wait_password(int32 api_id, string api_hash, WaitPasswordState wait_password_state) {
+ DbState state(State::WaitPassword, api_id, std::move(api_hash));
+ state.wait_password_state_ = std::move(wait_password_state);
+ return state;
+ }
+
+ static DbState wait_registration(int32 api_id, string api_hash, SendCodeHelper send_code_helper,
+ TermsOfService terms_of_service) {
+ DbState state(State::WaitRegistration, api_id, std::move(api_hash));
+ state.send_code_helper_ = std::move(send_code_helper);
+ state.terms_of_service_ = std::move(terms_of_service);
+ return state;
+ }
+
+ template <class StorerT>
+ void store(StorerT &storer) const;
+ template <class ParserT>
+ void parse(ParserT &parser);
+
+ private:
+ DbState(State state, int32 api_id, string &&api_hash)
+ : state_(state), api_id_(api_id), api_hash_(std::move(api_hash)) {
+ auto state_timeout = [state] {
+ switch (state) {
+ case State::WaitPassword:
+ case State::WaitRegistration:
+ return 86400;
+ case State::WaitEmailAddress:
+ case State::WaitEmailCode:
+ case State::WaitCode:
+ case State::WaitQrCodeConfirmation:
+ return 5 * 60;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+ }();
+ expires_at_ = Time::now() + state_timeout;
+ }
+};
+
+template <class StorerT>
+void AuthManager::DbState::store(StorerT &storer) const {
+ using td::store;
+ bool has_terms_of_service = !terms_of_service_.get_id().empty();
+ bool is_pbkdf2_supported = true;
+ bool is_srp_supported = true;
+ bool is_wait_registration_supported = true;
+ bool is_wait_registration_stores_phone_number = true;
+ bool is_wait_qr_code_confirmation_supported = true;
+ bool is_time_store_supported = true;
+ bool is_reset_email_address_supported = true;
+ BEGIN_STORE_FLAGS();
+ STORE_FLAG(has_terms_of_service);
+ STORE_FLAG(is_pbkdf2_supported);
+ STORE_FLAG(is_srp_supported);
+ STORE_FLAG(is_wait_registration_supported);
+ STORE_FLAG(is_wait_registration_stores_phone_number);
+ STORE_FLAG(is_wait_qr_code_confirmation_supported);
+ STORE_FLAG(allow_apple_id_);
+ STORE_FLAG(allow_google_id_);
+ STORE_FLAG(is_time_store_supported);
+ STORE_FLAG(is_reset_email_address_supported);
+ END_STORE_FLAGS();
+ store(state_, storer);
+ store(api_id_, storer);
+ store(api_hash_, storer);
+ store_time(expires_at_, storer);
+
+ if (has_terms_of_service) {
+ store(terms_of_service_, storer);
+ }
+
+ if (state_ == State::WaitEmailAddress) {
+ store(send_code_helper_, storer);
+ } else if (state_ == State::WaitEmailCode) {
+ store(send_code_helper_, storer);
+ store(email_address_, storer);
+ store(email_code_info_, storer);
+ store(reset_available_period_, storer);
+ store(reset_pending_date_, storer);
+ } else if (state_ == State::WaitCode) {
+ store(send_code_helper_, storer);
+ } else if (state_ == State::WaitQrCodeConfirmation) {
+ store(other_user_ids_, storer);
+ store(login_token_, storer);
+ store_time(login_token_expires_at_, storer);
+ } else if (state_ == State::WaitPassword) {
+ store(wait_password_state_, storer);
+ } else if (state_ == State::WaitRegistration) {
+ store(send_code_helper_, storer);
+ } else {
+ UNREACHABLE();
+ }
+}
+
+template <class ParserT>
+void AuthManager::DbState::parse(ParserT &parser) {
+ using td::parse;
+ bool has_terms_of_service = false;
+ bool is_pbkdf2_supported = false;
+ bool is_srp_supported = false;
+ bool is_wait_registration_supported = false;
+ bool is_wait_registration_stores_phone_number = false;
+ bool is_wait_qr_code_confirmation_supported = false;
+ bool is_time_store_supported = false;
+ bool is_reset_email_address_supported = false;
+ if (parser.version() >= static_cast<int32>(Version::AddTermsOfService)) {
+ BEGIN_PARSE_FLAGS();
+ PARSE_FLAG(has_terms_of_service);
+ PARSE_FLAG(is_pbkdf2_supported);
+ PARSE_FLAG(is_srp_supported);
+ PARSE_FLAG(is_wait_registration_supported);
+ PARSE_FLAG(is_wait_registration_stores_phone_number);
+ PARSE_FLAG(is_wait_qr_code_confirmation_supported);
+ PARSE_FLAG(allow_apple_id_);
+ PARSE_FLAG(allow_google_id_);
+ PARSE_FLAG(is_time_store_supported);
+ PARSE_FLAG(is_reset_email_address_supported);
+ END_PARSE_FLAGS();
+ }
+ if (!is_reset_email_address_supported) {
+ return parser.set_error("Have no reset email address support");
+ }
+ CHECK(is_pbkdf2_supported);
+ CHECK(is_srp_supported);
+ CHECK(is_wait_registration_supported);
+ CHECK(is_wait_registration_stores_phone_number);
+ CHECK(is_wait_qr_code_confirmation_supported);
+ CHECK(is_time_store_supported);
+
+ parse(state_, parser);
+ parse(api_id_, parser);
+ parse(api_hash_, parser);
+ parse_time(expires_at_, parser);
+
+ if (has_terms_of_service) {
+ parse(terms_of_service_, parser);
+ }
+
+ if (state_ == State::WaitEmailAddress) {
+ parse(send_code_helper_, parser);
+ } else if (state_ == State::WaitEmailCode) {
+ parse(send_code_helper_, parser);
+ parse(email_address_, parser);
+ parse(email_code_info_, parser);
+ parse(reset_available_period_, parser);
+ parse(reset_pending_date_, parser);
+ } else if (state_ == State::WaitCode) {
+ parse(send_code_helper_, parser);
+ } else if (state_ == State::WaitQrCodeConfirmation) {
+ parse(other_user_ids_, parser);
+ parse(login_token_, parser);
+ parse_time(login_token_expires_at_, parser);
+ } else if (state_ == State::WaitPassword) {
+ parse(wait_password_state_, parser);
+ } else if (state_ == State::WaitRegistration) {
+ parse(send_code_helper_, parser);
+ } else {
+ parser.set_error(PSTRING() << "Unexpected " << tag("state", static_cast<int32>(state_)));
+ }
+}
+
AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> parent)
: parent_(std::move(parent)), api_id_(api_id), api_hash_(api_hash) {
string auth_str = G()->td_db()->get_binlog_pmc()->get("auth");
@@ -48,7 +291,7 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par
if (is_bot_str == "true") {
is_bot_ = true;
}
- auto my_id = ContactsManager::load_my_id();
+ auto my_id = UserManager::load_my_id();
if (my_id.is_valid()) {
// just in case
LOG(INFO) << "Logged in as " << my_id;
@@ -56,8 +299,8 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par
update_state(State::Ok);
} else {
LOG(ERROR) << "Restore unknown my_id";
- ContactsManager::send_get_me_query(
- td_, PromiseCreator::lambda([this](Result<Unit> result) { update_state(State::Ok); }));
+ UserManager::send_get_me_query(td_,
+ PromiseCreator::lambda([this](Result<Unit> result) { update_state(State::Ok); }));
}
G()->net_query_dispatcher().check_authorization_is_ok();
} else if (auth_str == "logout") {
@@ -80,6 +323,8 @@ void AuthManager::start_up() {
G()->net_query_dispatcher().destroy_auth_keys(PromiseCreator::lambda([](Result<Unit> result) {
if (result.is_ok()) {
send_closure_later(G()->td(), &Td::destroy);
+ } else {
+ LOG(INFO) << "Failed to destroy auth keys";
}
}));
}
@@ -88,13 +333,6 @@ void AuthManager::tear_down() {
parent_.reset();
}
-bool AuthManager::is_bot() const {
- if (net_query_id_ != 0 && net_query_type_ == NetQueryType::BotAuthentication) {
- return true;
- }
- return is_bot_ && was_authorized();
-}
-
bool AuthManager::was_authorized() const {
return state_ == State::Ok || state_ == State::LoggingOut || state_ == State::DestroyingKeys ||
state_ == State::Closing;
@@ -305,6 +543,15 @@ void AuthManager::set_firebase_token(uint64 query_id, string token) {
G()->net_query_creator().create_unauth(send_code_helper_.request_firebase_sms(token)));
}
+void AuthManager::report_missing_code(uint64 query_id, string mobile_network_code) {
+ if (state_ != State::WaitCode) {
+ return on_query_error(query_id, Status::Error(400, "Call to reportAuthenticationCodeMissing unexpected"));
+ }
+ G()->net_query_dispatcher().dispatch_with_callback(
+ G()->net_query_creator().create_unauth(send_code_helper_.report_missing_code(mobile_network_code)),
+ actor_shared(this));
+}
+
void AuthManager::set_email_address(uint64 query_id, string email_address) {
if (state_ != State::WaitEmailAddress) {
if (state_ == State::WaitEmailCode && net_query_id_ == 0) {
@@ -325,7 +572,7 @@ void AuthManager::set_email_address(uint64 query_id, string email_address) {
G()->net_query_creator().create_unauth(send_code_helper_.send_verify_email_code(email_address_)));
}
-void AuthManager::resend_authentication_code(uint64 query_id) {
+void AuthManager::resend_authentication_code(uint64 query_id, td_api::object_ptr<td_api::ResendCodeReason> &&reason) {
if (state_ != State::WaitCode) {
if (state_ == State::WaitEmailCode) {
on_new_query(query_id);
@@ -337,7 +584,7 @@ void AuthManager::resend_authentication_code(uint64 query_id) {
return on_query_error(query_id, Status::Error(400, "Call to resendAuthenticationCode unexpected"));
}
- auto r_resend_code = send_code_helper_.resend_code();
+ auto r_resend_code = send_code_helper_.resend_code(std::move(reason));
if (r_resend_code.is_error()) {
return on_query_error(query_id, r_resend_code.move_as_error());
}
@@ -402,7 +649,7 @@ void AuthManager::check_code(uint64 query_id, string code) {
send_auth_sign_in_query();
}
-void AuthManager::register_user(uint64 query_id, string first_name, string last_name) {
+void AuthManager::register_user(uint64 query_id, string first_name, string last_name, bool disable_notification) {
if (state_ != State::WaitRegistration) {
return on_query_error(query_id, Status::Error(400, "Call to registerUser unexpected"));
}
@@ -410,12 +657,16 @@ void AuthManager::register_user(uint64 query_id, string first_name, string last_
on_new_query(query_id);
first_name = clean_name(first_name, MAX_NAME_LENGTH);
if (first_name.empty()) {
- return on_query_error(Status::Error(400, "First name must be non-empty"));
+ return on_current_query_error(Status::Error(400, "First name must be non-empty"));
}
last_name = clean_name(last_name, MAX_NAME_LENGTH);
+ int32 flags = 0;
+ if (disable_notification) {
+ flags |= telegram_api::auth_signUp::NO_JOINED_NOTIFICATIONS_MASK;
+ }
start_net_query(NetQueryType::SignUp, G()->net_query_creator().create_unauth(telegram_api::auth_signUp(
- send_code_helper_.phone_number().str(),
+ flags, false /*ignored*/, send_code_helper_.phone_number().str(),
send_code_helper_.phone_code_hash().str(), first_name, last_name)));
}
@@ -488,7 +739,7 @@ void AuthManager::log_out(uint64 query_id) {
// TODO: send auth.cancelCode if state_ == State::WaitCode
LOG(WARNING) << "Destroying auth keys by user request";
destroy_auth_keys();
- on_query_ok();
+ on_current_query_ok();
} else {
LOG(WARNING) << "Logging out by user request";
G()->td_db()->get_binlog_pmc()->set("auth", "logout");
@@ -539,16 +790,15 @@ void AuthManager::do_delete_account(uint64 query_id, string reason,
}
void AuthManager::on_closing(bool destroy_flag) {
- if (destroy_flag) {
- update_state(State::LoggingOut);
- } else {
- update_state(State::Closing);
+ auto new_state = destroy_flag ? State::LoggingOut : State::Closing;
+ if (new_state != state_) {
+ update_state(new_state);
}
}
void AuthManager::on_new_query(uint64 query_id) {
if (query_id_ != 0) {
- on_query_error(Status::Error(400, "Another authorization query has started"));
+ on_current_query_error(Status::Error(400, "Another authorization query has started"));
}
checking_password_ = false;
net_query_id_ = 0;
@@ -557,8 +807,10 @@ void AuthManager::on_new_query(uint64 query_id) {
// TODO: cancel older net_query
}
-void AuthManager::on_query_error(Status status) {
- CHECK(query_id_ != 0);
+void AuthManager::on_current_query_error(Status status) {
+ if (query_id_ == 0) {
+ return;
+ }
auto id = query_id_;
query_id_ = 0;
net_query_id_ = 0;
@@ -571,8 +823,10 @@ void AuthManager::on_query_error(uint64 query_id, Status status) {
send_closure(G()->td(), &Td::send_error, query_id, std::move(status));
}
-void AuthManager::on_query_ok() {
- CHECK(query_id_ != 0);
+void AuthManager::on_current_query_ok() {
+ if (query_id_ == 0) {
+ return;
+ }
auto id = query_id_;
net_query_id_ = 0;
net_query_type_ = NetQueryType::None;
@@ -606,7 +860,7 @@ void AuthManager::on_sent_code(telegram_api::object_ptr<telegram_api::auth_SentC
send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_));
allow_apple_id_ = code_type->apple_signin_allowed_;
allow_google_id_ = code_type->google_signin_allowed_;
- update_state(State::WaitEmailAddress, true);
+ update_state(State::WaitEmailAddress);
} else if (code_type_id == telegram_api::auth_sentCodeTypeEmailCode::ID) {
auto code_type = move_tl_object_as<telegram_api::auth_sentCodeTypeEmailCode>(std::move(sent_code->type_));
send_code_helper_.on_phone_code_hash(std::move(sent_code->phone_code_hash_));
@@ -627,26 +881,26 @@ void AuthManager::on_sent_code(telegram_api::object_ptr<telegram_api::auth_SentC
email_code_info_ = SentEmailCode("<unknown>", code_type->length_);
CHECK(!email_code_info_.is_empty());
}
- update_state(State::WaitEmailCode, true);
+ update_state(State::WaitEmailCode);
} else {
send_code_helper_.on_sent_code(std::move(sent_code));
- update_state(State::WaitCode, true);
+ update_state(State::WaitCode);
}
- on_query_ok();
+ on_current_query_ok();
}
-void AuthManager::on_send_code_result(NetQueryPtr &result) {
- auto r_sent_code = fetch_result<telegram_api::auth_sendCode>(result->ok());
+void AuthManager::on_send_code_result(NetQueryPtr &&net_query) {
+ auto r_sent_code = fetch_result<telegram_api::auth_sendCode>(std::move(net_query));
if (r_sent_code.is_error()) {
- return on_query_error(r_sent_code.move_as_error());
+ return on_current_query_error(r_sent_code.move_as_error());
}
on_sent_code(r_sent_code.move_as_ok());
}
-void AuthManager::on_send_email_code_result(NetQueryPtr &result) {
- auto r_sent_code = fetch_result<telegram_api::account_sendVerifyEmailCode>(result->ok());
+void AuthManager::on_send_email_code_result(NetQueryPtr &&net_query) {
+ auto r_sent_code = fetch_result<telegram_api::account_sendVerifyEmailCode>(std::move(net_query));
if (r_sent_code.is_error()) {
- return on_query_error(r_sent_code.move_as_error());
+ return on_current_query_error(r_sent_code.move_as_error());
}
auto sent_code = r_sent_code.move_as_ok();
@@ -654,23 +908,23 @@ void AuthManager::on_send_email_code_result(NetQueryPtr &result) {
email_code_info_ = SentEmailCode(std::move(sent_code));
if (email_code_info_.is_empty()) {
- return on_query_error(Status::Error(500, "Receive invalid response"));
+ return on_current_query_error(Status::Error(500, "Receive invalid response"));
}
- update_state(State::WaitEmailCode, true);
- on_query_ok();
+ update_state(State::WaitEmailCode);
+ on_current_query_ok();
}
-void AuthManager::on_verify_email_address_result(NetQueryPtr &result) {
- auto r_email_verified = fetch_result<telegram_api::account_verifyEmail>(result->ok());
+void AuthManager::on_verify_email_address_result(NetQueryPtr &&net_query) {
+ auto r_email_verified = fetch_result<telegram_api::account_verifyEmail>(std::move(net_query));
if (r_email_verified.is_error()) {
- return on_query_error(r_email_verified.move_as_error());
+ return on_current_query_error(r_email_verified.move_as_error());
}
auto email_verified = r_email_verified.move_as_ok();
LOG(INFO) << "Receive " << to_string(email_verified);
if (email_verified->get_id() != telegram_api::account_emailVerifiedLogin::ID) {
- return on_query_error(Status::Error(500, "Receive invalid response"));
+ return on_current_query_error(Status::Error(500, "Receive invalid response"));
}
reset_available_period_ = -1;
reset_pending_date_ = -1;
@@ -679,49 +933,42 @@ void AuthManager::on_verify_email_address_result(NetQueryPtr &result) {
on_sent_code(std::move(verified_login->sent_code_));
}
-void AuthManager::on_reset_email_address_result(NetQueryPtr &result) {
- auto r_sent_code = fetch_result<telegram_api::auth_resetLoginEmail>(result->ok());
+void AuthManager::on_reset_email_address_result(NetQueryPtr &&net_query) {
+ auto r_sent_code = fetch_result<telegram_api::auth_resetLoginEmail>(std::move(net_query));
if (r_sent_code.is_error()) {
if (reset_available_period_ > 0 && reset_pending_date_ == -1 &&
r_sent_code.error().message() == "TASK_ALREADY_EXISTS") {
reset_pending_date_ = G()->unix_time() + reset_available_period_;
reset_available_period_ = -1;
- update_state(State::WaitEmailCode, true);
+ update_state(State::WaitEmailCode);
}
- return on_query_error(r_sent_code.move_as_error());
+ return on_current_query_error(r_sent_code.move_as_error());
}
on_sent_code(r_sent_code.move_as_ok());
}
-void AuthManager::on_request_qr_code_result(NetQueryPtr &result, bool is_import) {
- Status status;
- if (result->is_ok()) {
- auto r_login_token = fetch_result<telegram_api::auth_exportLoginToken>(result->ok());
- if (r_login_token.is_ok()) {
- auto login_token = r_login_token.move_as_ok();
-
- if (is_import) {
- CHECK(DcId::is_valid(imported_dc_id_));
- G()->net_query_dispatcher().set_main_dc_id(imported_dc_id_);
- imported_dc_id_ = -1;
- }
+void AuthManager::on_request_qr_code_result(NetQueryPtr &&net_query, bool is_import) {
+ auto r_login_token = fetch_result<telegram_api::auth_exportLoginToken>(std::move(net_query));
+ if (r_login_token.is_ok()) {
+ auto login_token = r_login_token.move_as_ok();
- on_get_login_token(std::move(login_token));
- return;
+ if (is_import) {
+ CHECK(DcId::is_valid(imported_dc_id_));
+ G()->net_query_dispatcher().set_main_dc_id(imported_dc_id_);
+ imported_dc_id_ = -1;
}
- status = r_login_token.move_as_error();
- } else {
- status = std::move(result->error());
+ on_get_login_token(std::move(login_token));
+ return;
}
- CHECK(status.is_error());
+ auto status = r_login_token.move_as_error();
LOG(INFO) << "Receive " << status << " for login token " << (is_import ? "import" : "export");
if (is_import) {
imported_dc_id_ = -1;
}
if (query_id_ != 0) {
- on_query_error(std::move(status));
+ on_current_query_error(std::move(status));
} else {
login_code_retry_delay_ = clamp(2 * login_code_retry_delay_, 1, 60);
set_login_token_expires_at(Time::now() + login_code_retry_delay_);
@@ -739,10 +986,8 @@ void AuthManager::on_get_login_token(tl_object_ptr<telegram_api::auth_LoginToken
auto token = move_tl_object_as<telegram_api::auth_loginToken>(login_token);
login_token_ = token->token_.as_slice().str();
set_login_token_expires_at(Time::now() + td::max(token->expires_ - G()->server_time(), 1.0));
- update_state(State::WaitQrCodeConfirmation, true);
- if (query_id_ != 0) {
- on_query_ok();
- }
+ update_state(State::WaitQrCodeConfirmation);
+ on_current_query_ok();
break;
}
case telegram_api::auth_loginTokenMigrateTo::ID: {
@@ -751,9 +996,7 @@ void AuthManager::on_get_login_token(tl_object_ptr<telegram_api::auth_LoginToken
LOG(ERROR) << "Receive wrong DC " << token->dc_id_;
return;
}
- if (query_id_ != 0) {
- on_query_ok();
- }
+ on_current_query_ok();
imported_dc_id_ = token->dc_id_;
start_net_query(NetQueryType::ImportQrCode, G()->net_query_creator().create_unauth(
@@ -771,15 +1014,10 @@ void AuthManager::on_get_login_token(tl_object_ptr<telegram_api::auth_LoginToken
}
}
-void AuthManager::on_get_password_result(NetQueryPtr &result) {
- Result<telegram_api::object_ptr<telegram_api::account_password>> r_password;
- if (result->is_error()) {
- r_password = std::move(result->error());
- } else {
- r_password = fetch_result<telegram_api::account_getPassword>(result->ok());
- }
+void AuthManager::on_get_password_result(NetQueryPtr &&net_query) {
+ auto r_password = fetch_result<telegram_api::account_getPassword>(std::move(net_query));
if (r_password.is_error() && query_id_ != 0) {
- return on_query_error(r_password.move_as_error());
+ return on_current_query_error(r_password.move_as_error());
}
auto password = r_password.is_ok() ? r_password.move_as_ok() : nullptr;
LOG(INFO) << "Receive password info: " << to_string(password);
@@ -789,7 +1027,7 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
if (password != nullptr && password->current_algo_ != nullptr) {
switch (password->current_algo_->get_id()) {
case telegram_api::passwordKdfAlgoUnknown::ID:
- return on_query_error(Status::Error(400, "Application update is needed to log in"));
+ return on_current_query_error(Status::Error(400, "Application update is needed to log in"));
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
auto algo = move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
password->current_algo_);
@@ -828,13 +1066,13 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
if (state_ == State::WaitPassword && checking_password_) {
if (!new_password_.empty()) {
if (r_new_password_state.is_error()) {
- return on_query_error(r_new_password_state.move_as_error());
+ return on_current_query_error(r_new_password_state.move_as_error());
}
auto r_new_settings = PasswordManager::get_password_input_settings(std::move(new_password_), std::move(new_hint_),
r_new_password_state.ok());
if (r_new_settings.is_error()) {
- return on_query_error(r_new_settings.move_as_error());
+ return on_current_query_error(r_new_settings.move_as_error());
}
int32 flags = telegram_api::auth_recoverPassword::NEW_SETTINGS_MASK;
@@ -853,77 +1091,75 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
G()->net_query_creator().create_unauth(telegram_api::auth_checkPassword(std::move(hash))));
} else {
update_state(State::WaitPassword);
- if (query_id_ != 0) {
- on_query_ok();
- }
+ on_current_query_ok();
}
}
-void AuthManager::on_request_password_recovery_result(NetQueryPtr &result) {
- auto r_email_address_pattern = fetch_result<telegram_api::auth_requestPasswordRecovery>(result->ok());
+void AuthManager::on_request_password_recovery_result(NetQueryPtr &&net_query) {
+ auto r_email_address_pattern = fetch_result<telegram_api::auth_requestPasswordRecovery>(std::move(net_query));
if (r_email_address_pattern.is_error()) {
- return on_query_error(r_email_address_pattern.move_as_error());
+ return on_current_query_error(r_email_address_pattern.move_as_error());
}
auto email_address_pattern = r_email_address_pattern.move_as_ok();
- CHECK(email_address_pattern->get_id() == telegram_api::auth_passwordRecovery::ID);
wait_password_state_.email_address_pattern_ = std::move(email_address_pattern->email_pattern_);
- update_state(State::WaitPassword, true);
- on_query_ok();
+ update_state(State::WaitPassword);
+ on_current_query_ok();
}
-void AuthManager::on_check_password_recovery_code_result(NetQueryPtr &result) {
- auto r_success = fetch_result<telegram_api::auth_checkRecoveryPassword>(result->ok());
+void AuthManager::on_check_password_recovery_code_result(NetQueryPtr &&net_query) {
+ auto r_success = fetch_result<telegram_api::auth_checkRecoveryPassword>(std::move(net_query));
if (r_success.is_error()) {
- return on_query_error(r_success.move_as_error());
+ return on_current_query_error(r_success.move_as_error());
}
if (!r_success.ok()) {
- return on_query_error(Status::Error(400, "Invalid recovery code"));
+ return on_current_query_error(Status::Error(400, "Invalid recovery code"));
}
- on_query_ok();
+ on_current_query_ok();
}
-void AuthManager::on_request_firebase_sms_result(NetQueryPtr &result) {
- auto r_bool = fetch_result<telegram_api::auth_requestFirebaseSms>(result->ok());
+void AuthManager::on_request_firebase_sms_result(NetQueryPtr &&net_query) {
+ auto r_bool = fetch_result<telegram_api::auth_requestFirebaseSms>(std::move(net_query));
if (r_bool.is_error()) {
- return on_query_error(r_bool.move_as_error());
+ return on_current_query_error(r_bool.move_as_error());
}
- on_query_ok();
+ on_current_query_ok();
}
-void AuthManager::on_authentication_result(NetQueryPtr &result, bool is_from_current_query) {
- auto r_sign_in = fetch_result<telegram_api::auth_signIn>(result->ok());
+void AuthManager::on_authentication_result(NetQueryPtr &&net_query, bool is_from_current_query) {
+ auto r_sign_in = fetch_result<telegram_api::auth_signIn>(std::move(net_query));
if (r_sign_in.is_error()) {
- if (is_from_current_query && query_id_ != 0) {
- return on_query_error(r_sign_in.move_as_error());
+ if (is_from_current_query) {
+ return on_current_query_error(r_sign_in.move_as_error());
}
return;
}
on_get_authorization(r_sign_in.move_as_ok());
}
-void AuthManager::on_log_out_result(NetQueryPtr &result) {
- Status status;
- if (result->is_ok()) {
- auto r_log_out = fetch_result<telegram_api::auth_logOut>(result->ok());
- if (r_log_out.is_ok()) {
- auto logged_out = r_log_out.move_as_ok();
- if (!logged_out->future_auth_token_.empty()) {
- td_->option_manager_->set_option_string("authentication_token",
- base64url_encode(logged_out->future_auth_token_.as_slice()));
- }
- } else {
- status = r_log_out.move_as_error();
+void AuthManager::on_log_out_result(NetQueryPtr &&net_query) {
+ auto r_log_out = fetch_result<telegram_api::auth_logOut>(std::move(net_query));
+ if (r_log_out.is_ok()) {
+ auto logged_out = r_log_out.move_as_ok();
+ if (!logged_out->future_auth_token_.empty()) {
+ td_->option_manager_->set_option_string("authentication_token",
+ base64url_encode(logged_out->future_auth_token_.as_slice()));
}
- } else {
- status = std::move(result->error());
+ } else if (r_log_out.error().code() != 401) {
+ LOG(ERROR) << "Receive error for auth.logOut: " << r_log_out.error();
}
- LOG_IF(ERROR, status.is_error() && status.code() != 401) << "Receive error for auth.logOut: " << status;
- // state_ will stay LoggingOut, so no queries will work.
destroy_auth_keys();
- if (query_id_ != 0) {
- on_query_ok();
+ on_current_query_ok();
+}
+
+void AuthManager::on_account_banned() const {
+ if (is_bot()) {
+ return;
}
+ LOG(ERROR) << "Your account was banned for suspicious activity. If you think that this is a mistake, please try to "
+ "log in from an official mobile app and send an email to recover the account by following instructions "
+ "provided by the app";
}
+
void AuthManager::on_authorization_lost(string source) {
if (state_ == State::LoggingOut && net_query_type_ == NetQueryType::LogOut) {
LOG(INFO) << "Ignore authorization loss because of " << source << ", while logging out";
@@ -934,72 +1170,58 @@ void AuthManager::on_authorization_lost(string source) {
return;
}
LOG(WARNING) << "Lost authorization because of " << source;
+ if (source == "USER_DEACTIVATED_BAN") {
+ on_account_banned();
+ }
destroy_auth_keys();
}
void AuthManager::destroy_auth_keys() {
if (state_ == State::Closing || state_ == State::DestroyingKeys) {
+ LOG(INFO) << "Already destroying auth keys";
return;
}
update_state(State::DestroyingKeys);
- auto promise = PromiseCreator::lambda([](Result<Unit> result) {
+ G()->td_db()->get_binlog_pmc()->set("auth", "destroy");
+ G()->net_query_dispatcher().destroy_auth_keys(PromiseCreator::lambda([](Result<Unit> result) {
if (result.is_ok()) {
- G()->net_query_dispatcher().destroy_auth_keys(PromiseCreator::lambda([](Result<Unit> result) {
- if (result.is_ok()) {
- send_closure_later(G()->td(), &Td::destroy);
- }
- }));
+ send_closure_later(G()->td(), &Td::destroy);
+ } else {
+ LOG(INFO) << "Failed to destroy auth keys";
}
- });
- G()->td_db()->get_binlog_pmc()->set("auth", "destroy");
- G()->td_db()->get_binlog_pmc()->force_sync(std::move(promise));
+ }));
}
-void AuthManager::on_delete_account_result(NetQueryPtr &result) {
- Status status;
- if (result->is_ok()) {
- auto r_delete_account = fetch_result<telegram_api::account_deleteAccount>(result->ok());
- if (r_delete_account.is_ok()) {
- if (!r_delete_account.ok()) {
- // status = Status::Error(500, "Receive false as result of the request");
- }
- } else {
- status = r_delete_account.move_as_error();
+void AuthManager::on_delete_account_result(NetQueryPtr &&net_query) {
+ auto r_delete_account = fetch_result<telegram_api::account_deleteAccount>(std::move(net_query));
+ if (r_delete_account.is_ok()) {
+ if (!r_delete_account.ok()) {
+ // status = Status::Error(500, "Receive false as result of the request");
}
} else {
- status = std::move(result->error());
- }
- if (status.is_error() && status.message() != "USER_DEACTIVATED") {
- LOG(WARNING) << "Request account.deleteAccount failed: " << status;
- // TODO handle some errors
- if (query_id_ != 0) {
- on_query_error(std::move(status));
- }
- } else {
- destroy_auth_keys();
- if (query_id_ != 0) {
- on_query_ok();
+ auto status = r_delete_account.move_as_error();
+ if (status.message() != "USER_DEACTIVATED") {
+ LOG(WARNING) << "Request account.deleteAccount failed: " << status;
+ // TODO handle some errors
+ return on_current_query_error(std::move(status));
}
}
+
+ destroy_auth_keys();
+ on_current_query_ok();
}
void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authorization> auth_ptr) {
if (state_ == State::Ok) {
LOG(WARNING) << "Ignore duplicate auth.Authorization";
- if (query_id_ != 0) {
- on_query_ok();
- }
- return;
+ return on_current_query_ok();
}
CHECK(auth_ptr != nullptr);
if (auth_ptr->get_id() == telegram_api::auth_authorizationSignUpRequired::ID) {
auto sign_up_required = telegram_api::move_object_as<telegram_api::auth_authorizationSignUpRequired>(auth_ptr);
terms_of_service_ = TermsOfService(std::move(sign_up_required->terms_of_service_));
update_state(State::WaitRegistration);
- if (query_id_ != 0) {
- on_query_ok();
- }
- return;
+ return on_current_query_ok();
}
auto auth = telegram_api::move_object_as<telegram_api::auth_authorization>(auth_ptr);
@@ -1015,13 +1237,20 @@ void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authoriz
new_password_.clear();
new_hint_.clear();
state_ = State::Ok;
- td_->contacts_manager_->on_get_user(std::move(auth->user_), "on_get_authorization", true);
- update_state(State::Ok, true);
- if (!td_->contacts_manager_->get_my_id().is_valid()) {
- LOG(ERROR) << "Server doesn't send proper authorization";
- if (query_id_ != 0) {
- on_query_error(Status::Error(500, "Server doesn't send proper authorization"));
+ if (auth->user_->get_id() == telegram_api::user::ID) {
+ auto *user = static_cast<telegram_api::user *>(auth->user_.get());
+ int32 mask = 1 << 10;
+ if ((user->flags_ & mask) == 0) {
+ LOG(ERROR) << "Receive invalid authorization for " << to_string(auth->user_);
+ user->flags_ |= mask;
+ user->self_ = true;
}
+ }
+ td_->user_manager_->on_get_user(std::move(auth->user_), "on_get_authorization");
+ update_state(State::Ok);
+ if (!td_->user_manager_->get_my_id().is_valid()) {
+ LOG(ERROR) << "Server didsn't send proper authorization";
+ on_current_query_error(Status::Error(500, "Server didn't send proper authorization"));
log_out(0);
return;
}
@@ -1040,53 +1269,46 @@ void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authoriz
td_->dialog_filter_manager_->on_authorization_success(); // must be after MessagesManager::on_authorization_success()
// to have folders created
td_->notification_manager_->init();
+ td_->online_manager_->init();
+ td_->promo_data_manager_->init();
+ td_->reaction_manager_->init();
td_->stickers_manager_->init();
+ td_->terms_of_service_manager_->init();
td_->theme_manager_->init();
td_->top_dialog_manager_->init();
td_->updates_manager_->get_difference("on_get_authorization");
- td_->on_online_updated(false, true);
if (!is_bot()) {
- td_->schedule_get_terms_of_service(0);
- td_->reload_promo_data();
G()->td_db()->get_binlog_pmc()->set("fetched_marks_as_unread", "1");
- } else {
- td_->set_is_bot_online(true);
}
send_closure(G()->config_manager(), &ConfigManager::request_config, false);
- if (query_id_ != 0) {
- on_query_ok();
- }
+ on_current_query_ok();
}
-void AuthManager::on_result(NetQueryPtr result) {
- SCOPE_EXIT {
- result->clear();
- };
+void AuthManager::on_result(NetQueryPtr net_query) {
NetQueryType type = NetQueryType::None;
- LOG(INFO) << "Receive result of query " << result->id() << ", expecting " << net_query_id_ << " with type "
+ LOG(INFO) << "Receive result of query " << net_query->id() << ", expecting " << net_query_id_ << " with type "
<< static_cast<int32>(net_query_type_);
- if (result->id() == net_query_id_) {
+ if (net_query->id() == net_query_id_) {
net_query_id_ = 0;
type = net_query_type_;
net_query_type_ = NetQueryType::None;
- if (result->is_error()) {
+ if (net_query->is_error()) {
if ((type == NetQueryType::SendCode || type == NetQueryType::SendEmailCode ||
type == NetQueryType::VerifyEmailAddress || type == NetQueryType::SignIn ||
type == NetQueryType::RequestQrCode || type == NetQueryType::ImportQrCode) &&
- result->error().code() == 401 && result->error().message() == CSlice("SESSION_PASSWORD_NEEDED")) {
+ net_query->error().code() == 401 && net_query->error().message() == CSlice("SESSION_PASSWORD_NEEDED")) {
auto dc_id = DcId::main();
if (type == NetQueryType::ImportQrCode) {
CHECK(DcId::is_valid(imported_dc_id_));
dc_id = DcId::internal(imported_dc_id_);
}
+ net_query->clear();
start_net_query(NetQueryType::GetPassword,
G()->net_query_creator().create_unauth(telegram_api::account_getPassword(), dc_id));
return;
}
- if (result->error().message() == CSlice("PHONE_NUMBER_BANNED")) {
- LOG(PLAIN)
- << "Your phone number was banned for suspicious activity. If you think that this is a mistake, please "
- "write to recover@telegram.org your phone number and other details to recover the account.";
+ if (net_query->error().message() == CSlice("PHONE_NUMBER_BANNED")) {
+ on_account_banned();
}
if (type != NetQueryType::LogOut && type != NetQueryType::DeleteAccount) {
if (query_id_ != 0) {
@@ -1097,76 +1319,75 @@ void AuthManager::on_result(NetQueryPtr result) {
was_qr_code_request_ = false;
was_check_bot_token_ = false;
}
- on_query_error(std::move(result->error()));
+ on_current_query_error(net_query->move_as_error());
return;
}
if (type != NetQueryType::RequestQrCode && type != NetQueryType::ImportQrCode &&
type != NetQueryType::GetPassword) {
- LOG(INFO) << "Ignore error for net query of type " << static_cast<int32>(net_query_type_);
- return;
+ LOG(INFO) << "Ignore error for net query of type " << static_cast<int32>(type);
+ type = NetQueryType::None;
}
}
}
- } else if (result->is_ok() && result->ok_tl_constructor() == telegram_api::auth_authorization::ID) {
+ } else if (net_query->is_ok() && net_query->ok_tl_constructor() == telegram_api::auth_authorization::ID) {
type = NetQueryType::Authentication;
}
switch (type) {
case NetQueryType::None:
- result->ignore();
+ net_query->clear();
break;
case NetQueryType::SignIn:
case NetQueryType::SignUp:
case NetQueryType::BotAuthentication:
case NetQueryType::CheckPassword:
case NetQueryType::RecoverPassword:
- on_authentication_result(result, true);
+ on_authentication_result(std::move(net_query), true);
break;
case NetQueryType::Authentication:
- on_authentication_result(result, false);
+ on_authentication_result(std::move(net_query), false);
break;
case NetQueryType::SendCode:
- on_send_code_result(result);
+ on_send_code_result(std::move(net_query));
break;
case NetQueryType::SendEmailCode:
- on_send_email_code_result(result);
+ on_send_email_code_result(std::move(net_query));
break;
case NetQueryType::VerifyEmailAddress:
- on_verify_email_address_result(result);
+ on_verify_email_address_result(std::move(net_query));
break;
case NetQueryType::ResetEmailAddress:
- on_reset_email_address_result(result);
+ on_reset_email_address_result(std::move(net_query));
break;
case NetQueryType::RequestQrCode:
- on_request_qr_code_result(result, false);
+ on_request_qr_code_result(std::move(net_query), false);
break;
case NetQueryType::ImportQrCode:
- on_request_qr_code_result(result, true);
+ on_request_qr_code_result(std::move(net_query), true);
break;
case NetQueryType::GetPassword:
- on_get_password_result(result);
+ on_get_password_result(std::move(net_query));
break;
case NetQueryType::RequestPasswordRecovery:
- on_request_password_recovery_result(result);
+ on_request_password_recovery_result(std::move(net_query));
break;
case NetQueryType::CheckPasswordRecoveryCode:
- on_check_password_recovery_code_result(result);
+ on_check_password_recovery_code_result(std::move(net_query));
break;
case NetQueryType::RequestFirebaseSms:
- on_request_firebase_sms_result(result);
+ on_request_firebase_sms_result(std::move(net_query));
break;
case NetQueryType::LogOut:
- on_log_out_result(result);
+ on_log_out_result(std::move(net_query));
break;
case NetQueryType::DeleteAccount:
- on_delete_account_result(result);
+ on_delete_account_result(std::move(net_query));
break;
+ default:
+ UNREACHABLE();
}
}
-void AuthManager::update_state(State new_state, bool force, bool should_save_state) {
- if (state_ == new_state && !force) {
- return;
- }
+void AuthManager::update_state(State new_state, bool should_save_state) {
bool skip_update = (state_ == State::LoggingOut || state_ == State::DestroyingKeys) &&
(new_state == State::LoggingOut || new_state == State::DestroyingKeys);
state_ = new_state;
@@ -1237,7 +1458,7 @@ bool AuthManager::load_state() {
} else {
UNREACHABLE();
}
- update_state(db_state.state_, false, false);
+ update_state(db_state.state_, false);
return true;
}