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 |
|||
{ |
|||
/// <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); |
|||
} |
|||
} |
|||
|
|||
@ -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"> |
|||
<ConfigureAwait /> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</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