summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-09-18 11:40:41 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-09-18 11:40:45 +0200
commita7e7f7fdd2a9d38921476d57f305c9cd4459a556 (patch)
treed9ad3bdc3e275004a54f508025f0d52227ab18cb
parentea2e02ad656640c17d520b5a22c168c3c1faef56 (diff)
downloadsink-a7e7f7fdd2a9d38921476d57f305c9cd4459a556.tar.gz
sink-a7e7f7fdd2a9d38921476d57f305c9cd4459a556.zip
Avoid storing the password in the configuration
The password (or any other secret), is now cached in the client process (in-memory only), and delivered to the resource via command. The resource avoids doing any operations against the source until the secret is available.
-rw-r--r--common/CMakeLists.txt3
-rw-r--r--common/commands.h1
-rw-r--r--common/commands/secret.fbs7
-rw-r--r--common/domain/applicationdomaintype.h1
-rw-r--r--common/genericresource.cpp7
-rw-r--r--common/genericresource.h2
-rw-r--r--common/listener.cpp12
-rw-r--r--common/resource.cpp5
-rw-r--r--common/resource.h2
-rw-r--r--common/resourceaccess.cpp22
-rw-r--r--common/resourceaccess.h6
-rw-r--r--common/secretstore.cpp51
-rw-r--r--common/secretstore.h50
-rw-r--r--common/synchronizer.cpp18
-rw-r--r--common/synchronizer.h5
-rw-r--r--examples/davresource/davresource.cpp30
-rw-r--r--examples/davresource/davresource.h5
-rw-r--r--examples/dummyresource/resourcefactory.cpp2
-rw-r--r--examples/imapresource/imapresource.cpp16
-rw-r--r--examples/imapresource/imapserverproxy.cpp3
-rw-r--r--examples/imapresource/imapserverproxy.h1
-rw-r--r--examples/maildirresource/maildirresource.cpp2
22 files changed, 226 insertions, 25 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 8421fc2..b0e0d04 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -33,6 +33,7 @@ set(storage_LIBS lmdb)
33 33
34set(command_SRCS 34set(command_SRCS
35 store.cpp 35 store.cpp
36 secretstore.cpp
36 notifier.cpp 37 notifier.cpp
37 resourcecontrol.cpp 38 resourcecontrol.cpp
38 modelresult.cpp 39 modelresult.cpp
@@ -97,6 +98,7 @@ generate_flatbuffers(
97 commands/revisionreplayed 98 commands/revisionreplayed
98 commands/inspection 99 commands/inspection
99 commands/flush 100 commands/flush
101 commands/secret
100 domain/contact 102 domain/contact
101 domain/addressbook 103 domain/addressbook
102 domain/event 104 domain/event
@@ -144,6 +146,7 @@ install(FILES
144 test.h 146 test.h
145 log.h 147 log.h
146 flush.h 148 flush.h
149 secretstore.h
147 ${CMAKE_CURRENT_BINARY_DIR}/sink_export.h 150 ${CMAKE_CURRENT_BINARY_DIR}/sink_export.h
148 DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME} COMPONENT Devel 151 DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME} COMPONENT Devel
149) 152)
diff --git a/common/commands.h b/common/commands.h
index 1548eac..8ced268 100644
--- a/common/commands.h
+++ b/common/commands.h
@@ -48,6 +48,7 @@ enum CommandIds
48 InspectionCommand, 48 InspectionCommand,
49 RemoveFromDiskCommand, 49 RemoveFromDiskCommand,
50 FlushCommand, 50 FlushCommand,
51 SecretCommand,
51 CustomCommand = 0xffff 52 CustomCommand = 0xffff
52}; 53};
53 54
diff --git a/common/commands/secret.fbs b/common/commands/secret.fbs
new file mode 100644
index 0000000..5bb2246
--- /dev/null
+++ b/common/commands/secret.fbs
@@ -0,0 +1,7 @@
1namespace Sink.Commands;
2
3table Secret {
4 secret: string;
5}
6
7root_type Secret;
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index f7fd07e..de2b5c9 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -102,6 +102,7 @@ enum SINK_EXPORT ErrorCode {
102 ConfigurationError, 102 ConfigurationError,
103 TransmissionError, 103 TransmissionError,
104 ConnectionLostError, 104 ConnectionLostError,
105 MissingCredentialsError
105}; 106};
106 107
107enum SINK_EXPORT SuccessCode { 108enum SINK_EXPORT SuccessCode {
diff --git a/common/genericresource.cpp b/common/genericresource.cpp
index 7178b3d..b6a8f62 100644
--- a/common/genericresource.cpp
+++ b/common/genericresource.cpp
@@ -45,6 +45,13 @@ GenericResource::~GenericResource()
45{ 45{
46} 46}
47 47
48void GenericResource::setSecret(const QString &s)
49{
50 if (mSynchronizer) {
51 mSynchronizer->setSecret(s);
52 }
53}
54
48void GenericResource::setupPreprocessors(const QByteArray &type, const QVector<Sink::Preprocessor *> &preprocessors) 55void GenericResource::setupPreprocessors(const QByteArray &type, const QVector<Sink::Preprocessor *> &preprocessors)
49{ 56{
50 mPipeline->setPreprocessors(type, preprocessors); 57 mPipeline->setPreprocessors(type, preprocessors);
diff --git a/common/genericresource.h b/common/genericresource.h
index bffc697..4e86b75 100644
--- a/common/genericresource.h
+++ b/common/genericresource.h
@@ -47,6 +47,8 @@ public:
47 static void removeFromDisk(const QByteArray &instanceIdentifier); 47 static void removeFromDisk(const QByteArray &instanceIdentifier);
48 static qint64 diskUsage(const QByteArray &instanceIdentifier); 48 static qint64 diskUsage(const QByteArray &instanceIdentifier);
49 49
50 virtual void setSecret(const QString &s) Q_DECL_OVERRIDE;
51
50 //TODO Remove this API, it's only used in tests 52 //TODO Remove this API, it's only used in tests
51 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query); 53 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query);
52 //TODO Remove this API, it's only used in tests 54 //TODO Remove this API, it's only used in tests
diff --git a/common/listener.cpp b/common/listener.cpp
index c9fd9d3..c6747cd 100644
--- a/common/listener.cpp
+++ b/common/listener.cpp
@@ -33,6 +33,7 @@
33#include "common/revisionupdate_generated.h" 33#include "common/revisionupdate_generated.h"
34#include "common/notification_generated.h" 34#include "common/notification_generated.h"
35#include "common/revisionreplayed_generated.h" 35#include "common/revisionreplayed_generated.h"
36#include "common/secret_generated.h"
36 37
37#include <QLocalServer> 38#include <QLocalServer>
38#include <QLocalSocket> 39#include <QLocalSocket>
@@ -240,6 +241,17 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
240 } 241 }
241 break; 242 break;
242 } 243 }
244 case Sink::Commands::SecretCommand: {
245 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size());
246 if (Sink::Commands::VerifySecretBuffer(verifier)) {
247 auto buffer = Sink::Commands::GetSecret(commandBuffer.constData());
248 loadResource().setSecret(QString{buffer->secret()->c_str()});
249 } else {
250 SinkWarning() << "received invalid command";
251 }
252 break;
253 }
254
243 case Sink::Commands::SynchronizeCommand: 255 case Sink::Commands::SynchronizeCommand:
244 case Sink::Commands::InspectionCommand: 256 case Sink::Commands::InspectionCommand:
245 case Sink::Commands::DeleteEntityCommand: 257 case Sink::Commands::DeleteEntityCommand:
diff --git a/common/resource.cpp b/common/resource.cpp
index 804f0bf..78cc51b 100644
--- a/common/resource.cpp
+++ b/common/resource.cpp
@@ -51,6 +51,11 @@ void Resource::setLowerBoundRevision(qint64 revision)
51 Q_UNUSED(revision) 51 Q_UNUSED(revision)
52} 52}
53 53
54void Resource::setSecret(const QString &s)
55{
56 Q_UNUSED(s)
57}
58
54 59
55class ResourceFactory::Private 60class ResourceFactory::Private
56{ 61{
diff --git a/common/resource.h b/common/resource.h
index a50ffb5..938f267 100644
--- a/common/resource.h
+++ b/common/resource.h
@@ -47,6 +47,8 @@ public:
47 */ 47 */
48 virtual void setLowerBoundRevision(qint64 revision); 48 virtual void setLowerBoundRevision(qint64 revision);
49 49
50 virtual void setSecret(const QString &s);
51
50signals: 52signals:
51 void revisionUpdated(qint64); 53 void revisionUpdated(qint64);
52 void notify(Notification); 54 void notify(Notification);
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp
index 35fa46c..5ed3609 100644
--- a/common/resourceaccess.cpp
+++ b/common/resourceaccess.cpp
@@ -32,9 +32,11 @@
32#include "common/revisionreplayed_generated.h" 32#include "common/revisionreplayed_generated.h"
33#include "common/inspection_generated.h" 33#include "common/inspection_generated.h"
34#include "common/flush_generated.h" 34#include "common/flush_generated.h"
35#include "common/secret_generated.h"
35#include "common/entitybuffer.h" 36#include "common/entitybuffer.h"
36#include "common/bufferutils.h" 37#include "common/bufferutils.h"
37#include "common/test.h" 38#include "common/test.h"
39#include "common/secretstore.h"
38#include "log.h" 40#include "log.h"
39 41
40#include <QCoreApplication> 42#include <QCoreApplication>
@@ -234,6 +236,12 @@ ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier, con
234{ 236{
235 mResourceStatus = Sink::ApplicationDomain::NoStatus; 237 mResourceStatus = Sink::ApplicationDomain::NoStatus;
236 SinkTrace() << "Starting access"; 238 SinkTrace() << "Starting access";
239
240 QObject::connect(&SecretStore::instance(), &SecretStore::secretAvailable, this, [this] (const QByteArray &resourceId) {
241 if (resourceId == d->resourceInstanceIdentifier) {
242 sendSecret(SecretStore::instance().resourceSecret(d->resourceInstanceIdentifier)).exec();
243 }
244 });
237} 245}
238 246
239ResourceAccess::~ResourceAccess() 247ResourceAccess::~ResourceAccess()
@@ -387,6 +395,15 @@ KAsync::Job<void> ResourceAccess::sendFlushCommand(int flushType, const QByteArr
387 return sendCommand(Sink::Commands::FlushCommand, fbb); 395 return sendCommand(Sink::Commands::FlushCommand, fbb);
388} 396}
389 397
398KAsync::Job<void> ResourceAccess::sendSecret(const QString &secret)
399{
400 flatbuffers::FlatBufferBuilder fbb;
401 auto s = fbb.CreateString(secret.toStdString());
402 auto location = Sink::Commands::CreateSecret(fbb, s);
403 Sink::Commands::FinishSecretBuffer(fbb, location);
404 return sendCommand(Sink::Commands::SecretCommand, fbb);
405}
406
390void ResourceAccess::open() 407void ResourceAccess::open()
391{ 408{
392 if (d->socket && d->socket->isValid()) { 409 if (d->socket && d->socket->isValid()) {
@@ -483,6 +500,11 @@ void ResourceAccess::connected()
483 Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb); 500 Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb);
484 } 501 }
485 502
503 auto secret = SecretStore::instance().resourceSecret(d->resourceInstanceIdentifier);
504 if (!secret.isEmpty()) {
505 sendSecret(secret).exec();
506 }
507
486 // Reenqueue pending commands, we failed to send them 508 // Reenqueue pending commands, we failed to send them
487 processPendingCommandQueue(); 509 processPendingCommandQueue();
488 // Send queued commands 510 // Send queued commands
diff --git a/common/resourceaccess.h b/common/resourceaccess.h
index b6a0b34..890cc6d 100644
--- a/common/resourceaccess.h
+++ b/common/resourceaccess.h
@@ -80,6 +80,11 @@ public:
80 return KAsync::null<void>(); 80 return KAsync::null<void>();
81 } 81 }
82 82
83 virtual KAsync::Job<void> sendSecret(const QString &secret)
84 {
85 return KAsync::null<void>();
86 }
87
83 int getResourceStatus() const 88 int getResourceStatus() const
84 { 89 {
85 return mResourceStatus; 90 return mResourceStatus;
@@ -121,6 +126,7 @@ public:
121 KAsync::Job<void> 126 KAsync::Job<void>
122 sendInspectionCommand(int inspectionType,const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE; 127 sendInspectionCommand(int inspectionType,const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE;
123 KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId) Q_DECL_OVERRIDE; 128 KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId) Q_DECL_OVERRIDE;
129 KAsync::Job<void> sendSecret(const QString &secret) Q_DECL_OVERRIDE;
124 /** 130 /**
125 * Tries to connect to server, and returns a connected socket on success. 131 * Tries to connect to server, and returns a connected socket on success.
126 */ 132 */
diff --git a/common/secretstore.cpp b/common/secretstore.cpp
new file mode 100644
index 0000000..39d5206
--- /dev/null
+++ b/common/secretstore.cpp
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "secretstore.h"
22
23#include <QGlobalStatic>
24#include <QMap>
25#include <QString>
26#include <QMutexLocker>
27
28using namespace Sink;
29
30QMutex SecretStore::sMutex;
31
32SecretStore &SecretStore::instance()
33{
34 static SecretStore s;
35 return s;
36}
37
38void SecretStore::insert(const QByteArray &resourceId, const QString &secret)
39{
40 QMutexLocker locker{&sMutex};
41 mCache.insert(resourceId, secret);
42 locker.unlock();
43 emit secretAvailable(resourceId);
44}
45
46QString SecretStore::resourceSecret(const QByteArray &resourceId)
47{
48 QMutexLocker locker{&sMutex};
49 return mCache.value(resourceId);
50}
51
diff --git a/common/secretstore.h b/common/secretstore.h
new file mode 100644
index 0000000..04fdaba
--- /dev/null
+++ b/common/secretstore.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
23#include "sink_export.h"
24
25#include <QObject>
26#include <QString>
27#include <QMap>
28#include <QMutex>
29
30namespace Sink {
31
32class SINK_EXPORT SecretStore : public QObject
33{
34 Q_OBJECT
35public:
36 static SecretStore &instance();
37
38 void insert(const QByteArray &resourceId, const QString &secret);
39 QString resourceSecret(const QByteArray &resourceId);
40
41Q_SIGNALS:
42 void secretAvailable(const QByteArray &resourceId);
43
44private:
45 QMap<QByteArray, QString> mCache;
46 static QMutex sMutex;
47};
48
49}
50
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index 959cf48..4a0ac46 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -49,6 +49,20 @@ Synchronizer::~Synchronizer()
49 49
50} 50}
51 51
52void Synchronizer::setSecret(const QString &s)
53{
54 mSecret = s;
55
56 if (!mSyncRequestQueue.isEmpty()) {
57 processSyncQueue().exec();
58 }
59}
60
61QString Synchronizer::secret() const
62{
63 return mSecret;
64}
65
52void Synchronizer::setup(const std::function<void(int commandId, const QByteArray &data)> &enqueueCommandCallback, MessageQueue &mq) 66void Synchronizer::setup(const std::function<void(int commandId, const QByteArray &data)> &enqueueCommandCallback, MessageQueue &mq)
53{ 67{
54 mEnqueue = enqueueCommandCallback; 68 mEnqueue = enqueueCommandCallback;
@@ -474,6 +488,10 @@ void Synchronizer::setBusy(bool busy, const QString &reason, const QByteArray re
474 488
475KAsync::Job<void> Synchronizer::processSyncQueue() 489KAsync::Job<void> Synchronizer::processSyncQueue()
476{ 490{
491 if (secret().isEmpty()) {
492 SinkLogCtx(mLogCtx) << "Secret not available but required.";
493 return KAsync::null<void>();
494 }
477 if (mSyncRequestQueue.isEmpty()) { 495 if (mSyncRequestQueue.isEmpty()) {
478 SinkLogCtx(mLogCtx) << "All requests processed."; 496 SinkLogCtx(mLogCtx) << "All requests processed.";
479 return KAsync::null<void>(); 497 return KAsync::null<void>();
diff --git a/common/synchronizer.h b/common/synchronizer.h
index cc082be..bd03ba3 100644
--- a/common/synchronizer.h
+++ b/common/synchronizer.h
@@ -60,6 +60,8 @@ public:
60 bool allChangesReplayed() Q_DECL_OVERRIDE; 60 bool allChangesReplayed() Q_DECL_OVERRIDE;
61 void flushComplete(const QByteArray &flushId); 61 void flushComplete(const QByteArray &flushId);
62 62
63 void setSecret(const QString &s);
64
63signals: 65signals:
64 void notify(Notification); 66 void notify(Notification);
65 67
@@ -78,6 +80,8 @@ protected:
78 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 80 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
79 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 81 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
80protected: 82protected:
83 QString secret() const;
84
81 ///Calls the callback to enqueue the command 85 ///Calls the callback to enqueue the command
82 void enqueueCommand(int commandId, const QByteArray &data); 86 void enqueueCommand(int commandId, const QByteArray &data);
83 87
@@ -224,6 +228,7 @@ private:
224 MessageQueue *mMessageQueue; 228 MessageQueue *mMessageQueue;
225 bool mSyncInProgress; 229 bool mSyncInProgress;
226 QMultiHash<QByteArray, SyncRequest> mPendingSyncRequests; 230 QMultiHash<QByteArray, SyncRequest> mPendingSyncRequests;
231 QString mSecret;
227}; 232};
228 233
229} 234}
diff --git a/examples/davresource/davresource.cpp b/examples/davresource/davresource.cpp
index 22c502f..fa5e612 100644
--- a/examples/davresource/davresource.cpp
+++ b/examples/davresource/davresource.cpp
@@ -132,8 +132,8 @@ public:
132 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE 132 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE
133 { 133 {
134 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) { 134 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Addressbook>()) {
135 SinkLogCtx(mLogCtx) << "Synchronizing addressbooks:" << mResourceUrl.url(); 135 SinkLogCtx(mLogCtx) << "Synchronizing addressbooks:" << resourceUrl().url();
136 auto collectionsFetchJob = new KDAV2::DavCollectionsFetchJob(mResourceUrl); 136 auto collectionsFetchJob = new KDAV2::DavCollectionsFetchJob(resourceUrl());
137 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) { 137 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] (const KAsync::Error &error) {
138 if (error) { 138 if (error) {
139 SinkWarningCtx(mLogCtx) << "Failed to synchronize addressbooks." << collectionsFetchJob->errorString(); 139 SinkWarningCtx(mLogCtx) << "Failed to synchronize addressbooks." << collectionsFetchJob->errorString();
@@ -147,7 +147,7 @@ public:
147 auto ridList = QSharedPointer<QByteArrayList>::create(); 147 auto ridList = QSharedPointer<QByteArrayList>::create();
148 auto total = QSharedPointer<int>::create(0); 148 auto total = QSharedPointer<int>::create(0);
149 auto progress = QSharedPointer<int>::create(0); 149 auto progress = QSharedPointer<int>::create(0);
150 auto collectionsFetchJob = new KDAV2::DavCollectionsFetchJob(mResourceUrl); 150 auto collectionsFetchJob = new KDAV2::DavCollectionsFetchJob(resourceUrl());
151 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] { 151 auto job = runJob(collectionsFetchJob).then([this, collectionsFetchJob] {
152 synchronizeAddressbooks(collectionsFetchJob ->collections()); 152 synchronizeAddressbooks(collectionsFetchJob ->collections());
153 return collectionsFetchJob->collections(); 153 return collectionsFetchJob->collections();
@@ -233,8 +233,20 @@ KAsync::Job<QByteArray> replay(const ApplicationDomain::Contact &contact, Sink::
233 return KAsync::null<QByteArray>(); 233 return KAsync::null<QByteArray>();
234 } 234 }
235 235
236 KDAV2::DavUrl resourceUrl() const
237 {
238 if (secret().isEmpty()) {
239 return {};
240 }
241 auto resourceUrl = mServer;
242 resourceUrl.setUserName(mUsername);
243 resourceUrl.setPassword(secret());
244 return KDAV2::DavUrl{resourceUrl, KDAV2::CardDav};
245 }
246
236public: 247public:
237 KDAV2::DavUrl mResourceUrl; 248 QUrl mServer;
249 QString mUsername;
238}; 250};
239 251
240 252
@@ -242,14 +254,12 @@ DavResource::DavResource(const Sink::ResourceContext &resourceContext)
242 : Sink::GenericResource(resourceContext) 254 : Sink::GenericResource(resourceContext)
243{ 255{
244 auto config = ResourceConfig::getConfiguration(resourceContext.instanceId()); 256 auto config = ResourceConfig::getConfiguration(resourceContext.instanceId());
245 auto resourceUrl = QUrl::fromUserInput(config.value("server").toString()); 257 auto server = QUrl::fromUserInput(config.value("server").toString());
246 resourceUrl.setUserName(config.value("username").toString()); 258 auto username = config.value("username").toString();
247 resourceUrl.setPassword(config.value("password").toString());
248
249 mResourceUrl = KDAV2::DavUrl(resourceUrl, KDAV2::CardDav);
250 259
251 auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext); 260 auto synchronizer = QSharedPointer<ContactSynchronizer>::create(resourceContext);
252 synchronizer->mResourceUrl = mResourceUrl; 261 synchronizer->mServer = server;
262 synchronizer->mUsername = username;
253 setupSynchronizer(synchronizer); 263 setupSynchronizer(synchronizer);
254 264
255 setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor); 265 setupPreprocessors(ENTITY_TYPE_CONTACT, QVector<Sink::Preprocessor*>() << new ContactPropertyExtractor);
diff --git a/examples/davresource/davresource.h b/examples/davresource/davresource.h
index db175a4..b4f9e5a 100644
--- a/examples/davresource/davresource.h
+++ b/examples/davresource/davresource.h
@@ -44,11 +44,6 @@ class DavResource : public Sink::GenericResource
44{ 44{
45public: 45public:
46 DavResource(const Sink::ResourceContext &resourceContext); 46 DavResource(const Sink::ResourceContext &resourceContext);
47
48private:
49 QStringList listAvailableFolders();
50
51 KDAV2::DavUrl mResourceUrl;
52}; 47};
53 48
54class DavResourceFactory : public Sink::ResourceFactory 49class DavResourceFactory : public Sink::ResourceFactory
diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp
index dffdfc9..f3c8be2 100644
--- a/examples/dummyresource/resourcefactory.cpp
+++ b/examples/dummyresource/resourcefactory.cpp
@@ -50,7 +50,7 @@ class DummySynchronizer : public Sink::Synchronizer {
50 DummySynchronizer(const Sink::ResourceContext &context) 50 DummySynchronizer(const Sink::ResourceContext &context)
51 : Sink::Synchronizer(context) 51 : Sink::Synchronizer(context)
52 { 52 {
53 53 setSecret("dummy");
54 } 54 }
55 55
56 Sink::ApplicationDomain::Event::Ptr createEvent(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data) 56 Sink::ApplicationDomain::Event::Ptr createEvent(const QByteArray &ridBuffer, const QMap<QString, QVariant> &data)
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 3ae7fd7..2aba6b0 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -470,7 +470,7 @@ public:
470 { 470 {
471 SinkTrace() << "Connecting to:" << mServer << mPort; 471 SinkTrace() << "Connecting to:" << mServer << mPort;
472 SinkTrace() << "as:" << mUser; 472 SinkTrace() << "as:" << mUser;
473 return imap->login(mUser, mPassword) 473 return imap->login(mUser, secret())
474 .addToContext(imap); 474 .addToContext(imap);
475 } 475 }
476 476
@@ -513,6 +513,8 @@ public:
513 return {ApplicationDomain::NoServerError, error.errorMessage}; 513 return {ApplicationDomain::NoServerError, error.errorMessage};
514 case Imap::ConnectionLost: 514 case Imap::ConnectionLost:
515 return {ApplicationDomain::ConnectionLostError, error.errorMessage}; 515 return {ApplicationDomain::ConnectionLostError, error.errorMessage};
516 case Imap::MissingCredentialsError:
517 return {ApplicationDomain::MissingCredentialsError, error.errorMessage};
516 default: 518 default:
517 return {ApplicationDomain::UnknownError, error.errorMessage}; 519 return {ApplicationDomain::UnknownError, error.errorMessage};
518 } 520 }
@@ -631,7 +633,7 @@ public:
631 } 633 }
632 } 634 }
633 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache); 635 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache);
634 auto login = imap->login(mUser, mPassword); 636 auto login = imap->login(mUser, secret());
635 KAsync::Job<QByteArray> job = KAsync::null<QByteArray>(); 637 KAsync::Job<QByteArray> job = KAsync::null<QByteArray>();
636 if (operation == Sink::Operation_Creation) { 638 if (operation == Sink::Operation_Creation) {
637 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 639 const QString mailbox = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
@@ -716,7 +718,7 @@ public:
716 } 718 }
717 } 719 }
718 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache); 720 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache);
719 auto login = imap->login(mUser, mPassword); 721 auto login = imap->login(mUser, secret());
720 if (operation == Sink::Operation_Creation) { 722 if (operation == Sink::Operation_Creation) {
721 QString parentFolder; 723 QString parentFolder;
722 if (!folder.getParent().isEmpty()) { 724 if (!folder.getParent().isEmpty()) {
@@ -736,7 +738,7 @@ public:
736 }); 738 });
737 } else { //We try to merge special purpose folders first 739 } else { //We try to merge special purpose folders first
738 auto specialPurposeFolders = QSharedPointer<QHash<QByteArray, QString>>::create(); 740 auto specialPurposeFolders = QSharedPointer<QHash<QByteArray, QString>>::create();
739 auto mergeJob = imap->login(mUser, mPassword) 741 auto mergeJob = imap->login(mUser, secret())
740 .then(imap->fetchFolders([=](const Imap::Folder &folder) { 742 .then(imap->fetchFolders([=](const Imap::Folder &folder) {
741 if (SpecialPurpose::isSpecialPurposeFolderName(folder.name())) { 743 if (SpecialPurpose::isSpecialPurposeFolderName(folder.name())) {
742 specialPurposeFolders->insert(SpecialPurpose::getSpecialPurposeType(folder.name()), folder.path()); 744 specialPurposeFolders->insert(SpecialPurpose::getSpecialPurposeType(folder.name()), folder.path());
@@ -790,7 +792,6 @@ public:
790 QString mServer; 792 QString mServer;
791 int mPort; 793 int mPort;
792 QString mUser; 794 QString mUser;
793 QString mPassword;
794 int mDaysToSync = 0; 795 int mDaysToSync = 0;
795 QByteArray mResourceInstanceIdentifier; 796 QByteArray mResourceInstanceIdentifier;
796 Imap::SessionCache mSessionCache; 797 Imap::SessionCache mSessionCache;
@@ -959,7 +960,6 @@ ImapResource::ImapResource(const ResourceContext &resourceContext)
959 auto server = config.value("server").toString(); 960 auto server = config.value("server").toString();
960 auto port = config.value("port").toInt(); 961 auto port = config.value("port").toInt();
961 auto user = config.value("username").toString(); 962 auto user = config.value("username").toString();
962 auto password = config.value("password").toString();
963 if (server.startsWith("imap")) { 963 if (server.startsWith("imap")) {
964 server.remove("imap://"); 964 server.remove("imap://");
965 server.remove("imaps://"); 965 server.remove("imaps://");
@@ -974,7 +974,6 @@ ImapResource::ImapResource(const ResourceContext &resourceContext)
974 synchronizer->mServer = server; 974 synchronizer->mServer = server;
975 synchronizer->mPort = port; 975 synchronizer->mPort = port;
976 synchronizer->mUser = user; 976 synchronizer->mUser = user;
977 synchronizer->mPassword = password;
978 synchronizer->mDaysToSync = 14; 977 synchronizer->mDaysToSync = 14;
979 setupSynchronizer(synchronizer); 978 setupSynchronizer(synchronizer);
980 979
@@ -982,7 +981,8 @@ ImapResource::ImapResource(const ResourceContext &resourceContext)
982 inspector->mServer = server; 981 inspector->mServer = server;
983 inspector->mPort = port; 982 inspector->mPort = port;
984 inspector->mUser = user; 983 inspector->mUser = user;
985 inspector->mPassword = password; 984 //TODO
985 // inspector->mPassword = password;
986 setupInspector(inspector); 986 setupInspector(inspector);
987 987
988 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor << new MailPropertyExtractor); 988 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor << new MailPropertyExtractor);
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp
index 16887b1..317fbdc 100644
--- a/examples/imapresource/imapserverproxy.cpp
+++ b/examples/imapresource/imapserverproxy.cpp
@@ -139,6 +139,9 @@ ImapServerProxy::ImapServerProxy(const QString &serverUrl, int port, SessionCach
139 139
140KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString &password) 140KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString &password)
141{ 141{
142 if (password.isEmpty()) {
143 return KAsync::error(Imap::MissingCredentialsError);
144 }
142 if (mSessionCache) { 145 if (mSessionCache) {
143 auto session = mSessionCache->getSession(); 146 auto session = mSessionCache->getSession();
144 if (session.isValid()) { 147 if (session.isValid()) {
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h
index 86e3378..9e73f68 100644
--- a/examples/imapresource/imapserverproxy.h
+++ b/examples/imapresource/imapserverproxy.h
@@ -35,6 +35,7 @@ enum ErrorCode {
35 CouldNotConnectError, 35 CouldNotConnectError,
36 SslHandshakeError, 36 SslHandshakeError,
37 ConnectionLost, 37 ConnectionLost,
38 MissingCredentialsError,
38 UnknownError 39 UnknownError
39}; 40};
40 41
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp
index b406f63..41f2433 100644
--- a/examples/maildirresource/maildirresource.cpp
+++ b/examples/maildirresource/maildirresource.cpp
@@ -215,7 +215,7 @@ public:
215 MaildirSynchronizer(const Sink::ResourceContext &resourceContext) 215 MaildirSynchronizer(const Sink::ResourceContext &resourceContext)
216 : Sink::Synchronizer(resourceContext) 216 : Sink::Synchronizer(resourceContext)
217 { 217 {
218 218 setSecret("dummy");
219 } 219 }
220 220
221 static QStringList listRecursive( const QString &root, const KPIM::Maildir &dir ) 221 static QStringList listRecursive( const QString &root, const KPIM::Maildir &dir )