testsecurefiledrop.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * This software is in the public domain, furnished "as is", without technical
  3. * support, and with no warranty, express or implied, as to its usefulness for
  4. * any purpose.
  5. *
  6. */
  7. #include "updatefiledropmetadata.h"
  8. #include "syncengine.h"
  9. #include "syncenginetestutils.h"
  10. #include "testhelper.h"
  11. #include "owncloudpropagator_p.h"
  12. #include "propagatorjobs.h"
  13. #include "clientsideencryption.h"
  14. #include <QtTest>
  15. namespace
  16. {
  17. constexpr auto fakeE2eeFolderName = "fake_e2ee_folder";
  18. const QString fakeE2eeFolderPath = QStringLiteral("/") + fakeE2eeFolderName;
  19. };
  20. using namespace OCC;
  21. class TestSecureFileDrop : public QObject
  22. {
  23. Q_OBJECT
  24. FakeFolder _fakeFolder{FileInfo()};
  25. QSharedPointer<OwncloudPropagator> _propagator;
  26. QScopedPointer<FolderMetadata> _parsedMetadataWithFileDrop;
  27. QScopedPointer<FolderMetadata> _parsedMetadataAfterProcessingFileDrop;
  28. int _lockCallsCount = 0;
  29. int _unlockCallsCount = 0;
  30. int _propFindCallsCount = 0;
  31. int _getMetadataCallsCount = 0;
  32. int _putMetadataCallsCount = 0;
  33. private slots:
  34. void initTestCase()
  35. {
  36. _fakeFolder.remoteModifier().mkdir(fakeE2eeFolderName);
  37. _fakeFolder.remoteModifier().insert(fakeE2eeFolderName + QStringLiteral("/") + QStringLiteral("fake_e2ee_file"), 100);
  38. _fakeFolder.setServerOverride([this](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *device) {
  39. Q_UNUSED(device);
  40. QNetworkReply *reply = nullptr;
  41. const auto path = req.url().path();
  42. if (path.contains(QStringLiteral("/end_to_end_encryption/api/v1/lock/"))) {
  43. if (op == QNetworkAccessManager::DeleteOperation) {
  44. reply = new FakePayloadReply(op, req, {}, nullptr);
  45. ++_unlockCallsCount;
  46. } else if (op == QNetworkAccessManager::PostOperation) {
  47. QFile fakeJsonReplyFile(QStringLiteral("fake2eelocksucceeded.json"));
  48. if (fakeJsonReplyFile.open(QFile::ReadOnly)) {
  49. const auto jsonDoc = QJsonDocument::fromJson(fakeJsonReplyFile.readAll());
  50. reply = new FakePayloadReply(op, req, jsonDoc.toJson(), nullptr);
  51. ++_lockCallsCount;
  52. } else {
  53. qCritical() << "Could not open fake JSON file!";
  54. reply = new FakePayloadReply(op, req, {}, nullptr);
  55. }
  56. }
  57. } else if (path.contains(QStringLiteral("/end_to_end_encryption/api/v1/meta-data/"))) {
  58. if (op == QNetworkAccessManager::GetOperation) {
  59. QFile fakeJsonReplyFile(QStringLiteral("fakefiledrope2eefoldermetadata.json"));
  60. if (fakeJsonReplyFile.open(QFile::ReadOnly)) {
  61. const auto jsonDoc = QJsonDocument::fromJson(fakeJsonReplyFile.readAll());
  62. _parsedMetadataWithFileDrop.reset(new FolderMetadata(_fakeFolder.syncEngine().account(), jsonDoc.toJson()));
  63. _parsedMetadataAfterProcessingFileDrop.reset(new FolderMetadata(_fakeFolder.syncEngine().account(), jsonDoc.toJson()));
  64. [[maybe_unused]] const auto result = _parsedMetadataAfterProcessingFileDrop->moveFromFileDropToFiles();
  65. reply = new FakePayloadReply(op, req, jsonDoc.toJson(), nullptr);
  66. ++_getMetadataCallsCount;
  67. } else {
  68. qCritical() << "Could not open fake JSON file!";
  69. reply = new FakePayloadReply(op, req, {}, nullptr);
  70. }
  71. } else if (op == QNetworkAccessManager::PutOperation) {
  72. reply = new FakePayloadReply(op, req, {}, nullptr);
  73. ++_putMetadataCallsCount;
  74. }
  75. } else if (req.attribute(QNetworkRequest::CustomVerbAttribute) == QStringLiteral("PROPFIND") && path.endsWith(fakeE2eeFolderPath)) {
  76. auto fileState = _fakeFolder.currentRemoteState();
  77. reply = new FakePropfindReply(fileState, op, req, nullptr);
  78. ++_propFindCallsCount;
  79. }
  80. return reply;
  81. });
  82. auto transProgress = connect(&_fakeFolder.syncEngine(), &SyncEngine::transmissionProgress, [&](const ProgressInfo &pi) {
  83. Q_UNUSED(pi);
  84. _propagator = _fakeFolder.syncEngine().getPropagator();
  85. });
  86. QVERIFY(_fakeFolder.syncOnce());
  87. disconnect(transProgress);
  88. };
  89. void testUpdateFileDropMetadata()
  90. {
  91. const auto updateFileDropMetadataJob = new UpdateFileDropMetadataJob(_propagator.data(), fakeE2eeFolderPath);
  92. connect(updateFileDropMetadataJob, &UpdateFileDropMetadataJob::fileDropMetadataParsedAndAdjusted, this, [this](const FolderMetadata *const metadata) {
  93. if (!metadata || metadata->files().isEmpty() || metadata->fileDrop().isEmpty()) {
  94. return;
  95. }
  96. if (_parsedMetadataAfterProcessingFileDrop->files().size() != metadata->files().size()) {
  97. return;
  98. }
  99. if (_parsedMetadataAfterProcessingFileDrop->fileDrop() != metadata->fileDrop()) {
  100. return;
  101. }
  102. bool isAnyFileDropFileMissing = false;
  103. for (const auto &key : metadata->fileDrop().keys()) {
  104. if (std::find_if(metadata->files().constBegin(), metadata->files().constEnd(), [&key](const EncryptedFile &encryptedFile) {
  105. return encryptedFile.encryptedFilename == key;
  106. }) == metadata->files().constEnd()) {
  107. isAnyFileDropFileMissing = true;
  108. }
  109. }
  110. if (!isAnyFileDropFileMissing) {
  111. emit fileDropMetadataParsedAndAdjusted();
  112. }
  113. });
  114. QSignalSpy updateFileDropMetadataJobSpy(updateFileDropMetadataJob, &UpdateFileDropMetadataJob::finished);
  115. QSignalSpy fileDropMetadataParsedAndAdjustedSpy(this, &TestSecureFileDrop::fileDropMetadataParsedAndAdjusted);
  116. QVERIFY(updateFileDropMetadataJob->scheduleSelfOrChild());
  117. QVERIFY(updateFileDropMetadataJobSpy.wait(3000));
  118. QVERIFY(_parsedMetadataWithFileDrop);
  119. QVERIFY(_parsedMetadataWithFileDrop->isFileDropPresent());
  120. QVERIFY(_parsedMetadataAfterProcessingFileDrop);
  121. QVERIFY(_parsedMetadataAfterProcessingFileDrop->files().size() != _parsedMetadataWithFileDrop->files().size());
  122. QVERIFY(!updateFileDropMetadataJobSpy.isEmpty());
  123. QVERIFY(!updateFileDropMetadataJobSpy.at(0).isEmpty());
  124. QCOMPARE(updateFileDropMetadataJobSpy.at(0).first().toInt(), SyncFileItem::Status::Success);
  125. QVERIFY(!fileDropMetadataParsedAndAdjustedSpy.isEmpty());
  126. QCOMPARE(_lockCallsCount, 1);
  127. QCOMPARE(_unlockCallsCount, 1);
  128. QCOMPARE(_propFindCallsCount, 2);
  129. QCOMPARE(_getMetadataCallsCount, 1);
  130. QCOMPARE(_putMetadataCallsCount, 1);
  131. updateFileDropMetadataJob->deleteLater();
  132. }
  133. signals:
  134. void fileDropMetadataParsedAndAdjusted();
  135. };
  136. QTEST_GUILESS_MAIN(TestSecureFileDrop)
  137. #include "testsecurefiledrop.moc"