public void TestAccessPermissions() { // var (testPath, numFiles) = prepareExampleDirectory(); var(testPath, numFiles) = (_testPath, _numFiles); // Additional temporary folder without read permissions var subPath2 = Path.Combine(testPath, "sub2"); var forbiddenDir = Directory.CreateDirectory(subPath2); // Additional temporary folder with ordinary permissions var subPath3 = Path.Combine(testPath, "sub3"); Directory.CreateDirectory(subPath3); string srcPath = Path.Combine("TestData", "snapshot-test", "WMR"); const string srcFile1 = "MyBasic.structuredefinition.xml"; const string srcFile2 = "MyBundle.structuredefinition.xml"; const string profileUrl1 = @"http://example.org/fhir/StructureDefinition/MyBasic"; const string profileUrl2 = @"http://example.org/fhir/StructureDefinition/MyBundle"; // Create test file in inaccessible subfolder; should be ignored copy(srcPath, srcFile1, subPath2); // Create hidden test file in accessible subfolder; should also be ignored copy(srcPath, srcFile1, subPath3); var filePath = Path.Combine(subPath3, srcFile1); var attr = File.GetAttributes(filePath); File.SetAttributes(filePath, attr | FileAttributes.Hidden); // Create regular test file in accessible subfolder; should be included copy(srcPath, srcFile2, subPath3); numFiles++; bool initialized = false; try { // Abort unit test if we can't access folder permissions var ds = forbiddenDir.GetAccessControl(); // Revoke folder read permissions for the current user string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; var rule = new ssac.FileSystemAccessRule(userName, ssac.FileSystemRights.Read, ssac.AccessControlType.Deny); ds.AddAccessRule(rule); Debug.Print($"Removing read permissions from folder: '{subPath2}' ..."); // Abort unit test if we can't modify file permissions forbiddenDir.SetAccessControl(ds); try { var forbiddenFile = new FileInfo(Path.Combine(subPath2, srcFile1)); // Abort unit test if we can't access file permissions var fs = forbiddenFile.GetAccessControl(); // Revoke file read permissions for the current user fs.AddAccessRule(rule); Debug.Print($"Removing read permissions from fole: '{forbiddenFile}' ..."); // Abort unit test if we can't modify file permissions forbiddenFile.SetAccessControl(fs); initialized = true; try { // Note: we still have write permissions... var dirSource = new DirectorySource(testPath, new DirectorySourceSettings() { IncludeSubDirectories = true }); // [WMR 20170823] Test ListArtifactNames => prepareFiles() var names = dirSource.ListArtifactNames(); Assert.AreEqual(numFiles, names.Count()); Assert.IsFalse(names.Contains(srcFile1)); Assert.IsTrue(names.Contains(srcFile2)); // [WMR 20170823] Also test ListResourceUris => prepareResources() var profileUrls = dirSource.ListResourceUris(ResourceType.StructureDefinition); // Materialize the sequence var urlList = profileUrls.ToList(); Assert.IsFalse(urlList.Contains(profileUrl1)); Assert.IsTrue(urlList.Contains(profileUrl2)); } // API *should* grafecully handle security exceptions catch (UnauthorizedAccessException ex) { Assert.Fail($"Failed! Unexpected UnauthorizedAccessException: {ex.Message}"); } finally { var result = fs.RemoveAccessRule(rule); Assert.IsTrue(result); Debug.Print($"Restoring file read permissions..."); forbiddenFile.SetAccessControl(fs); Debug.Print($"Succesfully restored file read permissions."); // We should be able to delete the file File.Delete(forbiddenFile.FullName); } } finally { var result = ds.RemoveAccessRule(rule); Assert.IsTrue(result); Debug.Print($"Restoring folder read permissions..."); forbiddenDir.SetAccessControl(ds); Debug.Print($"Succesfully restored folder read permissions."); // We should be able to delete the subdirectory Directory.Delete(subPath2, true); } } // If acl initialization failed, then consume the exception and return success // Preferably, skip this unit test / return unknown result - how? catch (Exception ex) when(!initialized) { Debug.Print($"[{nameof(TestAccessPermissions)}] Could not modify directory access permissions: '{ex.Message}'. Skip unit test..."); } }