From 0530f0edbf57db8f8765be523bd1ad8f2f3deac8 Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 9 Feb 2023 09:14:36 +0100 Subject: [PATCH] gui: Add xattr filter editor (fixes #8660) (#8734) --- gui/default/assets/css/overrides.css | 4 + .../syncthing/core/syncthingController.js | 79 +++++++++++++++++++ .../syncthing/folder/editFolderModalView.html | 56 +++++++++++++ 3 files changed, 139 insertions(+) diff --git a/gui/default/assets/css/overrides.css b/gui/default/assets/css/overrides.css index 47147f3d2..06f705629 100644 --- a/gui/default/assets/css/overrides.css +++ b/gui/default/assets/css/overrides.css @@ -144,6 +144,10 @@ table.table-auto td { max-width: 0px; } +td input[type="checkbox"] { + margin-top: 13px; +} + /* Remote Devices connection-quality indicator */ .reception-0 { background: url('../../vendor/bootstrap/fonts/reception-0.svg') no-repeat; diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js index f61f0b0cf..495e4e1b0 100755 --- a/gui/default/syncthing/core/syncthingController.js +++ b/gui/default/syncthing/core/syncthingController.js @@ -2301,6 +2301,7 @@ angular.module('syncthing.core') return; } + $scope.validateXattrFilter(); var folderCfg = angular.copy($scope.currentFolder); $scope.currentSharing.selected[$scope.myID] = true; var newDevices = []; @@ -3330,6 +3331,84 @@ angular.module('syncthing.core') $scope.showTemporaryTooltip(event, message); }; + + $scope.newXattrEntry = function () { + var entries = $scope.currentFolder.xattrFilter.entries; + var newEntry = {match: '', permit: false}; + + if (entries.some(function (n) { + return n.match == ''; + })) { + return; + } + + if (entries.length > 0 && entries[entries.length -1].match === '*') { + if (newEntry.match !== '*') { + entries.splice(entries.length - 1, 0, newEntry); + } + + return; + } + + entries.push(newEntry); + }; + + $scope.removeXattrEntry = function (entry) { + $scope.currentFolder.xattrFilter.entries = $scope.currentFolder.xattrFilter.entries.filter(function (n) { + return n !== entry; + }); + }; + + $scope.getXattrHint = function () { + var xattrFilter = $scope.currentFolder.xattrFilter; + if (xattrFilter == null || xattrFilter == {}) { + return ''; + } + var filterEntries = xattrFilter.entries; + if (filterEntries.length === 0) { + return ''; + } + + // When the user explicitely added a wild-card, we don't show hints. + if (filterEntries.length === 1 && filterEntries[0].match === '*') { + return ''; + } + // If all the filter entries are 'deny', we suggest adding a permit-any + // rule in the end since the default is already deny in that case. + if (filterEntries.every(function (entry) { + return entry.permit === false; + })) { + return $translate.instant('Hint: only deny-rules detected while the default is deny. Consider adding "permit any" as last rule.'); + } + + return ''; + }; + + $scope.getXattrDefault = function () { + var xattrFilter = $scope.currentFolder.xattrFilter; + if (xattrFilter == null || xattrFilter == {}) { + return ''; + } + + var filterEntries = xattrFilter.entries; + // No entries present, default is thus 'allow' + if (filterEntries.length === 0) { + return $translate.instant('permit'); + } + // If any rule is present and the last entry isn't a wild-card, the default is deny. + if (filterEntries[filterEntries.length -1].match !== '*') { + return $translate.instant('deny'); + } + + return ''; + }; + + $scope.validateXattrFilter = function () { + // Fitlering out empty rules when saving the config + $scope.currentFolder.xattrFilter.entries = $scope.currentFolder.xattrFilter.entries.filter(function (n) { + return n.match !== ""; + }); + }; }) .directive('shareTemplate', function () { return { diff --git a/gui/default/syncthing/folder/editFolderModalView.html b/gui/default/syncthing/folder/editFolderModalView.html index a21c45472..6564479d0 100644 --- a/gui/default/syncthing/folder/editFolderModalView.html +++ b/gui/default/syncthing/folder/editFolderModalView.html @@ -323,7 +323,63 @@

+ +
+
+

+ +   Help +

+
+
+

+ To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked. +

+ + + + + + + + + + + + +
+ + + +
+
+ +
+

+ No rules set +

+

+ Default: {{getXattrDefault()}} +

+

+ {{getXattrHint()}} +

+
+
+ + +
+
+ + +
+
+