17 changed files with 443 additions and 10 deletions
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
public interface IWebhookSubscriptionAppService : |
||||
|
ICrudAppService< |
||||
|
WebhookSubscriptionDto, |
||||
|
Guid, |
||||
|
WebhookSubscriptionGetListInput, |
||||
|
WebhookSubscriptionCreateInput, |
||||
|
WebhookSubscriptionUpdateInput> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
public class WebhookSubscriptionCreateInput : WebhookSubscriptionCreateOrUpdateInput |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public class WebhookSubscriptionUpdateInput : WebhookSubscriptionCreateOrUpdateInput |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public abstract class WebhookSubscriptionCreateOrUpdateInput |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(WebhookSubscriptionConsts), nameof(WebhookSubscriptionConsts.MaxWebhookUriLength))] |
||||
|
public string WebhookUri { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(WebhookSubscriptionConsts), nameof(WebhookSubscriptionConsts.MaxSecretLength))] |
||||
|
public string Secret { get; set; } |
||||
|
|
||||
|
public bool IsActive { get; set; } |
||||
|
|
||||
|
public List<string> Webhooks { get; set; } = new List<string>(); |
||||
|
|
||||
|
public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(); |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
public class WebhookSubscriptionDto : CreationAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
public string WebhookUri { get; set; } |
||||
|
public string Secret { get; set; } |
||||
|
public bool IsActive { get; set; } |
||||
|
public List<string> Webhooks { get; set; } = new List<string>(); |
||||
|
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(); |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
public class WebhookSubscriptionGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
[DynamicStringLength(typeof(WebhookSubscriptionConsts), nameof(WebhookSubscriptionConsts.MaxWebhookUriLength))] |
||||
|
public string WebhookUri { get; set; } |
||||
|
|
||||
|
[DynamicStringLength(typeof(WebhookSubscriptionConsts), nameof(WebhookSubscriptionConsts.MaxSecretLength))] |
||||
|
public string Secret { get; set; } |
||||
|
|
||||
|
public bool? IsActive { get; set; } |
||||
|
|
||||
|
public string Webhooks { get; set; } |
||||
|
|
||||
|
public DateTime? BeginCreationTime { get; set; } |
||||
|
|
||||
|
public DateTime? EndCreationTime { get; set; } |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement.Extensions |
||||
|
{ |
||||
|
public static class WebhookSubscriptionExtensions |
||||
|
{ |
||||
|
public static WebhookSubscriptionDto ToWebhookSubscriptionDto(this WebhookSubscription webhookSubscription) |
||||
|
{ |
||||
|
return new WebhookSubscriptionDto |
||||
|
{ |
||||
|
Id = webhookSubscription.Id, |
||||
|
TenantId = webhookSubscription.TenantId, |
||||
|
IsActive = webhookSubscription.IsActive, |
||||
|
Secret = webhookSubscription.Secret, |
||||
|
WebhookUri = webhookSubscription.WebhookUri, |
||||
|
Webhooks = webhookSubscription.GetSubscribedWebhooks(), |
||||
|
Headers = webhookSubscription.GetWebhookHeaders(), |
||||
|
CreationTime = webhookSubscription.CreationTime, |
||||
|
CreatorId = webhookSubscription.CreatorId |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public static string ToSubscribedWebhooksString(this WebhookSubscriptionUpdateInput webhookSubscription) |
||||
|
{ |
||||
|
if (webhookSubscription.Webhooks.Any()) |
||||
|
{ |
||||
|
return JsonConvert.SerializeObject(webhookSubscription.Webhooks); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static string ToWebhookHeadersString(this WebhookSubscriptionUpdateInput webhookSubscription) |
||||
|
{ |
||||
|
if (webhookSubscription.Headers.Any()) |
||||
|
{ |
||||
|
return JsonConvert.SerializeObject(webhookSubscription.Headers); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
using LINGYUN.Abp.WebhooksManagement.Authorization; |
||||
|
using LINGYUN.Abp.WebhooksManagement.Extensions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Newtonsoft.Json; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Default)] |
||||
|
public class WebhookSubscriptionAppService : WebhooksManagementAppServiceBase, IWebhookSubscriptionAppService |
||||
|
{ |
||||
|
protected IWebhookSubscriptionRepository SubscriptionRepository { get; } |
||||
|
|
||||
|
public WebhookSubscriptionAppService( |
||||
|
IWebhookSubscriptionRepository subscriptionRepository) |
||||
|
{ |
||||
|
SubscriptionRepository = subscriptionRepository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Create)] |
||||
|
public async virtual Task<WebhookSubscriptionDto> CreateAsync(WebhookSubscriptionCreateInput input) |
||||
|
{ |
||||
|
await CheckSubscribedAsync(input); |
||||
|
|
||||
|
var subscription = new WebhookSubscription( |
||||
|
GuidGenerator.Create(), |
||||
|
input.WebhookUri, |
||||
|
input.Secret, |
||||
|
JsonConvert.SerializeObject(input.Webhooks), |
||||
|
JsonConvert.SerializeObject(input.Headers), |
||||
|
CurrentTenant.Id); |
||||
|
|
||||
|
await SubscriptionRepository.InsertAsync(subscription); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return subscription.ToWebhookSubscriptionDto(); |
||||
|
} |
||||
|
|
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Delete)] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return SubscriptionRepository.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<WebhookSubscriptionDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var subscription = await SubscriptionRepository.GetAsync(id); |
||||
|
|
||||
|
return subscription.ToWebhookSubscriptionDto(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<PagedResultDto<WebhookSubscriptionDto>> GetListAsync(WebhookSubscriptionGetListInput input) |
||||
|
{ |
||||
|
var filter = new WebhookSubscriptionFilter |
||||
|
{ |
||||
|
Filter = input.Filter, |
||||
|
BeginCreationTime = input.BeginCreationTime, |
||||
|
EndCreationTime = input.EndCreationTime, |
||||
|
IsActive = input.IsActive, |
||||
|
Secret = input.Secret, |
||||
|
TenantId = input.TenantId, |
||||
|
Webhooks = input.Webhooks, |
||||
|
WebhookUri = input.WebhookUri |
||||
|
}; |
||||
|
|
||||
|
var totalCount = await SubscriptionRepository.GetCountAsync(filter); |
||||
|
var subscriptions = await SubscriptionRepository.GetListAsync(filter, |
||||
|
input.Sorting, input.MaxResultCount, input.SkipCount); |
||||
|
|
||||
|
return new PagedResultDto<WebhookSubscriptionDto>(totalCount, |
||||
|
subscriptions.Select(subscription => subscription.ToWebhookSubscriptionDto()).ToList()); |
||||
|
} |
||||
|
|
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Update)] |
||||
|
public async virtual Task<WebhookSubscriptionDto> UpdateAsync(Guid id, WebhookSubscriptionUpdateInput input) |
||||
|
{ |
||||
|
var subscription = await SubscriptionRepository.GetAsync(id); |
||||
|
if (!string.Equals(subscription.WebhookUri, input.WebhookUri)) |
||||
|
{ |
||||
|
await CheckSubscribedAsync(input); |
||||
|
} |
||||
|
|
||||
|
subscription.SetWebhookUri(input.WebhookUri); |
||||
|
subscription.SetWebhooks(input.ToSubscribedWebhooksString()); |
||||
|
subscription.SetHeaders(input.ToWebhookHeadersString()); |
||||
|
|
||||
|
await SubscriptionRepository.UpdateAsync(subscription); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return subscription.ToWebhookSubscriptionDto(); |
||||
|
} |
||||
|
|
||||
|
protected async virtual Task CheckSubscribedAsync(WebhookSubscriptionCreateOrUpdateInput input) |
||||
|
{ |
||||
|
foreach (var webhookName in input.Webhooks) |
||||
|
{ |
||||
|
if (await SubscriptionRepository.IsSubscribedAsync(CurrentTenant.Id, input.WebhookUri, webhookName)) |
||||
|
{ |
||||
|
throw new BusinessException(WebhooksManagementErrorCodes.WebhookSubscription.DuplicateSubscribed) |
||||
|
.WithData(nameof(WebhookSubscription.WebhookUri), input.WebhookUri) |
||||
|
.WithData(nameof(WebhookSubscription.Webhooks), webhookName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,8 +1,27 @@ |
|||||
using System; |
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
using Volo.Abp.Domain.Repositories; |
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
namespace LINGYUN.Abp.WebhooksManagement; |
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
public interface IWebhookSubscriptionRepository : IRepository<WebhookSubscription, Guid> |
public interface IWebhookSubscriptionRepository : IRepository<WebhookSubscription, Guid> |
||||
{ |
{ |
||||
|
Task<bool> IsSubscribedAsync( |
||||
|
Guid? tenantId, |
||||
|
string webhookUri, |
||||
|
string webhookName, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<int> GetCountAsync( |
||||
|
WebhookSubscriptionFilter filter, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task<List<WebhookSubscription>> GetListAsync( |
||||
|
WebhookSubscriptionFilter filter, |
||||
|
string sorting = $"{nameof(WebhookSubscription.CreationTime)} DESC", |
||||
|
int maxResultCount = 10, |
||||
|
int skipCount = 0, |
||||
|
CancellationToken cancellationToken = default); |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
public class WebhookSubscriptionFilter |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
|
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public string WebhookUri { get; set; } |
||||
|
|
||||
|
public string Secret { get; set; } |
||||
|
|
||||
|
public bool? IsActive { get; set; } |
||||
|
|
||||
|
public string Webhooks { get; set; } |
||||
|
|
||||
|
public DateTime? BeginCreationTime { get; set; } |
||||
|
|
||||
|
public DateTime? EndCreationTime { get; set; } |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
using LINGYUN.Abp.WebhooksManagement.Authorization; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WebhooksManagement; |
||||
|
|
||||
|
[RemoteService(Name = WebhooksManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(WebhooksManagementRemoteServiceConsts.ModuleName)] |
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Default)] |
||||
|
[Route("api/webhooks/subscriptions")] |
||||
|
public class WebhookSubscriptionController : WebhooksManagementControllerBase, IWebhookSubscriptionAppService |
||||
|
{ |
||||
|
protected IWebhookSubscriptionAppService SubscriptionAppService { get; } |
||||
|
|
||||
|
public WebhookSubscriptionController(IWebhookSubscriptionAppService subscriptionAppService) |
||||
|
{ |
||||
|
SubscriptionAppService = subscriptionAppService; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Create)] |
||||
|
public Task<WebhookSubscriptionDto> CreateAsync(WebhookSubscriptionCreateInput input) |
||||
|
{ |
||||
|
return SubscriptionAppService.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Delete)] |
||||
|
public Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return SubscriptionAppService.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public Task<WebhookSubscriptionDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return SubscriptionAppService.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public Task<PagedResultDto<WebhookSubscriptionDto>> GetListAsync(WebhookSubscriptionGetListInput input) |
||||
|
{ |
||||
|
return SubscriptionAppService.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(WebhooksManagementPermissions.WebhookSubscription.Update)] |
||||
|
public Task<WebhookSubscriptionDto> UpdateAsync(Guid id, WebhookSubscriptionUpdateInput input) |
||||
|
{ |
||||
|
return SubscriptionAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue