Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/BackedUpFileWriterTest.cs =================================================================== diff -u -r7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8 -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/BackedUpFileWriterTest.cs (.../BackedUpFileWriterTest.cs) (revision 7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/BackedUpFileWriterTest.cs (.../BackedUpFileWriterTest.cs) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -32,7 +32,7 @@ public class BackedUpFileWriterTest { private readonly string testWorkDir = Path.Combine(".", "SafeOverwriteFileHelperTest"); - + [TestFixtureSetUp] public void SetUpFixture() { @@ -185,7 +185,7 @@ try { - using (new DirectoryRightsHelper(notWritableDirectory, FileSystemRights.Write)) + using (new DirectoryPermissionsRevoker(notWritableDirectory, FileSystemRights.Write)) { // Assert var expectedMessage = string.Format( @@ -201,7 +201,7 @@ } [Test] - public void Perform_TargetFileDoesNotExistAccessRightsRevoked_DoesNotThrow() + public void Perform_TargetFileDoesNotExistDeleteRightsRevoked_DoesNotThrow() { // Setup var noAccessDirectory = Path.Combine(testWorkDir, "NoAccess"); @@ -215,7 +215,7 @@ try { - using (new DirectoryRightsHelper(noAccessDirectory, FileSystemRights.FullControl)) + using (new DirectoryPermissionsRevoker(noAccessDirectory, FileSystemRights.Delete)) { // Assert Assert.DoesNotThrow(test); @@ -317,13 +317,13 @@ var helper = new BackedUpFileWriter(filePath); - DirectoryRightsHelper fileRightsHelper = null; + DirectoryPermissionsRevoker fileRightsHelper = null; try { // Call TestDelegate test = () => helper.Perform(() => { - fileRightsHelper = new DirectoryRightsHelper(noAccessDirectory, FileSystemRights.FullControl); + fileRightsHelper = new DirectoryPermissionsRevoker(noAccessDirectory, FileSystemRights.FullControl); throw new Exception(); }); Index: Core/Common/test/Core.Common.Gui.Test/Settings/SettingsHelperTest.cs =================================================================== diff -u -r7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8 -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Core/Common/test/Core.Common.Gui.Test/Settings/SettingsHelperTest.cs (.../SettingsHelperTest.cs) (revision 7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8) +++ Core/Common/test/Core.Common.Gui.Test/Settings/SettingsHelperTest.cs (.../SettingsHelperTest.cs) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -95,7 +95,7 @@ SetLocalSettingsDirectoryPath(workingDirectory); - using (new DirectoryRightsHelper(workingDirectory, FileSystemRights.Write)) + using (new DirectoryPermissionsRevoker(workingDirectory, FileSystemRights.Write)) { // Call TestDelegate test = () => SettingsHelper.GetApplicationLocalUserSettingsDirectory(notWritableFolder); Index: Core/Common/test/Core.Common.TestUtil.Test/Core.Common.TestUtil.Test.csproj =================================================================== diff -u -r7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8 -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Core/Common/test/Core.Common.TestUtil.Test/Core.Common.TestUtil.Test.csproj (.../Core.Common.TestUtil.Test.csproj) (revision 7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8) +++ Core/Common/test/Core.Common.TestUtil.Test/Core.Common.TestUtil.Test.csproj (.../Core.Common.TestUtil.Test.csproj) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -53,7 +53,7 @@ - + True Index: Core/Common/test/Core.Common.TestUtil.Test/DirectoryPermissionsRevokerTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.TestUtil.Test/DirectoryPermissionsRevokerTest.cs (revision 0) +++ Core/Common/test/Core.Common.TestUtil.Test/DirectoryPermissionsRevokerTest.cs (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -0,0 +1,268 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.IO; +using System.Linq; +using System.Security.AccessControl; +using System.Security.Principal; +using NUnit.Framework; + +namespace Core.Common.TestUtil.Test +{ + [TestFixture] + public class DirectoryPermissionsRevokerTest + { + private readonly string testWorkDir = Path.Combine(".", "DirectoryPermissionsRevokerTest"); + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase(" ")] + public void Constructor_NullPath_ThrowsArgumentException(string invalidPath) + { + // Call + TestDelegate test = () => new DirectoryPermissionsRevoker(invalidPath, FileSystemRights.Modify); + + // Assert + string paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("filePath", paramName); + } + + [Test] + public void Constructor_PathDoesNotExist_ThrowsDirectoryNotFoundException() + { + // Setup + const string invalidPath = @".\DirectoryDoesNotExist\fileDoesNotExist"; + + // Call + TestDelegate test = () => new DirectoryPermissionsRevoker(invalidPath, FileSystemRights.Modify); + + // Assert + Assert.Throws(test); + } + + [Test] + public void Constructor_UnsupportedRight_ThrowsNotSupportedException() + { + // Setup + const FileSystemRights rights = FileSystemRights.Synchronize; + var accessDirectory = Path.Combine(testWorkDir, "Constructor_UnsupportedRight_ThrowsNotSupportedException", rights.ToString()); + Directory.CreateDirectory(accessDirectory); + + try + { + // Call + TestDelegate test = () => { new DirectoryPermissionsRevoker(accessDirectory, rights); }; + + // Assert + Assert.Throws(test); + } + finally + { + Directory.Delete(accessDirectory, true); + } + } + + [Test] + [TestCase(FileSystemRights.AppendData)] + [TestCase(FileSystemRights.ChangePermissions)] + [TestCase(FileSystemRights.Delete)] + [TestCase(FileSystemRights.DeleteSubdirectoriesAndFiles)] + [TestCase(FileSystemRights.ExecuteFile)] + [TestCase(FileSystemRights.FullControl)] + [TestCase(FileSystemRights.Modify)] + [TestCase(FileSystemRights.Read)] + [TestCase(FileSystemRights.ReadAndExecute)] + [TestCase(FileSystemRights.ReadAttributes)] + [TestCase(FileSystemRights.ReadData)] + [TestCase(FileSystemRights.ReadExtendedAttributes)] + [TestCase(FileSystemRights.ReadPermissions)] + [TestCase(FileSystemRights.TakeOwnership)] + [TestCase(FileSystemRights.Write)] + [TestCase(FileSystemRights.WriteData)] + [TestCase(FileSystemRights.WriteAttributes)] + [TestCase(FileSystemRights.WriteExtendedAttributes)] + [TestCase(FileSystemRights.Delete | FileSystemRights.Read)] + [TestCase(FileSystemRights.Delete | FileSystemRights.Synchronize)] + public void Constructor_ValidPathDenyRight_SetsDenyRight(FileSystemRights rights) + { + // Setup + var accessDirectory = Path.Combine(testWorkDir, "Constructor_ValidPathDenyRight_SetsDenyRight", rights.ToString()); + Directory.CreateDirectory(accessDirectory); + + try + { + // Call + using (new DirectoryPermissionsRevoker(accessDirectory, rights)) + { + // Assert + AssertPathHasAccessRuleSet(accessDirectory, rights); + } + + AssertPathHasAccessRuleNotSet(accessDirectory, rights); + } + finally + { + Directory.Delete(accessDirectory, true); + } + } + + [Test] + [TestCase(FileSystemRights.AppendData)] + [TestCase(FileSystemRights.ChangePermissions)] + [TestCase(FileSystemRights.Delete)] + [TestCase(FileSystemRights.DeleteSubdirectoriesAndFiles)] + [TestCase(FileSystemRights.ExecuteFile)] + [TestCase(FileSystemRights.FullControl)] + [TestCase(FileSystemRights.Modify)] + [TestCase(FileSystemRights.Read)] + [TestCase(FileSystemRights.ReadAndExecute)] + [TestCase(FileSystemRights.ReadAttributes)] + [TestCase(FileSystemRights.ReadData)] + [TestCase(FileSystemRights.ReadExtendedAttributes)] + [TestCase(FileSystemRights.ReadPermissions)] + [TestCase(FileSystemRights.TakeOwnership)] + [TestCase(FileSystemRights.Write)] + [TestCase(FileSystemRights.WriteData)] + [TestCase(FileSystemRights.WriteAttributes)] + [TestCase(FileSystemRights.WriteExtendedAttributes)] + [TestCase(FileSystemRights.Delete | FileSystemRights.Read)] + [TestCase(FileSystemRights.Delete | FileSystemRights.Synchronize)] + public void Dispose_RightAlreadySet_DoesNotRemoveRight(FileSystemRights rights) + { + // Setup + var accessDirectory = Path.Combine(testWorkDir, "Dispose_RightAlreadySet_DoesNotRemoveRight", rights.ToString()); + Directory.CreateDirectory(accessDirectory); + + AddDirectoryAccessRule(accessDirectory, rights); + + // Precondition + AssertPathHasAccessRuleSet(accessDirectory, rights); + + try + { + // Call + using (new DirectoryPermissionsRevoker(accessDirectory, rights)) + { + // Assert + AssertPathHasAccessRuleSet(accessDirectory, rights); + } + + AssertPathHasAccessRuleSet(accessDirectory, rights); + } + finally + { + RemoveDirectoryAccessRule(accessDirectory, rights); + Directory.Delete(accessDirectory, true); + } + } + + [Test] + public void Dispose_DirectoryAlreadyRemoved_DoesNotThrowException() + { + // Setup + var accessDirectory = Path.Combine(testWorkDir, "Deleted"); + Directory.CreateDirectory(accessDirectory); + + TestDelegate test = () => + { + // Call + using (new DirectoryPermissionsRevoker(accessDirectory, FileSystemRights.Write)) + { + Directory.Delete(accessDirectory, true); + } + }; + + // Assert + Assert.DoesNotThrow(test); + } + + #region Assert access rules + + private static void AssertPathHasAccessRuleNotSet(string filePath, FileSystemRights rights) + { + DirectoryInfo directoryInfo = new DirectoryInfo(filePath); + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + var rules = directorySecurity.GetAccessRules(true, false, typeof(SecurityIdentifier)); + + var supportedFileSystemRights = GetSupportedFileSystemRights(rights); + + var fileSystemAccessRule = rules.OfType().FirstOrDefault( + fs => fs.FileSystemRights.HasFlag(supportedFileSystemRights) && fs.AccessControlType == AccessControlType.Deny); + Assert.IsNull(fileSystemAccessRule, string.Format("Rights '{0} {1}' are set for '{2}'", AccessControlType.Deny, supportedFileSystemRights, filePath)); + } + + private static FileSystemRights GetSupportedFileSystemRights(FileSystemRights rights) + { + return rights & ~FileSystemRights.Synchronize; + } + + private void AssertPathHasAccessRuleSet(string filePath, FileSystemRights rights) + { + DirectoryInfo directoryInfo = new DirectoryInfo(filePath); + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + var rules = directorySecurity.GetAccessRules(true, false, typeof(SecurityIdentifier)); + + var supportedFileSystemRights = GetSupportedFileSystemRights(rights); + + var fileSystemAccessRule = rules.OfType().FirstOrDefault( + fs => fs.FileSystemRights.HasFlag(supportedFileSystemRights) && fs.AccessControlType == AccessControlType.Deny); + Assert.IsNotNull(fileSystemAccessRule, string.Format("Rights '{0} {1}' not set for '{2}'", AccessControlType.Deny, (supportedFileSystemRights), filePath)); + } + + #endregion + + #region Apply access rules + + private static void AddDirectoryAccessRule(string filePath, FileSystemRights rights) + { + var sid = GetSecurityIdentifier(); + + DirectoryInfo directoryInfo = new DirectoryInfo(filePath); + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + + directorySecurity.AddAccessRule(new FileSystemAccessRule(sid, rights, AccessControlType.Deny)); + + directoryInfo.SetAccessControl(directorySecurity); + } + + private static void RemoveDirectoryAccessRule(string filePath, FileSystemRights rights) + { + var sid = GetSecurityIdentifier(); + + DirectoryInfo directoryInfo = new DirectoryInfo(filePath); + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + + directorySecurity.RemoveAccessRule(new FileSystemAccessRule(sid, rights, AccessControlType.Deny)); + + directoryInfo.SetAccessControl(directorySecurity); + } + + private static SecurityIdentifier GetSecurityIdentifier() + { + SecurityIdentifier id = WindowsIdentity.GetCurrent().User.AccountDomainSid; + return new SecurityIdentifier(WellKnownSidType.WorldSid, id); + } + + #endregion + } +} \ No newline at end of file Fisheye: Tag e8de9aaa898162dc695b7579c487a26571d03ce1 refers to a dead (removed) revision in file `Core/Common/test/Core.Common.TestUtil.Test/DirectoryRightsHelperTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Core/Common/test/Core.Common.TestUtil/Core.Common.TestUtil.csproj =================================================================== diff -u -r7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8 -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Core/Common/test/Core.Common.TestUtil/Core.Common.TestUtil.csproj (.../Core.Common.TestUtil.csproj) (revision 7e9e0ccec9caf49c8954f4d84c3f31c4c0a8d2a8) +++ Core/Common/test/Core.Common.TestUtil/Core.Common.TestUtil.csproj (.../Core.Common.TestUtil.csproj) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -86,7 +86,7 @@ - + Index: Core/Common/test/Core.Common.TestUtil/DirectoryPermissionsRevoker.cs =================================================================== diff -u --- Core/Common/test/Core.Common.TestUtil/DirectoryPermissionsRevoker.cs (revision 0) +++ Core/Common/test/Core.Common.TestUtil/DirectoryPermissionsRevoker.cs (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -0,0 +1,124 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.AccessControl; +using System.Security.Principal; + +namespace Core.Common.TestUtil +{ + /// + /// Class for providing a safe way to manipulating directory permissions. + /// + public class DirectoryPermissionsRevoker : IDisposable + { + private readonly IList appliedFileSystemAccessRules = new List(); + private readonly string filePath; + private readonly DirectoryInfo directoryInfo; + + /// + /// Creates an instance of . + /// Adds a of type to the access + /// rule set for the file at . + /// + /// The path of the file to change the right for. + /// The right to deny. + public DirectoryPermissionsRevoker(string filePath, FileSystemRights rights) + { + if (string.IsNullOrWhiteSpace(filePath)) + { + throw new ArgumentException(@"filePath must have a valid value.", "filePath"); + } + + this.filePath = filePath; + directoryInfo = new DirectoryInfo(Path.GetFullPath(filePath)); + if (!directoryInfo.Exists) + { + throw new DirectoryNotFoundException(@"filePath does not exist."); + } + + if ((rights ^ FileSystemRights.Synchronize) == 0) + { + // The FileSystemRights Synchronize by itself cannot be set. + throw new NotSupportedException(string.Format("Setting the right {0} is not supported.", rights)); + } + AddDenyDirectoryInfoRight(GetSupportedFileSystemRights(rights)); + } + + public void Dispose() + { + if (!Directory.Exists(filePath)) + { + return; + } + foreach (var appliedFileSystemAccessRule in appliedFileSystemAccessRules) + { + RevertDenyDirectoryInfoRight(appliedFileSystemAccessRule); + } + } + + private void AddDenyDirectoryInfoRight(FileSystemRights rights) + { + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + + if (IsFileSystemAccessRuleSet(rights, directorySecurity, AccessControlType.Deny)) + { + return; + } + + SecurityIdentifier sid = GetSecurityIdentifier(); + var fileSystemAccessRule = new FileSystemAccessRule(sid, rights, AccessControlType.Deny); + directorySecurity.AddAccessRule(fileSystemAccessRule); + + directoryInfo.SetAccessControl(directorySecurity); + appliedFileSystemAccessRules.Add(fileSystemAccessRule); + } + + private static bool IsFileSystemAccessRuleSet(FileSystemRights rights, CommonObjectSecurity commonObjectSecurity, AccessControlType accessControlType) + { + AuthorizationRuleCollection rules = commonObjectSecurity.GetAccessRules(true, false, typeof(SecurityIdentifier)); + return rules.OfType().Any(fs => fs.FileSystemRights.HasFlag(rights) && fs.AccessControlType == accessControlType); + } + + private static FileSystemRights GetSupportedFileSystemRights(FileSystemRights rights) + { + return rights & ~FileSystemRights.Synchronize; + } + + private void RevertDenyDirectoryInfoRight(FileSystemAccessRule rule) + { + DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); + + directorySecurity.RemoveAccessRule(rule); + + directoryInfo.SetAccessControl(directorySecurity); + } + + private static SecurityIdentifier GetSecurityIdentifier() + { + SecurityIdentifier id = WindowsIdentity.GetCurrent().User.AccountDomainSid; + return new SecurityIdentifier(WellKnownSidType.WorldSid, id); + } + } +} \ No newline at end of file Fisheye: Tag e8de9aaa898162dc695b7579c487a26571d03ce1 refers to a dead (removed) revision in file `Core/Common/test/Core.Common.TestUtil/DirectoryRightsHelper.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Core/Components/test/Core.Components.Gis.IO.Test/Writers/ShapeFileWriterBaseTest.cs =================================================================== diff -u -r4851d9c2b000de0707f6cce0872979ecc1e3dead -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Core/Components/test/Core.Components.Gis.IO.Test/Writers/ShapeFileWriterBaseTest.cs (.../ShapeFileWriterBaseTest.cs) (revision 4851d9c2b000de0707f6cce0872979ecc1e3dead) +++ Core/Components/test/Core.Components.Gis.IO.Test/Writers/ShapeFileWriterBaseTest.cs (.../ShapeFileWriterBaseTest.cs) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -108,7 +108,7 @@ try { - using (new DirectoryRightsHelper(directoryPath, FileSystemRights.Write)) + using (new DirectoryPermissionsRevoker(directoryPath, FileSystemRights.Write)) { using (var writer = new TestShapeFileWriterBase()) { Index: Ringtoets/Common/test/Ringtoets.Common.IO.Test/ReferenceLineExporterTest.cs =================================================================== diff -u -r4851d9c2b000de0707f6cce0872979ecc1e3dead -re8de9aaa898162dc695b7579c487a26571d03ce1 --- Ringtoets/Common/test/Ringtoets.Common.IO.Test/ReferenceLineExporterTest.cs (.../ReferenceLineExporterTest.cs) (revision 4851d9c2b000de0707f6cce0872979ecc1e3dead) +++ Ringtoets/Common/test/Ringtoets.Common.IO.Test/ReferenceLineExporterTest.cs (.../ReferenceLineExporterTest.cs) (revision e8de9aaa898162dc695b7579c487a26571d03ce1) @@ -114,7 +114,7 @@ bool isExported = true; try { - using (new DirectoryRightsHelper(directoryPath, FileSystemRights.Write)) + using (new DirectoryPermissionsRevoker(directoryPath, FileSystemRights.Write)) { // Call isExported = exporter.Export();