diff --git a/global.json b/global.json
index 391ba3c2a3..da113e4cbd 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,7 @@
{
"sdk": {
- "version": "8.0.100",
- "rollForward": "latestFeature"
+ "version": "8.0.0",
+ "rollForward": "latestFeature",
+ "allowPrerelease": false
}
-}
+}
\ No newline at end of file
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
new file mode 100644
index 0000000000..bfa71d3932
--- /dev/null
+++ b/src/Directory.Packages.props
@@ -0,0 +1,70 @@
+
+
+
+ true
+ NU1507
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj b/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj
index b6f8e44c5d..82439efec6 100644
--- a/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj
+++ b/src/Umbraco.Cms.Api.Common/Umbraco.Cms.Api.Common.csproj
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj b/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj
index db7ac432bc..bb9b44cf51 100644
--- a/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj
+++ b/src/Umbraco.Cms.Imaging.ImageSharp/Umbraco.Cms.Imaging.ImageSharp.csproj
@@ -2,11 +2,12 @@
Umbraco CMS - Imaging - ImageSharp
Adds imaging support using ImageSharp/ImageSharp.Web to Umbraco CMS.
+ false
-
-
+
+
diff --git a/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj b/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj
index 84370a54c2..d55479d8ec 100644
--- a/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj
+++ b/src/Umbraco.Cms.Imaging.ImageSharp2/Umbraco.Cms.Imaging.ImageSharp2.csproj
@@ -2,6 +2,7 @@
Umbraco CMS - Imaging - ImageSharp 2
Adds imaging support using ImageSharp/ImageSharp.Web version 2 to Umbraco CMS.
+ false
diff --git a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
index baab56e96e..5229f513a2 100644
--- a/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
+++ b/src/Umbraco.Cms.Persistence.EFCore.SqlServer/Umbraco.Cms.Persistence.EFCore.SqlServer.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj b/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj
index e17f16b8bb..36751bb869 100644
--- a/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj
+++ b/src/Umbraco.Cms.Persistence.EFCore.Sqlite/Umbraco.Cms.Persistence.EFCore.Sqlite.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
index 538a4d9f25..39f035407b 100644
--- a/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
+++ b/src/Umbraco.Cms.Persistence.EFCore/Umbraco.Cms.Persistence.EFCore.csproj
@@ -5,10 +5,9 @@
-
-
-
-
+
+
+
diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
index 37cd0da0f7..0de13a39b6 100644
--- a/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
+++ b/src/Umbraco.Cms.Persistence.SqlServer/Umbraco.Cms.Persistence.SqlServer.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj b/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj
index b49b4eebee..f9755aad61 100644
--- a/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj
+++ b/src/Umbraco.Cms.Persistence.Sqlite/Umbraco.Cms.Persistence.Sqlite.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj
index 37653bc9a8..b930ff1bc0 100644
--- a/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj
+++ b/src/Umbraco.Cms.Targets/Umbraco.Cms.Targets.csproj
@@ -4,6 +4,9 @@
Installs Umbraco CMS with minimal dependencies in your ASP.NET Core project.
false
false
+
+ false
+ false
diff --git a/src/Umbraco.Cms/Umbraco.Cms.csproj b/src/Umbraco.Cms/Umbraco.Cms.csproj
index 39a3b03c56..8b0dcb8a87 100644
--- a/src/Umbraco.Cms/Umbraco.Cms.csproj
+++ b/src/Umbraco.Cms/Umbraco.Cms.csproj
@@ -4,6 +4,7 @@
Installs Umbraco CMS with all default dependencies in your ASP.NET Core project.
false
false
+ false
diff --git a/src/Umbraco.Core/Constants-WebhookEvents.cs b/src/Umbraco.Core/Constants-WebhookEvents.cs
index afd57b5188..41b9849f08 100644
--- a/src/Umbraco.Core/Constants-WebhookEvents.cs
+++ b/src/Umbraco.Core/Constants-WebhookEvents.cs
@@ -6,6 +6,57 @@ public static partial class Constants
{
public static class Aliases
{
+
+ ///
+ /// Webhook event alias for content versions deleted
+ ///
+ public const string ContentDeletedVersions = "Umbraco.ContentDeletedVersions";
+
+ ///
+ /// Webhook event alias for content blueprint saved
+ ///
+ public const string ContentSavedBlueprint = "Umbraco.ContentSavedBlueprint";
+
+ ///
+ /// Webhook event alias for content blueprint deleted
+ ///
+ public const string ContentDeletedBlueprint = "Umbraco.ContentDeletedBlueprint";
+
+ ///
+ /// Webhook event alias for content moved into the recycle bin.
+ ///
+ public const string ContentMovedToRecycleBin = "Umbraco.ContentMovedToRecycleBin";
+
+ ///
+ /// Webhook event alias for content sorted.
+ ///
+ public const string ContentSorted = "Umbraco.ContentSorted";
+
+ ///
+ /// Webhook event alias for content moved.
+ ///
+ public const string ContentMoved = "Umbraco.ContentMoved";
+
+ ///
+ /// Webhook event alias for content copied.
+ ///
+ public const string ContentCopied = "Umbraco.ContentCopied";
+
+ ///
+ /// Webhook event alias for content emptied recycle bin.
+ ///
+ public const string ContentEmptiedRecycleBin = "Umbraco.ContentEmptiedRecycleBin";
+
+ ///
+ /// Webhook event alias for content rolled back.
+ ///
+ public const string ContentRolledBack = "Umbraco.ContentRolledBack";
+
+ ///
+ /// Webhook event alias for content saved.
+ ///
+ public const string ContentSaved = "Umbraco.ContentSaved";
+
///
/// Webhook event alias for content publish.
///
diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml
index 572fe05dd4..00cb113ddf 100644
--- a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml
+++ b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml
@@ -1941,6 +1941,14 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
Create header
Logs
No webhook headers have been added
+ No events were found.
+ Enabled
+ Events
+ Event
+ Url
+ Types
+ Webhook key
+ Retry count
Add language
diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
index 33901735ee..c6c0280997 100644
--- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
+++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
@@ -2023,6 +2023,14 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
Create header
Logs
No webhook headers have been added
+ No events were found.
+ Enabled
+ Events
+ Event
+ Url
+ Types
+ Webhook key
+ Retry count
Add language
diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/fr.xml b/src/Umbraco.Core/EmbeddedResources/Lang/fr.xml
index b30dba4a69..24da7d0066 100644
--- a/src/Umbraco.Core/EmbeddedResources/Lang/fr.xml
+++ b/src/Umbraco.Core/EmbeddedResources/Lang/fr.xml
@@ -1585,6 +1585,13 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
Ceci n'est pas d'application pour un Type d'Elément
Vous avez apporté des modifications à cette propriété. Etes-vous certain.e de vouloir les annuler?
+
+ Créer un webhook
+ Ajouter un header au webhook
+ Logs
+ Ajouter un Type de Document
+ Ajouter un Type de Media
+
Ajouter une langue
Langue obligatoire
@@ -1715,6 +1722,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à
Configuration
Modélisation
Parties Tierces
+ Webhooks
Nouvelle mise à jour disponible
diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs
index afeb8ba9fa..f88b96c9d6 100644
--- a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs
+++ b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs
@@ -53,6 +53,8 @@ public class HealthCheckResults
return new HealthCheckResults(results, allChecksSuccessful);
}
+ public static async Task Create(HealthCheck check) => await Create(new List() { check });
+
public void LogResults()
{
Logger.LogInformation("Scheduled health check results:");
diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs
index 4cf5bdd6af..9bced05ff5 100644
--- a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs
@@ -71,6 +71,14 @@ public interface IPublishedPropertyType
///
Type ModelClrType { get; }
+ ///
+ /// Gets the property model Delivery Api CLR type.
+ ///
+ ///
+ /// The model CLR type may be a type, or may contain types.
+ ///
+ Type DeliveryApiModelClrType => ModelClrType;
+
///
/// Gets the property CLR type.
///
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs
index 52e3371767..ed2d19cd6f 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs
@@ -24,6 +24,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
private PropertyCacheLevel _deliveryApiCacheLevelForExpansion;
private Type? _modelClrType;
+ private Type? _deliveryApiModelClrType;
private Type? _clrType;
#region Constructors
@@ -192,17 +193,13 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
}
}
+ var deliveryApiPropertyValueConverter = _converter as IDeliveryApiPropertyValueConverter;
+
_cacheLevel = _converter?.GetPropertyCacheLevel(this) ?? PropertyCacheLevel.Snapshot;
- if (_converter is IDeliveryApiPropertyValueConverter deliveryApiPropertyValueConverter)
- {
- _deliveryApiCacheLevel = deliveryApiPropertyValueConverter.GetDeliveryApiPropertyCacheLevel(this);
- _deliveryApiCacheLevelForExpansion = deliveryApiPropertyValueConverter.GetDeliveryApiPropertyCacheLevelForExpansion(this);
- }
- else
- {
- _deliveryApiCacheLevel = _deliveryApiCacheLevelForExpansion = _cacheLevel;
- }
+ _deliveryApiCacheLevel = deliveryApiPropertyValueConverter?.GetDeliveryApiPropertyCacheLevel(this) ?? _cacheLevel;
+ _deliveryApiCacheLevelForExpansion = deliveryApiPropertyValueConverter?.GetDeliveryApiPropertyCacheLevelForExpansion(this) ?? _cacheLevel;
_modelClrType = _converter?.GetPropertyValueType(this) ?? typeof(object);
+ _deliveryApiModelClrType = deliveryApiPropertyValueConverter?.GetDeliveryApiPropertyValueType(this) ?? _modelClrType;
}
///
@@ -352,6 +349,20 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
}
}
+ ///
+ public Type DeliveryApiModelClrType
+ {
+ get
+ {
+ if (!_initialized)
+ {
+ Initialize();
+ }
+
+ return _deliveryApiModelClrType!;
+ }
+ }
+
///
public Type? ClrType
{
diff --git a/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs b/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs
new file mode 100644
index 0000000000..67df86deb1
--- /dev/null
+++ b/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs
@@ -0,0 +1,13 @@
+using Umbraco.Cms.Core.HealthChecks;
+
+namespace Umbraco.Cms.Core.Notifications;
+
+public class HealthCheckCompletedNotification : INotification
+{
+ public HealthCheckCompletedNotification(HealthCheckResults healthCheckResults)
+ {
+ HealthCheckResults = healthCheckResults;
+ }
+
+ public HealthCheckResults HealthCheckResults { get; }
+}
diff --git a/src/Umbraco.Core/PublishedCache/IPublishedSnapshotAccessor.cs b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotAccessor.cs
index 0f9cc8fca9..8abc0906ce 100644
--- a/src/Umbraco.Core/PublishedCache/IPublishedSnapshotAccessor.cs
+++ b/src/Umbraco.Core/PublishedCache/IPublishedSnapshotAccessor.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
namespace Umbraco.Cms.Core.PublishedCache;
///
@@ -6,5 +8,5 @@ namespace Umbraco.Cms.Core.PublishedCache;
///
public interface IPublishedSnapshotAccessor
{
- bool TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot);
+ bool TryGetPublishedSnapshot([NotNullWhen(true)] out IPublishedSnapshot? publishedSnapshot);
}
diff --git a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
index 8f3e4fe827..91e32e6db4 100644
--- a/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
+++ b/src/Umbraco.Core/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
using Umbraco.Cms.Core.Web;
namespace Umbraco.Cms.Core.PublishedCache;
@@ -29,7 +30,7 @@ public class UmbracoContextPublishedSnapshotAccessor : IPublishedSnapshotAccesso
set => throw new NotSupportedException(); // not ok to set
}
- public bool TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot)
+ public bool TryGetPublishedSnapshot([NotNullWhen(true)] out IPublishedSnapshot? publishedSnapshot)
{
if (!_umbracoContextAccessor.TryGetUmbracoContext(out IUmbracoContext? umbracoContext))
{
diff --git a/src/Umbraco.Core/Services/UserServiceExtensions.cs b/src/Umbraco.Core/Services/UserServiceExtensions.cs
index f17a266616..7399f37fe8 100644
--- a/src/Umbraco.Core/Services/UserServiceExtensions.cs
+++ b/src/Umbraco.Core/Services/UserServiceExtensions.cs
@@ -8,6 +8,11 @@ namespace Umbraco.Extensions;
public static class UserServiceExtensions
{
public static EntityPermission? GetPermissions(this IUserService userService, IUser? user, string path)
+ {
+ return userService.GetAllPermissions(user, path).FirstOrDefault();
+ }
+
+ public static EntityPermissionCollection GetAllPermissions(this IUserService userService, IUser? user, string path)
{
var ids = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
@@ -23,7 +28,7 @@ public static class UserServiceExtensions
" could not be parsed into an array of integers or the path was empty");
}
- return userService.GetPermissions(user, ids[^1]).FirstOrDefault();
+ return userService.GetPermissions(user, ids[^1]);
}
///
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 7e56ff8f76..8aebb53f60 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -7,16 +7,16 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs
new file mode 100644
index 0000000000..3d6f0163d7
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs
@@ -0,0 +1,37 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Copied", Constants.WebhookEvents.Types.Content)]
+public class ContentCopiedWebhookEvent : WebhookEventBase
+{
+ public ContentCopiedWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentCopied;
+
+ public override object? ConvertNotificationToRequestPayload(ContentCopiedNotification notification)
+ {
+ return new
+ {
+ notification.Copy,
+ notification.Original,
+ notification.ParentId,
+ notification.RelateToOriginal
+ };
+ }
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs
new file mode 100644
index 0000000000..996b8abd15
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs
@@ -0,0 +1,32 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Template [Blueprint] Deleted", Constants.WebhookEvents.Types.Content)]
+public class ContentDeletedBlueprintWebhookEvent : WebhookEventContentBase
+{
+ public ContentDeletedBlueprintWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedBlueprint;
+
+ protected override IEnumerable GetEntitiesFromNotification(ContentDeletedBlueprintNotification notification) =>
+ notification.DeletedBlueprints;
+
+ protected override object ConvertEntityToRequestPayload(IContent entity) => entity;
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs
new file mode 100644
index 0000000000..c543bfe3ca
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs
@@ -0,0 +1,37 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Versions Deleted", Constants.WebhookEvents.Types.Content)]
+public class ContentDeletedVersionsWebhookEvent : WebhookEventBase
+{
+ public ContentDeletedVersionsWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedVersions;
+
+ public override object? ConvertNotificationToRequestPayload(ContentDeletedVersionsNotification notification)
+ {
+ return new
+ {
+ notification.Id,
+ notification.DeletePriorVersions,
+ notification.SpecificVersion,
+ notification.DateToRetain
+ };
+ }
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/ContentDeleteWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs
similarity index 77%
rename from src/Umbraco.Core/Webhooks/Events/ContentDeleteWebhookEvent.cs
rename to src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs
index 85a1f39ba9..1282822995 100644
--- a/src/Umbraco.Core/Webhooks/Events/ContentDeleteWebhookEvent.cs
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs
@@ -5,12 +5,12 @@ using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Sync;
-namespace Umbraco.Cms.Core.Webhooks.Events;
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
-[WebhookEvent("Content was deleted", Constants.WebhookEvents.Types.Content)]
-public class ContentDeleteWebhookEvent : WebhookEventContentBase
+[WebhookEvent("Content Deleted", Constants.WebhookEvents.Types.Content)]
+public class ContentDeletedWebhookEvent : WebhookEventContentBase
{
- public ContentDeleteWebhookEvent(
+ public ContentDeletedWebhookEvent(
IWebhookFiringService webhookFiringService,
IWebhookService webhookService,
IOptionsMonitor webhookSettings,
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs
new file mode 100644
index 0000000000..8670d23c49
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs
@@ -0,0 +1,41 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.DeliveryApi;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Recycle Bin Emptied", Constants.WebhookEvents.Types.Content)]
+public class ContentEmptiedRecycleBinWebhookEvent : WebhookEventContentBase
+{
+ private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
+ private readonly IApiContentBuilder _apiContentBuilder;
+
+ public ContentEmptiedRecycleBinWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor,
+ IPublishedSnapshotAccessor publishedSnapshotAccessor,
+ IApiContentBuilder apiContentBuilder)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ _publishedSnapshotAccessor = publishedSnapshotAccessor;
+ _apiContentBuilder = apiContentBuilder;
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentEmptiedRecycleBin;
+
+ protected override IEnumerable GetEntitiesFromNotification(ContentEmptiedRecycleBinNotification notification) =>
+ notification.DeletedEntities;
+
+ protected override object? ConvertEntityToRequestPayload(IContent entity) => entity;
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs
new file mode 100644
index 0000000000..6ed74d8c66
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs
@@ -0,0 +1,29 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Moved to Recycle Bin", Constants.WebhookEvents.Types.Content)]
+public class ContentMovedToRecycleBinWebhookEvent : WebhookEventBase
+{
+ public ContentMovedToRecycleBinWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentMovedToRecycleBin;
+
+ public override object? ConvertNotificationToRequestPayload(ContentMovedToRecycleBinNotification notification)
+ => notification.MoveInfoCollection;
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs
new file mode 100644
index 0000000000..46d487c499
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs
@@ -0,0 +1,29 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Moved", Constants.WebhookEvents.Types.Content)]
+public class ContentMovedWebhookEvent : WebhookEventBase
+{
+ public ContentMovedWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentMoved;
+
+ public override object? ConvertNotificationToRequestPayload(ContentMovedNotification notification)
+ => notification.MoveInfoCollection;
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/ContentPublishWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs
similarity index 86%
rename from src/Umbraco.Core/Webhooks/Events/ContentPublishWebhookEvent.cs
rename to src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs
index e1ba7125ec..5847fb450e 100644
--- a/src/Umbraco.Core/Webhooks/Events/ContentPublishWebhookEvent.cs
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs
@@ -8,15 +8,15 @@ using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Sync;
-namespace Umbraco.Cms.Core.Webhooks.Events;
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
-[WebhookEvent("Content was published", Constants.WebhookEvents.Types.Content)]
-public class ContentPublishWebhookEvent : WebhookEventContentBase
+[WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)]
+public class ContentPublishedWebhookEvent : WebhookEventContentBase
{
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IApiContentBuilder _apiContentBuilder;
- public ContentPublishWebhookEvent(
+ public ContentPublishedWebhookEvent(
IWebhookFiringService webhookFiringService,
IWebhookService webhookService,
IOptionsMonitor webhookSettings,
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBack.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBack.cs
new file mode 100644
index 0000000000..f38ff571f9
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBack.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.DeliveryApi;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Rolled Back", Constants.WebhookEvents.Types.Content)]
+public class ContentRolledBackWebhookEvent : WebhookEventContentBase
+{
+ private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
+ private readonly IApiContentBuilder _apiContentBuilder;
+
+ public ContentRolledBackWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor,
+ IPublishedSnapshotAccessor publishedSnapshotAccessor,
+ IApiContentBuilder apiContentBuilder)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ _publishedSnapshotAccessor = publishedSnapshotAccessor;
+ _apiContentBuilder = apiContentBuilder;
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentRolledBack;
+
+ protected override IEnumerable GetEntitiesFromNotification(ContentRolledBackNotification notification) =>
+ new List { notification.Entity };
+
+ protected override object? ConvertEntityToRequestPayload(IContent entity)
+ {
+ if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
+ {
+ return null;
+ }
+
+ // Get preview/saved version of content for a rollback
+ IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(true, entity.Key);
+ return publishedContent is null ? null : _apiContentBuilder.Build(publishedContent);
+ }
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs
new file mode 100644
index 0000000000..40630b453f
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs
@@ -0,0 +1,33 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Template [Blueprint] Saved", Constants.WebhookEvents.Types.Content)]
+public class ContentSavedBlueprintWebhookEvent : WebhookEventContentBase
+{
+ public ContentSavedBlueprintWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentSavedBlueprint;
+
+ protected override IEnumerable
+ GetEntitiesFromNotification(ContentSavedBlueprintNotification notification)
+ => new List { notification.SavedBlueprint };
+
+ protected override object ConvertEntityToRequestPayload(IContent entity) => entity;
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs
new file mode 100644
index 0000000000..fac16de822
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.DeliveryApi;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Saved", Constants.WebhookEvents.Types.Content)]
+public class ContentSavedWebhookEvent : WebhookEventContentBase
+{
+ private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
+ private readonly IApiContentBuilder _apiContentBuilder;
+
+ public ContentSavedWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor,
+ IPublishedSnapshotAccessor publishedSnapshotAccessor,
+ IApiContentBuilder apiContentBuilder)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ _publishedSnapshotAccessor = publishedSnapshotAccessor;
+ _apiContentBuilder = apiContentBuilder;
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentSaved;
+
+ protected override IEnumerable GetEntitiesFromNotification(ContentSavedNotification notification) =>
+ notification.SavedEntities;
+
+ protected override object? ConvertEntityToRequestPayload(IContent entity)
+ {
+ if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
+ {
+ return null;
+ }
+
+ // Get preview/saved version of content
+ IPublishedContent? publishedContent = publishedSnapshot.Content.GetById(true, entity.Key);
+ return publishedContent is null ? null : _apiContentBuilder.Build(publishedContent);
+ }
+}
diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs
new file mode 100644
index 0000000000..d2a95028e2
--- /dev/null
+++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs
@@ -0,0 +1,53 @@
+using Microsoft.Extensions.Options;
+using Umbraco.Cms.Core.Configuration.Models;
+using Umbraco.Cms.Core.DeliveryApi;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Notifications;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Core.Services;
+using Umbraco.Cms.Core.Sync;
+
+namespace Umbraco.Cms.Core.Webhooks.Events.Content;
+
+[WebhookEvent("Content Sorted", Constants.WebhookEvents.Types.Content)]
+public class ContentSortedWebhookEvent : WebhookEventBase
+{
+ private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
+ private readonly IApiContentBuilder _apiContentBuilder;
+
+ public ContentSortedWebhookEvent(
+ IWebhookFiringService webhookFiringService,
+ IWebhookService webhookService,
+ IOptionsMonitor webhookSettings,
+ IServerRoleAccessor serverRoleAccessor,
+ IPublishedSnapshotAccessor publishedSnapshotAccessor,
+ IApiContentBuilder apiContentBuilder)
+ : base(
+ webhookFiringService,
+ webhookService,
+ webhookSettings,
+ serverRoleAccessor)
+ {
+ _publishedSnapshotAccessor = publishedSnapshotAccessor;
+ _apiContentBuilder = apiContentBuilder;
+ }
+
+ public override string Alias => Constants.WebhookEvents.Aliases.ContentSorted;
+
+ public override object? ConvertNotificationToRequestPayload(ContentSortedNotification notification)
+ {
+ if (_publishedSnapshotAccessor.TryGetPublishedSnapshot(out IPublishedSnapshot? publishedSnapshot) is false || publishedSnapshot!.Content is null)
+ {
+ return null;
+ }
+ var sortedEntities = new List