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()}} +
+