File indexing completed on 2025-01-05 03:53:30
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2015-06-21 0007 * Description : a tool to export items to Google web services 0008 * 0009 * SPDX-FileCopyrightText: 2015 by Shourya Singh Gupta <shouryasgupta at gmail dot com> 0010 * SPDX-FileCopyrightText: 2015-2020 by Caulier Gilles <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2018 by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "gstalkerbase.h" 0018 0019 // Qt includes 0020 0021 #include <QMap> 0022 #include <QMultiMap> 0023 #include <QDateTime> 0024 #include <QDesktopServices> 0025 #include <QOAuthHttpServerReplyHandler> 0026 0027 // Local includes 0028 0029 #include "digikam_debug.h" 0030 #include "networkmanager.h" 0031 #include "wstoolutils.h" 0032 0033 using namespace Digikam; 0034 0035 namespace DigikamGenericGoogleServicesPlugin 0036 { 0037 0038 class Q_DECL_HIDDEN GSTalkerBase::Private 0039 { 0040 public: 0041 0042 explicit Private() 0043 : linked (false), 0044 authUrl (QLatin1String("https://accounts.google.com/o/oauth2/auth")), 0045 tokenUrl (QLatin1String("https://accounts.google.com/o/oauth2/token")), 0046 identity (QLatin1String("258540448336-hgdegpohibcjasvk1p595fpvjor15pbc.apps.googleusercontent.com")), 0047 sharedKey (QLatin1String("iiIKTNM4ggBXiTdquAzbs2xw")), 0048 netMngr (nullptr) 0049 { 0050 } 0051 0052 bool linked; 0053 0054 QString authUrl; 0055 QString tokenUrl; 0056 QString identity; 0057 QString sharedKey; 0058 0059 QNetworkAccessManager* netMngr; 0060 }; 0061 0062 GSTalkerBase::GSTalkerBase(QObject* const parent, const QStringList& scope, const QString& serviceName) 0063 : QObject (parent), 0064 m_scope (scope), 0065 m_serviceName(serviceName), 0066 m_reply (nullptr), 0067 m_service (nullptr), 0068 d (new Private) 0069 { 0070 d->netMngr = NetworkManager::instance()->getNetworkManager(this); 0071 m_service = new QOAuth2AuthorizationCodeFlow(d->netMngr, this); 0072 0073 m_service->setContentType(QAbstractOAuth::ContentType::Json); 0074 m_service->setClientIdentifierSharedKey(d->sharedKey); 0075 m_service->setScope(m_scope.join(QLatin1String(" "))); 0076 m_service->setAuthorizationUrl(QUrl(d->authUrl)); 0077 m_service->setAccessTokenUrl(QUrl(d->tokenUrl)); 0078 m_service->setClientIdentifier(d->identity); 0079 0080 #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 0081 0082 m_service->setModifyParametersFunction([](QAbstractOAuth::Stage stage, QVariantMap* parameters) 0083 { 0084 if (stage == QAbstractOAuth::Stage::RequestingAccessToken) 0085 { 0086 QByteArray code = parameters->value(QLatin1String("code")).toByteArray(); 0087 (*parameters)[QLatin1String("code")] = QUrl::fromPercentEncoding(code); 0088 } 0089 } 0090 ); 0091 0092 #else 0093 0094 m_service->setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* parameters) 0095 { 0096 if (stage == QAbstractOAuth::Stage::RequestingAccessToken) 0097 { 0098 QByteArray code = parameters->value(QLatin1String("code")).toByteArray(); 0099 (*parameters).replace(QLatin1String("code"), QUrl::fromPercentEncoding(code)); 0100 } 0101 } 0102 ); 0103 0104 #endif 0105 0106 QOAuthHttpServerReplyHandler* const replyHandler = new QOAuthHttpServerReplyHandler(8000, this); 0107 m_service->setReplyHandler(replyHandler); 0108 0109 // OAuth configuration saved to between dk sessions 0110 0111 m_service->setRefreshToken(WSToolUtils::readToken(m_serviceName)); 0112 0113 connect(m_service, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, 0114 this, &GSTalkerBase::slotOpenBrowser); 0115 0116 connect(m_service, &QOAuth2AuthorizationCodeFlow::tokenChanged, 0117 this, &GSTalkerBase::slotTokenChanged); 0118 0119 connect(m_service, &QOAuth2AuthorizationCodeFlow::granted, 0120 this, &GSTalkerBase::slotLinkingSucceeded); 0121 0122 connect(m_service, &QOAuth2AuthorizationCodeFlow::error, 0123 this, &GSTalkerBase::slotLinkingFailed); 0124 } 0125 0126 GSTalkerBase::~GSTalkerBase() 0127 { 0128 if (m_reply) 0129 { 0130 m_reply->abort(); 0131 } 0132 0133 delete d; 0134 } 0135 0136 void GSTalkerBase::link() 0137 { 0138 Q_EMIT signalBusy(true); 0139 m_service->grant(); 0140 } 0141 0142 void GSTalkerBase::unlink() 0143 { 0144 Q_EMIT signalBusy(true); 0145 0146 d->linked = false; 0147 0148 m_service->setToken(QString()); 0149 m_service->setRefreshToken(QString()); 0150 0151 WSToolUtils::clearToken(m_serviceName); 0152 0153 m_bearerAccessToken.clear(); 0154 m_accessToken.clear(); 0155 } 0156 0157 void GSTalkerBase::slotLinkingFailed() 0158 { 0159 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "LINK to" << m_serviceName << "fail"; 0160 0161 d->linked = false; 0162 0163 Q_EMIT signalBusy(false); 0164 Q_EMIT signalAuthenticationRefused(); 0165 } 0166 0167 void GSTalkerBase::slotLinkingSucceeded() 0168 { 0169 if (m_service->status() == QAbstractOAuth::Status::Granted) 0170 { 0171 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "LINK to" << m_serviceName << "ok"; 0172 0173 d->linked = true; 0174 0175 Q_EMIT signalAccessTokenObtained(); 0176 } 0177 } 0178 0179 void GSTalkerBase::slotOpenBrowser(const QUrl& url) 0180 { 0181 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Open Browser... (" << url << ")"; 0182 0183 QDesktopServices::openUrl(url); 0184 } 0185 0186 bool GSTalkerBase::authenticated() const 0187 { 0188 return d->linked; 0189 } 0190 0191 void GSTalkerBase::slotTokenChanged(const QString& token) 0192 { 0193 m_accessToken = token; 0194 m_bearerAccessToken = QLatin1String("Bearer ") + m_accessToken; 0195 0196 WSToolUtils::saveToken(m_serviceName, m_service->refreshToken()); 0197 } 0198 0199 void GSTalkerBase::doOAuth() 0200 { 0201 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "current time" << QDateTime::currentDateTime(); 0202 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "expires at: " << m_service->expirationAt(); 0203 0204 if (!m_service->refreshToken().isEmpty()) 0205 { 0206 m_service->refreshAccessToken(); 0207 } 0208 else 0209 { 0210 link(); 0211 } 0212 } 0213 0214 } // namespace DigikamGenericGoogleServicesPlugin 0215 0216 #include "moc_gstalkerbase.cpp"