mirror of https://github.com/abpframework/abp.git
14 changed files with 211 additions and 68 deletions
@ -0,0 +1,28 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.VirtualFileSystem |
||||
|
{ |
||||
|
public class AspNetCoreContentOptions |
||||
|
{ |
||||
|
public List<string> AllowedExtraWebContentFolders { get; } |
||||
|
public List<string> AllowedExtraWebContentFileExtensions { get; } |
||||
|
|
||||
|
public AspNetCoreContentOptions() |
||||
|
{ |
||||
|
AllowedExtraWebContentFolders = new List<string> |
||||
|
{ |
||||
|
"/Pages", |
||||
|
"/Views" |
||||
|
}; |
||||
|
|
||||
|
AllowedExtraWebContentFileExtensions = new List<string> |
||||
|
{ |
||||
|
".js", |
||||
|
".css", |
||||
|
".png", |
||||
|
".jpg", |
||||
|
".jpeg" |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
//using System;
|
||||
|
//using System.Linq;
|
||||
|
//using JetBrains.Annotations;
|
||||
|
//using Microsoft.Extensions.FileProviders;
|
||||
|
//using Microsoft.Extensions.Primitives;
|
||||
|
|
||||
|
//namespace Volo.Abp.VirtualFileSystem
|
||||
|
//{
|
||||
|
// //TODO: Ensure that merging such subfolders is secure! (anyone can add /.. to the beginning!)..?
|
||||
|
|
||||
|
// public class FileProviderSubFolderWrapper : IFileProvider
|
||||
|
// {
|
||||
|
// private readonly IFileProvider _fileProvider;
|
||||
|
// private readonly string _rootPath;
|
||||
|
// private readonly string[] _allowedExtraFolders;
|
||||
|
// private readonly string[] _allowedExtraFileExtensions;
|
||||
|
|
||||
|
// public FileProviderSubFolderWrapper(
|
||||
|
// IFileProvider fileProvider,
|
||||
|
// string rootPath,
|
||||
|
// string[] allowedExtraFolders = null,
|
||||
|
// string[] allowedExtraFileExtensions = null)
|
||||
|
// {
|
||||
|
// _fileProvider = fileProvider;
|
||||
|
// _rootPath = rootPath;
|
||||
|
// _allowedExtraFileExtensions = allowedExtraFileExtensions ?? Array.Empty<string>();
|
||||
|
// _allowedExtraFolders = allowedExtraFolders ?? Array.Empty<string>();
|
||||
|
// }
|
||||
|
|
||||
|
// public IFileInfo GetFileInfo(string subpath)
|
||||
|
// {
|
||||
|
// Check.NotNullOrEmpty(subpath, nameof(subpath));
|
||||
|
|
||||
|
// if (ExtraAllowedPath(subpath))
|
||||
|
// {
|
||||
|
// var fileInfo = _fileProvider.GetFileInfo(subpath);
|
||||
|
// if (fileInfo.Exists)
|
||||
|
// {
|
||||
|
// return fileInfo;
|
||||
|
// }
|
||||
|
// }
|
||||
|
|
||||
|
// return _fileProvider.GetFileInfo(_rootPath + subpath);
|
||||
|
// }
|
||||
|
|
||||
|
// public IDirectoryContents GetDirectoryContents([NotNull] string subpath)
|
||||
|
// {
|
||||
|
// Check.NotNullOrEmpty(subpath, nameof(subpath));
|
||||
|
|
||||
|
// if (ExtraAllowedPath(subpath))
|
||||
|
// {
|
||||
|
// var directory = _fileProvider.GetDirectoryContents(subpath);
|
||||
|
// if (directory.Exists)
|
||||
|
// {
|
||||
|
// return directory;
|
||||
|
// }
|
||||
|
// }
|
||||
|
|
||||
|
// return _fileProvider.GetDirectoryContents(_rootPath + subpath);
|
||||
|
// }
|
||||
|
|
||||
|
// private bool ExtraAllowedPath(string path)
|
||||
|
// {
|
||||
|
// return ExtraAllowedFolder(path) && ExtraAllowedExtension(path);
|
||||
|
// }
|
||||
|
|
||||
|
// private bool ExtraAllowedFolder(string path)
|
||||
|
// {
|
||||
|
// return _allowedExtraFolders.Any(s => path.StartsWith(s, StringComparison.OrdinalIgnoreCase));
|
||||
|
// }
|
||||
|
|
||||
|
// private bool ExtraAllowedExtension(string path)
|
||||
|
// {
|
||||
|
// return _allowedExtraFileExtensions.Any(e => path.EndsWith(e, StringComparison.OrdinalIgnoreCase));
|
||||
|
// }
|
||||
|
|
||||
|
// public IChangeToken Watch(string filter)
|
||||
|
// {
|
||||
|
// return _fileProvider.Watch(filter); //TODO: Why this does not use NormalizePath?
|
||||
|
// }
|
||||
|
// }
|
||||
|
//}
|
||||
@ -1,53 +1,102 @@ |
|||||
using System; |
using System; |
||||
using System.IO; |
using System.IO; |
||||
|
using System.Linq; |
||||
|
using JetBrains.Annotations; |
||||
using Microsoft.AspNetCore.Hosting; |
using Microsoft.AspNetCore.Hosting; |
||||
using Microsoft.Extensions.FileProviders; |
using Microsoft.Extensions.FileProviders; |
||||
|
using Microsoft.Extensions.Options; |
||||
using Microsoft.Extensions.Primitives; |
using Microsoft.Extensions.Primitives; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.VirtualFileSystem; |
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
namespace Volo.Abp.AspNetCore.VirtualFileSystem |
namespace Volo.Abp.AspNetCore.VirtualFileSystem |
||||
{ |
{ |
||||
|
//TODO: How to handle wwwroot naming?
|
||||
public class HybridWebRootFileProvider : IHybridWebRootFileProvider, ISingletonDependency |
public class HybridWebRootFileProvider : IHybridWebRootFileProvider, ISingletonDependency |
||||
{ |
{ |
||||
private readonly IVirtualFileProvider _virtualFileProvider; |
private readonly IVirtualFileProvider _virtualFileProvider; |
||||
private readonly IFileProvider _fileProvider; |
private readonly IFileProvider _fileProvider; |
||||
private readonly IHostingEnvironment _hostingEnvironment; |
private readonly IHostingEnvironment _hostingEnvironment; |
||||
|
private string _rootPath = "/wwwroot"; |
||||
|
|
||||
public HybridWebRootFileProvider(IVirtualFileProvider virtualFileProvider, IHostingEnvironment hostingEnvironment) |
protected AspNetCoreContentOptions Options { get; } |
||||
|
|
||||
|
public HybridWebRootFileProvider( |
||||
|
IVirtualFileProvider virtualFileProvider, |
||||
|
IHostingEnvironment hostingEnvironment, |
||||
|
IOptions<AspNetCoreContentOptions> options) |
||||
{ |
{ |
||||
_virtualFileProvider = virtualFileProvider; |
_virtualFileProvider = virtualFileProvider; |
||||
_hostingEnvironment = hostingEnvironment; |
_hostingEnvironment = hostingEnvironment; |
||||
|
Options = options.Value; |
||||
|
|
||||
_fileProvider = CreateHybridProvider(); |
_fileProvider = CreateHybridProvider(); |
||||
} |
} |
||||
|
|
||||
public virtual IFileInfo GetFileInfo(string subpath) |
public IFileInfo GetFileInfo(string subpath) |
||||
{ |
{ |
||||
return _fileProvider.GetFileInfo("/wwwroot" + subpath); //TODO: Hard-coded "/wwwroot" is not good!
|
Check.NotNullOrEmpty(subpath, nameof(subpath)); |
||||
|
|
||||
|
if (ExtraAllowedFolder(subpath) && ExtraAllowedExtension(subpath)) |
||||
|
{ |
||||
|
var fileInfo = _fileProvider.GetFileInfo(subpath); |
||||
|
if (fileInfo.Exists) |
||||
|
{ |
||||
|
return fileInfo; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return _fileProvider.GetFileInfo(_rootPath + subpath); |
||||
} |
} |
||||
|
|
||||
public virtual IDirectoryContents GetDirectoryContents(string subpath) |
public IDirectoryContents GetDirectoryContents([NotNull] string subpath) |
||||
{ |
{ |
||||
return _fileProvider.GetDirectoryContents("/wwwroot" + subpath); |
Check.NotNullOrEmpty(subpath, nameof(subpath)); |
||||
|
|
||||
|
if (ExtraAllowedFolder(subpath)) |
||||
|
{ |
||||
|
var directory = _fileProvider.GetDirectoryContents(subpath); |
||||
|
if (directory.Exists) |
||||
|
{ |
||||
|
return directory; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return _fileProvider.GetDirectoryContents(_rootPath + subpath); |
||||
} |
} |
||||
|
|
||||
public virtual IChangeToken Watch(string filter) |
public virtual IChangeToken Watch(string filter) |
||||
{ |
{ |
||||
return _fileProvider.Watch("/wwwroot" + filter); |
if (!ExtraAllowedFolder(filter)) |
||||
} |
{ |
||||
|
return _fileProvider.Watch("/wwwroot" + filter); |
||||
|
} |
||||
|
|
||||
public string GetAbsolutePath(string relativePath) |
return new CompositeChangeToken( |
||||
{ |
new[] |
||||
return Path.Combine(_hostingEnvironment.ContentRootPath, "wwwroot", relativePath.RemovePreFix("/")); |
{ |
||||
|
_fileProvider.Watch("/wwwroot" + filter), |
||||
|
_fileProvider.Watch(filter) |
||||
|
} |
||||
|
); |
||||
} |
} |
||||
|
|
||||
protected virtual IFileProvider CreateHybridProvider() |
protected virtual IFileProvider CreateHybridProvider() |
||||
{ |
{ |
||||
return new CompositeFileProvider( |
return new CompositeFileProvider( |
||||
_hostingEnvironment.ContentRootFileProvider, |
new PhysicalFileProvider(_hostingEnvironment.ContentRootPath), |
||||
_virtualFileProvider |
_virtualFileProvider |
||||
); |
); |
||||
} |
} |
||||
|
|
||||
|
protected virtual bool ExtraAllowedFolder(string path) |
||||
|
{ |
||||
|
return Options.AllowedExtraWebContentFolders.Any(s => path.StartsWith(s, StringComparison.OrdinalIgnoreCase)); |
||||
|
} |
||||
|
|
||||
|
protected virtual bool ExtraAllowedExtension(string path) |
||||
|
{ |
||||
|
return Options.AllowedExtraWebContentFileExtensions.Any(e => path.EndsWith(e, StringComparison.OrdinalIgnoreCase)); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
@ -1,39 +0,0 @@ |
|||||
using Microsoft.Extensions.FileProviders; |
|
||||
using Microsoft.Extensions.Primitives; |
|
||||
|
|
||||
namespace Volo.Abp.VirtualFileSystem |
|
||||
{ |
|
||||
public class FileProviderSubFolderWrapper : IFileProvider |
|
||||
{ |
|
||||
private readonly IFileProvider _fileProvider; |
|
||||
private readonly string _contentPath; |
|
||||
|
|
||||
public FileProviderSubFolderWrapper(IFileProvider fileProvider, string contentPath = null) |
|
||||
{ |
|
||||
_contentPath = contentPath; |
|
||||
_fileProvider = fileProvider; |
|
||||
} |
|
||||
|
|
||||
public IFileInfo GetFileInfo(string subpath) |
|
||||
{ |
|
||||
return _fileProvider.GetFileInfo(NormalizePath(subpath)); |
|
||||
} |
|
||||
|
|
||||
public IDirectoryContents GetDirectoryContents(string subpath) |
|
||||
{ |
|
||||
return _fileProvider.GetDirectoryContents(NormalizePath(subpath)); |
|
||||
} |
|
||||
|
|
||||
private string NormalizePath(string subpath) |
|
||||
{ |
|
||||
return _contentPath == null |
|
||||
? subpath |
|
||||
: _contentPath + subpath; |
|
||||
} |
|
||||
|
|
||||
public IChangeToken Watch(string filter) |
|
||||
{ |
|
||||
return _fileProvider.Watch(filter); //TODO: Why this does not use NormalizePath?
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue