Browse Source

feat: Use group isolation of Webhook definitions

pull/532/head
cKey 4 years ago
parent
commit
fce3123b63
  1. 24
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/IWebhookDefinitionContext.cs
  2. 6
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/IWebhookDefinitionManager.cs
  3. 35
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookDefinitionContext.cs
  4. 30
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookDefinitionManager.cs
  5. 101
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookGroupDefinition.cs
  6. 2
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/FodyWeavers.xml
  7. 5
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityRoleWebHooker.cs
  8. 4
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityUserWebHooker.cs
  9. 8
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityWebhookDefinitionProvider.cs
  10. 2
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityWebhookNames.cs
  11. 1
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/Localization/Resources/en.json
  12. 1
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/Localization/Resources/zh-Hans.json
  13. 4
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/OrganizationUnitWebHooker.cs
  14. 3
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/FodyWeavers.xml
  15. 30
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/FodyWeavers.xsd
  16. 30
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN.Abp.Webhooks.Saas.csproj
  17. 30
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/AbpWebhooksSaasModule.cs
  18. 48
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/EditionWebhooker.cs
  19. 11
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/EditionWto.cs
  20. 18
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/Localization/Resources/en.json
  21. 18
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/Localization/Resources/zh-Hans.json
  22. 60
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/SaasWebhookDefinitionProvider.cs
  23. 21
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/SaasWebhookNames.cs
  24. 48
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/TenantWebhooker.cs
  25. 12
      aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/TenantWto.cs
  26. 2
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhookSubscriptionAppService.cs
  27. 10
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhookAvailableGroupDto.cs
  28. 33
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhookSubscriptionAppService.cs
  29. 7
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain.Shared/LINGYUN/Abp/WebhooksManagement/Localization/Resources/en.json
  30. 7
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain.Shared/LINGYUN/Abp/WebhooksManagement/Localization/Resources/zh-Hans.json
  31. 10
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/Webhooks/WebhooksDefinitionProvider.cs
  32. 4
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/Webhooks/WebhooksNames.cs
  33. 2
      aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhookSubscriptionController.cs
  34. 1
      aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj
  35. 2
      aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs

24
aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/IWebhookDefinitionContext.cs

@ -1,22 +1,16 @@
namespace LINGYUN.Abp.Webhooks
using JetBrains.Annotations;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Webhooks
{
public interface IWebhookDefinitionContext
{
/// <summary>
/// Adds the specified webhook definition. Throws exception if it is already added
/// </summary>
void Add(params WebhookDefinition[] definitions);
WebhookGroupDefinition AddGroup(
[NotNull] string name,
ILocalizableString displayName = null);
/// <summary>
/// Gets a webhook definition by name.
/// Returns null if there is no webhook definition with given name.
/// </summary>
WebhookDefinition GetOrNull(string name);
WebhookGroupDefinition GetGroupOrNull(string name);
/// <summary>
/// Remove webhook with given name
/// </summary>
/// <param name="name">webhook definition name</param>
void Remove(string name);
void RemoveGroup(string name);
}
}

6
aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/IWebhookDefinitionManager.cs

@ -23,6 +23,12 @@ namespace LINGYUN.Abp.Webhooks
/// </summary>
IReadOnlyList<WebhookDefinition> GetAll();
/// <summary>
/// Gets all webhook group definitions.
/// </summary>
/// <returns></returns>
IReadOnlyList<WebhookGroupDefinition> GetGroups();
/// <summary>
/// Checks if given webhook name is available for given tenant.
/// </summary>

35
aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookDefinitionContext.cs

@ -7,48 +7,49 @@ namespace LINGYUN.Abp.Webhooks
{
public class WebhookDefinitionContext : IWebhookDefinitionContext
{
protected Dictionary<string, WebhookDefinition> Webhooks { get; }
protected Dictionary<string, WebhookGroupDefinition> Groups { get; }
public WebhookDefinitionContext(Dictionary<string, WebhookDefinition> webhooks)
public WebhookDefinitionContext(Dictionary<string, WebhookGroupDefinition> webhooks)
{
Webhooks = webhooks;
Groups = webhooks;
}
public void Add(params WebhookDefinition[] definitions)
public WebhookGroupDefinition AddGroup(
[NotNull] string name,
ILocalizableString displayName = null)
{
if (definitions.IsNullOrEmpty())
{
return;
}
Check.NotNull(name, nameof(name));
foreach (var definition in definitions)
if (Groups.ContainsKey(name))
{
Webhooks[definition.Name] = definition;
throw new AbpException($"There is already an existing webhook group with name: {name}");
}
return Groups[name] = new WebhookGroupDefinition(name, displayName);
}
public WebhookDefinition GetOrNull([NotNull] string name)
public WebhookGroupDefinition GetGroupOrNull([NotNull] string name)
{
Check.NotNull(name, nameof(name));
if (!Webhooks.ContainsKey(name))
if (!Groups.ContainsKey(name))
{
return null;
}
return Webhooks[name];
return Groups[name];
}
public void Remove(string name)
public void RemoveGroup(string name)
{
Check.NotNull(name, nameof(name));
if (!Webhooks.ContainsKey(name))
if (!Groups.ContainsKey(name))
{
throw new AbpException($"Undefined notification webhook: '{name}'.");
throw new AbpException($"Undefined notification webhook group: '{name}'.");
}
Webhooks.Remove(name);
Groups.Remove(name);
}
}
}

30
aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookDefinitionManager.cs

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.MultiTenancy;
@ -13,6 +14,9 @@ namespace LINGYUN.Abp.Webhooks
{
internal class WebhookDefinitionManager : IWebhookDefinitionManager, ISingletonDependency
{
protected IDictionary<string, WebhookGroupDefinition> WebhookGroupDefinitions => _lazyWebhookGroupDefinitions.Value;
private readonly Lazy<Dictionary<string, WebhookGroupDefinition>> _lazyWebhookGroupDefinitions;
protected IDictionary<string, WebhookDefinition> WebhookDefinitions => _lazyWebhookDefinitions.Value;
private readonly Lazy<Dictionary<string, WebhookDefinition>> _lazyWebhookDefinitions;
@ -26,6 +30,7 @@ namespace LINGYUN.Abp.Webhooks
_serviceProvider = serviceProvider;
_options = options.Value;
_lazyWebhookGroupDefinitions = new Lazy<Dictionary<string, WebhookGroupDefinition>>(CreateWebhookGroupDefinitions);
_lazyWebhookDefinitions = new Lazy<Dictionary<string, WebhookDefinition>>(CreateWebhookDefinitions);
}
@ -54,6 +59,11 @@ namespace LINGYUN.Abp.Webhooks
return WebhookDefinitions.Values.ToImmutableList();
}
public IReadOnlyList<WebhookGroupDefinition> GetGroups()
{
return WebhookGroupDefinitions.Values.ToImmutableList();
}
public async Task<bool> IsAvailableAsync(Guid? tenantId, string name)
{
if (tenantId == null) // host allowed to subscribe all webhooks
@ -90,6 +100,26 @@ namespace LINGYUN.Abp.Webhooks
{
var definitions = new Dictionary<string, WebhookDefinition>();
foreach (var groupDefinition in WebhookGroupDefinitions.Values)
{
foreach (var webhook in groupDefinition.Webhooks)
{
if (definitions.ContainsKey(webhook.Name))
{
throw new AbpException("Duplicate webhook name: " + webhook.Name);
}
definitions[webhook.Name] = webhook;
}
}
return definitions;
}
protected virtual Dictionary<string, WebhookGroupDefinition> CreateWebhookGroupDefinitions()
{
var definitions = new Dictionary<string, WebhookGroupDefinition>();
using (var scope = _serviceProvider.CreateScope())
{
var providers = _options

101
aspnet-core/modules/webhooks/LINGYUN.Abp.WebHooks/LINGYUN/Abp/Webhooks/WebhookGroupDefinition.cs

@ -0,0 +1,101 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Webhooks;
public class WebhookGroupDefinition
{
[NotNull]
public string Name { get; set; }
public Dictionary<string, object> Properties { get; }
private ILocalizableString _displayName;
public ILocalizableString DisplayName
{
get {
return _displayName;
}
set {
_displayName = value;
}
}
public IReadOnlyList<WebhookDefinition> Webhooks => _webhooks.ToImmutableList();
private readonly List<WebhookDefinition> _webhooks;
public object this[string name] {
get => Properties.GetOrDefault(name);
set => Properties[name] = value;
}
protected internal WebhookGroupDefinition(
string name,
ILocalizableString displayName = null)
{
Name = name;
DisplayName = displayName ?? new FixedLocalizableString(Name);
Properties = new Dictionary<string, object>();
_webhooks = new List<WebhookDefinition>();
}
public virtual WebhookDefinition AddWebhook(
string name,
ILocalizableString displayName = null,
ILocalizableString description = null)
{
if (Webhooks.Any(hook => hook.Name.Equals(name)))
{
throw new AbpException($"There is already an existing webhook with name: {name} in group {Name}");
}
var webhook = new WebhookDefinition(
name,
displayName,
description
);
_webhooks.Add(webhook);
return webhook;
}
public virtual void AddWebhooks(params WebhookDefinition[] webhooks)
{
foreach (var webhook in webhooks)
{
if (Webhooks.Any(hook => hook.Name.Equals(webhook.Name)))
{
throw new AbpException($"There is already an existing webhook with name: {webhook.Name} in group {Name}");
}
}
_webhooks.AddRange(webhooks);
}
[CanBeNull]
public WebhookDefinition GetWebhookOrNull([NotNull] string name)
{
Check.NotNull(name, nameof(name));
foreach (var webhook in Webhooks)
{
if (webhook.Name == name)
{
return webhook;
}
}
return null;
}
public override string ToString()
{
return $"[{nameof(WebhookGroupDefinition)} {Name}]";
}
}

2
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/FodyWeavers.xml

@ -1,3 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

5
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityRoleWebHooker.cs

@ -6,15 +6,16 @@ using Volo.Abp.Identity;
namespace LINGYUN.Abp.Webhooks.Identity;
public class IdentityRoleWebHooker :
public class IdentityRoleWebhooker :
IDistributedEventHandler<EntityCreatedEto<IdentityRoleEto>>,
IDistributedEventHandler<EntityUpdatedEto<IdentityRoleEto>>,
IDistributedEventHandler<EntityDeletedEto<IdentityRoleEto>>,
IDistributedEventHandler<IdentityRoleNameChangedEto>,
ITransientDependency
{
private readonly IWebhookPublisher _webhookPublisher;
public IdentityRoleWebHooker(
public IdentityRoleWebhooker(
IWebhookPublisher webhookPublisher)
{
_webhookPublisher = webhookPublisher;

4
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityUserWebHooker.cs

@ -6,7 +6,7 @@ using Volo.Abp.Users;
namespace LINGYUN.Abp.Webhooks.Identity;
public class IdentityUserWebHooker :
public class IdentityUserWebhooker :
IDistributedEventHandler<EntityCreatedEto<UserEto>>,
IDistributedEventHandler<EntityUpdatedEto<UserEto>>,
IDistributedEventHandler<EntityDeletedEto<UserEto>>,
@ -14,7 +14,7 @@ public class IdentityUserWebHooker :
{
private readonly IWebhookPublisher _webhookPublisher;
public IdentityUserWebHooker(
public IdentityUserWebhooker(
IWebhookPublisher webhookPublisher)
{
_webhookPublisher = webhookPublisher;

8
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityWebhookDefinitionProvider.cs

@ -7,8 +7,12 @@ public class IdentityWebhookDefinitionProvider : WebhookDefinitionProvider
{
public override void Define(IWebhookDefinitionContext context)
{
context.Add(CreateIdentityRoleWebhooks());
context.Add(CreateIdentityUserWebhooks());
var identityGroup = context.AddGroup(
IdentityWebhookNames.GroupName,
L("Webhooks:Identity"));
identityGroup.AddWebhooks(CreateIdentityRoleWebhooks());
identityGroup.AddWebhooks(CreateIdentityUserWebhooks());
}
protected virtual WebhookDefinition[] CreateIdentityRoleWebhooks()

2
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/IdentityWebhookNames.cs

@ -2,7 +2,7 @@
public static class IdentityWebhookNames
{
public const string GroupName = "abp.identity";
public const string GroupName = "abp.webhooks.identity";
public static class IdentityRole
{
public const string Prefix = GroupName + ".roles";

1
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/Localization/Resources/en.json

@ -1,6 +1,7 @@
{
"culture": "en",
"texts": {
"Webhooks:Identity": "Identity",
"Webhooks:CreateRole": "Create Role",
"Webhooks:CreateRoleDesc": "A new role has been created",
"Webhooks:UpdateRole": "Update Role",

1
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/Localization/Resources/zh-Hans.json

@ -1,6 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"Webhooks:Identity": "身份认证",
"Webhooks:CreateRole": "创建角色",
"Webhooks:CreateRoleDesc": "一个新角色已创建",
"Webhooks:UpdateRole": "编辑角色",

4
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Identity/LINGYUN/Abp/Webhooks/Identity/OrganizationUnitWebHooker.cs

@ -6,7 +6,7 @@ using Volo.Abp.Identity;
namespace LINGYUN.Abp.Webhooks.Identity;
public class OrganizationUnitWebHooker :
public class OrganizationUnitWebhooker :
IDistributedEventHandler<EntityCreatedEto<OrganizationUnitEto>>,
IDistributedEventHandler<EntityUpdatedEto<OrganizationUnitEto>>,
IDistributedEventHandler<EntityDeletedEto<OrganizationUnitEto>>,
@ -14,7 +14,7 @@ public class OrganizationUnitWebHooker :
{
private readonly IWebhookPublisher _webhookPublisher;
public OrganizationUnitWebHooker(
public OrganizationUnitWebhooker(
IWebhookPublisher webhookPublisher)
{
_webhookPublisher = webhookPublisher;

3
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

30
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN.Abp.Webhooks.Saas.csproj

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Webhooks\Saas\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Webhooks\Saas\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\Webhooks\Saas\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.EventBus" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Webhooks\LINGYUN.Abp.Webhooks.csproj" />
<ProjectReference Include="..\..\saas\LINGYUN.Abp.Saas.Domain.Shared\LINGYUN.Abp.Saas.Domain.Shared.csproj" />
</ItemGroup>
</Project>

30
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/AbpWebhooksSaasModule.cs

@ -0,0 +1,30 @@
using LINGYUN.Abp.Saas;
using LINGYUN.Abp.Saas.Localization;
using Volo.Abp.Domain;
using Volo.Abp.EventBus;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Webhooks.Saas;
[DependsOn(typeof(AbpDddDomainModule))]
[DependsOn(typeof(AbpEventBusModule))]
[DependsOn(typeof(AbpSaasDomainSharedModule))]
public class AbpWebhooksSaasModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpWebhooksSaasModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpSaasResource>()
.AddVirtualJson("/LINGYUN/Abp/Webhooks/Saas/Localization/Resources");
});
}
}

48
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/EditionWebhooker.cs

@ -0,0 +1,48 @@
using LINGYUN.Abp.Saas.Editions;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
namespace LINGYUN.Abp.Webhooks.Saas;
public class EditionWebhooker :
IDistributedEventHandler<EntityCreatedEto<EditionEto>>,
IDistributedEventHandler<EntityUpdatedEto<EditionEto>>,
IDistributedEventHandler<EntityDeletedEto<EditionEto>>,
ITransientDependency
{
private readonly IWebhookPublisher _webhookPublisher;
public EditionWebhooker(
IWebhookPublisher webhookPublisher)
{
_webhookPublisher = webhookPublisher;
}
public async virtual Task HandleEventAsync(EntityCreatedEto<EditionEto> eventData)
{
await PublishAsync(SaasWebhookNames.Edition.Create, eventData.Entity);
}
public async virtual Task HandleEventAsync(EntityUpdatedEto<EditionEto> eventData)
{
await PublishAsync(SaasWebhookNames.Edition.Update, eventData.Entity);
}
public async virtual Task HandleEventAsync(EntityDeletedEto<EditionEto> eventData)
{
await PublishAsync(SaasWebhookNames.Edition.Delete, eventData.Entity);
}
protected async virtual Task PublishAsync(string webhookName, EditionEto eto)
{
await _webhookPublisher.PublishAsync(
webhookName,
new EditionWto
{
Id = eto.Id,
DisplayName = eto.DisplayName
});
}
}

11
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/EditionWto.cs

@ -0,0 +1,11 @@
using System;
namespace LINGYUN.Abp.Webhooks.Saas;
[Serializable]
public class EditionWto
{
public Guid Id { get; set; }
public string DisplayName { get; set; }
}

18
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/Localization/Resources/en.json

@ -0,0 +1,18 @@
{
"culture": "en",
"texts": {
"Webhooks:Saas": "Saas",
"Webhooks:CreateEdition": "Create Edition",
"Webhooks:CreateEditionDesc": "A new Edition has been created",
"Webhooks:UpdateEdition": "Update Edition",
"Webhooks:UpdateEditionDesc": "A Edition has changed",
"Webhooks:DeleteEdition": "Delete Edition",
"Webhooks:DeleteEditionDesc": "Deleted Edition",
"Webhooks:CreateTenant": "Create Tenant",
"Webhooks:CreateTenantDesc": "A new Tenant has been created",
"Webhooks:UpdateTenant": "Update Tenant",
"Webhooks:UpdateTenantDesc": "A Tenant has been changed",
"Webhooks:DeleteTenant": "Delete Tenant",
"Webhooks:DeleteTenantDesc": "Deleted Tenant"
}
}

18
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/Localization/Resources/zh-Hans.json

@ -0,0 +1,18 @@
{
"culture": "zh-Hans",
"texts": {
"Webhooks:Saas": "Saas",
"Webhooks:CreateEdition": "创建版本",
"Webhooks:CreateEditionDesc": "一个新版本已创建",
"Webhooks:UpdateEdition": "编辑版本",
"Webhooks:UpdateEditionDesc": "一个版本属性已变更",
"Webhooks:DeleteEdition": "删除版本",
"Webhooks:DeleteEditionDesc": "已删除版本",
"Webhooks:CreateTenant": "创建租户",
"Webhooks:CreateTenantDesc": "一个新租户已创建",
"Webhooks:UpdateTenant": "编辑租户",
"Webhooks:UpdateTenantDesc": "一个租户属性已变更",
"Webhooks:DeleteTenant": "删除租户",
"Webhooks:DeleteTenantDesc": "已删除租户"
}
}

60
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/SaasWebhookDefinitionProvider.cs

@ -0,0 +1,60 @@
using LINGYUN.Abp.Saas.Localization;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Webhooks.Saas;
public class SaasWebhookDefinitionProvider : WebhookDefinitionProvider
{
public override void Define(IWebhookDefinitionContext context)
{
var saasGroup = context.AddGroup(
SaasWebhookNames.GroupName,
L("Webhooks:Saas"));
saasGroup.AddWebhooks(CreateEditionWebhooks());
saasGroup.AddWebhooks(CreateTenantWebhooks());
}
protected virtual WebhookDefinition[] CreateEditionWebhooks()
{
return new[]
{
new WebhookDefinition(
SaasWebhookNames.Edition.Create,
L("Webhooks:CreateEdition"),
L("Webhooks:CreateEditionDesc")),
new WebhookDefinition(
SaasWebhookNames.Edition.Update,
L("Webhooks:UpdateEdition"),
L("Webhooks:UpdateEditionDesc")),
new WebhookDefinition(
SaasWebhookNames.Edition.Delete,
L("Webhooks:DeleteEdition"),
L("Webhooks:DeleteEditionDesc")),
};
}
protected virtual WebhookDefinition[] CreateTenantWebhooks()
{
return new[]
{
new WebhookDefinition(
SaasWebhookNames.Tenant.Create,
L("Webhooks:CreateTenant"),
L("Webhooks:CreateTenantDesc")),
new WebhookDefinition(
SaasWebhookNames.Tenant.Update,
L("Webhooks:UpdateTenant"),
L("Webhooks:UpdateTenantDesc")),
new WebhookDefinition(
SaasWebhookNames.Tenant.Delete,
L("Webhooks:DeleteTenant"),
L("Webhooks:DeleteTenantDesc")),
};
}
private static ILocalizableString L(string name)
{
return LocalizableString.Create<AbpSaasResource>(name);
}
}

21
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/SaasWebhookNames.cs

@ -0,0 +1,21 @@
namespace LINGYUN.Abp.Webhooks.Saas;
public static class SaasWebhookNames
{
public const string GroupName = "abp.webhooks.saas";
public static class Edition
{
public const string Prefix = GroupName + ".editions";
public const string Create = Prefix + ".create";
public const string Update = Prefix + ".update";
public const string Delete = Prefix + ".delete";
}
public static class Tenant
{
public const string Prefix = GroupName + ".tenants";
public const string Create = Prefix + ".create";
public const string Update = Prefix + ".update";
public const string Delete = Prefix + ".delete";
}
}

48
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/TenantWebhooker.cs

@ -0,0 +1,48 @@
using LINGYUN.Abp.Saas.Tenants;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
namespace LINGYUN.Abp.Webhooks.Saas;
public class TenantWebhooker :
IDistributedEventHandler<EntityCreatedEto<TenantEto>>,
IDistributedEventHandler<EntityUpdatedEto<TenantEto>>,
IDistributedEventHandler<EntityDeletedEto<TenantEto>>,
ITransientDependency
{
private readonly IWebhookPublisher _webhookPublisher;
public TenantWebhooker(
IWebhookPublisher webhookPublisher)
{
_webhookPublisher = webhookPublisher;
}
public async virtual Task HandleEventAsync(EntityCreatedEto<TenantEto> eventData)
{
await PublishAsync(SaasWebhookNames.Tenant.Create, eventData.Entity);
}
public async virtual Task HandleEventAsync(EntityUpdatedEto<TenantEto> eventData)
{
await PublishAsync(SaasWebhookNames.Tenant.Update, eventData.Entity);
}
public async virtual Task HandleEventAsync(EntityDeletedEto<TenantEto> eventData)
{
await PublishAsync(SaasWebhookNames.Tenant.Delete, eventData.Entity);
}
protected async virtual Task PublishAsync(string webhookName, TenantEto eto)
{
await _webhookPublisher.PublishAsync(
webhookName,
new TenantWto
{
Id = eto.Id,
Name = eto.Name
});
}
}

12
aspnet-core/modules/webhooks/LINGYUN.Abp.Webhooks.Saas/LINGYUN/Abp/Webhooks/Saas/TenantWto.cs

@ -0,0 +1,12 @@
using System;
namespace LINGYUN.Abp.Webhooks.Saas;
[Serializable]
public class TenantWto
{
public Guid Id { get; set; }
public string Name { get; set; }
}

2
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/IWebhookSubscriptionAppService.cs

@ -13,5 +13,5 @@ public interface IWebhookSubscriptionAppService :
WebhookSubscriptionCreateInput,
WebhookSubscriptionUpdateInput>
{
Task<ListResultDto<WebhookAvailableDto>> GetAllAvailableWebhooksAsync();
Task<ListResultDto<WebhookAvailableGroupDto>> GetAllAvailableWebhooksAsync();
}

10
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application.Contracts/LINGYUN/Abp/WebhooksManagement/WebhookAvailableGroupDto.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WebhooksManagement;
public class WebhookAvailableGroupDto
{
public string Name { get; set; }
public string DisplayName { get; set; }
public List<WebhookAvailableDto> Webhooks { get; set; } = new List<WebhookAvailableDto>();
}

33
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Application/LINGYUN/Abp/WebhooksManagement/WebhookSubscriptionAppService.cs

@ -103,25 +103,36 @@ public class WebhookSubscriptionAppService : WebhooksManagementAppServiceBase, I
return subscription.ToWebhookSubscriptionDto();
}
public async virtual Task<ListResultDto<WebhookAvailableDto>> GetAllAvailableWebhooksAsync()
public async virtual Task<ListResultDto<WebhookAvailableGroupDto>> GetAllAvailableWebhooksAsync()
{
var webhooks = WebhookDefinitionManager.GetAll();
var definitions = new List<WebhookAvailableDto>();
var groups = WebhookDefinitionManager.GetGroups();
var definitions = new List<WebhookAvailableGroupDto>();
foreach (var webhookDefinition in webhooks)
foreach (var groupDefinition in groups)
{
if (await WebhookDefinitionManager.IsAvailableAsync(CurrentTenant.Id, webhookDefinition.Name))
var group = new WebhookAvailableGroupDto
{
definitions.Add(new WebhookAvailableDto
Name = groupDefinition.Name,
DisplayName = groupDefinition.DisplayName?.Localize(StringLocalizerFactory),
};
foreach (var webhookDefinition in groupDefinition.Webhooks.OrderBy(d => d.Name))
{
if (await WebhookDefinitionManager.IsAvailableAsync(CurrentTenant.Id, webhookDefinition.Name))
{
Name = webhookDefinition.Name,
Description = webhookDefinition.Description?.Localize(StringLocalizerFactory),
DisplayName = webhookDefinition.DisplayName?.Localize(StringLocalizerFactory)
});
group.Webhooks.Add(new WebhookAvailableDto
{
Name = webhookDefinition.Name,
Description = webhookDefinition.Description?.Localize(StringLocalizerFactory),
DisplayName = webhookDefinition.DisplayName?.Localize(StringLocalizerFactory)
});
}
}
definitions.Add(group);
}
return new ListResultDto<WebhookAvailableDto>(definitions.OrderBy(d => d.Name).ToList());
return new ListResultDto<WebhookAvailableGroupDto>(definitions.OrderBy(d => d.Name).ToList());
}
protected async virtual Task CheckSubscribedAsync(WebhookSubscriptionCreateOrUpdateInput input)

7
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain.Shared/LINGYUN/Abp/WebhooksManagement/Localization/Resources/en.json

@ -11,8 +11,9 @@
"Permission:Resend": "Resend",
"Permission:Publish": "Publish",
"Permission:ManageSettings": "Manage Settings",
"DisplayName:CheckConnect": "Check Connect",
"Description:CheckConnect": "When a third-party service is connected, it is used to check whether the communication is normal.",
"Webhooks:010001": "Payload address {WebhookUri} has been mounted event {Webhooks}!"
"Webhooks:010001": "Payload address {WebhookUri} has been mounted event {Webhooks}!",
"Webhooks:Tests": "Tests",
"Webhooks:CheckConnect": "Check Connect",
"Webhooks:CheckConnectDesc": "When a third-party service is connected, it is used to check whether the communication is normal."
}
}

7
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain.Shared/LINGYUN/Abp/WebhooksManagement/Localization/Resources/zh-Hans.json

@ -11,8 +11,9 @@
"Permission:Resend": "重新发送",
"Permission:Publish": "发布事件",
"Permission:ManageSettings": "管理设置",
"DisplayName:CheckConnect": "检查连接",
"Description:CheckConnect": "第三方服务接入时,用于检查是否通讯正常.",
"Webhooks:010001": "载荷地址 {WebhookUri} 已经挂载事件 {Webhooks}!"
"Webhooks:010001": "载荷地址 {WebhookUri} 已经挂载事件 {Webhooks}!",
"Webhooks:Tests": "测试",
"Webhooks:CheckConnect": "检查连接",
"Webhooks:CheckConnectDesc": "第三方服务接入时,用于检查是否通讯正常."
}
}

10
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/Webhooks/WebhooksDefinitionProvider.cs

@ -8,11 +8,15 @@ public class WebhooksDefinitionProvider : WebhookDefinitionProvider
{
public override void Define(IWebhookDefinitionContext context)
{
context.Add(
var testsGroup = context.AddGroup(
WebhooksNames.GroupName,
L("Webhooks:Tests"));
testsGroup.AddWebhooks(
new WebhookDefinition(
WebhooksNames.CheckConnect,
L("DisplayName:CheckConnect"),
L("Description:CheckConnect")));
L("Webhooks:CheckConnect"),
L("Webhooks:CheckConnectDesc")));
}
private static ILocalizableString L(string name)

4
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.Domain/LINGYUN/Abp/WebhooksManagement/Webhooks/WebhooksNames.cs

@ -2,5 +2,7 @@
public static class WebhooksNames
{
public const string CheckConnect = "abp.webhooks.check_connect";
public const string GroupName = "abp.webhooks.tests";
public const string CheckConnect = GroupName + ".check_connect";
}

2
aspnet-core/modules/webhooks/LINGYUN.Abp.WebhooksManagement.HttpApi/LINGYUN/Abp/WebhooksManagement/WebhookSubscriptionController.cs

@ -59,7 +59,7 @@ public class WebhookSubscriptionController : WebhooksManagementControllerBase, I
[HttpGet]
[Route("availables")]
public Task<ListResultDto<WebhookAvailableDto>> GetAllAvailableWebhooksAsync()
public Task<ListResultDto<WebhookAvailableGroupDto>> GetAllAvailableWebhooksAsync()
{
return SubscriptionAppService.GetAllAvailableWebhooksAsync();
}

1
aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/LY.MicroService.WebhooksManagement.HttpApi.Host.csproj

@ -58,6 +58,7 @@
<ItemGroup>
<ProjectReference Include="..\..\modules\webhooks\LINGYUN.Abp.Webhooks.Identity\LINGYUN.Abp.Webhooks.Identity.csproj" />
<ProjectReference Include="..\..\modules\webhooks\LINGYUN.Abp.Webhooks.Saas\LINGYUN.Abp.Webhooks.Saas.csproj" />
<ProjectReference Include="..\..\modules\webhooks\LINGYUN.Abp.WebhooksManagement.Application\LINGYUN.Abp.WebhooksManagement.Application.csproj" />
<ProjectReference Include="..\..\modules\webhooks\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore\LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\webhooks\LINGYUN.Abp.WebhooksManagement.HttpApi\LINGYUN.Abp.WebhooksManagement.HttpApi.csproj" />

2
aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/WebhooksManagementHttpApiHostModule.cs

@ -8,6 +8,7 @@ using LINGYUN.Abp.Saas.EntityFrameworkCore;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
using LINGYUN.Abp.Webhooks.Identity;
using LINGYUN.Abp.Webhooks.Saas;
using LINGYUN.Abp.WebhooksManagement;
using LINGYUN.Abp.WebhooksManagement.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
@ -40,6 +41,7 @@ namespace LY.MicroService.WebhooksManagement;
typeof(WebhooksManagementHttpApiModule),
typeof(WebhooksManagementEntityFrameworkCoreModule),
typeof(AbpWebhooksIdentityModule),
typeof(AbpWebhooksSaasModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEmailingExceptionHandlingModule),

Loading…
Cancel
Save