when deciding to create a new folder on server: check permissions
authorMatthieu Gallien <matthieu.gallien@nextcloud.com>
Thu, 22 Aug 2024 12:20:37 +0000 (14:20 +0200)
committerMatthieu Gallien <matthieu_gallien@yahoo.fr>
Fri, 23 Aug 2024 07:56:44 +0000 (09:56 +0200)
sometime we need to create a folder on server because some local files
or folders modifications would be lost without that

in that case instead of locally deleting teh folder, we create it back
on server

when doing that, it is important to check the remote permissions such
that we do not try to create a folder in a read-only folder on server

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
src/libsync/discovery.cpp
src/libsync/discovery.h
src/libsync/syncengine.cpp

index 089717f621684a3f5442b254bfe85f3bd5f5b963..037874d25a05d07ed112d771b70dc7095a6b7362 100644 (file)
@@ -57,6 +57,7 @@ ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinS
 ProcessDirectoryJob::ProcessDirectoryJob(const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp, ProcessDirectoryJob *parent)
     : QObject(parent)
     , _dirItem(dirItem)
+    , _dirParentItem(parent->_dirItem)
     , _lastSyncTimestamp(lastSyncTimestamp)
     , _queryServer(queryServer)
     , _queryLocal(queryLocal)
@@ -67,9 +68,10 @@ ProcessDirectoryJob::ProcessDirectoryJob(const PathTuple &path, const SyncFileIt
     computePinState(parent->_pinState);
 }
 
-ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem, QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent)
+ProcessDirectoryJob::ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem, const SyncFileItemPtr &parentDirItem, QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent)
         : QObject(parent)
         , _dirItem(dirItem)
+        , _dirParentItem(parentDirItem)
         , _lastSyncTimestamp(lastSyncTimestamp)
         , _queryLocal(queryLocal)
         , _discoveryData(data)
@@ -2017,6 +2019,18 @@ int ProcessDirectoryJob::processSubJobs(int nbJobs)
             if (_childModified && _dirItem->_instruction == CSYNC_INSTRUCTION_REMOVE) {
                 // re-create directory that has modified contents
                 _dirItem->_instruction = CSYNC_INSTRUCTION_NEW;
+
+                const auto perms = !_rootPermissions.isNull() ? _rootPermissions
+                    : _dirParentItem ? _dirParentItem->_remotePerm : _rootPermissions;
+
+                if (perms.isNull()) {
+                    // No permissions set
+                } else if (_dirItem->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddSubDirectories)) {
+                    qCWarning(lcDisco) << "checkForPermission: ERROR" << _dirItem->_file;
+                    _dirItem->_instruction = CSYNC_INSTRUCTION_ERROR;
+                    _dirItem->_errorString = tr("Not allowed because you don't have permission to add subfolders to that folder");
+                }
+
                 _dirItem->_direction = _dirItem->_direction == SyncFileItem::Up ? SyncFileItem::Down : SyncFileItem::Up;
             }
             if (_childModified && _dirItem->_instruction == CSYNC_INSTRUCTION_TYPE_CHANGE && !_dirItem->isDirectory()) {
index 62d1f493c51322ac448c3732955d9ef7a1e21acf..840eb15d61169e2d6d071a7893fd41cb4fbe6075 100644 (file)
@@ -108,8 +108,8 @@ public:
         QueryMode queryLocal, QueryMode queryServer, qint64 lastSyncTimestamp,
         ProcessDirectoryJob *parent);
 
-    explicit ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem,
-        QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent);
+    explicit ProcessDirectoryJob(DiscoveryPhase *data, PinState basePinState, const PathTuple &path, const SyncFileItemPtr &dirItem, const SyncFileItemPtr &parentDirItem,
+                                 QueryMode queryLocal, qint64 lastSyncTimestamp, QObject *parent);
 
     void start();
     /** Start up to nbJobs, return the number of job started; emit finished() when done */
@@ -126,6 +126,7 @@ public:
     }
 
     SyncFileItemPtr _dirItem;
+    SyncFileItemPtr _dirParentItem;
 
 private:
     struct Entries
index 4a95dc09819145986f47a3010ee583014d3905d0..3f0cd9b3cd7115c09d505001a13dc24d6f533725 100644 (file)
@@ -721,6 +721,7 @@ void SyncEngine::startSync()
             pinState,
             path,
             singleItemDiscoveryOptions().discoveryDirItem,
+            {},
             localQueryMode,
             _journal->keyValueStoreGetInt("last_sync", 0),
             _discoveryPhase.data()