2020-05-13 16:09:54 +10:00
using System ;
2020-08-07 00:48:32 +10:00
using System.IO ;
2021-01-18 15:40:22 +01:00
using System.Linq ;
2020-03-30 21:27:35 +02:00
using System.Threading.Tasks ;
2020-11-20 15:32:36 +11:00
using Microsoft.AspNetCore.Authorization ;
2021-02-10 11:11:18 +01:00
using Microsoft.AspNetCore.Mvc ;
using Microsoft.AspNetCore.Mvc.ViewEngines ;
using Microsoft.Extensions.Options ;
2021-04-15 09:52:55 +02:00
using Umbraco.Cms.Core ;
2021-02-09 10:22:42 +01:00
using Umbraco.Cms.Core.Configuration.Models ;
using Umbraco.Cms.Core.Editors ;
using Umbraco.Cms.Core.Features ;
using Umbraco.Cms.Core.Hosting ;
using Umbraco.Cms.Core.PublishedCache ;
using Umbraco.Cms.Core.Security ;
using Umbraco.Cms.Core.Services ;
using Umbraco.Cms.Core.Web ;
using Umbraco.Cms.Core.WebAssets ;
2021-02-15 13:07:12 +01:00
using Umbraco.Cms.Infrastructure.WebAssets ;
2021-02-10 11:11:18 +01:00
using Umbraco.Cms.Web.BackOffice.ActionResults ;
using Umbraco.Cms.Web.BackOffice.Filters ;
2021-02-10 11:42:04 +01:00
using Umbraco.Cms.Web.Common.Authorization ;
using Umbraco.Cms.Web.Common.Filters ;
2021-02-10 11:11:18 +01:00
using Umbraco.Extensions ;
2018-02-27 15:47:47 +01:00
2021-02-10 11:11:18 +01:00
namespace Umbraco.Cms.Web.BackOffice.Controllers
2018-02-27 15:47:47 +01:00
{
[DisableBrowserCache]
2020-05-14 20:59:29 +10:00
[Area(Constants.Web.Mvc.BackOfficeArea)]
2018-02-27 15:47:47 +01:00
public class PreviewController : Controller
{
2018-04-05 12:50:00 +02:00
private readonly UmbracoFeatures _features ;
2020-08-21 14:52:47 +01:00
private readonly GlobalSettings _globalSettings ;
2018-09-10 11:34:31 +10:00
private readonly IPublishedSnapshotService _publishedSnapshotService ;
2020-10-21 16:51:00 +11:00
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor ;
2020-09-22 10:01:00 +02:00
private readonly ILocalizationService _localizationService ;
2020-02-13 07:56:50 +01:00
private readonly IHostingEnvironment _hostingEnvironment ;
2020-02-19 09:26:51 +01:00
private readonly ICookieManager _cookieManager ;
2020-03-17 10:28:03 +01:00
private readonly IRuntimeMinifier _runtimeMinifier ;
2020-05-13 16:09:54 +10:00
private readonly ICompositeViewEngine _viewEngines ;
2021-01-18 15:40:22 +01:00
private readonly IUmbracoContextAccessor _umbracoContextAccessor ;
2018-04-05 12:50:00 +02:00
2019-01-29 15:30:25 +01:00
public PreviewController (
UmbracoFeatures features ,
2021-09-24 09:49:53 +02:00
IOptionsSnapshot < GlobalSettings > globalSettings ,
2019-01-29 15:30:25 +01:00
IPublishedSnapshotService publishedSnapshotService ,
2020-10-21 16:51:00 +11:00
IBackOfficeSecurityAccessor backofficeSecurityAccessor ,
2019-11-20 10:50:15 +01:00
ILocalizationService localizationService ,
2020-02-19 09:26:51 +01:00
IHostingEnvironment hostingEnvironment ,
2020-03-03 11:18:54 +00:00
ICookieManager cookieManager ,
2020-05-13 16:09:54 +10:00
IRuntimeMinifier runtimeMinifier ,
2021-01-18 15:40:22 +01:00
ICompositeViewEngine viewEngines ,
IUmbracoContextAccessor umbracoContextAccessor )
2018-04-05 12:50:00 +02:00
{
_features = features ;
2020-08-21 14:52:47 +01:00
_globalSettings = globalSettings . Value ;
2018-09-10 11:34:31 +10:00
_publishedSnapshotService = publishedSnapshotService ;
2020-09-22 10:01:00 +02:00
_backofficeSecurityAccessor = backofficeSecurityAccessor ;
2019-01-29 15:30:25 +01:00
_localizationService = localizationService ;
2020-02-13 07:56:50 +01:00
_hostingEnvironment = hostingEnvironment ;
2020-02-19 09:26:51 +01:00
_cookieManager = cookieManager ;
2020-03-17 10:28:03 +01:00
_runtimeMinifier = runtimeMinifier ;
2020-05-13 16:09:54 +10:00
_viewEngines = viewEngines ;
2021-01-18 15:40:22 +01:00
_umbracoContextAccessor = umbracoContextAccessor ;
2018-04-05 12:50:00 +02:00
}
2020-11-20 15:32:36 +11:00
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccessWithoutApproval)]
2018-09-14 00:14:03 +10:00
[DisableBrowserCache]
2021-01-18 15:40:22 +01:00
public ActionResult Index ( int? id = null )
2018-02-27 15:47:47 +01:00
{
2019-01-29 15:30:25 +01:00
var availableLanguages = _localizationService . GetAllLanguages ( ) ;
2021-01-18 15:40:22 +01:00
if ( id . HasValue )
{
2021-08-17 13:09:25 +02:00
var umbracoContext = _umbracoContextAccessor . GetRequiredUmbracoContext ( ) ;
2022-04-01 11:09:51 +02:00
var content = umbracoContext . Content ? . GetById ( true , id . Value ) ;
2021-01-18 15:40:22 +01:00
if ( content is null )
return NotFound ( ) ;
2019-01-29 15:30:25 +01:00
2021-01-18 15:40:22 +01:00
availableLanguages = availableLanguages . Where ( language = > content . Cultures . ContainsKey ( language . IsoCode ) ) ;
}
2020-08-07 00:48:32 +10:00
var model = new BackOfficePreviewModel ( _features , availableLanguages ) ;
2018-03-14 13:56:49 +11:00
2018-03-14 15:24:30 +11:00
if ( model . PreviewExtendedHeaderView . IsNullOrWhiteSpace ( ) = = false )
2018-03-14 13:56:49 +11:00
{
2022-04-01 11:09:51 +02:00
var viewEngineResult = _viewEngines . FindView ( ControllerContext , model . PreviewExtendedHeaderView ! , false ) ;
2018-03-14 13:56:49 +11:00
if ( viewEngineResult . View = = null )
2018-03-14 15:24:30 +11:00
throw new InvalidOperationException ( "Could not find the view " + model . PreviewExtendedHeaderView + ", the following locations were searched: " + Environment . NewLine + string . Join ( Environment . NewLine , viewEngineResult . SearchedLocations ) ) ;
2018-02-28 13:41:49 +01:00
}
2018-03-14 13:56:49 +11:00
2020-08-07 00:48:32 +10:00
var viewPath = Path . Combine (
2020-09-01 18:10:12 +02:00
_globalSettings . UmbracoPath ,
2020-08-07 00:48:32 +10:00
Constants . Web . Mvc . BackOfficeArea ,
ControllerExtensions . GetControllerName < PreviewController > ( ) + ".cshtml" )
. Replace ( "\\" , "/" ) ; // convert to forward slashes since it's a virtual path
return View ( viewPath , model ) ;
2018-02-27 15:47:47 +01:00
}
2021-01-18 15:40:22 +01:00
2018-09-14 00:14:03 +10:00
/// <summary>
/// Returns the JavaScript file for preview
/// </summary>
/// <returns></returns>
[MinifyJavaScriptResult(Order = 0)]
2020-05-13 16:09:54 +10:00
// TODO: Replace this with response caching https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-3.1
//[OutputCache(Order = 1, VaryByParam = "none", Location = OutputCacheLocation.Server, Duration = 5000)]
2020-03-30 21:27:35 +02:00
public async Task < JavaScriptResult > Application ( )
2018-09-14 00:14:03 +10:00
{
2021-04-15 09:52:55 +02:00
var files = await _runtimeMinifier . GetJsAssetPathsAsync ( BackOfficeWebAssets . UmbracoPreviewJsBundleName ) ;
2020-04-03 11:03:06 +11:00
var result = BackOfficeJavaScriptInitializer . GetJavascriptInitialization ( files , "umbraco.preview" , _globalSettings , _hostingEnvironment ) ;
2018-09-14 00:14:03 +10:00
2020-05-13 16:09:54 +10:00
return new JavaScriptResult ( result ) ;
2018-09-14 00:14:03 +10:00
}
2018-09-10 11:34:31 +10:00
/// <summary>
/// The endpoint that is loaded within the preview iframe
/// </summary>
2020-11-20 15:32:36 +11:00
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
2018-09-14 00:44:36 +10:00
public ActionResult Frame ( int id , string culture )
2018-09-10 11:34:31 +10:00
{
2020-10-08 16:36:25 +02:00
EnterPreview ( id ) ;
2018-09-10 11:34:31 +10:00
2020-10-05 20:48:38 +02:00
// use a numeric URL because content may not be in cache and so .Url would fail
2018-09-14 00:44:36 +10:00
var query = culture . IsNullOrWhiteSpace ( ) ? string . Empty : $"?culture={culture}" ;
2018-09-10 11:34:31 +10:00
2021-01-20 11:45:03 +01:00
return RedirectPermanent ( $"../../{id}{query}" ) ;
2018-09-10 11:34:31 +10:00
}
2020-12-14 17:04:02 +11:00
2022-04-01 11:09:51 +02:00
public ActionResult ? EnterPreview ( int id )
2020-10-08 16:36:25 +02:00
{
2022-04-01 11:09:51 +02:00
var user = _backofficeSecurityAccessor . BackOfficeSecurity ? . CurrentUser ;
2020-12-14 17:04:02 +11:00
_cookieManager . SetCookieValue ( Constants . Web . PreviewCookieName , "preview" ) ;
2020-10-08 16:36:25 +02:00
2022-04-25 10:02:06 +02:00
return new EmptyResult ( ) ;
2020-10-08 16:36:25 +02:00
}
2020-12-14 17:04:02 +11:00
2022-04-01 11:09:51 +02:00
public ActionResult End ( string? redir = null )
2018-12-14 13:11:36 +00:00
{
2020-05-13 16:09:54 +10:00
_cookieManager . ExpireCookie ( Constants . Web . PreviewCookieName ) ;
2018-12-14 13:11:36 +00:00
2020-10-21 13:03:53 +01:00
// Expire Client-side cookie that determines whether the user has accepted to be in Preview Mode when visiting the website.
2020-11-12 12:57:03 +01:00
_cookieManager . ExpireCookie ( Constants . Web . AcceptPreviewCookieName ) ;
2018-12-14 13:11:36 +00:00
if ( Uri . IsWellFormedUriString ( redir , UriKind . Relative )
& & redir . StartsWith ( "//" ) = = false
2020-05-13 16:09:54 +10:00
& & Uri . TryCreate ( redir , UriKind . Relative , out var url ) )
2018-12-14 13:11:36 +00:00
return Redirect ( url . ToString ( ) ) ;
return Redirect ( "/" ) ;
}
2018-02-27 15:47:47 +01:00
}
}