Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ public StaticFileTreeControllerBase(IPhysicalFileSystem physicalFileSystem, IPhy

protected override IFileSystem FileSystem { get; }

protected string[] GetDirectories(string path) =>
protected override string[] GetDirectories(string path) =>
IsTreeRootPath(path)
? _allowedRootFolders
: IsAllowedPath(path)
? _fileSystemTreeService.GetDirectories(path)
: Array.Empty<string>();

protected string[] GetFiles(string path)
protected override string[] GetFiles(string path)
=> IsTreeRootPath(path) || IsAllowedPath(path) == false
? Array.Empty<string>()
: _fileSystemTreeService.GetFiles(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Umbraco.Cms.Api.Management.Extensions;
using Umbraco.Cms.Api.Management.Extensions;
using Umbraco.Cms.Api.Management.ViewModels.FileSystem;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.IO;
Expand Down Expand Up @@ -68,12 +68,12 @@ public FileSystemTreeItemPresentationModel[] GetSiblingsViewModels(string path,
.ToArray();
}

public string[] GetDirectories(string path) => FileSystem
public virtual string[] GetDirectories(string path) => FileSystem
.GetDirectories(path)
.OrderBy(directory => directory)
.ToArray();

public string[] GetFiles(string path) => FileSystem
public virtual string[] GetFiles(string path) => FileSystem
.GetFiles(path)
.Where(FilterFile)
.OrderBy(file => file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,31 @@ namespace Umbraco.Cms.Api.Management.Services.FileSystem;

public class PhysicalFileSystemTreeService : FileSystemTreeServiceBase, IPhysicalFileSystemTreeService
{
private static readonly string[] _allowedRootFolders = { $"{Path.DirectorySeparatorChar}App_Plugins", $"{Path.DirectorySeparatorChar}wwwroot" };

private readonly IFileSystem _physicalFileSystem;

protected override IFileSystem FileSystem => _physicalFileSystem;

public PhysicalFileSystemTreeService(IPhysicalFileSystem physicalFileSystem) =>
_physicalFileSystem = physicalFileSystem;

/// <inheritdoc/>
public override string[] GetDirectories(string path) =>
IsTreeRootPath(path)
? _allowedRootFolders
: IsAllowedPath(path)
? base.GetDirectories(path)
: Array.Empty<string>();

/// <inheritdoc/>
public override string[] GetFiles(string path)
=> IsTreeRootPath(path) || IsAllowedPath(path) is false
? []
: base.GetFiles(path);

private static bool IsTreeRootPath(string path) => path == Path.DirectorySeparatorChar.ToString();

private static bool IsAllowedPath(string path) => _allowedRootFolders.Contains(path) || _allowedRootFolders.Any(folder => path.StartsWith($"{folder}{Path.DirectorySeparatorChar}"));

}
67 changes: 65 additions & 2 deletions tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
Expand All @@ -15,6 +15,69 @@
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.PartialViewTreeServiceTests.Can_Get_Ancestors_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.PartialViewTreeServiceTests.Can_Get_PathViewModels_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.PartialViewTreeServiceTests.Can_Get_Siblings_From_PartialView_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.ScriptTreeServiceTests.Can_Get_Ancestors_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.ScriptTreeServiceTests.Can_Get_PathViewModels_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.ScriptTreeServiceTests.Can_Get_Siblings_From_Script_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.StyleSheetTreeServiceTests.Can_Get_Ancestors_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.StyleSheetTreeServiceTests.Can_Get_PathViewModels_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees.StyleSheetTreeServiceTests.Can_Get_Siblings_From_StyleSheet_Tree_Service</Target>
<Left>lib/net10.0/Umbraco.Tests.Integration.dll</Left>
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Examine.Lucene.UmbracoExamine.IndexInitializer.#ctor(Umbraco.Cms.Core.Strings.IShortStringHelper,Umbraco.Cms.Core.PropertyEditors.PropertyEditorCollection,Umbraco.Cms.Core.PropertyEditors.MediaUrlGeneratorCollection,Umbraco.Cms.Core.Scoping.IScopeProvider,Microsoft.Extensions.Logging.ILoggerFactory,Microsoft.Extensions.Options.IOptions{Umbraco.Cms.Core.Configuration.Models.ContentSettings},Umbraco.Cms.Core.Services.ILocalizationService,Umbraco.Cms.Core.Services.IContentTypeService,Umbraco.Cms.Core.Services.IDocumentUrlService,Umbraco.Cms.Core.Services.ILanguageService)</Target>
Expand All @@ -29,4 +92,4 @@
<Right>lib/net10.0/Umbraco.Tests.Integration.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
</Suppressions>
</Suppressions>
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,23 @@ public virtual void SetUpFileSystem()
GetStylesheetsFileSystem(),
GetScriptsFileSystem(),
null);

CreateFiles();
}

protected virtual void CreateFiles()
{
for (int i = 0; i < 10; i++)
{
using var stream = CreateStream(Path.Join("tests"));
using var stream = CreateStream();
TestFileSystem.AddFile($"file{i}{FileExtension}", stream);
}
}

protected static Stream CreateStream(string contents = null)
{
if (string.IsNullOrEmpty(contents))
{
contents = "/* test */";
}

var bytes = Encoding.UTF8.GetBytes(contents);
const string DefaultFileContent = "/* test */";
var bytes = Encoding.UTF8.GetBytes(contents ?? DefaultFileContent);
return new MemoryStream(bytes);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class PartialViewTreeServiceTests : FileSystemTreeServiceTestsBase
protected override IFileSystem? GetPartialViewsFileSystem() => TestFileSystem;

[Test]
public void Can_Get_Siblings_From_PartialView_Tree_Service()
public void Can_Get_Siblings()
{
var service = new PartialViewTreeService(FileSystems);

Expand All @@ -31,20 +31,20 @@ public void Can_Get_Siblings_From_PartialView_Tree_Service()
}

[Test]
public void Can_Get_Ancestors_From_StyleSheet_Tree_Service()
public void Can_Get_Ancestors()
{
var service = new PartialViewTreeService(FileSystems);

var path = Path.Join("tests", $"file5{FileExtension}");
FileSystemTreeItemPresentationModel[] treeModel = service.GetAncestorModels(path, true);
FileSystemTreeItemPresentationModel[] treeModels = service.GetAncestorModels(path, true);

Assert.IsNotEmpty(treeModel);
Assert.AreEqual(treeModel.Length, 2);
Assert.AreEqual(treeModel[0].Name, "tests");
Assert.IsNotEmpty(treeModels);
Assert.AreEqual(treeModels.Length, 2);
Assert.AreEqual(treeModels[0].Name, "tests");
}

[Test]
public void Can_Get_PathViewModels_From_StyleSheet_Tree_Service()
public void Can_Get_PathViewModels()
{
var service = new PartialViewTreeService(FileSystems);

Expand All @@ -60,7 +60,7 @@ public void Will_Hide_Unsupported_File_Extensions()
var service = new PartialViewTreeService(FileSystems);
for (int i = 0; i < 2; i++)
{
using var stream = CreateStream(Path.Join("tests"));
using var stream = CreateStream();
TestFileSystem.AddFile($"file{i}.invalid", stream);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.IO;
using Microsoft.Extensions.Logging;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Services.FileSystem;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core.IO;

namespace Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees;

public class PhysicalFileSystemTreeServiceTests : FileSystemTreeServiceTestsBase
{
protected override string FileExtension { get; set; } = string.Empty;

protected override string FileSystemPath => "/";

protected override void CreateFiles()
{
var paths = new[]
{
Path.Join("App_Plugins", "test-extension", "test.js"),
Path.Join("wwwroot", "css", "test.css"),
Path.Join("wwwroot", "css", "test2.css"),
Path.Join("wwwroot", "css", "test3.css"),
Path.Join("wwwroot", "css", "test4.css"),
Path.Join("Program.cs"),
};
foreach (var path in paths)
{
var stream = CreateStream();
TestFileSystem.AddFile(path, stream);
}
}

[Test]
public void Can_Get_Siblings()
{
var service = CreateService();

FileSystemTreeItemPresentationModel[] treeModels = service.GetSiblingsViewModels("wwwroot/css/test2.css", 1, 1, out long before, out var after);

Assert.AreEqual(3, treeModels.Length);
Assert.AreEqual(treeModels[0].Name, "test.css");
Assert.AreEqual(treeModels[1].Name, "test2.css");
Assert.AreEqual(treeModels[2].Name, "test3.css");
Assert.AreEqual(before, 0);
Assert.AreEqual(after, 1);
}

[Test]
public void Can_Get_Ancestors()
{
var service = CreateService();

FileSystemTreeItemPresentationModel[] treeModels = service.GetAncestorModels(Path.Join("wwwroot", "css", "test.css"), true);

Assert.IsNotEmpty(treeModels);
Assert.AreEqual(treeModels.Length, 3);
Assert.AreEqual(treeModels[0].Name, "wwwroot");
Assert.AreEqual(treeModels[1].Name, "css");
Assert.AreEqual(treeModels[2].Name, "test.css");
}

[Test]
public void Can_Get_Root_PathViewModels()
{
var service = CreateService();

FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels(string.Empty, 0, int.MaxValue, out var totalItems);

Assert.IsNotEmpty(treeModels);
Assert.AreEqual(totalItems, 2);
Assert.AreEqual(treeModels.Length, totalItems);
Assert.AreEqual(treeModels[0].Name, "App_Plugins");
Assert.AreEqual(treeModels[1].Name, "wwwroot");
}

[Test]
public void Can_Get_Child_PathViewModels()
{
var service = CreateService();

FileSystemTreeItemPresentationModel[] treeModels = service.GetPathViewModels("App_Plugins/test-extension", 0, int.MaxValue, out var totalItems);

Assert.IsNotEmpty(treeModels);
Assert.AreEqual(totalItems, 1);
Assert.AreEqual(treeModels.Length, totalItems);
Assert.AreEqual(treeModels[0].Name, "test.js");
}

private PhysicalFileSystemTreeService CreateService()
{
var physicalFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, LoggerFactory.CreateLogger<PhysicalFileSystem>(), HostingEnvironment.MapPathWebRoot(FileSystemPath), HostingEnvironment.ToAbsolute(FileSystemPath));
return new PhysicalFileSystemTreeService(physicalFileSystem);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ namespace Umbraco.Cms.Tests.Integration.ManagementApi.Services.Trees;
public class ScriptTreeServiceTests : FileSystemTreeServiceTestsBase
{
protected override string FileExtension { get; set; } = ".js";

protected override string FileSystemPath => GlobalSettings.UmbracoScriptsPath;

protected override IFileSystem? GetScriptsFileSystem() => TestFileSystem;

[Test]
public void Can_Get_Siblings_From_Script_Tree_Service()
public void Can_Get_Siblings()
{
var service = new ScriptTreeService(FileSystems);

Expand All @@ -29,20 +30,20 @@ public void Can_Get_Siblings_From_Script_Tree_Service()
}

[Test]
public void Can_Get_Ancestors_From_StyleSheet_Tree_Service()
public void Can_Get_Ancestors()
{
var service = new ScriptTreeService(FileSystems);

var path = Path.Join("tests", $"file5{FileExtension}");
FileSystemTreeItemPresentationModel[] treeModel = service.GetAncestorModels(path, true);
FileSystemTreeItemPresentationModel[] treeModels = service.GetAncestorModels(path, true);

Assert.IsNotEmpty(treeModel);
Assert.AreEqual(treeModel.Length, 2);
Assert.AreEqual(treeModel[0].Name, "tests");
Assert.IsNotEmpty(treeModels);
Assert.AreEqual(treeModels.Length, 2);
Assert.AreEqual(treeModels[0].Name, "tests");
}

[Test]
public void Can_Get_PathViewModels_From_StyleSheet_Tree_Service()
public void Can_Get_PathViewModels()
{
var service = new ScriptTreeService(FileSystems);

Expand All @@ -58,7 +59,7 @@ public void Will_Hide_Unsupported_File_Extensions()
var service = new ScriptTreeService(FileSystems);
for (int i = 0; i < 2; i++)
{
using var stream = CreateStream(Path.Join("tests"));
using var stream = CreateStream();
TestFileSystem.AddFile($"file{i}.invalid", stream);
}

Expand Down
Loading
Loading