guiutility.cpp
elidedlabel.cpp
iconjob.cpp
+ remotewipe.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
_accounts.clear();
foreach (const auto &acc, accountsCopy) {
emit accountRemoved(acc.data());
+ emit removeAccountFolders(acc.data());
}
}
*/
void deleteAccount(AccountState *account);
-
/**
* Creates an account and sets up some basic handlers.
* Does *not* add the account to the account manager just yet.
Q_SIGNALS:
void accountAdded(AccountState *account);
void accountRemoved(AccountState *account);
+ void removeAccountFolders(AccountState *account);
private:
AccountManager() {}
createAccountToolbox();
connect(AccountManager::instance(), &AccountManager::accountAdded,
this, &AccountSettings::slotAccountAdded);
+ connect(this, &AccountSettings::removeAccountFolders,
+ AccountManager::instance(), &AccountManager::removeAccountFolders);
connect(ui->_folderList, &QWidget::customContextMenuRequested,
this, &AccountSettings::slotCustomContextMenuRequested);
connect(ui->_folderList, &QAbstractItemView::clicked,
void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, const QByteArray &token)
{
- accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
+ accountsState()->account()->e2e()->setTokenForFolder(fileId, token);
- FolderMetadata emptyMetadata(accountsState()->account());
+ FolderMetadata emptyMetadata(accountsState()->account());
auto encryptedMetadata = emptyMetadata.encryptedMetadata();
if (encryptedMetadata.isEmpty()) {
//TODO: Mark the folder as unencrypted as the metadata generation failed.
return;
}
auto storeMetadataJob = new StoreMetaDataApiJob(accountsState()->account(), fileId, emptyMetadata.encryptedMetadata());
- connect(storeMetadataJob, &StoreMetaDataApiJob::success,
- this, &AccountSettings::slotUploadMetadataSuccess);
- connect(storeMetadataJob, &StoreMetaDataApiJob::error,
- this, &AccountSettings::slotUpdateMetadataError);
+ connect(storeMetadataJob, &StoreMetaDataApiJob::success,
+ this, &AccountSettings::slotUploadMetadataSuccess);
+ connect(storeMetadataJob, &StoreMetaDataApiJob::error,
+ this, &AccountSettings::slotUpdateMetadataError);
- storeMetadataJob->start();
+ storeMetadataJob->start();
}
void AccountSettings::slotUploadMetadataSuccess(const QByteArray& folderId)
{
- const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
- auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
- connect(unlockJob, &UnlockEncryptFolderApiJob::success,
- this, &AccountSettings::slotUnlockFolderSuccess);
- connect(unlockJob, &UnlockEncryptFolderApiJob::error,
- this, &AccountSettings::slotUnlockFolderError);
- unlockJob->start();
+ const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
+ auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
+ connect(unlockJob, &UnlockEncryptFolderApiJob::success,
+ this, &AccountSettings::slotUnlockFolderSuccess);
+ connect(unlockJob, &UnlockEncryptFolderApiJob::error,
+ this, &AccountSettings::slotUnlockFolderError);
+ unlockJob->start();
}
void AccountSettings::slotUpdateMetadataError(const QByteArray& folderId, int httpReturnCode)
{
Q_UNUSED(httpReturnCode);
- const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
- auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
- connect(unlockJob, &UnlockEncryptFolderApiJob::success,
- this, &AccountSettings::slotUnlockFolderSuccess);
- connect(unlockJob, &UnlockEncryptFolderApiJob::error,
- this, &AccountSettings::slotUnlockFolderError);
- unlockJob->start();
+ const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId);
+ auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token);
+ connect(unlockJob, &UnlockEncryptFolderApiJob::success,
+ this, &AccountSettings::slotUnlockFolderSuccess);
+ connect(unlockJob, &UnlockEncryptFolderApiJob::error,
+ this, &AccountSettings::slotUnlockFolderError);
+ unlockJob->start();
}
void AccountSettings::slotLockForEncryptionError(const QByteArray& fileId, int httpErrorCode)
void openFolderAlias(const QString &);
void showIssuesList(AccountState *account);
void requesetMnemonic();
+ void removeAccountFolders(AccountState *account);
public slots:
void slotOpenOC();
#include "accountstate.h"
#include "accountmanager.h"
+#include "remotewipe.h"
#include "account.h"
#include "creds/abstractcredentials.h"
#include "creds/httpcredentials.h"
#include <QTimer>
#include <qfontmetrics.h>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QNetworkRequest>
+#include <QBuffer>
+
namespace OCC {
Q_LOGGING_CATEGORY(lcAccountState, "nextcloud.gui.account.state", QtInfoMsg)
, _waitingForNewCredentials(false)
, _notificationsEtagResponseHeader("*")
, _maintenanceToConnectedDelay(60000 + (qrand() % (4 * 60000))) // 1-5min delay
+ , _remoteWipe(new RemoteWipe(_account))
{
qRegisterMetaType<AccountState *>("AccountState*");
connect(account.data(), &Account::invalidCredentials,
- this, &AccountState::slotInvalidCredentials);
+ this, &AccountState::slotHandleRemoteWipeCheck);
connect(account.data(), &Account::credentialsFetched,
this, &AccountState::slotCredentialsFetched);
connect(account.data(), &Account::credentialsAsked,
break;
case ConnectionValidator::CredentialsWrong:
case ConnectionValidator::CredentialsNotReady:
- slotInvalidCredentials();
+ handleInvalidCredentials();
break;
case ConnectionValidator::SslError:
setState(SignedOut);
}
}
-void AccountState::slotInvalidCredentials()
+void AccountState::slotHandleRemoteWipeCheck()
+{
+ // make sure it changes account state and icons
+ signOutByUi();
+
+ qCInfo(lcAccountState) << "Invalid credentials for" << _account->url().toString()
+ << "checking for remote wipe request";
+
+ _waitingForNewCredentials = false;
+ setState(SignedOut);
+}
+
+
+void AccountState::handleInvalidCredentials()
{
if (isSignedOut() || _waitingForNewCredentials)
return;
account()->credentials()->askFromUser();
}
+
void AccountState::slotCredentialsFetched(AbstractCredentials *)
{
// Make a connection attempt, no matter whether the credentials are
class AccountState;
class Account;
+class RemoteWipe;
typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
*/
void setNavigationAppsEtagResponseHeader(const QByteArray &value);
+ ///Asks for user credentials
+ void handleInvalidCredentials();
+
public slots:
/// Triggers a ping to the server to update state and
/// connection status and errors.
protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
- void slotInvalidCredentials();
+
+ /// When client gets a 401 or 403 checks if server requested remote wipe
+ /// before asking for user credentials again
+ void slotHandleRemoteWipeCheck();
+
void slotCredentialsFetched(AbstractCredentials *creds);
void slotCredentialsAsked(AbstractCredentials *creds);
* Milliseconds for which to delay reconnection after 503/maintenance.
*/
int _maintenanceToConnectedDelay;
+
+ /**
+ * Connects remote wipe check with the account
+ * the log out triggers the check (loads app password -> create request)
+ */
+ RemoteWipe *_remoteWipe;
+
};
}
fetchUser();
+ _account->deleteAppPassword();
+
const QString kck = keychainKey(_account->url().toString(), _user, _account->id());
if (kck.isEmpty()) {
qCDebug(lcWebFlowCredentials()) << "InvalidateToken: User is empty, bailing out!";
if (reply->error() == QNetworkReply::NoError) {
_credentialsValid = true;
+
+ /// Used later for remote wipe
+ _account->setAppPassword(_password);
}
}
this, &FolderMan::slotScheduleFolderByTime);
_timeScheduler.start();
- connect(AccountManager::instance(), &AccountManager::accountRemoved,
+ connect(AccountManager::instance(), &AccountManager::removeAccountFolders,
this, &FolderMan::slotRemoveFoldersForAccount);
connect(_lockWatcher.data(), &LockWatcher::fileUnlocked,
void FolderMan::slotFolderCanSyncChanged()
{
Folder *f = qobject_cast<Folder *>(sender());
- ASSERT(f);
+ ASSERT(f);
if (f->canSync()) {
_socketApi->slotRegisterPath(f->alias());
} else {
return true;
}
+void FolderMan::slotWipeFolderForAccount(AccountState *accountState)
+{
+ QVarLengthArray<Folder *, 16> foldersToRemove;
+ Folder::MapIterator i(_folderMap);
+ while (i.hasNext()) {
+ i.next();
+ Folder *folder = i.value();
+ if (folder->accountState() == accountState) {
+ foldersToRemove.append(folder);
+ }
+ }
+
+ bool success = false;
+ foreach (const auto &f, foldersToRemove) {
+ if (!f) {
+ qCCritical(lcFolderMan) << "Can not remove null folder";
+ return;
+ }
+
+ qCInfo(lcFolderMan) << "Removing " << f->alias();
+
+ const bool currentlyRunning = (_currentSyncFolder == f);
+ if (currentlyRunning) {
+ // abort the sync now
+ terminateSyncProcess();
+ }
+
+ if (_scheduledFolders.removeAll(f) > 0) {
+ emit scheduleQueueChanged();
+ }
+
+ // wipe database
+ f->wipe();
+
+ // wipe data
+ QDir userFolder(f->path());
+ if (userFolder.exists()) {
+ success = userFolder.removeRecursively();
+ if (!success) {
+ qCWarning(lcFolderMan) << "Failed to remove existing folder " << f->path();
+ } else {
+ qCInfo(lcFolderMan) << "wipe: Removed file " << f->path();
+ }
+
+
+ } else {
+ success = true;
+ qCWarning(lcFolderMan) << "folder does not exist, can not remove.";
+ }
+
+ f->setSyncPaused(true);
+
+ // remove the folder configuration
+ f->removeFromSettings();
+
+ unloadFolder(f);
+ if (currentlyRunning) {
+ delete f;
+ }
+
+ _navigationPaneHelper.scheduleUpdateCloudStorageRegistry();
+ }
+
+ emit folderListChanged(_folderMap);
+ emit wipeDone(accountState, success);
+}
+
void FolderMan::setDirtyProxy()
{
foreach (Folder *f, _folderMap.values()) {
*/
void folderListChanged(const Folder::Map &);
+ /**
+ * Emitted once slotRemoveFoldersForAccount is done wiping
+ */
+ void wipeDone(AccountState *account, bool success);
+
public slots:
/**
// slot to schedule an ETag job (from Folder only)
void slotScheduleETagJob(const QString &alias, RequestEtagJob *job);
+ /** Wipe folder */
+ void slotWipeFolderForAccount(AccountState *accountState);
+
private slots:
void slotFolderSyncPaused(Folder *, bool paused);
void slotFolderCanSyncChanged();
--- /dev/null
+/*
+ * Copyright (C) by Camila Ayres <hello@camila.codes>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "remotewipe.h"
+#include "folderman.h"
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QNetworkRequest>
+#include <QBuffer>
+
+namespace OCC {
+
+Q_LOGGING_CATEGORY(lcRemoteWipe, "nextcloud.gui.remotewipe", QtInfoMsg)
+
+RemoteWipe::RemoteWipe(AccountPtr account, QObject *parent)
+ : _account(account),
+ _appPassword(QString()),
+ _accountRemoved(false),
+ _networkManager(nullptr),
+ _networkReplyCheck(nullptr),
+ _networkReplySuccess(nullptr)
+{
+ QObject::connect(AccountManager::instance(), &AccountManager::accountRemoved,
+ this, [=](AccountState *) {
+ _accountRemoved = true;
+ });
+ QObject::connect(this, &RemoteWipe::authorized, FolderMan::instance(),
+ &FolderMan::slotWipeFolderForAccount);
+ QObject::connect(FolderMan::instance(), &FolderMan::wipeDone, this,
+ &RemoteWipe::notifyServerSuccessJob);
+ QObject::connect(_account.data(), &Account::appPasswordRetrieved, this,
+ &RemoteWipe::startCheckJobWithAppPassword);
+}
+
+void RemoteWipe::startCheckJobWithAppPassword(QString pwd){
+ if(pwd.isEmpty())
+ return;
+
+ _appPassword = pwd;
+ QUrl requestUrl = Utility::concatUrlPath(_account->url().toString(),
+ QLatin1String("/index.php/core/wipe/check"));
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
+ "application/x-www-form-urlencoded");
+ request.setUrl(requestUrl);
+ request.setSslConfiguration(_account->getOrCreateSslConfig());
+ auto requestBody = new QBuffer;
+ QUrlQuery arguments(QString("token=%1").arg(_appPassword));
+ requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1());
+ _networkReplyCheck = _networkManager.post(request, requestBody);
+ QObject::connect(_networkReplyCheck, &QNetworkReply::finished, this,
+ &RemoteWipe::checkJobSlot);
+}
+
+void RemoteWipe::checkJobSlot()
+{
+ auto jsonData = _networkReplyCheck->readAll();
+ QJsonParseError jsonParseError;
+ QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
+ bool wipe = false;
+
+ //check for errors
+ if (_networkReplyCheck->error() != QNetworkReply::NoError ||
+ jsonParseError.error != QJsonParseError::NoError) {
+ QString errorReason;
+ QString errorFromJson = json["error"].toString();
+ if (!errorFromJson.isEmpty()) {
+ qCWarning(lcRemoteWipe) << QString("Error returned from the server: <em>%1<em>")
+ .arg(errorFromJson.toHtmlEscaped());
+ } else if (_networkReplyCheck->error() != QNetworkReply::NoError) {
+ qCWarning(lcRemoteWipe) << QString("There was an error accessing the 'token' endpoint: <br><em>%1</em>")
+ .arg(_networkReplyCheck->errorString().toHtmlEscaped());
+ } else if (jsonParseError.error != QJsonParseError::NoError) {
+ qCWarning(lcRemoteWipe) << QString("Could not parse the JSON returned from the server: <br><em>%1</em>")
+ .arg(jsonParseError.errorString());
+ } else {
+ qCWarning(lcRemoteWipe) << QString("The reply from the server did not contain all expected fields");
+ }
+
+ // check for wipe request
+ } else if(!json.value("wipe").isUndefined()){
+ wipe = json["wipe"].toBool();
+ }
+
+ auto manager = AccountManager::instance();
+ auto accountState = manager->account(_account->displayName()).data();
+
+ if(wipe){
+ // delete account
+ manager->deleteAccount(accountState);
+ manager->save();
+
+ // delete data
+ emit authorized(accountState);
+
+ } else {
+ // ask user for his credentials again
+ accountState->handleInvalidCredentials();
+ }
+
+ _networkReplyCheck->deleteLater();
+}
+
+void RemoteWipe::notifyServerSuccessJob(AccountState *accountState, bool dataWiped){
+ if(_accountRemoved && dataWiped && _account == accountState->account()){
+ QUrl requestUrl = Utility::concatUrlPath(_account->url().toString(),
+ QLatin1String("/index.php/core/wipe/success"));
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
+ "application/x-www-form-urlencoded");
+ request.setUrl(requestUrl);
+ request.setSslConfiguration(_account->getOrCreateSslConfig());
+ auto requestBody = new QBuffer;
+ QUrlQuery arguments(QString("token=%1").arg(_appPassword));
+ requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1());
+ _networkReplySuccess = _networkManager.post(request, requestBody);
+ QObject::connect(_networkReplySuccess, &QNetworkReply::finished, this,
+ &RemoteWipe::notifyServerSuccessJobSlot);
+ }
+}
+
+void RemoteWipe::notifyServerSuccessJobSlot()
+{
+ auto jsonData = _networkReplySuccess->readAll();
+ QJsonParseError jsonParseError;
+ QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
+ if (_networkReplySuccess->error() != QNetworkReply::NoError ||
+ jsonParseError.error != QJsonParseError::NoError) {
+ QString errorReason;
+ QString errorFromJson = json["error"].toString();
+ if (!errorFromJson.isEmpty()) {
+ qCWarning(lcRemoteWipe) << QString("Error returned from the server: <em>%1</em>")
+ .arg(errorFromJson.toHtmlEscaped());
+ } else if (_networkReplySuccess->error() != QNetworkReply::NoError) {
+ qCWarning(lcRemoteWipe) << QString("There was an error accessing the 'success' endpoint: <br><em>%1</em>")
+ .arg(_networkReplySuccess->errorString().toHtmlEscaped());
+ } else if (jsonParseError.error != QJsonParseError::NoError) {
+ qCWarning(lcRemoteWipe) << QString("Could not parse the JSON returned from the server: <br><em>%1</em>")
+ .arg(jsonParseError.errorString());
+ } else {
+ qCWarning(lcRemoteWipe) << QString("The reply from the server did not contain all expected fields.");
+ }
+ }
+
+ _networkReplySuccess->deleteLater();
+}
+}
--- /dev/null
+#ifndef REMOTEWIPE_H
+#define REMOTEWIPE_H
+
+#include "accountmanager.h"
+#include <QNetworkAccessManager>
+
+class QJsonDocument;
+class TestRemoteWipe;
+
+namespace OCC {
+
+class RemoteWipe : public QObject
+{
+ Q_OBJECT
+public:
+ explicit RemoteWipe(AccountPtr account, QObject *parent = nullptr);
+
+signals:
+ /**
+ * Notify if wipe was requested
+ */
+ void authorized(AccountState*);
+
+ /**
+ * Notify if user only needs to login again
+ */
+ void askUserCredentials();
+
+public slots:
+ /**
+ * Once receives a 401 or 403 status response it will do a fetch to
+ * <server>/index.php/core/wipe/check
+ */
+ void startCheckJobWithAppPassword(QString);
+
+private slots:
+ /**
+ * If wipe is requested, delete account and data, if not continue by asking
+ * the user to login again
+ */
+ void checkJobSlot();
+
+ /**
+ * Once the client has wiped all the required data a POST to
+ * <server>/index.php/core/wipe/success
+ */
+ void notifyServerSuccessJob(AccountState *accountState, bool);
+ void notifyServerSuccessJobSlot();
+
+private:
+ AccountPtr _account;
+ QString _appPassword;
+ bool _accountRemoved;
+ QNetworkAccessManager _networkManager;
+ QNetworkReply *_networkReplyCheck;
+ QNetworkReply *_networkReplySuccess;
+
+ friend class ::TestRemoteWipe;
+};
+}
+#endif // REMOTEWIPE_H
\ No newline at end of file
_appPassword = appPassword;
OwncloudWizard *ocWizard = qobject_cast<OwncloudWizard *>(wizard());
Q_ASSERT(ocWizard);
+
emit connectToOCUrl(ocWizard->account()->url().toString());
break;
}
#include <QAuthenticator>
#include <QStandardPaths>
+#include <keychain.h>
+#include "creds/abstractcredentials.h"
+
+using namespace QKeychain;
+
namespace OCC {
Q_LOGGING_CATEGORY(lcAccount, "nextcloud.sync.account", QtInfoMsg)
+const char app_password[] = "_app-password";
Account::Account(QObject *parent)
: QObject(parent)
AccountPtr acc = AccountPtr(new Account);
acc->setSharedThis(acc);
- //TODO: This probably needs to have a better
- // coupling, but it should work for now.
- acc->e2e()->setAccount(acc);
+ //TODO: This probably needs to have a better
+ // coupling, but it should work for now.
+ acc->e2e()->setAccount(acc);
+
return acc;
}
ClientSideEncryption* Account::e2e()
{
- // Qt expects everything in the connect to be a pointer, so return a pointer.
- return &_e2e;
+ // Qt expects everything in the connect to be a pointer, so return a pointer.
+ return &_e2e;
}
Account::~Account()
void Account::handleInvalidCredentials()
{
+ // Retrieving password will trigger remote wipe check job
+ retrieveAppPassword();
+
emit invalidCredentials();
}
}
}
+void Account::setAppPassword(QString appPassword){
+ const QString kck = AbstractCredentials::keychainKey(
+ url().toString(),
+ davUser() + app_password,
+ id()
+ );
+
+ WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
+ job->setInsecureFallback(false);
+ job->setKey(kck);
+ job->setBinaryData(appPassword.toLatin1());
+ connect(job, &WritePasswordJob::finished, [](Job *) {
+ qCInfo(lcAccount) << "appPassword stored in keychain";
+ });
+ job->start();
+}
+
+void Account::retrieveAppPassword(){
+ const QString kck = AbstractCredentials::keychainKey(
+ url().toString(),
+ credentials()->user() + app_password,
+ id()
+ );
+
+ ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
+ job->setInsecureFallback(false);
+ job->setKey(kck);
+ connect(job, &WritePasswordJob::finished, [this](Job *incoming) {
+ ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(incoming);
+ QString pwd("");
+ // Error or no valid public key error out
+ if (readJob->error() == NoError &&
+ readJob->binaryData().length() > 0) {
+ pwd = readJob->binaryData();
+ }
+
+ emit appPasswordRetrieved(pwd);
+ });
+ job->start();
+}
+
+void Account::deleteAppPassword(){
+ const QString kck = AbstractCredentials::keychainKey(
+ url().toString(),
+ credentials()->user() + app_password,
+ id()
+ );
+
+ if (kck.isEmpty()) {
+ qCDebug(lcAccount) << "appPassword is empty";
+ return;
+ }
+
+ DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
+ job->setInsecureFallback(false);
+ job->setKey(kck);
+ job->start();
+}
+
} // namespace OCC
class QUrl;
class QNetworkAccessManager;
+namespace QKeychain {
+class Job;
+class WritePasswordJob;
+class ReadPasswordJob;
+}
+
namespace OCC {
class AbstractCredentials;
class AccessManager;
class SimpleNetworkJob;
-
/**
* @brief Reimplement this to handle SSL errors from libsync
* @ingroup libsync
ClientSideEncryption* e2e();
+ /// Used in RemoteWipe
+ void retrieveAppPassword();
+ void setAppPassword(QString appPassword);
+ void deleteAppPassword();
+
public slots:
/// Used when forgetting credentials
void clearQNAMCache();
void accountChangedAvatar();
void accountChangedDisplayName();
+ /// Used in RemoteWipe
+ void appPasswordRetrieved(QString);
+
protected Q_SLOTS:
void slotCredentialsFetched();
void slotCredentialsAsked();
SET(FolderMan_SRC ../src/gui/folderman.cpp)
list(APPEND FolderMan_SRC ../src/gui/folder.cpp )
list(APPEND FolderMan_SRC ../src/gui/socketapi.cpp )
-list(APPEND FolderMan_SRC ../src/gui/accountstate.cpp )
list(APPEND FolderMan_SRC ../src/gui/syncrunfilelog.cpp )
list(APPEND FolderMan_SRC ../src/gui/lockwatcher.cpp )
list(APPEND FolderMan_SRC ../src/gui/guiutility.cpp )
list(APPEND FolderMan_SRC ../src/gui/navigationpanehelper.cpp )
list(APPEND FolderMan_SRC ../src/gui/connectionvalidator.cpp )
list(APPEND FolderMan_SRC ../src/gui/clientproxy.cpp )
+list(APPEND FolderMan_SRC ../src/gui/accountstate.cpp )
+list(APPEND FolderMan_SRC ../src/gui/remotewipe.cpp )
list(APPEND FolderMan_SRC ${FolderWatcher_SRC})
-list(APPEND FolderMan_SRC stub.cpp )
+list(APPEND FolderMan_SRC stubfolderman.cpp )
nextcloud_add_test(FolderMan "${FolderMan_SRC}")
+SET(RemoteWipe_SRC ../src/gui/remotewipe.cpp)
+list(APPEND RemoteWipe_SRC ../src/gui/clientproxy.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/guiutility.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/connectionvalidator.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/accountstate.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/socketapi.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/folder.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/syncrunfilelog.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/folderwatcher_linux.cpp )
+list(APPEND RemoteWipe_SRC ../src/gui/folderwatcher.cpp )
+list(APPEND RemoteWipe_SRC ${RemoteWipe_SRC})
+list(APPEND RemoteWipe_SRC stubremotewipe.cpp )
+nextcloud_add_test(RemoteWipe "${RemoteWipe_SRC}")
+
nextcloud_add_test(OAuth "syncenginetestutils.h;../src/gui/creds/oauth.cpp")
configure_file(test_journal.db "${PROJECT_BINARY_DIR}/bin/test_journal.db" COPYONLY)
+++ /dev/null
-// stub to prevent linker error
-#include "accountmanager.h"
-OCC::AccountManager *OCC::AccountManager::instance() { return static_cast<AccountManager *>(new QObject); }
-void OCC::AccountManager::saveAccountState(AccountState *) { }
-void OCC::AccountManager::save(bool saveCredentials) { Q_UNUSED(saveCredentials); }
-void OCC::AccountManager::accountRemoved(OCC::AccountState*) { }
-const QMetaObject OCC::AccountManager::staticMetaObject = QObject::staticMetaObject;
--- /dev/null
+// stub to prevent linker error
+#include "accountmanager.h"
+
+OCC::AccountManager *OCC::AccountManager::instance() { return static_cast<AccountManager *>(new QObject); }
+void OCC::AccountManager::save(bool) { }
+void OCC::AccountManager::saveAccountState(AccountState *) { }
+void OCC::AccountManager::deleteAccount(AccountState *) { }
+void OCC::AccountManager::accountRemoved(OCC::AccountState*) { }
+OCC::AccountStatePtr OCC::AccountManager::account(const QString &){ return AccountStatePtr(); }
+void OCC::AccountManager::removeAccountFolders(OCC::AccountState*) { }
+const QMetaObject OCC::AccountManager::staticMetaObject = QObject::staticMetaObject;
--- /dev/null
+// stub to prevent linker error
+#include "accountmanager.h"
+#include "accountstate.h"
+#include "socketapi.h"
+#include "folderman.h"
+
+OCC::AccountManager *OCC::AccountManager::instance() { return static_cast<AccountManager *>(new QObject); }
+void OCC::AccountManager::save(bool) { }
+OCC::AccountState *OCC::AccountManager::addAccount(const AccountPtr& ac) { return new OCC::AccountState(ac); }
+void OCC::AccountManager::deleteAccount(AccountState *) { }
+void OCC::AccountManager::accountRemoved(OCC::AccountState*) { }
+OCC::AccountStatePtr OCC::AccountManager::account(const QString &){ return AccountStatePtr(); }
+const QMetaObject OCC::AccountManager::staticMetaObject = QObject::staticMetaObject;
+
+OCC::FolderMan *OCC::FolderMan::instance() { return static_cast<FolderMan *>(new QObject); }
+void OCC::FolderMan::wipeDone(OCC::AccountState*, bool) { }
+OCC::Folder* OCC::FolderMan::addFolder(OCC::AccountState* as, OCC::FolderDefinition const &f) { return nullptr; }
+void OCC::FolderMan::slotWipeFolderForAccount(OCC::AccountState*) { }
+QString OCC::FolderMan::unescapeAlias(QString const&){ return QString(); }
+QString OCC::FolderMan::escapeAlias(QString const&){ return QString(); }
+void OCC::FolderMan::scheduleFolder(OCC::Folder*){ }
+OCC::SocketApi *OCC::FolderMan::socketApi(){ return new SocketApi; }
+OCC::Folder::Map OCC::FolderMan::map() { return OCC::Folder::Map(); }
+void OCC::FolderMan::setSyncEnabled(bool) { }
+void OCC::FolderMan::slotSyncOnceFileUnlocks(QString const&) { }
+void OCC::FolderMan::slotScheduleETagJob(QString const&, OCC::RequestEtagJob*){ }
+OCC::Folder *OCC::FolderMan::folderForPath(QString const&) { return nullptr; }
+OCC::Folder* OCC::FolderMan::folder(QString const&) { return nullptr; }
+void OCC::FolderMan::folderSyncStateChange(OCC::Folder*) { }
+const QMetaObject OCC::FolderMan::staticMetaObject = QObject::staticMetaObject;
#include "account.h"
#include "accountstate.h"
#include "configfile.h"
-#include "creds/httpcredentials.h"
+#include "testhelper.h"
using namespace OCC;
-
-class HttpCredentialsTest : public HttpCredentials {
-public:
- HttpCredentialsTest(const QString& user, const QString& password)
- : HttpCredentials(user, password)
- {}
-
- void askFromUser() Q_DECL_OVERRIDE {
-
- }
-};
-
-static FolderDefinition folderDefinition(const QString &path) {
- FolderDefinition d;
- d.localPath = path;
- d.targetPath = path;
- d.alias = path;
- return d;
-}
-
+class HttpCredentials;
class TestFolderMan: public QObject
{
--- /dev/null
+#ifndef TESTHELPER_H
+#define TESTHELPER_H
+
+#include "folder.h"
+#include "creds/httpcredentials.h"
+
+using namespace OCC;
+
+class HttpCredentialsTest : public HttpCredentials {
+public:
+ HttpCredentialsTest(const QString& user, const QString& password)
+ : HttpCredentials(user, password)
+ {}
+
+ void askFromUser() Q_DECL_OVERRIDE {
+
+ }
+};
+
+static FolderDefinition folderDefinition(const QString &path) {
+ FolderDefinition d;
+ d.localPath = path;
+ d.targetPath = path;
+ d.alias = path;
+ return d;
+}
+
+#endif // TESTHELPER_H
--- /dev/null
+/*
+ * This software is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ *
+ */
+
+#include <qglobal.h>
+#include <QTemporaryDir>
+#include <QtTest>
+
+#include "remotewipe.h"
+
+#include "common/utility.h"
+#include "folderman.h"
+#include "account.h"
+#include "accountstate.h"
+#include "configfile.h"
+
+#include "testhelper.h"
+
+using namespace OCC;
+
+class TestRemoteWipe: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ // TODO
+ void testWipe(){
+// QTemporaryDir dir;
+// ConfigFile::setConfDir(dir.path()); // we don't want to pollute the user's config file
+// QVERIFY(dir.isValid());
+
+// QDir dirToRemove(dir.path());
+// QVERIFY(dirToRemove.mkpath("nextcloud"));
+
+// QString dirPath = dirToRemove.canonicalPath();
+
+// AccountPtr account = Account::create();
+// QVERIFY(account);
+
+// auto manager = AccountManager::instance();
+// QVERIFY(manager);
+
+// AccountState *newAccountState = manager->addAccount(account);
+// manager->save();
+// QVERIFY(newAccountState);
+
+// QUrl url("http://example.de");
+// HttpCredentialsTest *cred = new HttpCredentialsTest("testuser", "secret");
+// account->setCredentials(cred);
+// account->setUrl( url );
+
+// FolderMan *folderman = FolderMan::instance();
+// folderman->addFolder(newAccountState, folderDefinition(dirPath + "/sub/nextcloud/"));
+
+// // check if account exists
+// qDebug() << "Does account exists?!";
+// QVERIFY(!account->id().isEmpty());
+
+// manager->deleteAccount(newAccountState);
+// manager->save();
+
+// // check if account exists
+// qDebug() << "Does account exists yet?!";
+// QVERIFY(account);
+
+// // check if folder exists
+// QVERIFY(dirToRemove.exists());
+
+// // remote folders
+// qDebug() << "Removing folder for account " << newAccountState->account()->url();
+
+// folderman->slotWipeFolderForAccount(newAccountState);
+
+// // check if folders dont exist anymore
+// QCOMPARE(dirToRemove.exists(), false);
+ }
+};
+
+QTEST_APPLESS_MAIN(TestRemoteWipe)
+#include "testremotewipe.moc"