From 3e7c232e76015436436e1381006b0be4976659ea Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Sat, 26 Mar 2022 11:56:24 +0800 Subject: [PATCH] feat(webhooks): add a client proxy publishing module to address layered module calls --- .../LINGYUN.Abp.WebHooks.ClientProxies.csproj | 16 ++++ .../AbpWebHooksClientProxiesModule.cs | 10 ++ .../ClientProxiesWebhookPublisher.cs | 91 +++++++++++++++++++ .../Abp/Webhooks/DefaultWebhookPublisher.cs | 35 +++++-- ...sManagementPermissionDefinitionProvider.cs | 5 + .../WebhooksManagementPermissions.cs | 5 + .../IWebhooksPublishAppService.cs | 9 ++ .../WebhooksManagementRemoteServiceConsts.cs | 2 +- .../WebhooksPublishInput.cs | 30 ++++++ .../WebhooksPublishAppService.cs | 45 +++++++++ ...NGYUN.Abp.WebhooksManagement.Domain.csproj | 2 +- .../WebhooksPublishController.cs | 27 ++++++ 12 files changed, 267 insertions(+), 10 deletions(-) create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN.Abp.WebHooks.ClientProxies.csproj create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/AbpWebHooksClientProxiesModule.cs create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/ClientProxiesWebhookPublisher.cs create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhooksPublishAppService.cs create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksPublishInput.cs create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhooksPublishAppService.cs create mode 100644 aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhooksPublishController.cs diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN.Abp.WebHooks.ClientProxies.csproj b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN.Abp.WebHooks.ClientProxies.csproj new file mode 100644 index 000000000..251dd53d3 --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN.Abp.WebHooks.ClientProxies.csproj @@ -0,0 +1,16 @@ + + + + + + + netstandard2.0 + + + + + + + + + diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/AbpWebHooksClientProxiesModule.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/AbpWebHooksClientProxiesModule.cs new file mode 100644 index 000000000..41e08a4a7 --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/AbpWebHooksClientProxiesModule.cs @@ -0,0 +1,10 @@ +using LINGYUN.Abp.WebhooksManagement; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Webhooks.ClientProxies; + +[DependsOn(typeof(AbpWebhooksModule))] +[DependsOn(typeof(WebhooksManagementHttpApiClientModule))] +public class AbpWebHooksClientProxiesModule : AbpModule +{ +} diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/ClientProxiesWebhookPublisher.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/ClientProxiesWebhookPublisher.cs new file mode 100644 index 000000000..85b25db61 --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks.ClientProxies/LINGYUN/Abp/WebHooks/ClientProxies/ClientProxiesWebhookPublisher.cs @@ -0,0 +1,91 @@ +using LINGYUN.Abp.WebhooksManagement; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Webhooks.ClientProxies; + +[Dependency(ReplaceServices = true)] +public class ClientProxiesWebhookPublisher : IWebhookPublisher, ITransientDependency +{ + protected IWebhooksPublishAppService PublishAppService { get; } + + public ClientProxiesWebhookPublisher( + IWebhooksPublishAppService publishAppService) + { + PublishAppService = publishAppService; + } + + public async virtual Task PublishAsync(string webhookName, object data, bool sendExactSameData = false, WebhookHeader headers = null) + { + var input = new WebhooksPublishInput + { + WebhookName = webhookName, + Data = JsonConvert.SerializeObject(data), + SendExactSameData = sendExactSameData, + }; + if (headers != null) + { + input.Header = new WebhooksHeaderInput + { + UseOnlyGivenHeaders = headers.UseOnlyGivenHeaders, + Headers = headers.Headers + }; + } + + await PublishAsync(input); + } + + public async virtual Task PublishAsync(string webhookName, object data, Guid? tenantId, bool sendExactSameData = false, WebhookHeader headers = null) + { + var input = new WebhooksPublishInput + { + WebhookName = webhookName, + Data = JsonConvert.SerializeObject(data), + SendExactSameData = sendExactSameData, + TenantIds = new List + { + tenantId + }, + }; + if (headers != null) + { + input.Header = new WebhooksHeaderInput + { + UseOnlyGivenHeaders = headers.UseOnlyGivenHeaders, + Headers = headers.Headers + }; + } + + await PublishAsync(input); + } + + public async virtual Task PublishAsync(Guid?[] tenantIds, string webhookName, object data, bool sendExactSameData = false, WebhookHeader headers = null) + { + var input = new WebhooksPublishInput + { + WebhookName = webhookName, + Data = JsonConvert.SerializeObject(data), + SendExactSameData = sendExactSameData, + TenantIds = tenantIds.ToList(), + }; + if (headers != null) + { + input.Header = new WebhooksHeaderInput + { + UseOnlyGivenHeaders = headers.UseOnlyGivenHeaders, + Headers = headers.Headers + }; + } + + await PublishAsync(input); + } + + protected virtual async Task PublishAsync(WebhooksPublishInput input) + { + await PublishAppService.PublishAsync(input); + } +} diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/DefaultWebhookPublisher.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/DefaultWebhookPublisher.cs index 5b2d38c71..176614535 100644 --- a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/DefaultWebhookPublisher.cs +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/DefaultWebhookPublisher.cs @@ -33,28 +33,45 @@ namespace LINGYUN.Abp.Webhooks } #region Async Publish Methods - public virtual async Task PublishAsync(string webhookName, object data, bool sendExactSameData = false, WebhookHeader headers = null) + + public virtual async Task PublishAsync( + string webhookName, + object data, + bool sendExactSameData = false, + WebhookHeader headers = null) { var subscriptions = await _webhookSubscriptionManager.GetAllSubscriptionsIfFeaturesGrantedAsync(_currentTenant.Id, webhookName); await PublishAsync(webhookName, data, subscriptions, sendExactSameData, headers); } - public virtual async Task PublishAsync(string webhookName, object data, Guid? tenantId, - bool sendExactSameData = false, WebhookHeader headers = null) + public virtual async Task PublishAsync( + string webhookName, + object data, + Guid? tenantId, + bool sendExactSameData = false, + WebhookHeader headers = null) { var subscriptions = await _webhookSubscriptionManager.GetAllSubscriptionsIfFeaturesGrantedAsync(tenantId, webhookName); await PublishAsync(webhookName, data, subscriptions, sendExactSameData, headers); } - public virtual async Task PublishAsync(Guid?[] tenantIds, string webhookName, object data, - bool sendExactSameData = false, WebhookHeader headers = null) + public virtual async Task PublishAsync( + Guid?[] tenantIds, + string webhookName, + object data, + bool sendExactSameData = false, + WebhookHeader headers = null) { var subscriptions = await _webhookSubscriptionManager.GetAllSubscriptionsOfTenantsIfFeaturesGrantedAsync(tenantIds, webhookName); await PublishAsync(webhookName, data, subscriptions, sendExactSameData, headers); } - private async Task PublishAsync(string webhookName, object data, List webhookSubscriptions, - bool sendExactSameData = false, WebhookHeader headers = null) + protected virtual async Task PublishAsync( + string webhookName, + object data, + List webhookSubscriptions, + bool sendExactSameData = false, + WebhookHeader headers = null) { if (webhookSubscriptions.IsNullOrEmpty()) { @@ -104,7 +121,9 @@ namespace LINGYUN.Abp.Webhooks #endregion - protected virtual async Task SaveAndGetWebhookAsync(Guid? tenantId, string webhookName, + protected virtual async Task SaveAndGetWebhookAsync( + Guid? tenantId, + string webhookName, object data) { var webhookInfo = new WebhookEvent diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissionDefinitionProvider.cs index b9295955e..3570b8a63 100644 --- a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissionDefinitionProvider.cs +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissionDefinitionProvider.cs @@ -10,6 +10,11 @@ public class WebhooksManagementPermissionDefinitionProvider : PermissionDefiniti { var group = context.AddGroup(WebhooksManagementPermissions.GroupName, L("Permission:WebhooksManagement")); + group.AddPermission( + WebhooksManagementPermissions.Publish, + L("Permission:Publish")) + .WithProviders(ClientPermissionValueProvider.ProviderName); + group.AddPermission( WebhooksManagementPermissions.ManageSettings, L("Permission:ManageSettings")); diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissions.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissions.cs index 0a1d9b0f7..307d94b49 100644 --- a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissions.cs +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/Authorization/WebhooksManagementPermissions.cs @@ -4,5 +4,10 @@ public static class WebhooksManagementPermissions { public const string GroupName = "WebhooksManagement"; + /// + /// 授权允许发布Webhooks事件, 建议客户端授权 + /// + public const string Publish = GroupName + ".Publish"; + public const string ManageSettings = GroupName + ".ManageSettings"; } diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhooksPublishAppService.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhooksPublishAppService.cs new file mode 100644 index 000000000..b3236f244 --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhooksPublishAppService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.WebhooksManagement; + +public interface IWebhooksPublishAppService : IApplicationService +{ + Task PublishAsync(WebhooksPublishInput input); +} diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksManagementRemoteServiceConsts.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksManagementRemoteServiceConsts.cs index f05d02644..3d5a2b9f6 100644 --- a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksManagementRemoteServiceConsts.cs +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksManagementRemoteServiceConsts.cs @@ -3,5 +3,5 @@ public static class WebhooksManagementRemoteServiceConsts { public const string RemoteServiceName = "WebhooksManagement"; - public const string ModuleName = "WebhooksManagement"; + public const string ModuleName = "webhooks-management"; } diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksPublishInput.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksPublishInput.cs new file mode 100644 index 000000000..a7879d87f --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhooksPublishInput.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.WebhooksManagement; + +public class WebhooksPublishInput +{ + [Required] + [DynamicStringLength(typeof(WebhookEventRecordConsts), nameof(WebhookEventRecordConsts.MaxWebhookNameLength))] + public string WebhookName { get; set; } + + [Required] + [DynamicStringLength(typeof(WebhookEventRecordConsts), nameof(WebhookEventRecordConsts.MaxDataLength))] + public string Data { get; set; } + + public bool SendExactSameData { get; set; } + + public WebhooksHeaderInput Header { get; set; } = new WebhooksHeaderInput(); + + public List TenantIds { get; set; } = new List(); +} + +public class WebhooksHeaderInput +{ + public bool UseOnlyGivenHeaders { get; set; } + + public IDictionary Headers { get; set; } = new Dictionary(); +} diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhooksPublishAppService.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhooksPublishAppService.cs new file mode 100644 index 000000000..7e2bee65e --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhooksPublishAppService.cs @@ -0,0 +1,45 @@ +using LINGYUN.Abp.Webhooks; +using LINGYUN.Abp.WebhooksManagement.Authorization; +using Microsoft.AspNetCore.Authorization; +using Newtonsoft.Json; +using System.Linq; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WebhooksManagement; + +[Authorize(WebhooksManagementPermissions.Publish)] +public class WebhooksPublishAppService : WebhooksManagementAppServiceBase, IWebhooksPublishAppService +{ + protected IWebhookPublisher InnerPublisher { get; } + + public WebhooksPublishAppService(IWebhookPublisher innerPublisher) + { + InnerPublisher = innerPublisher; + } + + public async virtual Task PublishAsync(WebhooksPublishInput input) + { + var webhookHeader = new WebhookHeader + { + UseOnlyGivenHeaders = input.Header.UseOnlyGivenHeaders, + Headers = input.Header.Headers, + }; + var inputData = JsonConvert.DeserializeObject(input.Data); + + if (input.TenantIds.Any()) + { + await InnerPublisher.PublishAsync( + input.TenantIds.ToArray(), + input.WebhookName, + inputData, + input.SendExactSameData, + webhookHeader); + return; + } + await InnerPublisher.PublishAsync( + input.WebhookName, + inputData, + input.SendExactSameData, + webhookHeader); + } +} diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN.Abp.WebhooksManagement.Domain.csproj b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN.Abp.WebhooksManagement.Domain.csproj index 2ba7caa77..5234b20c6 100644 --- a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN.Abp.WebhooksManagement.Domain.csproj +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN.Abp.WebhooksManagement.Domain.csproj @@ -16,7 +16,7 @@ - + diff --git a/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhooksPublishController.cs b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhooksPublishController.cs new file mode 100644 index 000000000..e9b3275f9 --- /dev/null +++ b/aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhooksPublishController.cs @@ -0,0 +1,27 @@ +using LINGYUN.Abp.WebhooksManagement.Authorization; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; + +namespace LINGYUN.Abp.WebhooksManagement; + +[RemoteService(Name = WebhooksManagementRemoteServiceConsts.RemoteServiceName)] +[Area(WebhooksManagementRemoteServiceConsts.ModuleName)] +[Authorize(WebhooksManagementPermissions.Publish)] +[Route("api/webhooks/publish")] +public class WebhooksPublishController : WebhooksManagementControllerBase, IWebhooksPublishAppService +{ + protected IWebhooksPublishAppService PublishAppService { get; } + + public WebhooksPublishController(IWebhooksPublishAppService publishAppService) + { + PublishAppService = publishAppService; + } + + [HttpPost] + public virtual Task PublishAsync(WebhooksPublishInput input) + { + return PublishAppService.PublishAsync(input); + } +}