Skip to content

Commit

Permalink
Improve ioc registration order
Browse files Browse the repository at this point in the history
When intercepting default IContentLoader we need to make sure to
fall back to it in some cases but without the risk of running
into an infinite loop. The default implementation should be passed
in the constructor to the wrapper, named `defaultContentLoader` so
that it's clear it will not go through the interceptor once again.

Closes #255
  • Loading branch information
barteksekula committed Nov 4, 2024
1 parent 3724038 commit 67224d1
Show file tree
Hide file tree
Showing 64 changed files with 3,080 additions and 3,099 deletions.
10 changes: 5 additions & 5 deletions build/dependencies.props
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<CmsCoreVersion>12.14.0</CmsCoreVersion>
<CmsUIVersion>12.19.0</CmsUIVersion>
<CmsUmbrellaVersion>12.19.0</CmsUmbrellaVersion>
<CommerceVersion>14.11.0</CommerceVersion>
<CmsCoreVersion>12.21.8</CmsCoreVersion>
<CmsUIVersion>12.31.2</CmsUIVersion>
<CmsUmbrellaVersion>12.31.2</CmsUmbrellaVersion>
<CommerceVersion>14.29.0</CommerceVersion>
</PropertyGroup>
<ItemGroup>
<!-- CMS CORE -->
Expand Down Expand Up @@ -33,7 +33,7 @@
<PackageReference Update="AngleSharp" Version="0.14.0" />
<PackageReference Update="JObject" Version="1.0.0" />

<PackageReference Update="EPiServer.CMS.TinyMce" Version="4.2.0"/>
<PackageReference Update="EPiServer.CMS.TinyMce" Version="4.8.1"/>
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Advanced.CMS.ExternalReviews;
using EPiServer.ServiceLocation;
using EPiServer.Web.Routing;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Constraints;

namespace Advanced.CMS.AdvancedReviews;

internal class AdvancedReviewsEndpointRoutingExtension : IEndpointRoutingExtension
{
public void MapEndpoints(IEndpointRouteBuilder endpointRouteBuilder)
{
var options = endpointRouteBuilder.ServiceProvider.GetInstance<ExternalReviewOptions>();

endpointRouteBuilder.MapControllerRoute("ImageProxy", "/ImageProxy/{token}/{contentLink}",
new { controller = "ImageProxy", action = "Index" });

endpointRouteBuilder.MapControllerRoute("ExternalReviewLogin",
$"/{options.PinCodeSecurity.ExternalReviewLoginUrl}",
new { controller = "ExternalReviewLogin", action = "Index" });

endpointRouteBuilder.MapControllerRoute("ExternalReviewLoginSubmit",
$"/{options.PinCodeSecurity.ExternalReviewLoginUrl}",
new { controller = "ExternalReviewLogin", action = "Submit" },
new { httpMethod = new HttpMethodRouteConstraint(HttpMethods.Post) });
}
}
97 changes: 48 additions & 49 deletions src/Advanced.CMS.AdvancedReviews/ExternalReviewLoginController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,69 +3,68 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Advanced.CMS.AdvancedReviews
namespace Advanced.CMS.AdvancedReviews;

/// <summary>
/// Controller used to authenticate user using PIN code
/// </summary>
internal class ExternalReviewLoginController : Controller
{
/// <summary>
/// Controller used to authenticate user using PIN code
/// </summary>
public class ExternalReviewLoginController : Controller
private readonly IExternalReviewLinksRepository _externalReviewLinksRepository;
private readonly IExternalLinkPinCodeSecurityHandler _externalLinkPinCodeSecurityHandler;
private readonly IHttpContextAccessor _httpContextAccessor;

public ExternalReviewLoginController(IExternalReviewLinksRepository externalReviewLinksRepository, IExternalLinkPinCodeSecurityHandler externalLinkPinCodeSecurityHandler, IHttpContextAccessor httpContextAccessor)
{
private readonly IExternalReviewLinksRepository _externalReviewLinksRepository;
private readonly IExternalLinkPinCodeSecurityHandler _externalLinkPinCodeSecurityHandler;
private readonly IHttpContextAccessor _httpContextAccessor;
_externalReviewLinksRepository = externalReviewLinksRepository;
_externalLinkPinCodeSecurityHandler = externalLinkPinCodeSecurityHandler;
_httpContextAccessor = httpContextAccessor;
}

public ExternalReviewLoginController(IExternalReviewLinksRepository externalReviewLinksRepository, IExternalLinkPinCodeSecurityHandler externalLinkPinCodeSecurityHandler, IHttpContextAccessor httpContextAccessor)
[HttpGet]
public ActionResult Index(string id)
{
if (string.IsNullOrEmpty(id))
{
_externalReviewLinksRepository = externalReviewLinksRepository;
_externalLinkPinCodeSecurityHandler = externalLinkPinCodeSecurityHandler;
_httpContextAccessor = httpContextAccessor;
return new NotFoundObjectResult("Content not found");
}

[HttpGet]
public ActionResult Index(string id)
var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(id);
if (string.IsNullOrEmpty(externalReviewLink?.PinCode))
{
if (string.IsNullOrEmpty(id))
{
return new NotFoundObjectResult("Content not found");
}
return new NotFoundObjectResult("Content not found");
}

var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(id);
if (string.IsNullOrEmpty(externalReviewLink?.PinCode))
{
return new NotFoundObjectResult("Content not found");
}
return View();
}

return View();
[HttpPost]
public ActionResult Submit([FromForm] LoginModel loginModel)
{
if (string.IsNullOrEmpty(loginModel.Token))
{
return new NotFoundObjectResult("Content not found");
}

[HttpPost]
public ActionResult Submit([FromForm] LoginModel loginModel)
var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(loginModel.Token);
if (string.IsNullOrEmpty(externalReviewLink?.PinCode))
{
if (string.IsNullOrEmpty(loginModel.Token))
{
return new NotFoundObjectResult("Content not found");
}

var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(loginModel.Token);
if (string.IsNullOrEmpty(externalReviewLink?.PinCode))
{
return new NotFoundObjectResult("Content not found");
}
return new NotFoundObjectResult("Content not found");
}

if (_externalLinkPinCodeSecurityHandler.TryToSignIn(externalReviewLink, loginModel.Code))
{
return new RedirectResult(externalReviewLink.LinkUrl);
}
else
{
return new NotFoundObjectResult("Content not found");
}
if (_externalLinkPinCodeSecurityHandler.TryToSignIn(externalReviewLink, loginModel.Code))
{
return new RedirectResult(externalReviewLink.LinkUrl);
}
else
{
return new NotFoundObjectResult("Content not found");
}
}
}

public class LoginModel
{
public string Code { get; set; }
public string Token { get; set; }
}
public class LoginModel
{
public string Code { get; set; }
public string Token { get; set; }
}
121 changes: 60 additions & 61 deletions src/Advanced.CMS.AdvancedReviews/ImageProxyController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,75 +8,74 @@
using EPiServer.Web;
using Microsoft.AspNetCore.Mvc;

namespace Advanced.CMS.AdvancedReviews
{
public class ImageProxyController: Controller
{
private readonly IExternalReviewLinksRepository _externalReviewLinksRepository;
private readonly IContentLoader _contentLoader;
private readonly ThumbnailManager _thumbnailManager;
private readonly IMimeTypeResolver _mimeTypeResolver;
namespace Advanced.CMS.AdvancedReviews;

private string ThumbnailMimeType => _mimeTypeResolver.GetMimeMapping(ThumbnailHelper.ThumbnailExtension);
internal class ImageProxyController: Controller
{
private readonly IExternalReviewLinksRepository _externalReviewLinksRepository;
private readonly IContentLoader _contentLoader;
private readonly ThumbnailManager _thumbnailManager;
private readonly IMimeTypeResolver _mimeTypeResolver;

public ImageProxyController(IExternalReviewLinksRepository externalReviewLinksRepository,
IContentLoader contentLoader, ThumbnailManager thumbnailManager, IMimeTypeResolver mimeTypeResolver)
{
_externalReviewLinksRepository = externalReviewLinksRepository;
_contentLoader = contentLoader;
_thumbnailManager = thumbnailManager;
_mimeTypeResolver = mimeTypeResolver;
}
private string ThumbnailMimeType => _mimeTypeResolver.GetMimeMapping(ThumbnailHelper.ThumbnailExtension);

public IActionResult Index([FromRoute] string token, [FromRoute] string contentLink, [FromQuery] int? width, [FromQuery] int? height)
{
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(contentLink))
{
return new NotFoundResult();
}
public ImageProxyController(IExternalReviewLinksRepository externalReviewLinksRepository,
IContentLoader contentLoader, ThumbnailManager thumbnailManager, IMimeTypeResolver mimeTypeResolver)
{
_externalReviewLinksRepository = externalReviewLinksRepository;
_contentLoader = contentLoader;
_thumbnailManager = thumbnailManager;
_mimeTypeResolver = mimeTypeResolver;
}

var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);
if (externalReviewLink.IsExpired())
{
return new NotFoundResult();
}
public IActionResult Index([FromRoute] string token, [FromRoute] string contentLink, [FromQuery] int? width, [FromQuery] int? height)
{
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(contentLink))
{
return new NotFoundResult();
}

if(!ContentReference.TryParse(contentLink.Trim('/'), out var contentReference))
{
return new NotFoundResult();
}
var externalReviewLink = _externalReviewLinksRepository.GetContentByToken(token);
if (externalReviewLink.IsExpired())
{
return new NotFoundResult();
}

var content = _contentLoader.Get<IContent>(contentReference);
if (content is not ImageData imageData)
{
return new NotFoundResult();
}
if(!ContentReference.TryParse(contentLink.Trim('/'), out var contentReference))
{
return new NotFoundResult();
}

var returnThumbnail = width.HasValue && height.HasValue;
var content = _contentLoader.Get<IContent>(contentReference);
if (content is not ImageData imageData)
{
return new NotFoundResult();
}

var originalBlobBytes = imageData.BinaryData.ReadAllBytes();
var blobToReturn = returnThumbnail ? Generate(originalBlobBytes, width.Value, height.Value) : originalBlobBytes;
var returnThumbnail = width.HasValue && height.HasValue;

return File(blobToReturn, imageData.MimeType);
}
var originalBlobBytes = imageData.BinaryData.ReadAllBytes();
var blobToReturn = returnThumbnail ? Generate(originalBlobBytes, width.Value, height.Value) : originalBlobBytes;

private byte[] Generate(byte[] blobBytes, int width, int height)
{
var imgOperation = new ImageOperation(ImageEditorCommand.ResizeKeepScale, width, height)
{
// use transparency color
BackgroundColor = "#00000000"
};
return File(blobToReturn, imageData.MimeType);
}

try
{
return _thumbnailManager.ImageService.RenderImage(blobBytes,
new List<ImageOperation> { imgOperation }, ThumbnailMimeType, 1, 50);
}
catch
{
return null;
}
}
}
}
private byte[] Generate(byte[] blobBytes, int width, int height)
{
var imgOperation = new ImageOperation(ImageEditorCommand.ResizeKeepScale, width, height)
{
// use transparency color
BackgroundColor = "#00000000"
};

try
{
return _thumbnailManager.ImageService.RenderImage(blobBytes,
new List<ImageOperation> { imgOperation }, ThumbnailMimeType, 1, 50);
}
catch
{
return null;
}
}
}
Loading

0 comments on commit 67224d1

Please sign in to comment.