35 changed files with 565 additions and 65 deletions
@ -1,22 +1,16 @@ |
|||||
namespace LINGYUN.Abp.Webhooks |
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Webhooks |
||||
{ |
{ |
||||
public interface IWebhookDefinitionContext |
public interface IWebhookDefinitionContext |
||||
{ |
{ |
||||
/// <summary>
|
WebhookGroupDefinition AddGroup( |
||||
/// Adds the specified webhook definition. Throws exception if it is already added
|
[NotNull] string name, |
||||
/// </summary>
|
ILocalizableString displayName = null); |
||||
void Add(params WebhookDefinition[] definitions); |
|
||||
|
|
||||
/// <summary>
|
WebhookGroupDefinition GetGroupOrNull(string name); |
||||
/// Gets a webhook definition by name.
|
|
||||
/// Returns null if there is no webhook definition with given name.
|
|
||||
/// </summary>
|
|
||||
WebhookDefinition GetOrNull(string name); |
|
||||
|
|
||||
/// <summary>
|
void RemoveGroup(string name); |
||||
/// Remove webhook with given name
|
|
||||
/// </summary>
|
|
||||
/// <param name="name">webhook definition name</param>
|
|
||||
void Remove(string name); |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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}]"; |
||||
|
} |
||||
|
} |
||||
@ -1,3 +1,3 @@ |
|||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
<ConfigureAwait /> |
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
</Weavers> |
</Weavers> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
@ -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" |
||||
|
} |
||||
|
} |
||||
@ -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": "已删除租户" |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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"; |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
|
||||
@ -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>(); |
||||
|
} |
||||
Loading…
Reference in new issue