File indexing completed on 2025-01-26 04:38:18
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Riccardo Iaconelli <riccardo@kde.org> 0003 * SPDX-FileCopyrightText: 2018 Veluri Mithun <velurimithun38@gmail.com> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 * 0007 * 0008 */ 0009 0010 #include "googlejob.h" 0011 #include "googleauthenticationplugin_debug.h" 0012 #include "ruqola_debug.h" 0013 0014 #include <QDesktopServices> 0015 #include <QFile> 0016 #include <QJsonDocument> 0017 #include <QJsonObject> 0018 #include <QNetworkAccessManager> 0019 #include <QNetworkReply> 0020 #include <QNetworkRequest> 0021 0022 #include <o2/o0globals.h> 0023 #include <o2/o0settingsstore.h> 0024 #include <o2/o2google.h> 0025 0026 GoogleJob::GoogleJob(QObject *parent) 0027 : QObject(parent) 0028 { 0029 mO2Google = new O2Google(this); 0030 0031 getDataFromJson(); 0032 0033 mO2Google->setClientId(m_clientID); 0034 mO2Google->setClientSecret(m_clientSecret); 0035 mO2Google->setLocalPort(8888); // it is from redirect url(http://127.0.0.1:8888/) 0036 mO2Google->setRequestUrl(m_authUri); // Use the desktop login UI 0037 mO2Google->setScope(QStringLiteral("email")); 0038 0039 // Create a store object for writing the received tokens 0040 O0SettingsStore *store = new O0SettingsStore(QLatin1String(O2_ENCRYPTION_KEY), this); 0041 store->setGroupKey(QStringLiteral("Google")); 0042 mO2Google->setStore(store); 0043 0044 connect(mO2Google, &O2Google::linkedChanged, this, &GoogleJob::onLinkedChanged); 0045 connect(mO2Google, &O2Google::linkingFailed, this, [this]() { 0046 Q_EMIT linkingFailed(); 0047 }); 0048 connect(mO2Google, &O2Google::linkingSucceeded, this, &GoogleJob::onLinkingSucceeded); 0049 connect(mO2Google, &O2Google::openBrowser, this, &GoogleJob::onOpenBrowser); 0050 connect(mO2Google, &O2Google::closeBrowser, this, &GoogleJob::onCloseBrowser); 0051 connect(mO2Google, &O2Google::linkingSucceeded, this, &GoogleJob::OAuthLoginMethodParameter); 0052 } 0053 0054 GoogleJob::~GoogleJob() 0055 { 0056 } 0057 0058 void GoogleJob::getDataFromJson() 0059 { 0060 QFile f(QStringLiteral(":/client_secret.json")); 0061 0062 QString val; 0063 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { 0064 val = QString::fromLatin1(f.readAll()); 0065 } else { 0066 qCWarning(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << "Impossible to read client_secret.json"; 0067 // TODO exit ? 0068 return; 0069 } 0070 0071 //******github******* 0072 // 38a607244195a0d7af8 > clientID 0073 // bb617841568d7c1e0c0888f292cf69b7b11d327e3 > clientSecret 0074 // https://github.com/login/oauth/authorize 0075 // https://github.com/login/oauth/access_token 0076 const QJsonDocument document = QJsonDocument::fromJson(val.toUtf8()); 0077 const QJsonObject object = document.object(); 0078 const auto settingsObject = object[QStringLiteral("web")].toObject(); 0079 const auto authUri(settingsObject[QStringLiteral("auth_uri")].toString()); 0080 const auto clientID = settingsObject[QStringLiteral("client_id")].toString(); 0081 const auto clientSecret(settingsObject[QStringLiteral("client_secret")].toString()); 0082 0083 m_clientID = clientID; 0084 m_clientSecret = clientSecret; 0085 m_authUri = authUri; 0086 m_tokenUri = QStringLiteral("https://accounts.google.com/o/oauth2/token"); 0087 } 0088 0089 void GoogleJob::doOAuth(O2::GrantFlow grantFlowType) 0090 { 0091 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << "Starting OAuth 2 with grant flow type: Authorization Grant Flow..."; 0092 mO2Google->setGrantFlow(grantFlowType); 0093 mO2Google->unlink(); 0094 0095 // TODO: refresh the token if it is expired(not valid) 0096 validateToken(); 0097 if (m_isValidToken) { 0098 OAuthLoginMethodParameter(); 0099 } else { 0100 mO2Google->link(); 0101 } 0102 } 0103 0104 // currently not used 0105 void GoogleJob::validateToken() 0106 { 0107 if (!mO2Google->linked()) { 0108 qCWarning(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << "ERROR: Application is not linked!"; 0109 Q_EMIT linkingFailed(QString()); 0110 return; 0111 } 0112 0113 const QString accessToken = mO2Google->token(); 0114 QString debugUrlStr = QString(m_tokenUri).arg(accessToken); 0115 QNetworkRequest request = QNetworkRequest(QUrl(debugUrlStr)); 0116 QNetworkAccessManager *mgr = new QNetworkAccessManager(this); 0117 QNetworkReply *reply = mgr->get(request); 0118 connect(reply, &QNetworkReply::finished, this, &GoogleJob::onFinished); 0119 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Validating user token. Please wait..."); 0120 } 0121 0122 void GoogleJob::onOpenBrowser(const QUrl &url) 0123 { 0124 QDesktopServices::openUrl(url); 0125 } 0126 0127 void GoogleJob::onCloseBrowser() 0128 { 0129 // TODO: close the browser 0130 } 0131 0132 void GoogleJob::onLinkedChanged() 0133 { 0134 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Link changed!"); 0135 } 0136 0137 void GoogleJob::onLinkingSucceeded() 0138 { 0139 O2Google *o1t = qobject_cast<O2Google *>(sender()); 0140 if (!o1t || !o1t->linked()) { 0141 return; 0142 } 0143 m_accessToken = o1t->token(); 0144 const QVariantMap extraTokens = o1t->extraTokens(); 0145 if (!extraTokens.isEmpty()) { 0146 Q_EMIT extraTokensReady(extraTokens); 0147 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Extra tokens in response:"); 0148 foreach (const QString &key, extraTokens.keys()) { 0149 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) 0150 << key << QStringLiteral(":") << (extraTokens.value(key).toString().left(3) + QStringLiteral("...")); 0151 } 0152 } 0153 } 0154 0155 // currently not used 0156 void GoogleJob::onFinished() 0157 { 0158 QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); 0159 if (!reply) { 0160 qCWarning(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << "NULL reply!"; 0161 Q_EMIT linkingFailed(QString()); 0162 return; 0163 } 0164 0165 reply->deleteLater(); 0166 if (reply->error() != QNetworkReply::NoError) { 0167 qCWarning(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Reply error:") << reply->error(); 0168 qCWarning(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Reason:") << reply->errorString(); 0169 Q_EMIT linkingFailed(QString()); 0170 return; 0171 } 0172 0173 const QByteArray replyData = reply->readAll(); 0174 bool valid = !replyData.contains("error"); 0175 if (valid) { 0176 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Token is valid"); 0177 Q_EMIT linkingSucceeded(); 0178 m_isValidToken = true; 0179 } else { 0180 qCDebug(RUQOLA_GOOGLEAUTHENTICATION_PLUGIN_LOG) << QStringLiteral("Token is invalid"); 0181 // TODO 0182 Q_EMIT linkingFailed(QString()); 0183 } 0184 } 0185 0186 void GoogleJob::OAuthLoginMethodParameter() 0187 { 0188 Q_EMIT loginMethodCalled(m_accessToken, m_clientSecret); 0189 } 0190 0191 #include "moc_googlejob.cpp"