Support new url-auth auto-logins in links.

This commit is contained in:
John Preston 2021-03-11 20:21:25 +04:00
parent a2695ea0d7
commit e681b0d95a
4 changed files with 146 additions and 12 deletions

View file

@ -64,7 +64,9 @@ void UrlAuthBox::Activate(
}, [&](const MTPDurlAuthResultDefault &data) {
HiddenUrlClickHandler::Open(url);
}, [&](const MTPDurlAuthResultRequest &data) {
Request(data, session->data().message(itemId), row, column);
if (const auto item = session->data().message(itemId)) {
Request(data, item, row, column);
}
});
}).fail([=](const RPCError &error) {
const auto button = HistoryMessageMarkupButton::Get(
@ -79,6 +81,36 @@ void UrlAuthBox::Activate(
}).send();
}
void UrlAuthBox::Activate(
not_null<Main::Session*> session,
const QString &url,
QVariant context) {
context = QVariant::fromValue([&] {
auto result = context.value<ClickHandlerContext>();
result.skipBotAutoLogin = true;
return result;
}());
using Flag = MTPmessages_RequestUrlAuth::Flag;
session->api().request(MTPmessages_RequestUrlAuth(
MTP_flags(Flag::f_url),
MTPInputPeer(),
MTPint(), // msg_id
MTPint(), // button_id
MTP_string(url)
)).done([=](const MTPUrlAuthResult &result) {
result.match([&](const MTPDurlAuthResultAccepted &data) {
UrlClickHandler::Open(qs(data.vurl()), context);
}, [&](const MTPDurlAuthResultDefault &data) {
HiddenUrlClickHandler::Open(url, context);
}, [&](const MTPDurlAuthResultRequest &data) {
Request(data, session, url, context);
});
}).fail([=](const RPCError &error) {
HiddenUrlClickHandler::Open(url, context);
}).send();
}
void UrlAuthBox::Request(
const MTPDurlAuthResultRequest &request,
not_null<const HistoryItem*> message,
@ -144,6 +176,57 @@ void UrlAuthBox::Request(
Ui::LayerOption::KeepOther);
}
void UrlAuthBox::Request(
const MTPDurlAuthResultRequest &request,
not_null<Main::Session*> session,
const QString &url,
QVariant context) {
const auto bot = request.is_request_write_access()
? session->data().processUser(request.vbot()).get()
: nullptr;
const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
const auto finishWithUrl = [=](const QString &url) {
if (*box) {
(*box)->closeBox();
}
UrlClickHandler::Open(url, context);
};
const auto callback = [=](Result result) {
if (result == Result::None) {
finishWithUrl(url);
} else {
const auto allowWrite = (result == Result::AuthAndAllowWrite);
using Flag = MTPmessages_AcceptUrlAuth::Flag;
const auto flags = (allowWrite ? Flag::f_write_allowed : Flag(0))
| Flag::f_url;
session->api().request(MTPmessages_AcceptUrlAuth(
MTP_flags(flags),
MTPInputPeer(),
MTPint(), // msg_id
MTPint(), // button_id
MTP_string(url)
)).done([=](const MTPUrlAuthResult &result) {
const auto to = result.match(
[&](const MTPDurlAuthResultAccepted &data) {
return qs(data.vurl());
}, [&](const MTPDurlAuthResultDefault &data) {
return url;
}, [&](const MTPDurlAuthResultRequest &data) {
LOG(("API Error: "
"got urlAuthResultRequest after acceptUrlAuth."));
return url;
});
finishWithUrl(to);
}).fail([=](const RPCError &error) {
finishWithUrl(url);
}).send();
}
};
*box = Ui::show(
Box<UrlAuthBox>(session, url, qs(request.vdomain()), bot, callback),
Ui::LayerOption::KeepOther);
}
UrlAuthBox::UrlAuthBox(
QWidget*,
not_null<Main::Session*> session,

View file

@ -22,6 +22,10 @@ public:
not_null<const HistoryItem*> message,
int row,
int column);
static void Activate(
not_null<Main::Session*> session,
const QString &url,
QVariant context);
protected:
void prepare() override;
@ -32,6 +36,11 @@ private:
not_null<const HistoryItem*> message,
int row,
int column);
static void Request(
const MTPDurlAuthResultRequest &request,
not_null<Main::Session*> session,
const QString &url,
QVariant context);
enum class Result {
None,

View file

@ -27,6 +27,7 @@ struct ClickHandlerContext {
FullMsgId itemId;
Fn<HistoryView::ElementDelegate*()> elementDelegate;
base::weak_ptr<Window::SessionController> sessionWindow;
bool skipBotAutoLogin = false;
};
Q_DECLARE_METATYPE(ClickHandlerContext);

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/emoji_config.h"
#include "lang/lang_keys.h"
#include "platform/platform_specific.h"
#include "boxes/url_auth_box.h"
#include "main/main_account.h"
#include "main/main_session.h"
#include "main/main_app_config.h"
@ -24,30 +25,65 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Core {
namespace {
QString UrlWithAutoLoginToken(const QString &url) {
const auto kGoodPrefix = u"https://"_q;
const auto kBadPrefix = u"http://"_q;
[[nodiscard]] QUrl UrlForAutoLogin(const QString &url) {
return (url.startsWith(kGoodPrefix, Qt::CaseInsensitive)
|| url.startsWith(kBadPrefix, Qt::CaseInsensitive))
? QUrl(url)
: QUrl();
}
[[nodiscard]] QString DomainForAutoLogin(const QUrl &url) {
return url.isValid() ? url.host().toLower() : QString();
}
[[nodiscard]] QString UrlWithAutoLoginToken(
const QString &url,
QUrl parsed,
const QString &domain) {
const auto &config = Core::App().activeAccount().appConfig();
const auto token = config.get<QString>("autologin_token", {});
const auto domains = config.get<std::vector<QString>>(
"autologin_domains",
{});
if (domains.empty()
|| token.isEmpty()
|| !url.startsWith("https://", Qt::CaseInsensitive)) {
return url;
}
auto parsed = QUrl(url);
if (!parsed.isValid()) {
return url;
} else if (!ranges::contains(domains, parsed.host().toLower())) {
if (token.isEmpty()
|| domain.isEmpty()
|| !ranges::contains(domains, domain)) {
return url;
}
const auto added = "autologin_token=" + token;
parsed.setQuery(parsed.hasQuery()
? (parsed.query() + '&' + added)
: added);
if (url.startsWith(kBadPrefix, Qt::CaseInsensitive)) {
parsed.setScheme("https");
}
return QString::fromUtf8(parsed.toEncoded());
}
[[nodiscard]] bool BotAutoLogin(
const QString &url,
const QString &domain,
QVariant context) {
auto &account = Core::App().activeAccount();
const auto &config = account.appConfig();
const auto domains = config.get<std::vector<QString>>(
"url_auth_domains",
{});
if (!account.sessionExists()
|| domain.isEmpty()
|| !ranges::contains(domains, domain)) {
return false;
}
const auto good = url.startsWith(kBadPrefix, Qt::CaseInsensitive)
? (kGoodPrefix + url.mid(kBadPrefix.size()))
: url;
UrlAuthBox::Activate(&account.session(), good, context);
return true;
}
} // namespace
void UiIntegration::postponeCall(FnMut<void()> &&callable) {
@ -179,7 +215,12 @@ bool UiIntegration::handleUrlClick(
return true;
}
File::OpenUrl(UrlWithAutoLoginToken(url));
auto parsed = UrlForAutoLogin(url);
const auto domain = DomainForAutoLogin(parsed);
const auto skip = context.value<ClickHandlerContext>().skipBotAutoLogin;
if (skip || !BotAutoLogin(url, domain, context)) {
File::OpenUrl(UrlWithAutoLoginToken(url, std::move(parsed), domain));
}
return true;
}