Browse Source

feat(notifications): 完善企业微信消息.

pull/1141/head
colin 1 year ago
parent
commit
c1454ee243
  1. 4
      aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/WeChatWorkInternalUserFinder.cs
  2. 18
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs
  3. 20
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthConsts.cs
  4. 12
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthHandler.cs
  5. 8
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthOptions.cs
  6. 13
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChatWorkAuthenticationExtensions.cs
  7. 6
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkGlobalConsts.cs
  8. 4
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Authorize/IWeChatWorkInternalUserFinder.cs
  9. 2
      aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Authorize/NullWeChatWorkInternalUserFinder.cs
  10. 6
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/NotificationProviderDto.cs
  11. 2
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/INotificationAppService.cs
  12. 1
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Permissions/NotificationsPermissions.cs
  13. 1
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Permissions/NotificationsPermissionsDefinitionProvider.cs
  14. 2
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application/LINGYUN/Abp/Notifications/Definitions/Notifications/NotificationDefinitionAppService.cs
  15. 22
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application/LINGYUN/Abp/Notifications/NotificationAppService.cs
  16. 5
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain.Shared/LINGYUN/Abp/Notifications/Localization/DomainShared/en.json
  17. 5
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain.Shared/LINGYUN/Abp/Notifications/Localization/DomainShared/zh-Hans.json
  18. 19
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDefinitionRecord.cs
  19. 11
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.HttpApi/LINGYUN/Abp/Notifications/NotificationController.cs
  20. 5
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN.Abp.Notifications.WeChat.Work.csproj
  21. 15
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/AbpNotificationsWeChatWorkModule.cs
  22. 8
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/Localization/Resources/en.json
  23. 8
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/Localization/Resources/zh-Hans.json
  24. 27
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationDefinitionProvider.cs
  25. 7
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationNames.cs
  26. 32
      aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationPublishProvider.cs
  27. 1
      aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
  28. 7
      aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs

4
aspnet-core/framework/wechat/LINGYUN.Abp.Identity.WeChat.Work/LINGYUN/Abp/Identity/WeChat/Work/WeChatWorkInternalUserFinder.cs

@ -33,14 +33,14 @@ public class WeChatWorkInternalUserFinder : IWeChatWorkInternalUserFinder
return userLogin?.ProviderKey;
}
public async virtual Task<string> FindUserIdentifierAsync(string agentId, Guid userId, CancellationToken cancellationToken = default)
public async virtual Task<string> FindUserIdentifierAsync(Guid userId, CancellationToken cancellationToken = default)
{
var user = await UserManager.FindByIdAsync(userId.ToString());
return GetUserOpenIdOrNull(user, AbpWeChatWorkGlobalConsts.ProviderName);
}
public async virtual Task<List<string>> FindUserIdentifierListAsync(string agentId, IEnumerable<Guid> userIdList, CancellationToken cancellationToken = default)
public async virtual Task<List<string>> FindUserIdentifierListAsync(IEnumerable<Guid> userIdList, CancellationToken cancellationToken = default)
{
var userIdentifiers = new List<string>();
foreach (var userId in userIdList)

18
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.Application/LINGYUN/Abp/WeChat/Work/Message/WeChatWorkMessageAppService.cs

@ -27,16 +27,16 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag
public async virtual Task<string> Handle(MessageValidationInput input)
{
var allSettings = await SettingProvider.GetAllAsync(
var settings = await SettingProvider.GetAllAsync(
new[] {
WeChatWorkSettingNames.Connection.CorpId,
WeChatWorkSettingNames.Connection.Token,
WeChatWorkSettingNames.Connection.EncodingAESKey,
} );
});
var corpId = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.CorpId)?.Value;
var token = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.Token)?.Value;
var aesKey = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.EncodingAESKey)?.Value;
var corpId = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.CorpId)?.Value;
var token = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.Token)?.Value;
var aesKey = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.EncodingAESKey)?.Value;
Check.NotNullOrEmpty(corpId, nameof(corpId));
Check.NotNullOrEmpty(token, nameof(token));
@ -58,16 +58,16 @@ public class WeChatWorkMessageAppService : ApplicationService, IWeChatWorkMessag
public async virtual Task<string> Handle(MessageHandleInput input)
{
var allSettings = await SettingProvider.GetAllAsync(
var settings = await SettingProvider.GetAllAsync(
new[] {
WeChatWorkSettingNames.Connection.CorpId,
WeChatWorkSettingNames.Connection.Token,
WeChatWorkSettingNames.Connection.EncodingAESKey,
});
var corpId = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.CorpId)?.Value;
var token = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.Token)?.Value;
var aesKey = allSettings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.EncodingAESKey)?.Value;
var corpId = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.CorpId)?.Value;
var token = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.Token)?.Value;
var aesKey = settings.FirstOrDefault(x => x.Name == WeChatWorkSettingNames.Connection.EncodingAESKey)?.Value;
Check.NotNullOrEmpty(corpId, nameof(corpId));
Check.NotNullOrEmpty(token, nameof(token));

20
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthConsts.cs

@ -5,13 +5,9 @@ namespace Microsoft.AspNetCore.Authentication.WeChat.Work;
public static class WeChatWorkOAuthConsts
{
/// <summary>
/// 微信个人信息标识
/// 企业微信授权名称
/// </summary>
public static string ProfileKey => AbpWeChatWorkGlobalConsts.ProfileKey;
/// <summary>
/// 微信提供者标识
/// </summary>
public static string ProviderKey => AbpWeChatWorkGlobalConsts.ProviderName;
public static string AuthenticationScheme => AbpWeChatWorkGlobalConsts.ProviderName;
/// <summary>
/// 微信提供者显示名称
/// </summary>
@ -23,7 +19,11 @@ public static class WeChatWorkOAuthConsts
/// <summary>
/// 微信客户端内的网页登录
/// </summary>
public const string AuthorizationEndpoint = "https://login.work.weixin.qq.com/wwlogin/sso/login";
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize";
/// <summary>
/// Web网页登录
/// </summary>
public const string AuthorizationSsoEndpoint = "https://login.work.weixin.qq.com/wwlogin/sso/login";
/// <summary>
/// 用户允许授权后通过返回的code换取access_token地址
/// </summary>
@ -32,7 +32,11 @@ public static class WeChatWorkOAuthConsts
/// <summary>
/// 使用access_token获取用户个人信息地址
/// </summary>
public const string UserInformationEndpoint = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo";
public const string UserInfoEndpoint = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo";
/// <summary>
/// 使用access_token获取用户敏感信息地址
/// </summary>
public const string UserDetailEndpoint = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail";
public const string UserInfoScope = "snsapi_privateinfo";

12
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthHandler.cs

@ -77,6 +77,10 @@ public class WeChatWorkOAuthHandler : OAuthHandler<WeChatWorkOAuthOptions>
? WeChatWorkOAuthConsts.UserInfoScope
: WeChatWorkOAuthConsts.LoginScope;
var endpoint = isWeChatBrewserRequest
? WeChatWorkOAuthConsts.AuthorizationEndpoint
: WeChatWorkOAuthConsts.AuthorizationSsoEndpoint;
var parameters = new Dictionary<string, string>
{
{ "appid", Options.CorpId },
@ -91,7 +95,7 @@ public class WeChatWorkOAuthHandler : OAuthHandler<WeChatWorkOAuthOptions>
parameters["state"] = state; ;
return $"{QueryHelpers.AddQueryString(Options.AuthorizationEndpoint, parameters)}";
return $"{QueryHelpers.AddQueryString(endpoint, parameters)}";
}
/// <summary>
@ -143,7 +147,11 @@ public class WeChatWorkOAuthHandler : OAuthHandler<WeChatWorkOAuthOptions>
/// <exception cref="HttpRequestException"></exception>
protected async virtual Task<AuthenticationTicket> CreateTicketAsync(string code, ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
var userInfoEndpoint = IsWeChatBrowser()
? WeChatWorkOAuthConsts.UserDetailEndpoint
: WeChatWorkOAuthConsts.UserInfoEndpoint;
var address = QueryHelpers.AddQueryString(userInfoEndpoint, new Dictionary<string, string>
{
["access_token"] = tokens.AccessToken,
["code"] = code

8
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChat/Work/WeChatWorkOAuthOptions.cs

@ -12,6 +12,10 @@ public class WeChatWorkOAuthOptions : OAuthOptions
/// 企业Id
/// </summary>
public string CorpId { get; set; }
/// <summary>
/// 访问用户敏感信息端点
/// </summary>
public string UserDetailEndpoint { get; set; }
public WeChatWorkOAuthOptions()
{
// 用于防止初始化错误,会在OAuthHandler.InitializeHandlerAsync中进行重写
@ -23,7 +27,9 @@ public class WeChatWorkOAuthOptions : OAuthOptions
AuthorizationEndpoint = WeChatWorkOAuthConsts.AuthorizationEndpoint;
TokenEndpoint = WeChatWorkOAuthConsts.TokenEndpoint;
UserInformationEndpoint = WeChatWorkOAuthConsts.UserInformationEndpoint;
UserInformationEndpoint = WeChatWorkOAuthConsts.UserInfoEndpoint;
UserDetailEndpoint = WeChatWorkOAuthConsts.UserDetailEndpoint;
Scope.Add(WeChatWorkOAuthConsts.LoginScope);
Scope.Add(WeChatWorkOAuthConsts.UserInfoScope);

13
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.AspNetCore/Microsoft/AspNetCore/Authentication/WeChatWorkAuthenticationExtensions.cs

@ -1,5 +1,4 @@
using LINGYUN.Abp.WeChat.Work;
using Microsoft.AspNetCore.Authentication.WeChat.Work;
using Microsoft.AspNetCore.Authentication.WeChat.Work;
using Microsoft.Extensions.DependencyInjection;
using System;
@ -14,8 +13,8 @@ public static class WeChatWorkAuthenticationExtensions
{
return builder
.AddWeChatWork(
AbpWeChatWorkGlobalConsts.AuthenticationScheme,
AbpWeChatWorkGlobalConsts.DisplayName,
WeChatWorkOAuthConsts.AuthenticationScheme,
WeChatWorkOAuthConsts.DisplayName,
options => { });
}
@ -27,8 +26,8 @@ public static class WeChatWorkAuthenticationExtensions
{
return builder
.AddWeChatWork(
AbpWeChatWorkGlobalConsts.AuthenticationScheme,
AbpWeChatWorkGlobalConsts.DisplayName,
WeChatWorkOAuthConsts.AuthenticationScheme,
WeChatWorkOAuthConsts.DisplayName,
configureOptions);
}
@ -42,7 +41,7 @@ public static class WeChatWorkAuthenticationExtensions
return builder
.AddWeChatWork(
authenticationScheme,
AbpWeChatWorkGlobalConsts.DisplayName,
WeChatWorkOAuthConsts.DisplayName,
configureOptions);
}

6
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkGlobalConsts.cs

@ -5,16 +5,12 @@ public class AbpWeChatWorkGlobalConsts
/// <summary>
/// 企业微信对应的Provider名称
/// </summary>
public static string ProviderName { get; set; } = "WeChat.WeCom";
public static string ProviderName { get; set; } = "WeCom";
/// <summary>
/// 企业微信授权类型
/// </summary>
public static string GrantType { get; set; } = "wecom";
/// <summary>
/// 企业微信授权名称
/// </summary>
public static string AuthenticationScheme { get; set; }= "WeCom";
/// <summary>
/// 企业微信个人信息标识
/// </summary>
public static string ProfileKey { get; set; } = "wecom.profile";

4
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Authorize/IWeChatWorkInternalUserFinder.cs

@ -9,23 +9,19 @@ public interface IWeChatWorkInternalUserFinder
/// <summary>
/// 通过用户标识查询企业微信用户标识
/// </summary>
/// <param name="agentId"></param>
/// <param name="userId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<string> FindUserIdentifierAsync(
string agentId,
Guid userId,
CancellationToken cancellationToken = default);
/// <summary>
/// 通过用户标识列表查询企业微信用户标识列表
/// </summary>
/// <param name="agentId"></param>
/// <param name="userIdList"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<List<string>> FindUserIdentifierListAsync(
string agentId,
IEnumerable<Guid> userIdList,
CancellationToken cancellationToken = default);
}

2
aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Authorize/NullWeChatWorkInternalUserFinder.cs

@ -12,7 +12,6 @@ public class NullWeChatWorkInternalUserFinder : IWeChatWorkInternalUserFinder
{
public readonly static IWeChatWorkInternalUserFinder Instance = new NullWeChatWorkInternalUserFinder();
public Task<string> FindUserIdentifierAsync(
string agentId,
Guid userId,
CancellationToken cancellationToken = default)
{
@ -21,7 +20,6 @@ public class NullWeChatWorkInternalUserFinder : IWeChatWorkInternalUserFinder
}
public Task<List<string>> FindUserIdentifierListAsync(
string agentId,
IEnumerable<Guid> userIdList,
CancellationToken cancellationToken = default)
{

6
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/NotificationProviderDto.cs

@ -0,0 +1,6 @@
namespace LINGYUN.Abp.Notifications;
public class NotificationProviderDto
{
public string Name { get; set; }
}

2
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/INotificationAppService.cs

@ -5,6 +5,8 @@ namespace LINGYUN.Abp.Notifications;
public interface INotificationAppService
{
Task<ListResultDto<NotificationProviderDto>> GetAssignableProvidersAsync();
Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync();
Task<ListResultDto<NotificationTemplateDto>> GetAssignableTemplatesAsync();

1
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Permissions/NotificationsPermissions.cs

@ -9,6 +9,7 @@ public class NotificationsPermissions
public const string Default = GroupName + ".Notification";
public const string Delete = Default + ".Delete";
public const string Send = Default + ".Send";
}
public static class GroupDefinition

1
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Permissions/NotificationsPermissionsDefinitionProvider.cs

@ -47,6 +47,7 @@ public class NotificationsPermissionsDefinitionProvider : PermissionDefinitionPr
var noticeGroup = group.AddPermission(NotificationsPermissions.Notification.Default, L("Permission:Notification"));
noticeGroup.AddChild(NotificationsPermissions.Notification.Delete, L("Permission:Delete"));
noticeGroup.AddChild(NotificationsPermissions.Notification.Send, L("Permission:Send"));
}
private static LocalizableString L(string name)

2
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application/LINGYUN/Abp/Notifications/Definitions/Notifications/NotificationDefinitionAppService.cs

@ -213,7 +213,7 @@ public class NotificationDefinitionAppService : AbpNotificationsApplicationServi
}
if (!string.Equals(record.Providers, allowedProviders, StringComparison.InvariantCultureIgnoreCase))
{
record.UseProviders(input.Providers.ToArray());
record.Providers = allowedProviders;
}
record.ExtraProperties.Clear();
foreach (var property in input.ExtraProperties)

22
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Application/LINGYUN/Abp/Notifications/NotificationAppService.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Authorization;
using LINGYUN.Abp.Notifications.Permissions;
using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@ -14,15 +15,31 @@ public class NotificationAppService : AbpNotificationsApplicationServiceBase, IN
protected ITemplateContentProvider TemplateContentProvider { get; }
protected INotificationSender NotificationSender { get; }
protected INotificationDefinitionManager NotificationDefinitionManager { get; }
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; }
public NotificationAppService(
INotificationSender notificationSender,
ITemplateContentProvider templateContentProvider,
INotificationDefinitionManager notificationDefinitionManager)
INotificationDefinitionManager notificationDefinitionManager,
INotificationPublishProviderManager notificationPublishProviderManager)
{
NotificationSender = notificationSender;
TemplateContentProvider = templateContentProvider;
NotificationDefinitionManager = notificationDefinitionManager;
NotificationPublishProviderManager = notificationPublishProviderManager;
}
public virtual Task<ListResultDto<NotificationProviderDto>> GetAssignableProvidersAsync()
{
var providers = NotificationPublishProviderManager
.Providers
.Select(x => new NotificationProviderDto
{
Name = x.Name
})
.ToList();
return Task.FromResult(new ListResultDto<NotificationProviderDto>(providers));
}
public async virtual Task<ListResultDto<NotificationGroupDto>> GetAssignableNotifiersAsync()
@ -95,6 +112,7 @@ public class NotificationAppService : AbpNotificationsApplicationServiceBase, IN
return new ListResultDto<NotificationTemplateDto>(templates);
}
[Authorize(NotificationsPermissions.Notification.Send)]
public async virtual Task SendAsync(NotificationSendDto input)
{
var notificationData = new NotificationData();

5
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain.Shared/LINGYUN/Abp/Notifications/Localization/DomainShared/en.json

@ -4,9 +4,11 @@
"Permission:Notifications": "Notification",
"Permission:GroupDefinitions": "Group Definitions",
"Permission:NotificationDefinitions": "Notification Definitions",
"Permission:Notification": "Manage Notification",
"Permission:Create": "Create",
"Permission:Edit": "Edit",
"Permission:Delete": "Delete",
"Permission:Send": "Send",
"Notifications:001404": "The notification template does not exist!",
"Notifications:002400": "The static notification group {Name} is not allowed to change!",
"Notifications:002403": "Notification that the {Name} group already exists!",
@ -46,6 +48,7 @@
"Properties": "Properties",
"TemplateContent": "Template Content",
"ItemWillBeDeleteOrRestoreMessage": "If the notification has been changed, it will revert to the default notification. Otherwise, the custom notification is removed.",
"Notifications:Send": "Send Notification"
"Notifications:Send": "Send Notification",
"SendSuccessfully": "Send Successfully"
}
}

5
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain.Shared/LINGYUN/Abp/Notifications/Localization/DomainShared/zh-Hans.json

@ -4,9 +4,11 @@
"Permission:Notifications": "通知管理",
"Permission:GroupDefinitions": "分组定义",
"Permission:NotificationDefinitions": "通知定义",
"Permission:Notification": "管理通知",
"Permission:Create": "新增",
"Permission:Edit": "编辑",
"Permission:Delete": "删除",
"Permission:Send": "发送通知",
"Notifications:001404": "通知模板不存在!",
"Notifications:002400": "静态通知分组 {Name} 不允许变更!",
"Notifications:002403": "通知分组 {Name} 已经存在!",
@ -46,6 +48,7 @@
"Properties": "属性",
"TemplateContent": "模板内容",
"ItemWillBeDeleteOrRestoreMessage": "如果已改变通知, 将还原到默认通知。否则会删除自定义通知.",
"Notifications:Send": "发送通知"
"Notifications:Send": "发送通知",
"SendSuccessfully": "发送成功"
}
}

19
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDefinitionRecord.cs

@ -53,7 +53,7 @@ public class NotificationDefinitionRecord : BasicAggregateRoot<Guid>, IHasExtraP
/// <remarks>
/// 多个之间用;分隔
/// </remarks>
public virtual string Providers { get; protected set; }
public virtual string Providers { get; set; }
/// <summary>
/// 允许客户端订阅
/// </summary>
@ -93,23 +93,6 @@ public class NotificationDefinitionRecord : BasicAggregateRoot<Guid>, IHasExtraP
AllowSubscriptionToClients = true;
}
public void UseProviders(params string[] providers)
{
var currentProviders = Providers.IsNullOrWhiteSpace()
? new List<string>()
: Providers.Split(';').ToList();
if (!providers.IsNullOrEmpty())
{
currentProviders.AddIfNotContains(providers);
}
if (currentProviders.Any())
{
Providers = currentProviders.JoinAsString(";");
}
}
public bool HasSameData(NotificationDefinitionRecord otherRecord)
{
if (Name != otherRecord.Name)

11
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.HttpApi/LINGYUN/Abp/Notifications/NotificationController.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Authorization;
using LINGYUN.Abp.Notifications.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
@ -24,6 +25,7 @@ public class NotificationController : AbpControllerBase, INotificationAppService
[HttpPost]
[Route("send")]
[Authorize(NotificationsPermissions.Notification.Send)]
public virtual Task SendAsync(NotificationSendDto input)
{
return NotificationAppService.SendAsync(input);
@ -49,4 +51,11 @@ public class NotificationController : AbpControllerBase, INotificationAppService
{
return NotificationAppService.GetAssignableTemplatesAsync();
}
[HttpGet]
[Route("assignable-providers")]
public virtual Task<ListResultDto<NotificationProviderDto>> GetAssignableProvidersAsync()
{
return NotificationAppService.GetAssignableProvidersAsync();
}
}

5
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN.Abp.Notifications.WeChat.Work.csproj

@ -13,6 +13,11 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Notifications\WeChat\Work\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\Notifications\WeChat\Work\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\framework\wechat\LINGYUN.Abp.WeChat.Work\LINGYUN.Abp.WeChat.Work.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj" />

15
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/AbpNotificationsWeChatWorkModule.cs

@ -1,5 +1,8 @@
using LINGYUN.Abp.WeChat.Work;
using LINGYUN.Abp.WeChat.Work.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Notifications.WeChat.Work;
@ -10,6 +13,18 @@ public class AbpNotificationsWeChatWorkModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpNotificationsWeChatWorkModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<WeChatWorkResource>()
.AddVirtualJson("/LINGYUN/Abp/Notifications/WeChat/Work/Localization/Resources");
});
Configure<AbpNotificationsPublishOptions>(options =>
{
options.PublishProviders.Add<WeChatWorkNotificationPublishProvider>();

8
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/Localization/Resources/en.json

@ -0,0 +1,8 @@
{
"culture": "en",
"texts": {
"Notification:WeChatWork": "WeCom",
"Notification:WeChatWorkTest": "WeCom notification testing",
"Notification:WeChatWorkTestDesc": "Used to test wecom notification sending"
}
}

8
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/Localization/Resources/zh-Hans.json

@ -0,0 +1,8 @@
{
"culture": "zh-Hans",
"texts": {
"Notification:WeChatWork": "企业微信",
"Notification:WeChatWorkTest": "企业微信消息测试",
"Notification:WeChatWorkTestDesc": "用于测试企业微信消息发送"
}
}

27
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationDefinitionProvider.cs

@ -0,0 +1,27 @@
using LINGYUN.Abp.WeChat.Work.Localization;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Notifications.WeChat.Work;
public class WeChatWorkNotificationDefinitionProvider : NotificationDefinitionProvider
{
public override void Define(INotificationDefinitionContext context)
{
var group = context.AddGroup(
WeChatWorkNotificationNames.GroupName,
L("Notification:WeChatWork"),
L("Notification:WeChatWork"));
group.AddNotification(
WeChatWorkNotificationNames.TestNotification,
L("Notification:WeChatWorkTest"),
L("Notification:WeChatWorkTestDesc"),
allowSubscriptionToClients: true)
.WithProviders(WeChatWorkNotificationPublishProvider.ProviderName);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<WeChatWorkResource>(name);
}
}

7
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationNames.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.Notifications.WeChat.Work;
public static class WeChatWorkNotificationNames
{
public const string GroupName = "WeChat.Work";
public const string TestNotification = GroupName + ".Test";
}

32
aspnet-core/modules/realtime-notifications/LINGYUN.Abp.Notifications.WeChat.Work/LINGYUN/Abp/Notifications/WeChat/Work/WeChatWorkNotificationPublishProvider.cs

@ -3,6 +3,7 @@ using LINGYUN.Abp.WeChat.Work.Authorize;
using LINGYUN.Abp.WeChat.Work.Features;
using LINGYUN.Abp.WeChat.Work.Messages;
using LINGYUN.Abp.WeChat.Work.Messages.Models;
using LINGYUN.Abp.WeChat.Work.Settings;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System;
@ -11,6 +12,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Features;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Notifications.WeChat.Work;
public class WeChatWorkNotificationPublishProvider : NotificationPublishProvider
@ -18,24 +20,12 @@ public class WeChatWorkNotificationPublishProvider : NotificationPublishProvider
public const string ProviderName = NotificationProviderNames.WechatWork;
public override string Name => ProviderName;
protected IFeatureChecker FeatureChecker { get; }
protected IStringLocalizerFactory LocalizerFactory { get; }
protected IWeChatWorkMessageSender WeChatWorkMessageSender { get; }
protected IWeChatWorkInternalUserFinder WeChatWorkInternalUserFinder { get; }
protected INotificationDefinitionManager NotificationDefinitionManager { get; }
public WeChatWorkNotificationPublishProvider(
IFeatureChecker featureChecker,
IStringLocalizerFactory localizerFactory,
IWeChatWorkMessageSender weChatWorkMessageSender,
IWeChatWorkInternalUserFinder weChatWorkInternalUserFinder,
INotificationDefinitionManager notificationDefinitionManager)
{
FeatureChecker = featureChecker;
LocalizerFactory = localizerFactory;
WeChatWorkMessageSender = weChatWorkMessageSender;
WeChatWorkInternalUserFinder = weChatWorkInternalUserFinder;
NotificationDefinitionManager = notificationDefinitionManager;
}
protected IFeatureChecker FeatureChecker => ServiceProvider.LazyGetRequiredService<IFeatureChecker>();
protected ISettingProvider SettingProvider => ServiceProvider.LazyGetRequiredService<ISettingProvider>();
protected IStringLocalizerFactory LocalizerFactory => ServiceProvider.LazyGetRequiredService<IStringLocalizerFactory>();
protected IWeChatWorkMessageSender WeChatWorkMessageSender => ServiceProvider.LazyGetRequiredService<IWeChatWorkMessageSender>();
protected IWeChatWorkInternalUserFinder WeChatWorkInternalUserFinder => ServiceProvider.LazyGetRequiredService<IWeChatWorkInternalUserFinder>();
protected INotificationDefinitionManager NotificationDefinitionManager => ServiceProvider.LazyGetRequiredService<INotificationDefinitionManager>();
protected async override Task<bool> CanPublishAsync(NotificationInfo notification, CancellationToken cancellationToken = default)
{
@ -59,9 +49,10 @@ public class WeChatWorkNotificationPublishProvider : NotificationPublishProvider
{
var sendToAgentIds = new List<string>();
var notificationDefine = await NotificationDefinitionManager.GetOrNullAsync(notification.Name);
var agentId = notification.Data.GetAgentIdOrNull() ?? notificationDefine?.GetAgentIdOrNull();
var agentId = await SettingProvider.GetOrNullAsync(WeChatWorkSettingNames.Connection.AgentId);
if (agentId.IsNullOrWhiteSpace())
{
Logger.LogWarning("Unable to send enterprise wechat messages because agentId is not set.");
return;
}
@ -96,7 +87,7 @@ public class WeChatWorkNotificationPublishProvider : NotificationPublishProvider
}
var findUserList = await WeChatWorkInternalUserFinder
.FindUserIdentifierListAsync(agentId, identifiers.Select(id => id.UserId));
.FindUserIdentifierListAsync(identifiers.Select(id => id.UserId));
if (!findUserList.Any())
{
@ -148,6 +139,7 @@ public class WeChatWorkNotificationPublishProvider : NotificationPublishProvider
return;
}
message.ToUser = toUser;
message.ToTag = toTag;
message.ToParty = toParty;

1
aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj

@ -104,6 +104,7 @@
<ProjectReference Include="..\..\framework\open-api\LINGYUN.Abp.OpenApi\LINGYUN.Abp.OpenApi.csproj" />
<ProjectReference Include="..\..\framework\settings\LINGYUN.Abp.SettingManagement.Application.Contracts\LINGYUN.Abp.SettingManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\..\framework\tenants\LINGYUN.Abp.MultiTenancy.Editions\LINGYUN.Abp.MultiTenancy.Editions.csproj" />
<ProjectReference Include="..\..\framework\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj" />
<ProjectReference Include="..\..\framework\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj" />
<ProjectReference Include="..\..\framework\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" />
<ProjectReference Include="..\..\framework\wechat\LINGYUN.Abp.WeChat.Official.Handlers\LINGYUN.Abp.WeChat.Official.Handlers.csproj" />

7
aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs

@ -1,3 +1,6 @@
using LINGYUN.Abp.Identity.WeChat.Work;
using LINGYUN.Abp.Notifications.WeChat.Work;
namespace LY.MicroService.Applications.Single;
[DependsOn(
@ -19,6 +22,8 @@ namespace LY.MicroService.Applications.Single;
typeof(AbpIdentityOrganizaztionUnitsModule),
// 身份认证模块 微信身份标识
typeof(AbpIdentityWeChatModule),
// 身份认证模块 企业微信身份标识
typeof(AbpIdentityWeChatWorkModule),
// 身份认证模块 领域服务
typeof(AbpIdentityDomainModule),
// 身份认证模块 应用服务
@ -301,6 +306,8 @@ namespace LY.MicroService.Applications.Single;
typeof(AbpNotificationsEmailingModule),
// 通知模块 微信小程序
typeof(AbpNotificationsWeChatMiniProgramModule),
// 通知模块 企业微信
typeof(AbpNotificationsWeChatWorkModule),
// 多租户模块 版本
typeof(AbpMultiTenancyEditionsModule),

Loading…
Cancel
Save