-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
using Umbraco.Cms.Core.Cache; | ||
using Umbraco.Cms.Core.Events; | ||
using Umbraco.Cms.Core.Models; | ||
using Umbraco.Cms.Core.Notifications; | ||
using Umbraco.Cms.Core.Services; | ||
using Umbraco.Cms.Core.Strings; | ||
|
||
using uSync.BackOffice.Configuration; | ||
using uSync.BackOffice.Services; | ||
using uSync.Core; | ||
|
||
using static Umbraco.Cms.Core.Constants; | ||
|
||
namespace uSync.BackOffice.SyncHandlers.Handlers; | ||
|
||
[SyncHandler(uSyncConstants.Handlers.WebhookHandler, "Webhooks", "Webhooks", | ||
uSyncConstants.Priorites.Webhooks, | ||
Icon = "icon-filter-arrows", | ||
EntityType = UdiEntityType.Webhook, | ||
IsTwoPass = false | ||
)] | ||
public class WebhookHandler : SyncHandlerRoot<IWebhook, IWebhook>, ISyncHandler, | ||
Check failure on line 30 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
INotificationHandler<SavedNotification<IWebhook>>, | ||
INotificationHandler<DeletedNotification<IWebhook>>, | ||
INotificationHandler<SavingNotification<IWebhook>>, | ||
INotificationHandler<DeletingNotification<IWebhook>> | ||
{ | ||
private readonly IWebhookService _webhookService; | ||
|
||
public WebhookHandler( | ||
Check failure on line 38 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
Check failure on line 38 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
ILogger<SyncHandlerRoot<IWebhook, IWebhook>> logger, | ||
AppCaches appCaches, | ||
IShortStringHelper shortStringHelper, | ||
SyncFileService syncFileService, | ||
uSyncEventService mutexService, | ||
uSyncConfigService uSyncConfig, | ||
ISyncItemFactory itemFactory, | ||
IWebhookService webhookService) | ||
: base(logger, appCaches, shortStringHelper, syncFileService, mutexService, uSyncConfig, itemFactory) | ||
{ | ||
_webhookService = webhookService; | ||
} | ||
|
||
protected override IEnumerable<uSyncAction> DeleteMissingItems(IWebhook parent, IEnumerable<Guid> keysToKeep, bool reportOnly) | ||
Check failure on line 52 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
{ | ||
return []; | ||
} | ||
|
||
protected override IEnumerable<IWebhook> GetChildItems(IWebhook parent) | ||
Check failure on line 57 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
{ | ||
if (parent == null) | ||
{ | ||
return _webhookService.GetAllAsync(0, 1000).Result.Items; | ||
} | ||
|
||
return []; | ||
} | ||
|
||
protected override IEnumerable<IWebhook> GetFolders(IWebhook parent) => []; | ||
Check failure on line 67 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
|
||
protected override IWebhook GetFromService(IWebhook item) | ||
Check failure on line 69 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
=> _webhookService.GetAsync(item.Key).Result; | ||
|
||
protected override string GetItemName(IWebhook item) => item.Key.ToString(); | ||
Check failure on line 72 in uSync.BackOffice/SyncHandlers/Handlers/WebhookHandler.cs GitHub Actions / build
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Xml.Linq; | ||
|
||
using Lucene.Net.Queries.Function.ValueSources; | ||
|
||
using Microsoft.Extensions.Logging; | ||
|
||
using Umbraco.Cms.Core.Models; | ||
using Umbraco.Cms.Core.Services; | ||
|
||
using uSync.Core.Models; | ||
|
||
namespace uSync.Core.Serialization.Serializers; | ||
|
||
[SyncSerializer("ED18C89D-A9FF-4217-9F8E-6898CA63ED81", "Webhook Serializer", uSyncConstants.Serialization.Webhook, IsTwoPass = false)] | ||
public class WebhookSerializer : SyncSerializerBase<IWebhook>, ISyncSerializer<IWebhook> | ||
{ | ||
private readonly IWebhookService _webhookService; | ||
|
||
public WebhookSerializer( | ||
IEntityService entityService, | ||
ILogger<SyncSerializerBase<IWebhook>> logger, | ||
IWebhookService webhookService) | ||
: base(entityService, logger) | ||
{ | ||
_webhookService = webhookService; | ||
} | ||
|
||
public override void DeleteItem(IWebhook item) | ||
{ | ||
_webhookService.DeleteAsync(item.Key).Wait(); | ||
} | ||
|
||
public override IWebhook FindItem(int id) => null; | ||
|
||
public override IWebhook FindItem(Guid key) | ||
=> _webhookService.GetAsync(key).Result; | ||
|
||
public override IWebhook FindItem(string alias) | ||
{ | ||
if (Guid.TryParse(alias, out Guid key)) | ||
return FindItem(key); | ||
|
||
return null; | ||
} | ||
|
||
public override string ItemAlias(IWebhook item) | ||
=> item.Key.ToString(); | ||
|
||
public override void SaveItem(IWebhook item) | ||
{ | ||
if (item.Id > 0) | ||
{ | ||
_webhookService.UpdateAsync(item).Wait(); | ||
} | ||
else | ||
{ | ||
_webhookService.CreateAsync(item).Wait(); | ||
} | ||
} | ||
|
||
protected override SyncAttempt<IWebhook> DeserializeCore(XElement node, SyncSerializerOptions options) | ||
{ | ||
var key = node.GetKey(); | ||
var alias = node.GetAlias(); | ||
|
||
var details = new List<uSyncChange>(); | ||
|
||
var item = FindItem(key); | ||
if (item == null) | ||
{ | ||
// try and find by url/etc??? | ||
} | ||
|
||
var url = node.Element("Url").ValueOrDefault(string.Empty); | ||
|
||
if (item == null) | ||
{ | ||
item = new Webhook(url); | ||
} | ||
|
||
if (item.Key != key) | ||
{ | ||
details.AddUpdate("Key", item.Key, key); | ||
item.Key = key; | ||
} | ||
|
||
if (item.Url != url) | ||
{ | ||
details.AddUpdate("Url", item.Url, url); | ||
item.Url = url; | ||
} | ||
|
||
details.AddRange(DeserializeContentKeys(item, node)); | ||
details.AddRange(DeserializeEvents(item, node)); | ||
details.AddRange(DeserializeHeaders(item, node)); | ||
|
||
return SyncAttempt<IWebhook>.Succeed(node.GetAlias(), item, ChangeType.Import, details); | ||
} | ||
|
||
private static List<uSyncChange> DeserializeContentKeys(IWebhook item, XElement node) | ||
{ | ||
var details = new List<uSyncChange>(); | ||
|
||
var keys = node.Element("ContentTypeKeys"); | ||
if (keys == null) return details; | ||
|
||
List<Guid> newKeys = []; | ||
|
||
foreach (var key in keys.Elements("Key")) | ||
{ | ||
var keyValue = key.ValueOrDefault(Guid.Empty); | ||
if (keyValue == Guid.Empty) continue; | ||
newKeys.Add(keyValue); | ||
} | ||
|
||
var newOrderedKeys = newKeys.Order().ToArray(); | ||
var existingOrderedKeys = item.ContentTypeKeys.Order().ToArray(); | ||
|
||
if (existingOrderedKeys.Equals(newOrderedKeys) is false) | ||
{ | ||
details.AddUpdate("ContentTypeKeys", | ||
string.Join(",", existingOrderedKeys), | ||
string.Join(",", newOrderedKeys) | ||
, "/"); | ||
item.ContentTypeKeys = newOrderedKeys; | ||
} | ||
|
||
return details; | ||
|
||
} | ||
|
||
private static List<uSyncChange> DeserializeEvents(IWebhook item, XElement node) | ||
{ | ||
var details = new List<uSyncChange>(); | ||
|
||
var keys = node.Element("Events"); | ||
if (keys == null) return details; | ||
|
||
List<string> newKeys = []; | ||
|
||
foreach (var eventNode in keys.Elements("Event")) | ||
{ | ||
var eventValue = eventNode.ValueOrDefault(string.Empty); | ||
if (eventValue == string.Empty) continue; | ||
newKeys.Add(eventValue); | ||
} | ||
|
||
var newOrderedEvents = newKeys.Order().ToArray(); | ||
var existingOrderedEvents = item.Events.Order().ToArray(); | ||
|
||
if (existingOrderedEvents.Equals(newOrderedEvents) is false) | ||
{ | ||
details.AddUpdate("Events", | ||
string.Join(",", existingOrderedEvents), | ||
string.Join(",", newOrderedEvents) | ||
, "/"); | ||
item.Events = newOrderedEvents; | ||
} | ||
|
||
return details; | ||
} | ||
|
||
private static List<uSyncChange> DeserializeHeaders(IWebhook item, XElement node) | ||
{ | ||
var details = new List<uSyncChange>(); | ||
|
||
var keys = node.Element("Headers"); | ||
if (keys == null) return details; | ||
|
||
Dictionary<string, string> newHeaders = new(); | ||
|
||
foreach (var header in keys.Elements("Header")) | ||
{ | ||
var headerKey = header.Attribute("Key").ValueOrDefault(string.Empty); | ||
var headerValue = header.ValueOrDefault(string.Empty); | ||
|
||
if (headerKey == string.Empty) continue; | ||
if (newHeaders.ContainsKey(headerKey)) continue; // stop duplicates. | ||
newHeaders.Add(headerKey, headerValue); | ||
} | ||
|
||
var existingOrderedEvents = item.Headers.OrderBy(x => x.Key).ToDictionary(); | ||
var newOrderedHeaders = newHeaders.OrderBy(x => x.Key).ToDictionary(); | ||
|
||
if (existingOrderedEvents.Equals(newOrderedHeaders) is false) | ||
{ | ||
details.AddUpdate("Events", | ||
string.Join(",", existingOrderedEvents), | ||
string.Join(",", newOrderedHeaders) | ||
, "/"); | ||
item.Headers = newOrderedHeaders; | ||
} | ||
|
||
return details; | ||
} | ||
|
||
|
||
|
||
protected override SyncAttempt<XElement> SerializeCore(IWebhook item, SyncSerializerOptions options) | ||
{ | ||
var node = InitializeBaseNode(item, item.Url); | ||
|
||
node.Add(new XElement("Url", item.Url)); | ||
node.Add(new XElement("Enabled", item.Enabled)); | ||
|
||
node.Add(SerializeContentKeys(item)); | ||
node.Add(SerializeEvents(item)); | ||
node.Add(SerializeHeaders(item)); | ||
|
||
return SyncAttempt<XElement>.Succeed(item.Url, node, typeof(IWebhook), ChangeType.Export); | ||
|
||
} | ||
|
||
private static XElement SerializeContentKeys(IWebhook item) | ||
{ | ||
var keysNode = new XElement("ContentTypeKeys"); | ||
foreach (var contentTypeKey in item.ContentTypeKeys.Order()) | ||
{ | ||
keysNode.Add(new XElement("Key", contentTypeKey)); | ||
} | ||
|
||
return keysNode; | ||
} | ||
|
||
private static XElement SerializeEvents(IWebhook item) | ||
{ | ||
var eventsNode = new XElement("Events"); | ||
foreach(var eventItem in item.Events.Order()) | ||
{ | ||
eventsNode.Add(new XElement("Event", eventItem)); | ||
} | ||
return eventsNode; | ||
} | ||
|
||
private static XElement SerializeHeaders(IWebhook item) | ||
{ | ||
var headerNode = new XElement("Headers"); | ||
foreach(var headerItem in item.Headers.OrderBy(x => x.Key)) | ||
{ | ||
headerNode.Add(new XElement("Header", | ||
new XAttribute("Key", headerItem.Key), | ||
new XCData(headerItem.Value))); | ||
} | ||
|
||
return headerNode; | ||
} | ||
} |