Further implementing NextcloudApi clann
This commit is contained in:
parent
538bc6c54f
commit
c68ec1ee57
9 changed files with 368 additions and 130 deletions
|
@ -19,13 +19,11 @@ DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
|||
HEADERS += src/note.h \
|
||||
src/accounthash.h \
|
||||
src/nextcloudapi.h \
|
||||
src/notesapi.h \
|
||||
src/notesmodel.h
|
||||
|
||||
SOURCES += src/harbour-nextcloudnotes.cpp \
|
||||
src/nextcloudapi.cpp \
|
||||
src/note.cpp \
|
||||
src/notesapi.cpp \
|
||||
src/notesmodel.cpp
|
||||
|
||||
DISTFILES += qml/harbour-nextcloudnotes.qml \
|
||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.2
|
|||
import Sailfish.Silica 1.0
|
||||
import Nemo.Configuration 1.0
|
||||
import Nemo.Notifications 1.0
|
||||
import NextcloudApi 1.0
|
||||
import "pages"
|
||||
|
||||
ApplicationWindow
|
||||
|
@ -136,32 +137,11 @@ ApplicationWindow
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: notesApi
|
||||
|
||||
onNetworkAccessibleChanged: {
|
||||
console.log("Device is " + (accessible ? "online" : "offline"))
|
||||
if (accessible) {
|
||||
offlineNotification.close(Notification.Closed)
|
||||
notesApi.getAllNotes()
|
||||
}
|
||||
else {
|
||||
offlineNotification.publish()
|
||||
}
|
||||
}
|
||||
onNoteError: {
|
||||
apiErrorNotification.close()
|
||||
if (error)
|
||||
console.log("Notes API error (" + error + "): " + notesApi.errorMessage(error))
|
||||
if (error && notesApi.networkAccessible) {
|
||||
apiErrorNotification.body = notesApi.errorMessage(error)
|
||||
apiErrorNotification.publish()
|
||||
}
|
||||
}
|
||||
onLastSyncChanged: {
|
||||
console.log("Last API sync: " + lastSync)
|
||||
account.update = lastSync
|
||||
}
|
||||
Nextcloud {
|
||||
id: nextcloud
|
||||
server: account.url
|
||||
username: account.username
|
||||
password: account.passowrd
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <QtQml>
|
||||
#include <QObject>
|
||||
#include "accounthash.h"
|
||||
#include "note.h"
|
||||
#include "notesapi.h"
|
||||
#include "nextcloudapi.h"
|
||||
#include "notesmodel.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -19,19 +18,7 @@ int main(int argc, char *argv[])
|
|||
qDebug() << app->applicationDisplayName() << app->applicationVersion();
|
||||
|
||||
AccountHash* accountHash = new AccountHash;
|
||||
qRegisterMetaType<Note>();
|
||||
NotesModel* notesModel = new NotesModel;
|
||||
NotesProxyModel* notesProxyModel = new NotesProxyModel;
|
||||
notesProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
notesProxyModel->setSortLocaleAware(true);
|
||||
notesProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
notesProxyModel->setFilterRole(NotesModel::ContentRole);
|
||||
notesProxyModel->setSourceModel(notesModel);
|
||||
|
||||
NotesApi* notesApi = new NotesApi;
|
||||
notesModel->setNotesApi(notesApi);
|
||||
|
||||
qmlRegisterType<NotesApi>("NextcloudNotes", 1, 0, "NotesApi");
|
||||
qmlRegisterType<NextcloudApi>("NextcloudApi", 1, 0, "Nextcloud");
|
||||
|
||||
QQuickView* view = SailfishApp::createView();
|
||||
#ifdef QT_DEBUG
|
||||
|
@ -40,17 +27,11 @@ int main(int argc, char *argv[])
|
|||
view->rootContext()->setContextProperty("debug", QVariant(false));
|
||||
#endif
|
||||
view->rootContext()->setContextProperty("accountHash", accountHash);
|
||||
view->rootContext()->setContextProperty("notesModel", notesModel);
|
||||
view->rootContext()->setContextProperty("notesProxyModel", notesProxyModel);
|
||||
view->rootContext()->setContextProperty("notesApi", notesApi);
|
||||
|
||||
view->setSource(SailfishApp::pathTo("qml/harbour-nextcloudnotes.qml"));
|
||||
view->show();
|
||||
|
||||
int retval = app->exec();
|
||||
|
||||
notesApi->deleteLater();
|
||||
notesProxyModel->deleteLater();
|
||||
notesModel->deleteLater();
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
#include "nextcloudapi.h"
|
||||
#include <QGuiApplication>
|
||||
#include <QAuthenticator>
|
||||
#include <QJsonDocument>
|
||||
|
||||
NextcloudApi::NextcloudApi(QObject *parent) : QObject(parent)
|
||||
{
|
||||
// Initial status
|
||||
setStatus(NextcloudStatus::NextcloudUnknown);
|
||||
setCababilitiesStatus(CapabilitiesStatus::CapabilitiesUnknown);
|
||||
setStatus(ApiCallStatus::ApiUnknown);
|
||||
setLoginStatus(LoginStatus::LoginUnknown);
|
||||
setCababilitiesStatus(ApiCallStatus::ApiUnknown);
|
||||
setUserListStatus(ApiCallStatus::ApiUnknown);
|
||||
setUserMetaStatus(ApiCallStatus::ApiUnknown);
|
||||
m_status_installed = false;
|
||||
m_status_maintenance = false;
|
||||
m_status_needsDbUpgrade = false;
|
||||
m_status_extendedSupport = false;
|
||||
m_running_requests = 0;
|
||||
|
||||
// Login Flow V2 poll timer
|
||||
m_loginPollTimer.setInterval(LOGIN_FLOWV2_POLL_INTERVALL);
|
||||
|
@ -37,6 +40,12 @@ NextcloudApi::NextcloudApi(QObject *parent) : QObject(parent)
|
|||
}
|
||||
|
||||
NextcloudApi::~NextcloudApi() {
|
||||
while (!m_replies.empty()) {
|
||||
QNetworkReply* reply = m_replies.first();
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
m_replies.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
void NextcloudApi::setVerifySsl(bool verify) {
|
||||
|
@ -175,8 +184,7 @@ bool NextcloudApi::get(const QString& endpoint, bool authenticated) {
|
|||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
QNetworkRequest request = authenticated ? m_authenticatedRequest : m_request;
|
||||
request.setUrl(url);
|
||||
m_manager.get(request);
|
||||
m_running_requests ++;
|
||||
m_replies << m_manager.get(request);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -185,24 +193,6 @@ bool NextcloudApi::get(const QString& endpoint, bool authenticated) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NextcloudApi::post(const QString& endpoint, const QByteArray& data, bool authenticated) {
|
||||
QUrl url = server();
|
||||
url.setPath(url.path() + endpoint);
|
||||
qDebug() << "POST" << url.toDisplayString();
|
||||
qDebug() << data;
|
||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
QNetworkRequest request = authenticated ? m_authenticatedRequest : m_request;
|
||||
request.setUrl(url);
|
||||
m_manager.post(request, data);
|
||||
m_running_requests ++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "POST URL not valid" << url.toDisplayString();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NextcloudApi::put(const QString& endpoint, const QByteArray& data, bool authenticated) {
|
||||
QUrl url = server();
|
||||
url.setPath(url.path() + endpoint);
|
||||
|
@ -211,8 +201,7 @@ bool NextcloudApi::put(const QString& endpoint, const QByteArray& data, bool aut
|
|||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
QNetworkRequest request = authenticated ? m_authenticatedRequest : m_request;
|
||||
request.setUrl(url);
|
||||
m_manager.put(request, data);
|
||||
m_running_requests ++;
|
||||
m_replies << m_manager.put(request, data);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -221,6 +210,23 @@ bool NextcloudApi::put(const QString& endpoint, const QByteArray& data, bool aut
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NextcloudApi::post(const QString& endpoint, const QByteArray& data, bool authenticated) {
|
||||
QUrl url = server();
|
||||
url.setPath(url.path() + endpoint);
|
||||
qDebug() << "POST" << url.toDisplayString();
|
||||
qDebug() << data;
|
||||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
QNetworkRequest request = authenticated ? m_authenticatedRequest : m_request;
|
||||
request.setUrl(url);
|
||||
m_replies << m_manager.post(request, data);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebug() << "POST URL not valid" << url.toDisplayString();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NextcloudApi::del(const QString& endpoint, bool authenticated) {
|
||||
QUrl url = server();
|
||||
url.setPath(url.path() + endpoint);
|
||||
|
@ -228,8 +234,7 @@ bool NextcloudApi::del(const QString& endpoint, bool authenticated) {
|
|||
if (url.isValid() && !url.scheme().isEmpty() && !url.host().isEmpty()) {
|
||||
QNetworkRequest request = authenticated ? m_authenticatedRequest : m_request;
|
||||
request.setUrl(url);
|
||||
m_manager.deleteResource(request);
|
||||
m_running_requests ++;
|
||||
m_replies << m_manager.deleteResource(request);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -240,11 +245,11 @@ bool NextcloudApi::del(const QString& endpoint, bool authenticated) {
|
|||
|
||||
bool NextcloudApi::getStatus() {
|
||||
if (get(STATUS_ENDPOINT, false)) {
|
||||
setStatus(NextcloudStatus::NextcloudBusy);
|
||||
setStatus(ApiCallStatus::ApiBusy);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
setStatus(NextcloudStatus::NextcloudFailed);
|
||||
setStatus(ApiCallStatus::ApiFailed);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -284,6 +289,28 @@ bool NextcloudApi::deleteAppPassword() {
|
|||
return del(DEL_APPPASSWORD_ENDPOINT, true);
|
||||
}
|
||||
|
||||
void NextcloudApi::verifyUrl(QUrl url) {
|
||||
emit urlValidChanged(
|
||||
url.isValid()&&
|
||||
!url.isRelative() &&
|
||||
!url.userName().isEmpty() &&
|
||||
!url.password().isEmpty() &&
|
||||
!url.host().isEmpty());
|
||||
}
|
||||
|
||||
void NextcloudApi::requireAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) {
|
||||
if (reply && authenticator) {
|
||||
authenticator->setUser(username());
|
||||
authenticator->setPassword(password());
|
||||
}
|
||||
else
|
||||
emit apiError(AuthenticationError);
|
||||
}
|
||||
|
||||
void NextcloudApi::onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible) {
|
||||
emit networkAccessibleChanged(accessible == QNetworkAccessManager::Accessible);
|
||||
}
|
||||
|
||||
bool NextcloudApi::pollLoginUrl() {
|
||||
if (post(m_pollUrl.path(), QByteArray("token=").append(m_pollToken), false)) {
|
||||
setLoginStatus(LoginStatus::LoginFlowV2Polling);
|
||||
|
@ -295,3 +322,153 @@ bool NextcloudApi::pollLoginUrl() {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NextcloudApi::sslError(QNetworkReply *reply, const QList<QSslError> &errors) {
|
||||
qDebug() << "SSL errors accured while calling" << reply->url().toDisplayString();
|
||||
for (int i = 0; i < errors.size(); ++i) {
|
||||
qDebug() << errors[i].errorString();
|
||||
}
|
||||
emit apiError(SslHandshakeError);
|
||||
}
|
||||
|
||||
void NextcloudApi::replyFinished(QNetworkReply* reply) {
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
qDebug() << reply->error() << reply->errorString();
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument json = QJsonDocument::fromJson(data);
|
||||
qDebug() << data;
|
||||
|
||||
switch (reply->error()) {
|
||||
case QNetworkReply::NoError:
|
||||
emit apiError(NoError);
|
||||
switch (reply->operation()) {
|
||||
case QNetworkAccessManager::GetOperation:
|
||||
if (reply->url().toString().endsWith(STATUS_ENDPOINT)) {
|
||||
updateStatus(json.object());
|
||||
}
|
||||
else if (reply->url().toString().endsWith(GET_APPPASSWORD_ENDPOINT)) {
|
||||
updateAppPassword(json.object());
|
||||
}
|
||||
else if (reply->url().toString().endsWith(LIST_USERS_ENDPOINT)) {
|
||||
updateUserList(json.object());
|
||||
}
|
||||
else if (reply->url().toString().contains(USER_METADATA_ENDPOINT)) {
|
||||
updateUserMeta(json.object());
|
||||
}
|
||||
else if (reply->url().toString().endsWith(CAPABILITIES_ENDPOINT)) {
|
||||
updateCapabilities(json.object());
|
||||
}
|
||||
else {
|
||||
emit getFinished(reply);
|
||||
break;
|
||||
}
|
||||
m_replies.removeOne(reply);
|
||||
reply->deleteLater();
|
||||
break;
|
||||
case QNetworkAccessManager::PutOperation:
|
||||
if (false) {
|
||||
}
|
||||
else {
|
||||
emit putFinished(reply);
|
||||
break;
|
||||
}
|
||||
m_replies.removeOne(reply);
|
||||
reply->deleteLater();
|
||||
break;
|
||||
case QNetworkAccessManager::PostOperation:
|
||||
if (reply->url().toString().endsWith(LOGIN_FLOWV2_ENDPOINT)) {
|
||||
|
||||
}
|
||||
else if (reply->url() == m_pollUrl) {
|
||||
|
||||
}
|
||||
else {
|
||||
emit postFinished(reply);
|
||||
break;
|
||||
}
|
||||
m_replies.removeOne(reply);
|
||||
reply->deleteLater();
|
||||
break;
|
||||
case QNetworkAccessManager::DeleteOperation:
|
||||
if (reply->url().toString().endsWith(DEL_APPPASSWORD_ENDPOINT)) {
|
||||
|
||||
}
|
||||
else {
|
||||
emit delFinished(reply);
|
||||
break;
|
||||
}
|
||||
m_replies.removeOne(reply);
|
||||
reply->deleteLater();
|
||||
break;
|
||||
default:
|
||||
qDebug() << "Unknown operation" << reply->operation() << reply->url();
|
||||
m_replies.removeOne(reply);
|
||||
reply->deleteLater();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
emit apiError(AuthenticationError);
|
||||
break;
|
||||
case QNetworkReply::ContentNotFoundError:
|
||||
if (reply->url() == m_pollUrl) {
|
||||
emit apiError(NoError);
|
||||
}
|
||||
else {
|
||||
emit apiError(CommunicationError);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
emit apiError(CommunicationError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateStatus(const QJsonObject &status) {
|
||||
|
||||
}
|
||||
|
||||
void NextcloudApi::setStatus(ApiCallStatus status, bool *changed) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateLoginFlow(const QJsonObject &login) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateLoginCredentials(const QJsonObject &credentials) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateAppPassword(const QJsonObject &password) {
|
||||
|
||||
}
|
||||
|
||||
void NextcloudApi::setLoginStatus(LoginStatus status, bool *changed) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateUserList(const QJsonObject &users) {
|
||||
|
||||
}
|
||||
|
||||
void NextcloudApi::setUserListStatus(ApiCallStatus status, bool *changed) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateUserMeta(const QJsonObject &userMeta) {
|
||||
|
||||
}
|
||||
|
||||
void NextcloudApi::setUserMetaStatus(ApiCallStatus status, bool *changed) {
|
||||
|
||||
}
|
||||
|
||||
bool NextcloudApi::updateCapabilities(const QJsonObject &capabilities) {
|
||||
|
||||
}
|
||||
|
||||
void NextcloudApi::setCababilitiesStatus(ApiCallStatus status, bool *changed) {
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
const QString STATUS_ENDPOINT("/status.php");
|
||||
|
||||
// Capabilites and users
|
||||
const QString CAPABILITIES_ENDPOINT("/ocs/v1.php/cloud/capabilities");
|
||||
const QString USERS_ENDPOINT("/ocs/v1.php/cloud/users");
|
||||
const QString USER_CAPABILITIES_ENDPOINT("/ocs/v1.php/cloud/users/%1");
|
||||
const QString CAPABILITIES_ENDPOINT("/ocs/v2.php/cloud/capabilities");
|
||||
const QString LIST_USERS_ENDPOINT("/ocs/v2.php/cloud/users");
|
||||
const QString USER_METADATA_ENDPOINT("/ocs/v2.php/cloud/users/%1");
|
||||
const QString USER_NOTIFICATION_ENDPOINT("/ocs/v2.php/cloud/capabilities");
|
||||
|
||||
// Login and authentication
|
||||
const QString GET_APPPASSWORD_ENDPOINT("/ocs/v2.php/core/getapppassword");
|
||||
|
@ -49,7 +50,7 @@ class NextcloudApi : public QObject
|
|||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||
|
||||
// Nextcloud status (status.php), these properties will be automatically updated on changes of the generic properties
|
||||
Q_PROPERTY(NextcloudStatus statusStatus READ statusStatus NOTIFY statusStatusChanged)
|
||||
Q_PROPERTY(ApiCallStatus statusStatus READ statusStatus NOTIFY statusStatusChanged)
|
||||
Q_PROPERTY(bool statusInstalled READ statusInstalled NOTIFY statusInstalledChanged)
|
||||
Q_PROPERTY(bool statusMaintenance READ statusMaintenance NOTIFY statusMaintenanceChanged)
|
||||
Q_PROPERTY(bool statusNeedsDbUpgrade READ statusNeedsDbUpgrade NOTIFY statusNeedsDbUpgradeChanged)
|
||||
|
@ -60,32 +61,28 @@ class NextcloudApi : public QObject
|
|||
Q_PROPERTY(bool statusExtendedSupport READ statusExtendedSupport NOTIFY statusExtendedSupportChanged)
|
||||
Q_PROPERTY(bool loginFlowV2Possible READ loginFlowV2Possible NOTIFY loginFlowV2PossibleChanged)
|
||||
|
||||
// Nextcloud capabilities
|
||||
Q_PROPERTY(CapabilitiesStatus capabilitiesStatus READ capabilitiesStatus NOTIFY capabilitiesStatusChanged)
|
||||
|
||||
// Login status
|
||||
Q_PROPERTY(LoginStatus loginStatus READ loginStatus NOTIFY loginStatusChanged)
|
||||
Q_PROPERTY(ApiCallStatus loginStatus READ loginStatus NOTIFY loginStatusChanged)
|
||||
|
||||
// User(s) status
|
||||
Q_PROPERTY(ApiCallStatus userListStatus READ userListStatus NOTIFY userListStatusChanged)
|
||||
Q_PROPERTY(ApiCallStatus userMetaStatus READ userMetaStatus NOTIFY userMetaStatusChanged)
|
||||
|
||||
// Nextcloud capabilities
|
||||
Q_PROPERTY(ApiCallStatus capabilitiesStatus READ capabilitiesStatus NOTIFY capabilitiesStatusChanged)
|
||||
|
||||
public:
|
||||
explicit NextcloudApi(QObject *parent = nullptr);
|
||||
virtual ~NextcloudApi();
|
||||
|
||||
// Status codes
|
||||
enum NextcloudStatus {
|
||||
NextcloudUnknown, // Initial unknown state
|
||||
NextcloudBusy, // Getting information from the nextcloud server
|
||||
NextcloudSuccess, // Got information about the nextcloud server
|
||||
NextcloudFailed // Error getting information from the nextcloud server, see ErrorCodes
|
||||
enum ApiCallStatus {
|
||||
ApiUnknown, // Initial unknown state
|
||||
ApiBusy, // Getting information from the nextcloud server
|
||||
ApiSuccess, // Got information from the nextcloud server
|
||||
ApiFailed // Error getting information from the nextcloud server, see ErrorCodes
|
||||
};
|
||||
Q_ENUM(NextcloudStatus)
|
||||
|
||||
enum CapabilitiesStatus {
|
||||
CapabilitiesUnknown, // Initial unknown state
|
||||
CapabilitiesBusy, // Gettin information
|
||||
CapabilitiesSuccess, // Capabilities successfully read
|
||||
CapabilitiesFailed // Faild to retreive capabilities
|
||||
};
|
||||
Q_ENUM(CapabilitiesStatus)
|
||||
Q_ENUM(ApiCallStatus)
|
||||
|
||||
enum LoginStatus {
|
||||
LoginUnknown, // Inital unknown state
|
||||
|
@ -130,10 +127,10 @@ public:
|
|||
bool ready() const { return urlValid() && networkAccessible() && !busy() && statusInstalled() && !statusMaintenance() && loginStatus() == LoginSuccess; }
|
||||
bool urlValid() const { return m_url.isValid(); }
|
||||
bool networkAccessible() const { return m_manager.networkAccessible() == QNetworkAccessManager::Accessible; }
|
||||
bool busy() const { return m_running_requests > 0; }
|
||||
bool busy() const { return m_replies.count() > 0; }
|
||||
|
||||
// Nextcloud status (status.php)
|
||||
NextcloudStatus statusStatus() const { return m_statusStatus; }
|
||||
ApiCallStatus statusStatus() const { return m_statusStatus; }
|
||||
bool statusInstalled() const { return m_status_installed; }
|
||||
bool statusMaintenance() const { return m_status_maintenance; }
|
||||
bool statusNeedsDbUpgrade() const { return m_status_needsDbUpgrade; }
|
||||
|
@ -144,12 +141,16 @@ public:
|
|||
bool statusExtendedSupport() const { return m_status_extendedSupport; }
|
||||
bool loginFlowV2Possible() const { return QVersionNumber::fromString(statusVersion()) >= QVersionNumber(LOGIN_FLOWV2_MIN_VERSION); }
|
||||
|
||||
// Nextcloud capabilities
|
||||
CapabilitiesStatus capabilitiesStatus() const { return m_capabilitiesStatus; }
|
||||
|
||||
// Login status
|
||||
LoginStatus loginStatus() const { return m_loginStatus; }
|
||||
|
||||
// User(s) status
|
||||
ApiCallStatus userListStatus() const { return m_userListStatus; }
|
||||
ApiCallStatus userMetaStatus() const { return m_userMetaStatus; }
|
||||
|
||||
// Nextcloud capabilities
|
||||
ApiCallStatus capabilitiesStatus() const { return m_capabilitiesStatus; }
|
||||
|
||||
enum ErrorCodes {
|
||||
NoError,
|
||||
NoConnectionError,
|
||||
|
@ -163,8 +164,8 @@ public:
|
|||
public slots:
|
||||
// API helper functions
|
||||
Q_INVOKABLE bool get(const QString& endpoint, bool authenticated = true);
|
||||
Q_INVOKABLE bool post(const QString& endpoint, const QByteArray& data, bool authenticated = true);
|
||||
Q_INVOKABLE bool put(const QString& endpoint, const QByteArray& data, bool authenticated = true);
|
||||
Q_INVOKABLE bool post(const QString& endpoint, const QByteArray& data, bool authenticated = true);
|
||||
Q_INVOKABLE bool del(const QString& endpoint, bool authenticated = true);
|
||||
|
||||
// Callable functions
|
||||
|
@ -174,6 +175,9 @@ public slots:
|
|||
Q_INVOKABLE bool verifyLogin();
|
||||
Q_INVOKABLE bool getAppPassword();
|
||||
Q_INVOKABLE bool deleteAppPassword();
|
||||
Q_INVOKABLE bool getUserList();
|
||||
Q_INVOKABLE bool getUserMetaData(const QString& user = QString());
|
||||
Q_INVOKABLE bool getCapabilities();
|
||||
|
||||
signals:
|
||||
// Generic API properties
|
||||
|
@ -188,15 +192,16 @@ signals:
|
|||
void passwordChanged(QString password);
|
||||
|
||||
// Class status information
|
||||
void readyChanged(bool ready);
|
||||
void urlValidChanged(bool valid);
|
||||
void networkAccessibleChanged(bool accessible);
|
||||
void busyChanged(bool busy);
|
||||
|
||||
// Nextcloud capabilities
|
||||
void capabilitiesStatusChanged(CapabilitiesStatus status);
|
||||
void capabilitiesStatusChanged(ApiCallStatus status);
|
||||
|
||||
// Nextcloud status (status.php)
|
||||
void statusChanged(NextcloudStatus status);
|
||||
void statusStatusChanged(ApiCallStatus status);
|
||||
void statusInstalledChanged(bool installed);
|
||||
void statusMaintenanceChanged(bool maintenance);
|
||||
void statusNeedsDbUpgradeChanged(bool needsDbUpgrade);
|
||||
|
@ -208,33 +213,34 @@ signals:
|
|||
|
||||
// Login status
|
||||
void loginStatusChanged(LoginStatus status);
|
||||
void loginFlowV2PossibleChanged(bool loginV2possible);
|
||||
|
||||
// API helper updates
|
||||
void getFinished(QNetworkReply& reply);
|
||||
void postFinished(QNetworkReply& reply);
|
||||
void putFinished(QNetworkReply& reply);
|
||||
void delFinished(QNetworkReply& reply);
|
||||
void getFinished(QNetworkReply* reply);
|
||||
void postFinished(QNetworkReply* reply);
|
||||
void putFinished(QNetworkReply* reply);
|
||||
void delFinished(QNetworkReply* reply);
|
||||
void apiError(ErrorCodes error);
|
||||
|
||||
private slots:
|
||||
void verifyUrl(QUrl url);
|
||||
void requireAuthentication(QNetworkReply * reply, QAuthenticator * authenticator);
|
||||
void onNetworkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
|
||||
void replyFinished(QNetworkReply* reply);
|
||||
bool pollLoginUrl();
|
||||
void sslError(QNetworkReply* reply, const QList<QSslError> &errors);
|
||||
void replyFinished(QNetworkReply* reply);
|
||||
|
||||
private:
|
||||
QUrl m_url;
|
||||
QNetworkAccessManager m_manager;
|
||||
QVector<QNetworkReply*> m_replies;
|
||||
QNetworkRequest m_request;
|
||||
QNetworkRequest m_authenticatedRequest;
|
||||
uint m_running_requests;
|
||||
|
||||
// Nextcloud status.php
|
||||
void updateStatus(const QJsonObject &status);
|
||||
void setStatus(NextcloudStatus status, bool *changed = NULL);
|
||||
NextcloudStatus m_statusStatus;
|
||||
bool updateStatus(const QJsonObject &status);
|
||||
void setStatus(ApiCallStatus status, bool *changed = NULL);
|
||||
ApiCallStatus m_statusStatus;
|
||||
bool m_status_installed;
|
||||
bool m_status_maintenance;
|
||||
bool m_status_needsDbUpgrade;
|
||||
|
@ -245,15 +251,28 @@ private:
|
|||
bool m_status_extendedSupport;
|
||||
|
||||
// Nextcloud capabilities
|
||||
bool updateCapabilities(const QJsonObject & capabilities);
|
||||
void setCababilitiesStatus(CapabilitiesStatus status, bool *changed = NULL);
|
||||
CapabilitiesStatus m_capabilitiesStatus;
|
||||
bool updateCapabilities(const QJsonObject &capabilities);
|
||||
void setCababilitiesStatus(ApiCallStatus status, bool *changed = NULL);
|
||||
ApiCallStatus m_capabilitiesStatus;
|
||||
QJsonObject m_capabilities;
|
||||
|
||||
// Nextcloud users list
|
||||
bool updateUserList(const QJsonObject &users);
|
||||
void setUserListStatus(ApiCallStatus status, bool *changed = NULL);
|
||||
ApiCallStatus m_userListStatus;
|
||||
QStringList m_userList;
|
||||
|
||||
// Nextcloud user metadata
|
||||
bool updateUserMeta(const QJsonObject &userMeta);
|
||||
void setUserMetaStatus(ApiCallStatus status, bool *changed = NULL);
|
||||
ApiCallStatus m_userMetaStatus;
|
||||
QHash<QString, QJsonObject> m_userMeta;
|
||||
|
||||
// Nextcloud Login Flow v2
|
||||
// https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2
|
||||
bool updateLoginFlow(const QJsonObject &login);
|
||||
bool updateLoginCredentials(const QJsonObject &credentials);
|
||||
bool updateAppPassword(const QJsonObject &password);
|
||||
void setLoginStatus(LoginStatus status, bool *changed = NULL);
|
||||
LoginStatus m_loginStatus;
|
||||
QTimer m_loginPollTimer;
|
||||
|
|
|
@ -10,12 +10,8 @@
|
|||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include "nextcloudapi.h"
|
||||
|
||||
const QString STATUS_ENDPOINT("/status.php");
|
||||
const QString LOGIN_ENDPOINT("/index.php/login/v2");
|
||||
const QString USERS_ENDPOINT("/ocs/v1.php/cloud/users");
|
||||
const QString CAPABILITIES_ENDPOINT("/ocs/v1.php/cloud/capabilities");
|
||||
const QString APPPASSWORD_ENDPOINT("/ocs/v2.php/core/");
|
||||
const QString NOTES_ENDPOINT("/index.php/apps/notes/api/v0.2/notes");
|
||||
const QString EXCLUDE_QUERY("exclude=");
|
||||
const QString PURGE_QUERY("purgeBefore=");
|
||||
|
|
|
@ -222,6 +222,33 @@
|
|||
<translation>MIT Lizenz</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NextcloudApi</name>
|
||||
<message>
|
||||
<source>No error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No network connection available</source>
|
||||
<translation type="unfinished">Netzwerk Verbindung nicht verfügbar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to communicate with the Nextcloud server</source>
|
||||
<translation type="unfinished">Fehler bei der Server-Kommunikation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error occured while establishing an encrypted connection</source>
|
||||
<translation type="unfinished">Fehler beim Aufbau einer verschlüsselten Kommunikation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not authenticate to the Nextcloud instance</source>
|
||||
<translation type="unfinished">Fehler bei der Authentifizierung am Server</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished">Unbekannter Fehler</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Note</name>
|
||||
<message>
|
||||
|
|
|
@ -222,6 +222,33 @@
|
|||
<translation>MIT License</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NextcloudApi</name>
|
||||
<message>
|
||||
<source>No error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No network connection available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to communicate with the Nextcloud server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error occured while establishing an encrypted connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not authenticate to the Nextcloud instance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Note</name>
|
||||
<message>
|
||||
|
|
|
@ -272,6 +272,39 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>NextcloudApi</name>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="157"/>
|
||||
<source>No error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="160"/>
|
||||
<source>No network connection available</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="163"/>
|
||||
<source>Failed to communicate with the Nextcloud server</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="166"/>
|
||||
<source>An error occured while establishing an encrypted connection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="169"/>
|
||||
<source>Could not authenticate to the Nextcloud instance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/nextcloudapi.cpp" line="172"/>
|
||||
<source>Unknown error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Note</name>
|
||||
<message>
|
||||
|
@ -879,27 +912,27 @@ You can also use other markdown syntax inside them.</source>
|
|||
<context>
|
||||
<name>harbour-nextcloudnotes</name>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="100"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="101"/>
|
||||
<source>Notes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="101"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="102"/>
|
||||
<source>Offline</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="102"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="103"/>
|
||||
<source>Synced</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="116"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="117"/>
|
||||
<source>API error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="109"/>
|
||||
<location filename="../qml/harbour-nextcloudnotes.qml" line="110"/>
|
||||
<source>File error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
Loading…
Reference in a new issue