v14: Add Preview controller (#15481)

* Add Preview controller

* Implement PreviewService

* Add tests for endpoints.

* Add Authorization to previews

* Apply suggestions from code review

Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>

---------

Co-authored-by: Elitsa <elm@umbraco.dk>
Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>
This commit is contained in:
Nikolaj Geisle
2024-01-09 15:51:59 +01:00
committed by GitHub
parent c937d0f2ed
commit 3acda751b9
8 changed files with 149 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Api.Management.Controllers.Preview;
[ApiVersion("1.0")]
public class EndPreviewController : PreviewControllerBase
{
private readonly IPreviewService _previewService;
public EndPreviewController(IPreviewService previewService) => _previewService = previewService;
[HttpDelete]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult End()
{
_previewService.EndPreview();
return Ok();
}
}

View File

@@ -0,0 +1,23 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Api.Management.Controllers.Preview;
[ApiVersion("1.0")]
public class EnterPreviewController : PreviewControllerBase
{
private readonly IPreviewService _previewService;
public EnterPreviewController(IPreviewService previewService) => _previewService = previewService;
[HttpPost]
[MapToApiVersion("1.0")]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult Enter()
{
_previewService.EnterPreview();
return Ok();
}
}

View File

@@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Web.Common.Authorization;
namespace Umbraco.Cms.Api.Management.Controllers.Preview;
[ApiController]
[VersionedApiBackOfficeRoute("preview")]
[ApiExplorerSettings(GroupName = "Preview")]
public class PreviewControllerBase : ManagementApiControllerBase
{
}

View File

@@ -348,6 +348,7 @@ namespace Umbraco.Cms.Core.DependencyInjection
Services.AddSingleton<ConflictingPackageData>();
Services.AddSingleton<CompiledPackageXmlParser>();
Services.AddUnique<IPreviewService, PreviewService>();
// Register a noop IHtmlSanitizer to be replaced
Services.AddUnique<IHtmlSanitizer, NoopHtmlSanitizer>();

View File

@@ -0,0 +1,14 @@
namespace Umbraco.Cms.Core.Services;
public interface IPreviewService
{
/// <summary>
/// Enters preview mode for a given user that calls this
/// </summary>
void EnterPreview();
/// <summary>
/// Exits preview mode for a given user that calls this
/// </summary>
void EndPreview();
}

View File

@@ -0,0 +1,15 @@
using Umbraco.Cms.Core.Web;
namespace Umbraco.Cms.Core.Services;
public class PreviewService : IPreviewService
{
private readonly ICookieManager _cookieManager;
public PreviewService(ICookieManager cookieManager) => _cookieManager = cookieManager;
public void EnterPreview() => _cookieManager.SetCookieValue(Constants.Web.PreviewCookieName, "preview");
public void EndPreview() => _cookieManager.ExpireCookie(Constants.Web.PreviewCookieName);
}

View File

@@ -0,0 +1,30 @@
using System.Linq.Expressions;
using System.Net;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Controllers.Preview;
using Umbraco.Cms.Core;
namespace Umbraco.Cms.Tests.Integration.ManagementApi.Preview;
public class EndPreviewTests : ManagementApiTest<EndPreviewController>
{
protected override Expression<Func<EndPreviewController, object>> MethodSelector =>
x => x.End();
[Test]
public virtual async Task As_Admin_I_Have_Access()
{
await AuthenticateClientAsync(Client, "admin@umbraco.com", "1234567890", true);
var response = await Client.DeleteAsync(Url);
// Check if the set cookie header is sent
var doesHeaderExist = response.Headers.TryGetValues("Set-Cookie", out var setCookieValues) &&
setCookieValues.Any(value => value.Contains($"{Constants.Web.PreviewCookieName}=; expires"));
Assert.IsTrue(doesHeaderExist);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, await response.Content.ReadAsStringAsync());
}
}

View File

@@ -0,0 +1,30 @@
using System.Linq.Expressions;
using System.Net;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Controllers.Preview;
using Umbraco.Cms.Core;
namespace Umbraco.Cms.Tests.Integration.ManagementApi.Preview;
public class EnterPreviewTests : ManagementApiTest<EnterPreviewController>
{
protected override Expression<Func<EnterPreviewController, object>> MethodSelector =>
x => x.Enter();
[Test]
public virtual async Task As_Admin_I_Have_Access()
{
await AuthenticateClientAsync(Client, "admin@umbraco.com", "1234567890", true);
var response = await Client.PostAsync(Url, null);
// Check if the set cookie header is sent
var doesHeaderExist = response.Headers.TryGetValues("Set-Cookie", out var setCookieValues) &&
setCookieValues.Any(value => value.Contains($"{Constants.Web.PreviewCookieName}=preview; path=/"));
Assert.IsTrue(doesHeaderExist);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, await response.Content.ReadAsStringAsync());
}
}