10#include "accountinfo/accountinfo.h"
11#include "accountinfo/accountinfofetchjob.h"
13#include "fullauthenticationjob_p.h"
14#include "newtokensfetchjob_p.h"
16#include <QAbstractSocket>
18#include <QDesktopServices>
30class Q_DECL_HIDDEN FullAuthenticationJob::Private
36 , mSecretKey(secretKey)
44 q->setErrorString(text);
51 mConnection->deleteLater();
53 qCDebug(KGAPIDebug) <<
"Socket error when receiving response:" <<
error;
54 emitError(
InvalidResponse, tr(
"Error receiving response: %1").arg(error));
59 Q_ASSERT(mConnection);
60 const QByteArray data = mConnection->readLine();
61 const QString title = tr(
"Authentication successful");
62 const QString text = tr(
"You can close this tab and return to the application now.");
63 mConnection->write(
"HTTP/1.1 200 OK\n"
64 "Content-Type: text/html\n"
67 "<head><meta charset=\"UTF-8\"><title>" + title.
toUtf8() +
"</title></head>"
68 "<body><h1>" + text.
toUtf8() +
"</h1></body>"
71 mConnection->deleteLater();
72 qCDebug(KGAPIDebug) <<
"Got connection on socket";
74 const auto line = data.
split(
' ');
75 if (line.size() != 3 || line.at(0) !=
QByteArray(
"GET") || !line.
at(2).startsWith(
QByteArray(
"HTTP/1.1"))) {
76 qCDebug(KGAPIDebug) <<
"Token response invalid";
84 const QString code =
query.queryItemValue(QStringLiteral(
"code"));
87 if (!
error.isEmpty()) {
88 qCDebug(KGAPIDebug) <<
"Google has returned an error response:" <<
error;
91 qCDebug(KGAPIDebug) <<
"Could not extract token from HTTP answer";
92 emitError(
InvalidAccount, tr(
"Could not extract token from HTTP answer"));
97 auto fetch =
new KGAPI2::NewTokensFetchJob(code, mApiKey, mSecretKey, mServerPort);
103 void tokensReceived(
Job *job)
105 auto tokensFetchJob = qobject_cast<NewTokensFetchJob *>(job);
106 if (tokensFetchJob->error()) {
107 qCDebug(KGAPIDebug) <<
"Error when retrieving tokens:" << job->
errorString();
112 mAccount->setAccessToken(tokensFetchJob->accessToken());
113 mAccount->setRefreshToken(tokensFetchJob->refreshToken());
115 tokensFetchJob->deleteLater();
119 accountInfoReceived(job);
121 qCDebug(KGAPIDebug) <<
"Requesting AccountInfo";
124 void accountInfoReceived(
Job *job)
127 qCDebug(KGAPIDebug) <<
"Error when retrieving AccountInfo:" << job->
errorString();
132 const auto objects = qobject_cast<AccountInfoFetchJob *>(job)->items();
133 Q_ASSERT(!objects.isEmpty());
135 const auto accountInfo = objects.first().staticCast<
AccountInfo>();
136 mAccount->setAccountName(accountInfo->email());
149 std::unique_ptr<QTcpServer> mServer;
151 uint16_t mServerPort = 0;
154 FullAuthenticationJob *
const q;
161 , d(new Private(account, apiKey, secretKey, this))
165FullAuthenticationJob::~FullAuthenticationJob() =
default;
167void FullAuthenticationJob::setServerPort(uint16_t port)
169 d->mServerPort = port;
172void FullAuthenticationJob::setUsername(
const QString &username)
174 d->mUsername = username;
177AccountPtr FullAuthenticationJob::account()
const
182void FullAuthenticationJob::start()
184 if (d->mAccount.isNull()) {
188 if (d->mAccount->scopes().isEmpty()) {
189 d->emitError(
InvalidAccount, tr(
"No scopes to authenticate for"));
194 scopes.
reserve(d->mAccount->scopes().size());
195 const auto scopesList = d->mAccount->scopes();
196 for (
const QUrl &scope : scopesList) {
197 scopes << scope.toString();
200 d->mServer = std::make_unique<QTcpServer>();
202 d->emitError(
InvalidAccount, tr(
"Could not start OAuth HTTP server"));
205 d->mServerPort = d->mServer->serverPort();
210 d->mConnection = d->mServer->nextPendingConnection();
211 d->mConnection->setParent(this);
212 connect(d->mConnection,
213 static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::errorOccurred),
215 [this](QAbstractSocket::SocketError e) {
224 QUrl url(QStringLiteral(
"https://accounts.google.com/o/oauth2/auth"));
226 query.addQueryItem(QStringLiteral(
"client_id"), d->mApiKey);
227 query.addQueryItem(QStringLiteral(
"redirect_uri"), QStringLiteral(
"http://127.0.0.1:%1").arg(d->mServerPort));
229 query.addQueryItem(QStringLiteral(
"response_type"), QStringLiteral(
"code"));
230 if (!d->mUsername.isEmpty()) {
231 query.addQueryItem(QStringLiteral(
"login_hint"), d->mUsername);
253#include "moc_fullauthenticationjob_p.cpp"
A job to fetch AccountInfo.
AccountInfo contains information about user's Google account.
Abstract base class for all jobs in LibKGAPI.
KGAPI2::Error error() const
Error code.
void finished(KGAPI2::Job *job)
Emitted when job has finished.
QString errorString() const
Error string.
std::optional< QSqlQuery > query(const QString &queryStatement)
A job to fetch a single map tile described by a StaticMapUrl.
@ UnknownError
LibKGAPI error - a general unidentified error.
@ InvalidAccount
LibKGAPI error - the KGAPI2::Account object is invalid.
@ InvalidResponse
LibKGAPI error - Google returned invalid response.
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
char at(qsizetype i) const const
QList< QByteArray > split(char sep) const const
QDateTime currentDateTime()
bool openUrl(const QUrl &url)
void reserve(qsizetype size)
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
QByteArray toUtf8() const const
QString join(QChar separator) const const
void acceptError(QAbstractSocket::SocketError socketError)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)