diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs index 8043e645b7..ee22b5beed 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -18,6 +18,10 @@ namespace Umbraco.Web.BackOffice.Extensions // TODO: This is temporary, 'umbraco' cannot be hard coded, needs to use GetUmbracoMvcArea() // but actually we need to route all back office stuff in a back office area like we do in v8 + // TODO: We will also need to detect runtime state here and redirect to the installer, + // Potentially switch this to dynamic routing so we can essentially disable/overwrite the back office routes to redirect to install + // when required, example https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/ + endpoints.MapControllerRoute("Backoffice", "/umbraco/{Action}", new { Controller = "BackOffice", diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index da68e4d634..228f133ab0 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Serilog.Context; @@ -11,6 +12,7 @@ using Umbraco.Web.Common.Middleware; namespace Umbraco.Extensions { + public static class ApplicationBuilderExtensions { /// @@ -25,24 +27,7 @@ namespace Umbraco.Extensions return runtime.State.Level > RuntimeLevel.BootFailed; } - /// - /// Enables the Umbraco installer - /// - /// - /// - public static IApplicationBuilder UseUmbracoInstaller(this IApplicationBuilder app) - { - app.UseEndpoints(endpoints => - { - // TODO: Fix this routing with an area - endpoints.MapControllerRoute("Install", "/install/{controller}/{Action}", defaults: new { Area = "Install" }); - - //TODO register routing correct: Name must be like this - endpoints.MapControllerRoute("umbraco-api-UmbracoInstall-InstallApi", "/install/api/{Action}", defaults: new { Area = "Install", Controller = "InstallApi" }); - }); - - return app; - } + /// /// Start Umbraco diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoInstallApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoInstallApplicationBuilderExtensions.cs new file mode 100644 index 0000000000..b23519f389 --- /dev/null +++ b/src/Umbraco.Web.Common/Extensions/UmbracoInstallApplicationBuilderExtensions.cs @@ -0,0 +1,70 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Core; +using Umbraco.Core.Logging; +using Umbraco.Web; + +namespace Umbraco.Extensions +{ + public static class UmbracoInstallApplicationBuilderExtensions + { + /// + /// Enables the Umbraco installer + /// + /// + /// + public static IApplicationBuilder UseUmbracoInstaller(this IApplicationBuilder app) + { + app.UseEndpoints(endpoints => + { + var runtime = app.ApplicationServices.GetRequiredService(); + var logger = app.ApplicationServices.GetRequiredService(); + var uriUtility = app.ApplicationServices.GetRequiredService(); + switch (runtime.Level) + { + case RuntimeLevel.Install: + case RuntimeLevel.Upgrade: + + // TODO: Fix this routing with an area + endpoints.MapControllerRoute("Install", "/install/{controller}/{Action}", defaults: new { Area = "Install" }); + + // TODO register routing correct: Name must be like this + endpoints.MapControllerRoute("umbraco-api-UmbracoInstall-InstallApi", "/install/api/{Action}", defaults: new { Area = "Install", Controller = "InstallApi" }); + + // TODO: Potentially switch this to dynamic routing so we can essentially disable/overwrite the back office routes to redirect to install, + // example https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/ + + // register catch all because if we are in install/upgrade mode then we'll catch everything and redirect + endpoints.MapGet("{*url}", context => + { + var uri = context.Request.GetEncodedUrl(); + // redirect to install + ReportRuntime(logger, runtime.Level, "Umbraco must install or upgrade."); + var installPath = uriUtility.ToAbsolute(Constants.SystemDirectories.Install); + var installUrl = $"{installPath}/?redir=true&url={uri}"; + context.Response.Redirect(installUrl, true); + return Task.CompletedTask; + }); + + break; + } + }); + + return app; + } + + private static bool _reported; + private static RuntimeLevel _reportedLevel; + + private static void ReportRuntime(ILogger logger, RuntimeLevel level, string message) + { + if (_reported && _reportedLevel == level) return; + _reported = true; + _reportedLevel = level; + logger.Warn(typeof(UmbracoInstallApplicationBuilderExtensions), message); + } + } + +}