Merge pull request #9512 from umbraco/netcore/feature/plugin_static_files
Netcore: Read static files from app_plugins folder
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Typed configuration options for the plugins.
|
||||
/// </summary>
|
||||
public class UmbracoPluginSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the allowed file extensions (including the period ".") that should be accessible from the browser.
|
||||
/// </summary>
|
||||
public ISet<string> BrowsableFileExtensions { get; set; } = new HashSet<string>(new[]
|
||||
{
|
||||
".html", // markup
|
||||
".css", // styles
|
||||
".js", // scripts
|
||||
".jpg", ".jpeg", ".gif", ".png", ".svg", // images
|
||||
".eot", ".ttf", ".woff", // fonts
|
||||
".xml", ".json", ".config", // configurations
|
||||
".lic" // license
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword";
|
||||
public const string ConfigModelsBuilder = ConfigPrefix + "ModelsBuilder";
|
||||
public const string ConfigNuCache = ConfigPrefix + "NuCache";
|
||||
public const string ConfigPlugins = ConfigPrefix + "Plugins";
|
||||
public const string ConfigRequestHandler = ConfigPrefix + "RequestHandler";
|
||||
public const string ConfigRuntime = ConfigPrefix + "Runtime";
|
||||
public const string ConfigRuntimeMinification = ConfigPrefix + "RuntimeMinification";
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SixLabors.ImageSharp.Web.DependencyInjection;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Web.BackOffice.Middleware;
|
||||
using Umbraco.Web.BackOffice.Plugins;
|
||||
using Umbraco.Web.BackOffice.Routing;
|
||||
using Umbraco.Web.Common.Security;
|
||||
|
||||
@@ -21,6 +27,7 @@ namespace Umbraco.Extensions
|
||||
app.UseRequestLocalization();
|
||||
app.UseUmbracoRequestLogging();
|
||||
app.UseUmbracoBackOffice();
|
||||
app.UseUmbracoPlugins();
|
||||
app.UseUmbracoPreview();
|
||||
app.UseUmbracoInstaller();
|
||||
|
||||
@@ -57,6 +64,30 @@ namespace Umbraco.Extensions
|
||||
return app;
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseUmbracoPlugins(this IApplicationBuilder app)
|
||||
{
|
||||
var hostingEnvironment = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
var umbracoPluginSettings = app.ApplicationServices.GetRequiredService<IOptions<UmbracoPluginSettings>>();
|
||||
|
||||
var pluginFolder = hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins);
|
||||
|
||||
// Ensure the plugin folder exists
|
||||
Directory.CreateDirectory(pluginFolder);
|
||||
|
||||
var fileProvider = new UmbracoPluginPhysicalFileProvider(
|
||||
pluginFolder,
|
||||
umbracoPluginSettings);
|
||||
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = fileProvider,
|
||||
RequestPath = Constants.SystemDirectories.AppPlugins
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
public static IApplicationBuilder UseUmbracoPreview(this IApplicationBuilder app)
|
||||
{
|
||||
app.UseEndpoints(endpoints =>
|
||||
@@ -67,7 +98,6 @@ namespace Umbraco.Extensions
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
private static IApplicationBuilder UseBackOfficeUserManagerAuditing(this IApplicationBuilder app)
|
||||
{
|
||||
var auditer = app.ApplicationServices.GetRequiredService<BackOfficeUserManagerAuditer>();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders.Physical;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Plugins
|
||||
{
|
||||
/// <summary>
|
||||
/// Looks up files using the on-disk file system and check file extensions are on a allow list
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When the environment variable "DOTNET_USE_POLLING_FILE_WATCHER" is set to "1" or "true", calls to
|
||||
/// <see cref="PhysicalFileProvider.Watch" /> will use <see cref="PollingFileChangeToken" />.
|
||||
/// </remarks>
|
||||
public class UmbracoPluginPhysicalFileProvider : PhysicalFileProvider, IFileProvider
|
||||
{
|
||||
private readonly IOptions<UmbracoPluginSettings> _options;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoPluginPhysicalFileProvider"/> class, at the given root directory.
|
||||
/// </summary>
|
||||
/// <param name="root">The root directory. This should be an absolute path.</param>
|
||||
/// <param name="options">The configuration options.</param>
|
||||
/// <param name="filters">Specifies which files or directories are excluded.</param>
|
||||
public UmbracoPluginPhysicalFileProvider(string root, IOptions<UmbracoPluginSettings> options, ExclusionFilters filters = ExclusionFilters.Sensitive)
|
||||
: base(root, filters) => _options = options;
|
||||
|
||||
/// <summary>
|
||||
/// Locate a file at the given path by directly mapping path segments to physical directories.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The path needs to pass the <see cref="ExclusionFilters"/> and the <see cref="UmbracoPluginSettings.BrowsableFileExtensions"/> to be found.
|
||||
/// </remarks>
|
||||
/// <param name="subpath">A path under the root directory</param>
|
||||
/// <returns>The file information. Caller must check <see cref="IFileInfo.Exists"/> property. </returns>
|
||||
public new IFileInfo GetFileInfo(string subpath)
|
||||
{
|
||||
var extension = Path.GetExtension(subpath);
|
||||
var subPathInclAppPluginsFolder = Path.Combine(Constants.SystemDirectories.AppPlugins, subpath);
|
||||
if (!_options.Value.BrowsableFileExtensions.Contains(extension))
|
||||
{
|
||||
return new NotFoundFileInfo(subPathInclAppPluginsFolder);
|
||||
}
|
||||
|
||||
return base.GetFileInfo(subPathInclAppPluginsFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,11 @@ using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
using Smidge;
|
||||
using Smidge.Nuglify;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Configuration.Models.Validation;
|
||||
using Umbraco.Core.DependencyInjection;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -195,6 +193,7 @@ namespace Umbraco.Core.DependencyInjection
|
||||
builder.Services.Configure<TypeFinderSettings>(builder.Config.GetSection(Core.Constants.Configuration.ConfigTypeFinder));
|
||||
builder.Services.Configure<UserPasswordConfigurationSettings>(builder.Config.GetSection(Core.Constants.Configuration.ConfigUserPassword));
|
||||
builder.Services.Configure<WebRoutingSettings>(builder.Config.GetSection(Core.Constants.Configuration.ConfigWebRouting));
|
||||
builder.Services.Configure<UmbracoPluginSettings>(builder.Config.GetSection(Core.Constants.Configuration.ConfigPlugins));
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Umbraco.Extensions;
|
||||
using Umbraco.Core.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Web.UI.NetCore
|
||||
{
|
||||
@@ -28,11 +28,14 @@ namespace Umbraco.Web.UI.NetCore
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
|
||||
/// <summary>
|
||||
/// Configures the services
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method gets called by the runtime. Use this method to add services to the container.
|
||||
/// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
|
||||
/// </remarks>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
#pragma warning disable IDE0022 // Use expression body for methods
|
||||
|
||||
Reference in New Issue
Block a user