File indexing completed on 2024-11-24 04:17:00

0001 /*
0002     SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "nextcloudauthenticator.h"
0007 
0008 #include <QDebug>
0009 #include <QDesktopServices>
0010 #include <QJsonDocument>
0011 #include <QJsonObject>
0012 #include <QNetworkAccessManager>
0013 #include <QNetworkReply>
0014 #include <QTimer>
0015 
0016 NextcloudAuthenticator::NextcloudAuthenticator(QObject *parent)
0017     : QObject(parent)
0018 {
0019 }
0020 
0021 NextcloudAuthenticator::~NextcloudAuthenticator() = default;
0022 
0023 void NextcloudAuthenticator::setNetworkAccessManager(QNetworkAccessManager *nam)
0024 {
0025     m_nam = nam;
0026 }
0027 
0028 void NextcloudAuthenticator::authenticate(const QUrl &baseUrl, const QString &appName)
0029 {
0030     Q_ASSERT(m_nam);
0031 
0032     QUrl login2Url(baseUrl);
0033     login2Url.setPath(login2Url.path() + QLatin1String("/index.php/login/v2"));
0034 
0035     QNetworkRequest req(login2Url);
0036     req.setHeader(QNetworkRequest::UserAgentHeader, appName);
0037     auto reply = m_nam->post(req, QByteArray());
0038     connect(reply, &QNetworkReply::finished, this, [this, reply]() { post1Finished(reply); });
0039 }
0040 
0041 void NextcloudAuthenticator::post1Finished(QNetworkReply *reply)
0042 {
0043     reply->deleteLater();
0044     if (reply->error() != QNetworkReply::NoError) {
0045         qWarning() << reply->errorString();
0046         return;
0047     }
0048 
0049     const auto obj = QJsonDocument::fromJson(reply->readAll()).object();
0050     const auto loginUrl = QUrl(obj.value(QLatin1String("login")).toString());
0051     QDesktopServices::openUrl(loginUrl);
0052 
0053     const auto pollObj = obj.value(QLatin1String("poll")).toObject();
0054     m_pollEndpoint = QUrl(pollObj.value(QLatin1String("endpoint")).toString());
0055     m_pollToken = "token=" + pollObj.value(QLatin1String("token")).toString().toUtf8();
0056 
0057     QTimer::singleShot(std::chrono::seconds(5), Qt::VeryCoarseTimer, this, &NextcloudAuthenticator::login2Poll);
0058 }
0059 
0060 void NextcloudAuthenticator::login2Poll()
0061 {
0062     QNetworkRequest req(m_pollEndpoint);
0063     req.setHeader(QNetworkRequest::ContentTypeHeader, QByteArray("application/x-www-form-urlencoded"));
0064     auto reply = m_nam->post(req, m_pollToken);
0065     connect(reply, &QNetworkReply::finished, this, [this, reply]() {
0066         reply->deleteLater();
0067         if (reply->error() == QNetworkReply::ContentNotFoundError) {
0068             QTimer::singleShot(std::chrono::seconds(5), Qt::VeryCoarseTimer, this, &NextcloudAuthenticator::login2Poll);
0069             return;
0070         }
0071         if (reply->error() != QNetworkReply::NoError) {
0072             qWarning() << reply->errorString();
0073             return;
0074         }
0075 
0076         const auto obj = QJsonDocument::fromJson(reply->readAll()).object();
0077         Q_EMIT authenticated(obj.value(QLatin1String("loginName")).toString(), obj.value(QLatin1String("appPassword")).toString());
0078     });
0079 }