Serverside generated preview URLs (#20021)
* Serverside generated preview URLs * Add URL provider notation to UrlInfo * Change preview URL generation to happen at preview time based on provider alias * Update XML docs * Always add culture (if available) to preview URL * Do not log user input (security vulnerability) * Fix typo * Re-generate TypeScript client from Management API * Deprecated `UmbDocumentPreviewRepository.enter()` (for v19) Fixed TS errors Added temp stub for `getPreviewUrl` * Adds `previewOption` extension-type * Adds "default" `previewOption` kind * Relocated "Save and Preview" workspace action reworked using the "default" `previewOption` kind. * Added stub for "urlProvider" `previewOption` kind * Renamed "workspace-action-default-kind.element.ts" to a more suitable filename. Exported element so can be reused in other packages, e.g. documents, for the new "save and preview" feature. * Refactored "Save and Preview" button to work with first action's manifest/API. * Reverted `previewOption` extension-type Re-engineered to make a "urlProvider" kind for `workspaceActionMenuItem`. This is to simplify the extension point and surrounding logic. * Modified `saveAndPreview` Document Workspace Context to accept a URL Provider Alias. * Refactored "Save and Preview" button to extend `UmbWorkspaceActionElement`. This did mean exposing certain methods/properties to be overridable. * Used `umbPeekError` to surface any errors to the user * Renamed `urlProvider` kind to `previewOption` * Relocated `urlProviderAlias` inside the `meta` property * also throw an error * Added missing `await` * Fix build errors after forward merge --------- Co-authored-by: leekelleher <leekelleher@gmail.com> Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
|
||||
@@ -29,13 +30,15 @@ internal sealed class PublishedUrlInfoProviderTests : PublishedUrlInfoProviderTe
|
||||
|
||||
// Assert the url of subpage is correct
|
||||
Assert.AreEqual(1, subPageUrls.Count);
|
||||
Assert.IsTrue(subPageUrls.First().IsUrl);
|
||||
Assert.AreEqual("/text-page-1/", subPageUrls.First().Text);
|
||||
Assert.IsNotNull(subPageUrls.First().Url);
|
||||
Assert.AreEqual("/text-page-1/", subPageUrls.First().Url!.ToString());
|
||||
Assert.AreEqual(Constants.UrlProviders.Content, subPageUrls.First().Provider);
|
||||
Assert.AreEqual(Subpage.Key, DocumentUrlService.GetDocumentKeyByRoute("/text-page-1/", "en-US", null, false));
|
||||
|
||||
// Assert the url of child of second root is not exposed
|
||||
Assert.AreEqual(1, childOfSecondRootUrls.Count);
|
||||
Assert.IsFalse(childOfSecondRootUrls.First().IsUrl);
|
||||
Assert.IsNull(childOfSecondRootUrls.First().Url);
|
||||
Assert.AreEqual(Constants.UrlProviders.Content, childOfSecondRootUrls.First().Provider);
|
||||
|
||||
// Ensure the url without hide top level is not finding the child of second root
|
||||
Assert.AreNotEqual(childOfSecondRoot.Key, DocumentUrlService.GetDocumentKeyByRoute("/second-root/text-page-1/", "en-US", null, false));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
@@ -35,11 +36,13 @@ internal sealed class PublishedUrlInfoProvider_hidetoplevel_false : PublishedUrl
|
||||
var childOfSecondRootUrls = await PublishedUrlInfoProvider.GetAllAsync(childOfSecondRoot);
|
||||
|
||||
Assert.AreEqual(1, subPageUrls.Count);
|
||||
Assert.IsTrue(subPageUrls.First().IsUrl);
|
||||
Assert.AreEqual("/textpage/text-page-1/", subPageUrls.First().Text);
|
||||
Assert.IsNotNull(subPageUrls.First().Url);
|
||||
Assert.AreEqual("/textpage/text-page-1/", subPageUrls.First().Url!.ToString());
|
||||
Assert.AreEqual(Constants.UrlProviders.Content, subPageUrls.First().Provider);
|
||||
|
||||
Assert.AreEqual(1, childOfSecondRootUrls.Count);
|
||||
Assert.IsTrue(childOfSecondRootUrls.First().IsUrl);
|
||||
Assert.AreEqual("/second-root/text-page-1/", childOfSecondRootUrls.First().Text);
|
||||
Assert.IsNotNull(childOfSecondRootUrls.First().Url);
|
||||
Assert.AreEqual("/second-root/text-page-1/", childOfSecondRootUrls.First().Url!.ToString());
|
||||
Assert.AreEqual(Constants.UrlProviders.Content, childOfSecondRootUrls.First().Provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,8 +233,8 @@ internal sealed class DomainAndUrlsTests : UmbracoIntegrationTest
|
||||
foreach (var culture in Cultures)
|
||||
{
|
||||
var domain = GetDomainUrlFromCultureCode(culture);
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Text == domain));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Text == "https://localhost" + domain));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url?.ToString() == domain && x.Message == null));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url?.ToString() == "https://localhost" + domain && x.Message == null));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -263,14 +263,14 @@ internal sealed class DomainAndUrlsTests : UmbracoIntegrationTest
|
||||
Assert.AreEqual(4, rootUrls.Count());
|
||||
|
||||
//We expect two for the domain that is setup
|
||||
Assert.IsTrue(rootUrls.Any(x => x.IsUrl && x.Text == domain && x.Culture == culture));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.IsUrl && x.Text == "https://localhost" + domain && x.Culture == culture));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url?.ToString() == domain && x.Culture == culture && x.Message == null));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url?.ToString() == "https://localhost" + domain && x.Culture == culture && x.Message == null));
|
||||
|
||||
//We expect the default language to be routable on the default path "/"
|
||||
Assert.IsTrue(rootUrls.Any(x => x.IsUrl && x.Text == "/" && x.Culture == Cultures[0]));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url?.ToString() == "/" && x.Culture == Cultures[0] && x.Message == null));
|
||||
|
||||
//We dont expect non-default languages without a domain to be routable
|
||||
Assert.IsTrue(rootUrls.Any(x => x.IsUrl == false && x.Culture == Cultures[2]));
|
||||
Assert.IsTrue(rootUrls.Any(x => x.Url == null && x.Culture == Cultures[2]));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class HtmlImageSourceParserTests
|
||||
It.IsAny<UrlMode>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/media/1001/my-image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("/media/1001/my-image.jpg", "Test Provider"));
|
||||
|
||||
var umbracoContextAccessor = new TestUmbracoContextAccessor();
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ public class HtmlLocalLinkParserTests
|
||||
It.IsAny<UrlMode>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/my-test-url"));
|
||||
.Returns(UrlInfo.AsUrl("/my-test-url", "Test Provider"));
|
||||
var contentType = new PublishedContentType(
|
||||
Guid.NewGuid(),
|
||||
666,
|
||||
@@ -213,7 +213,7 @@ public class HtmlLocalLinkParserTests
|
||||
It.IsAny<UrlMode>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/media/1001/my-image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("/media/1001/my-image.jpg", "Test Provider"));
|
||||
|
||||
var umbracoContextAccessor = new TestUmbracoContextAccessor();
|
||||
|
||||
@@ -257,14 +257,14 @@ public class HtmlLocalLinkParserTests
|
||||
UrlMode.Relative,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/relative-url"));
|
||||
.Returns(UrlInfo.AsUrl("/relative-url", "Test Provider"));
|
||||
contentUrlProvider
|
||||
.Setup(x => x.GetUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
UrlMode.Absolute,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("http://example.com/absolute-url"));
|
||||
.Returns(UrlInfo.AsUrl("http://example.com/absolute-url", "Test Provider"));
|
||||
|
||||
var contentType = new PublishedContentType(
|
||||
Guid.NewGuid(),
|
||||
@@ -328,28 +328,28 @@ public class HtmlLocalLinkParserTests
|
||||
UrlMode.Default,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/relative-url"));
|
||||
.Returns(UrlInfo.AsUrl("/relative-url", "Test Provider"));
|
||||
contentUrlProvider
|
||||
.Setup(x => x.GetUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
UrlMode.Relative,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/relative-url"));
|
||||
.Returns(UrlInfo.AsUrl("/relative-url", "Test Provider"));
|
||||
contentUrlProvider
|
||||
.Setup(x => x.GetUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
UrlMode.Absolute,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("https://example.com/absolute-url"));
|
||||
.Returns(UrlInfo.AsUrl("https://example.com/absolute-url", "Test Provider"));
|
||||
contentUrlProvider
|
||||
.Setup(x => x.GetUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
UrlMode.Auto,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/relative-url"));
|
||||
.Returns(UrlInfo.AsUrl("/relative-url", "Test Provider"));
|
||||
|
||||
var contentType = new PublishedContentType(
|
||||
Guid.NewGuid(),
|
||||
@@ -371,28 +371,28 @@ public class HtmlLocalLinkParserTests
|
||||
UrlMode.Default,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/media/relative/image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("/media/relative/image.jpg", "Test Provider"));
|
||||
mediaUrlProvider.Setup(x => x.GetMediaUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
It.IsAny<string>(),
|
||||
UrlMode.Relative,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/media/relative/image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("/media/relative/image.jpg", "Test Provider"));
|
||||
mediaUrlProvider.Setup(x => x.GetMediaUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
It.IsAny<string>(),
|
||||
UrlMode.Absolute,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("https://example.com/media/absolute/image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("https://example.com/media/absolute/image.jpg", "Test Provider"));
|
||||
mediaUrlProvider.Setup(x => x.GetMediaUrl(
|
||||
It.IsAny<IPublishedContent>(),
|
||||
It.IsAny<string>(),
|
||||
UrlMode.Auto,
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Uri>()))
|
||||
.Returns(UrlInfo.Url("/media/relative/image.jpg"));
|
||||
.Returns(UrlInfo.AsUrl("/media/relative/image.jpg", "Test Provider"));
|
||||
|
||||
var mediaType = new PublishedContentType(
|
||||
Guid.NewGuid(),
|
||||
|
||||
Reference in New Issue
Block a user