Page MenuHomePhorge

D189.1732288083.diff
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

D189.1732288083.diff

diff --git a/src/matrix-sdk.hpp b/src/matrix-sdk.hpp
--- a/src/matrix-sdk.hpp
+++ b/src/matrix-sdk.hpp
@@ -12,6 +12,7 @@
#include <QString>
#include <memory>
+#include <filesystem>
#include <lager/extra/qt.hpp>
@@ -38,6 +39,8 @@
struct MatrixSdkPrivate;
+std::filesystem::path sessionDirForUserAndDeviceId(std::filesystem::path userDataDir, std::string userId, std::string deviceId);
+
class MatrixSdk : public QObject
{
Q_OBJECT
diff --git a/src/matrix-sdk.cpp b/src/matrix-sdk.cpp
--- a/src/matrix-sdk.cpp
+++ b/src/matrix-sdk.cpp
@@ -80,6 +80,14 @@
void resume() { throw std::runtime_error{"not implemented!"}; }
};
+std::filesystem::path sessionDirForUserAndDeviceId(std::filesystem::path userDataDir, std::string userId, std::string deviceId)
+{
+ auto encodedUserId = encodeBase64(userId, Base64Opts::urlSafe);
+ auto sessionDir = userDataDir / "sessions"
+ / encodedUserId / deviceId;
+ return sessionDir;
+}
+
struct MatrixSdkPrivate
{
MatrixSdkPrivate(MatrixSdk *q, bool testing, std::unique_ptr<KazvSessionLockGuard> lockGuard);
@@ -169,11 +177,10 @@
using StdPath = std::filesystem::path;
auto userDataDir = StdPath(this->userDataDir);
- auto encodedUserId = encodeBase64(userId, Base64Opts::urlSafe);
- auto sessionDir = userDataDir / "sessions"
- / encodedUserId / deviceId;
+ auto sessionDir = sessionDirForUserAndDeviceId(userDataDir, userId, deviceId);
auto storeFile = sessionDir / "store";
+ auto storeFileNew = sessionDir / "store.new";
auto metadataFile = sessionDir / "metadata";
@@ -195,18 +202,29 @@
}
}
- {
- auto storeStream = std::ofstream(storeFile);
+ try {
+ auto storeStream = std::ofstream(storeFileNew);
if (! storeStream) {
- qDebug() << "Unable to open storeFile";
+ qCWarning(kazvLog) << "Unable to open storeFile";
return;
}
using OAr = boost::archive::text_oarchive;
auto archive = OAr{storeStream};
c.serializeTo(archive);
- qDebug() << "Serialization done";
+ } catch (const std::exception &e) {
+ qCWarning(kazvLog) << "Cannot write to store file: " << e.what();
+ return;
}
+ err.clear();
+ std::filesystem::rename(storeFileNew, storeFile, err);
+ if (err) {
+ qCWarning(kazvLog) << "Cannot move storeFile into place: " << QString::fromStdString(err.message());
+ return;
+ }
+ qDebug() << "Serialization done";
+
+
// store metadata
{
KConfig metadata(QString::fromStdString(metadataFile.string()));
@@ -530,9 +548,8 @@
auto parts = sessionName.split(u'/');
if (parts.size() == 2) {
auto userId = parts[0].toStdString();
- auto sessionId = parts[1].toStdString();
- auto encodedUserId = encodeBase64(userId, Base64Opts::urlSafe);
- auto sessionDir = userDataDir / "sessions" / encodedUserId / sessionId;
+ auto deviceId = parts[1].toStdString();
+ auto sessionDir = sessionDirForUserAndDeviceId(userDataDir, userId, deviceId);
try {
lockGuard = std::make_unique<KazvSessionLockGuard>(sessionDir);
} catch (const std::runtime_error &e) {
@@ -552,16 +569,14 @@
auto parts = sessionName.split(u'/');
if (parts.size() == 2) {
auto userId = parts[0].toStdString();
- auto sessionId = parts[1].toStdString();
- auto encodedUserId = encodeBase64(userId, Base64Opts::urlSafe);
- qCDebug(kazvLog) << "trying new path";
- auto sessionDir = userDataDir / "sessions" / encodedUserId / sessionId;
+ auto deviceId = parts[1].toStdString();
+ auto sessionDir = sessionDirForUserAndDeviceId(userDataDir, userId, deviceId);
if (std::filesystem::exists(sessionDir)) {
qCDebug(kazvLog) << "new path works";
return std::filesystem::remove_all(sessionDir);
}
qCDebug(kazvLog) << "trying legacy path";
- auto legacySessionDir = userDataDir / "sessions" / userId / sessionId;
+ auto legacySessionDir = userDataDir / "sessions" / userId / deviceId;
if (std::filesystem::exists(legacySessionDir)) {
qCDebug(kazvLog) << "legacy path works";
return std::filesystem::remove_all(legacySessionDir);
diff --git a/src/tests/matrix-sdk-sessions-test.hpp b/src/tests/matrix-sdk-sessions-test.hpp
--- a/src/tests/matrix-sdk-sessions-test.hpp
+++ b/src/tests/matrix-sdk-sessions-test.hpp
@@ -44,4 +44,5 @@
void testListLegacySessions();
void testLoadSession();
void testSessionLock();
+ void testSaveSessionFailure();
};
diff --git a/src/tests/matrix-sdk-sessions-test.cpp b/src/tests/matrix-sdk-sessions-test.cpp
--- a/src/tests/matrix-sdk-sessions-test.cpp
+++ b/src/tests/matrix-sdk-sessions-test.cpp
@@ -136,6 +136,60 @@
#endif
}
+void MatrixSdkSessionsTest::testSaveSessionFailure()
+{
+#if KAZV_IS_WINDOWS
+ QSKIP("Skipping because session the condition cannot be easily satisfied on Windows");
+#endif
+
+ auto userId = std::string("@mew:example.com");
+ auto deviceId = std::string("device1");
+ createSession(userId, deviceId);
+
+ auto sessionDir = sessionDirForUserAndDeviceId(Fs::path(m_userDataDir), userId, deviceId);
+ // there is store, metadata and lock under the sessionDir
+
+ std::error_code err;
+ // make the sessionDir readonly, so that new file cannot be created
+ Fs::permissions(
+ sessionDir,
+ Fs::perms::owner_read | Fs::perms::owner_exec,
+ Fs::perm_options::replace,
+ err);
+ QVERIFY(!err);
+ err.clear();
+
+ // a model that is slightly different from the original one
+ SdkModel model;
+ model.client.userId = userId;
+ model.client.deviceId = deviceId;
+ model.client.serverUrl = "https://example.com";
+
+ {
+ auto sdk = makeMatrixSdk(model, /* testing = */ false);
+ // this should fail
+ sdk->serializeToFile();
+ }
+ // Not ideal, but this is the only way to wait for
+ // MatrixSdkPravite to be destroyed.
+ QTest::qWait(100);
+
+ auto sdk = makeMatrixSdk();
+ auto res = sdk->loadSession(QString::fromStdString(userId + "/" + deviceId));
+ QCOMPARE(res, MatrixSdk::SessionLoadSuccess);
+ // verify that the original data is kept
+ QCOMPARE(sdk->serverUrl(), u""_s);
+
+ // before cleaning up, add write permissions back so the files can be removed
+ Fs::permissions(
+ sessionDir,
+ Fs::perms::owner_read | Fs::perms::owner_write | Fs::perms::owner_exec,
+ Fs::perm_options::replace,
+ err);
+ QVERIFY(!err);
+ err.clear();
+}
+
#ifndef MATRIX_SDK_SESSIONS_TEST_NO_MAIN
QTEST_MAIN(MatrixSdkSessionsTest)
#endif

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 22, 7:08 AM (4 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38890
Default Alt Text
D189.1732288083.diff (6 KB)

Event Timeline