committed by
GitHub
60 changed files with 1312 additions and 39 deletions
@ -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,33 @@ |
|||||
|
namespace LINGYUN.Abp.Notifications; |
||||
|
public static class NotificationDataExtensions |
||||
|
{ |
||||
|
private const string Prefix = "push-plus:"; |
||||
|
private const string WebhookKey = Prefix + "webhook"; |
||||
|
private const string CallbackUrlKey = Prefix + "callback"; |
||||
|
|
||||
|
public static void SetWebhook( |
||||
|
this NotificationData notificationData, |
||||
|
string url) |
||||
|
{ |
||||
|
notificationData.TrySetData(WebhookKey, url); |
||||
|
} |
||||
|
|
||||
|
public static string GetWebhookOrNull( |
||||
|
this NotificationData notificationData) |
||||
|
{ |
||||
|
return notificationData.TryGetData(WebhookKey)?.ToString(); |
||||
|
} |
||||
|
|
||||
|
public static void SetCallbackUrl( |
||||
|
this NotificationData notificationData, |
||||
|
string callbackUrl) |
||||
|
{ |
||||
|
notificationData.TrySetData(CallbackUrlKey, callbackUrl); |
||||
|
} |
||||
|
|
||||
|
public static string GetCallbackUrlOrNull( |
||||
|
this NotificationData notificationData) |
||||
|
{ |
||||
|
return notificationData.TryGetData(CallbackUrlKey)?.ToString(); |
||||
|
} |
||||
|
} |
||||
@ -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,29 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\PushPlus\SettingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\PushPlus\SettingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\settings\LINGYUN.Abp.SettingManagement.Application.Contracts\LINGYUN.Abp.SettingManagement.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.PushPlus\LINGYUN.Abp.PushPlus.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,48 @@ |
|||||
|
using LINGYUN.Abp.PushPlus.Localization; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpPushPlusModule), |
||||
|
typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AbpPushPlusSettingManagementModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||
|
{ |
||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpPushPlusSettingManagementModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpPushPlusSettingManagementModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<PushPlusResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/PushPlus/SettingManagement/Localization/Resources"); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<PushPlusResource>() |
||||
|
.AddBaseTypes( |
||||
|
typeof(AbpUiResource) |
||||
|
); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
|
||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
public interface IPushPlusSettingAppService : IReadonlySettingAppService |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Permission:PushPlus": "PushPlus", |
||||
|
"Permission:ManageSetting": "Manage Setting" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Permission:PushPlus": "PushPlus", |
||||
|
"Permission:ManageSetting": "管理设置" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,67 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
using LINGYUN.Abp.PushPlus.Localization; |
||||
|
using LINGYUN.Abp.PushPlus.Settings; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.SettingManagement; |
||||
|
using Volo.Abp.Settings; |
||||
|
|
||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
public class WxPusherSettingAppService : ApplicationService, IPushPlusSettingAppService |
||||
|
{ |
||||
|
protected ISettingManager SettingManager { get; } |
||||
|
protected IPermissionChecker PermissionChecker { get; } |
||||
|
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
||||
|
|
||||
|
public WxPusherSettingAppService( |
||||
|
ISettingManager settingManager, |
||||
|
IPermissionChecker permissionChecker, |
||||
|
ISettingDefinitionManager settingDefinitionManager) |
||||
|
{ |
||||
|
SettingManager = settingManager; |
||||
|
PermissionChecker = permissionChecker; |
||||
|
SettingDefinitionManager = settingDefinitionManager; |
||||
|
LocalizationResource = typeof(PushPlusResource); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
||||
|
{ |
||||
|
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() |
||||
|
{ |
||||
|
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); |
||||
|
} |
||||
|
|
||||
|
protected async virtual Task<SettingGroupResult> GetAllForProviderAsync(string providerName, string providerKey) |
||||
|
{ |
||||
|
var settingGroups = new SettingGroupResult(); |
||||
|
var pushPlusSettingGroup = new SettingGroupDto(L["DisplayName:PushPlus"], L["Description:PushPlus"]); |
||||
|
|
||||
|
if (await PermissionChecker.IsGrantedAsync(PushPlusSettingPermissionNames.ManageSetting)) |
||||
|
{ |
||||
|
var securitySetting = pushPlusSettingGroup.AddSetting(L["Security"], L["Security"]); |
||||
|
securitySetting.AddDetail( |
||||
|
SettingDefinitionManager.Get(PushPlusSettingNames.Security.Token), |
||||
|
StringLocalizerFactory, |
||||
|
await SettingManager.GetOrNullAsync(PushPlusSettingNames.Security.Token, providerName, providerKey), |
||||
|
ValueType.String, |
||||
|
providerName); |
||||
|
securitySetting.AddDetail( |
||||
|
SettingDefinitionManager.Get(PushPlusSettingNames.Security.SecretKey), |
||||
|
StringLocalizerFactory, |
||||
|
await SettingManager.GetOrNullAsync(PushPlusSettingNames.Security.SecretKey, providerName, providerKey), |
||||
|
ValueType.String, |
||||
|
providerName); |
||||
|
} |
||||
|
|
||||
|
settingGroups.AddGroup(pushPlusSettingGroup); |
||||
|
|
||||
|
return settingGroups; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(AbpSettingManagementRemoteServiceConsts.ModuleName)] |
||||
|
[Route($"api/{AbpSettingManagementRemoteServiceConsts.ModuleName}/push-plus")] |
||||
|
public class WxPusherSettingController : AbpController, IPushPlusSettingAppService |
||||
|
{ |
||||
|
protected IPushPlusSettingAppService Service { get; } |
||||
|
|
||||
|
public WxPusherSettingController( |
||||
|
IPushPlusSettingAppService service) |
||||
|
{ |
||||
|
Service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-current-tenant")] |
||||
|
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
||||
|
{ |
||||
|
return await Service.GetAllForCurrentTenantAsync(); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-global")] |
||||
|
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() |
||||
|
{ |
||||
|
return await Service.GetAllForGlobalAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using LINGYUN.Abp.PushPlus.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
public class PushPlusSettingPermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var pushPlusGroup = context.AddGroup( |
||||
|
PushPlusSettingPermissionNames.GroupName, |
||||
|
L("Permission:PushPlus")); |
||||
|
|
||||
|
pushPlusGroup.AddPermission( |
||||
|
PushPlusSettingPermissionNames.ManageSetting, L("Permission:ManageSetting")); |
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<PushPlusResource>(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace LINGYUN.Abp.PushPlus.SettingManagement |
||||
|
{ |
||||
|
public class PushPlusSettingPermissionNames |
||||
|
{ |
||||
|
public const string GroupName = "Abp.PushPlus"; |
||||
|
|
||||
|
public const string ManageSetting = GroupName + ".ManageSetting"; |
||||
|
} |
||||
|
} |
||||
@ -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,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,19 @@ |
|||||
|
namespace LINGYUN.Abp.Notifications; |
||||
|
public static class NotificationDataExtensions |
||||
|
{ |
||||
|
private const string Prefix = "wx-pusher:"; |
||||
|
private const string UrlKey = Prefix + "url"; |
||||
|
|
||||
|
public static void SetUrl( |
||||
|
this NotificationData notificationData, |
||||
|
string url) |
||||
|
{ |
||||
|
notificationData.TrySetData(UrlKey, url); |
||||
|
} |
||||
|
|
||||
|
public static string GetUrlOrNull( |
||||
|
this NotificationData notificationData) |
||||
|
{ |
||||
|
return notificationData.TryGetData(UrlKey)?.ToString(); |
||||
|
} |
||||
|
} |
||||
@ -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,29 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\WxPusher\SettingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\WxPusher\SettingManagement\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\settings\LINGYUN.Abp.SettingManagement.Application.Contracts\LINGYUN.Abp.SettingManagement.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.WxPusher\LINGYUN.Abp.WxPusher.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,48 @@ |
|||||
|
using LINGYUN.Abp.WxPusher.Localization; |
||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpWxPusherModule), |
||||
|
typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AbpWxPusherSettingManagementModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||
|
{ |
||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpWxPusherSettingManagementModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpWxPusherSettingManagementModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<WxPusherResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/WxPusher/SettingManagement/Localization/Resources"); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<WxPusherResource>() |
||||
|
.AddBaseTypes( |
||||
|
typeof(AbpUiResource) |
||||
|
); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
public interface IWxPusherSettingAppService : IReadonlySettingAppService |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Permission:WxPusher": "WxPusher", |
||||
|
"Permission:ManageSetting": "Manage Setting" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Permission:WxPusher": "WxPusher", |
||||
|
"Permission:ManageSetting": "管理设置" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
using LINGYUN.Abp.WxPusher.Localization; |
||||
|
using LINGYUN.Abp.WxPusher.Settings; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.SettingManagement; |
||||
|
using Volo.Abp.Settings; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
public class WxPusherSettingAppService : ApplicationService, IWxPusherSettingAppService |
||||
|
{ |
||||
|
protected ISettingManager SettingManager { get; } |
||||
|
protected IPermissionChecker PermissionChecker { get; } |
||||
|
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
||||
|
|
||||
|
public WxPusherSettingAppService( |
||||
|
ISettingManager settingManager, |
||||
|
IPermissionChecker permissionChecker, |
||||
|
ISettingDefinitionManager settingDefinitionManager) |
||||
|
{ |
||||
|
SettingManager = settingManager; |
||||
|
PermissionChecker = permissionChecker; |
||||
|
SettingDefinitionManager = settingDefinitionManager; |
||||
|
LocalizationResource = typeof(WxPusherResource); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
||||
|
{ |
||||
|
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() |
||||
|
{ |
||||
|
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); |
||||
|
} |
||||
|
|
||||
|
protected async virtual Task<SettingGroupResult> GetAllForProviderAsync(string providerName, string providerKey) |
||||
|
{ |
||||
|
var settingGroups = new SettingGroupResult(); |
||||
|
var wxPusherSettingGroup = new SettingGroupDto(L["DisplayName:WxPusher"], L["Description:WxPusher"]); |
||||
|
|
||||
|
if (await PermissionChecker.IsGrantedAsync(WxPusherSettingPermissionNames.ManageSetting)) |
||||
|
{ |
||||
|
var securitySetting = wxPusherSettingGroup.AddSetting(L["Security"], L["Security"]); |
||||
|
securitySetting.AddDetail( |
||||
|
SettingDefinitionManager.Get(WxPusherSettingNames.Security.AppToken), |
||||
|
StringLocalizerFactory, |
||||
|
await SettingManager.GetOrNullAsync(WxPusherSettingNames.Security.AppToken, providerName, providerKey), |
||||
|
ValueType.String, |
||||
|
providerName); |
||||
|
} |
||||
|
|
||||
|
settingGroups.AddGroup(wxPusherSettingGroup); |
||||
|
|
||||
|
return settingGroups; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using LINGYUN.Abp.SettingManagement; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(AbpSettingManagementRemoteServiceConsts.ModuleName)] |
||||
|
[Route($"api/{AbpSettingManagementRemoteServiceConsts.ModuleName}/wx-pusher")] |
||||
|
public class WxPusherSettingController : AbpController, IWxPusherSettingAppService |
||||
|
{ |
||||
|
protected IWxPusherSettingAppService Service { get; } |
||||
|
|
||||
|
public WxPusherSettingController( |
||||
|
IWxPusherSettingAppService service) |
||||
|
{ |
||||
|
Service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-current-tenant")] |
||||
|
public async virtual Task<SettingGroupResult> GetAllForCurrentTenantAsync() |
||||
|
{ |
||||
|
return await Service.GetAllForCurrentTenantAsync(); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-global")] |
||||
|
public async virtual Task<SettingGroupResult> GetAllForGlobalAsync() |
||||
|
{ |
||||
|
return await Service.GetAllForGlobalAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using LINGYUN.Abp.WxPusher.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
public class WxPusherSettingPermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var wxPusherGroup = context.AddGroup( |
||||
|
WxPusherSettingPermissionNames.GroupName, |
||||
|
L("Permission:WxPusher")); |
||||
|
|
||||
|
wxPusherGroup.AddPermission( |
||||
|
WxPusherSettingPermissionNames.ManageSetting, L("Permission:ManageSetting")); |
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<WxPusherResource>(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace LINGYUN.Abp.WxPusher.SettingManagement |
||||
|
{ |
||||
|
public class WxPusherSettingPermissionNames |
||||
|
{ |
||||
|
public const string GroupName = "Abp.WxPusher"; |
||||
|
|
||||
|
public const string ManageSetting = GroupName + ".ManageSetting"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,205 @@ |
|||||
|
using Microsoft.Extensions.Localization; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.TextTemplating; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications; |
||||
|
|
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
public class FakeNotificationSender : INotificationSender, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<FakeNotificationSender> Logger { get; set; } |
||||
|
|
||||
|
protected AbpNotificationOptions Options { get; } |
||||
|
|
||||
|
protected IJsonSerializer JsonSerializer { get; } |
||||
|
|
||||
|
protected ITemplateRenderer TemplateRenderer { get; } |
||||
|
|
||||
|
protected INotificationStore NotificationStore { get; } |
||||
|
|
||||
|
protected IStringLocalizerFactory StringLocalizerFactory { get; } |
||||
|
|
||||
|
protected INotificationDefinitionManager NotificationDefinitionManager { get; } |
||||
|
|
||||
|
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } |
||||
|
|
||||
|
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; } |
||||
|
|
||||
|
public FakeNotificationSender( |
||||
|
IJsonSerializer jsonSerializer, |
||||
|
ITemplateRenderer templateRenderer, |
||||
|
IStringLocalizerFactory stringLocalizerFactory, |
||||
|
IOptions<AbpNotificationOptions> options, |
||||
|
INotificationStore notificationStore, |
||||
|
INotificationDefinitionManager notificationDefinitionManager, |
||||
|
INotificationSubscriptionManager notificationSubscriptionManager, |
||||
|
INotificationPublishProviderManager notificationPublishProviderManager) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
JsonSerializer = jsonSerializer; |
||||
|
TemplateRenderer = templateRenderer; |
||||
|
StringLocalizerFactory = stringLocalizerFactory; |
||||
|
NotificationStore = notificationStore; |
||||
|
NotificationDefinitionManager = notificationDefinitionManager; |
||||
|
NotificationSubscriptionManager = notificationSubscriptionManager; |
||||
|
NotificationPublishProviderManager = notificationPublishProviderManager; |
||||
|
|
||||
|
Logger = NullLogger<FakeNotificationSender>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> SendNofiterAsync( |
||||
|
string name, |
||||
|
NotificationData data, |
||||
|
IEnumerable<UserIdentifier> users = null, |
||||
|
Guid? tenantId = null, |
||||
|
NotificationSeverity severity = NotificationSeverity.Info) |
||||
|
{ |
||||
|
var notification = NotificationDefinitionManager.GetOrNull(name); |
||||
|
if (notification == null) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
var notificationInfo = new NotificationInfo |
||||
|
{ |
||||
|
Name = notification.Name, |
||||
|
CreationTime = DateTime.Now, |
||||
|
Data = data, |
||||
|
Severity = severity, |
||||
|
Lifetime = notification.NotificationLifetime, |
||||
|
TenantId = tenantId, |
||||
|
Type = notification.NotificationType |
||||
|
}; |
||||
|
notificationInfo.SetId(DateTimeOffset.Now.ToUnixTimeMilliseconds()); |
||||
|
|
||||
|
notificationInfo.Data = NotificationDataConverter.Convert(notificationInfo.Data); |
||||
|
|
||||
|
Logger.LogDebug($"Persistent notification {notificationInfo.Name}"); |
||||
|
|
||||
|
await NotificationStore.InsertNotificationAsync(notificationInfo); |
||||
|
|
||||
|
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers); |
||||
|
|
||||
|
if (notification.Providers.Any()) |
||||
|
{ |
||||
|
providers = providers.Where(p => notification.Providers.Contains(p.Name)); |
||||
|
} |
||||
|
|
||||
|
await PublishFromProvidersAsync( |
||||
|
providers, |
||||
|
users ?? new List<UserIdentifier>(), |
||||
|
notificationInfo); |
||||
|
|
||||
|
return notificationInfo.Id; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> SendNofiterAsync( |
||||
|
string name, |
||||
|
NotificationTemplate template, |
||||
|
IEnumerable<UserIdentifier> users = null, |
||||
|
Guid? tenantId = null, |
||||
|
NotificationSeverity severity = NotificationSeverity.Info) |
||||
|
{ |
||||
|
var notification = NotificationDefinitionManager.GetOrNull(name); |
||||
|
if (notification == null) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
var notificationInfo = new NotificationInfo |
||||
|
{ |
||||
|
Name = notification.Name, |
||||
|
TenantId = tenantId, |
||||
|
Severity = severity, |
||||
|
Type = notification.NotificationType, |
||||
|
CreationTime = DateTime.Now, |
||||
|
Lifetime = notification.NotificationLifetime, |
||||
|
}; |
||||
|
notificationInfo.SetId(DateTimeOffset.Now.ToUnixTimeMilliseconds()); |
||||
|
|
||||
|
var title = notification.DisplayName.Localize(StringLocalizerFactory); |
||||
|
|
||||
|
var message = await TemplateRenderer.RenderAsync( |
||||
|
templateName: name, |
||||
|
model: template.ExtraProperties); |
||||
|
|
||||
|
var notificationData = new NotificationData(); |
||||
|
notificationData.WriteStandardData( |
||||
|
title: title, |
||||
|
message: message, |
||||
|
createTime: notificationInfo.CreationTime, |
||||
|
formUser: "Fake User"); |
||||
|
notificationData.ExtraProperties.AddIfNotContains(template.ExtraProperties); |
||||
|
|
||||
|
notificationInfo.Data = notificationData; |
||||
|
|
||||
|
Logger.LogDebug($"Persistent notification {notificationInfo.Name}"); |
||||
|
|
||||
|
// 持久化通知
|
||||
|
await NotificationStore.InsertNotificationAsync(notificationInfo); |
||||
|
|
||||
|
var providers = Enumerable.Reverse(NotificationPublishProviderManager.Providers); |
||||
|
|
||||
|
// 过滤用户指定提供者
|
||||
|
if (notification.Providers.Any()) |
||||
|
{ |
||||
|
providers = providers.Where(p => notification.Providers.Contains(p.Name)); |
||||
|
} |
||||
|
|
||||
|
await PublishFromProvidersAsync( |
||||
|
providers, |
||||
|
users ?? new List<UserIdentifier>(), |
||||
|
notificationInfo); |
||||
|
|
||||
|
return notificationInfo.Id; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 指定提供者发布通知
|
||||
|
/// </summary>
|
||||
|
/// <param name="providers">提供者列表</param>
|
||||
|
/// <param name="notificationInfo">通知信息</param>
|
||||
|
/// <returns></returns>
|
||||
|
protected async Task PublishFromProvidersAsync( |
||||
|
IEnumerable<INotificationPublishProvider> providers, |
||||
|
IEnumerable<UserIdentifier> users, |
||||
|
NotificationInfo notificationInfo) |
||||
|
{ |
||||
|
foreach (var provider in providers) |
||||
|
{ |
||||
|
await PublishAsync(provider, notificationInfo, users); |
||||
|
} |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// 发布通知
|
||||
|
/// </summary>
|
||||
|
/// <param name="provider">通知发布者</param>
|
||||
|
/// <param name="notificationInfo">通知信息</param>
|
||||
|
/// <param name="subscriptionUserIdentifiers">订阅用户列表</param>
|
||||
|
/// <returns></returns>
|
||||
|
protected async Task PublishAsync( |
||||
|
INotificationPublishProvider provider, |
||||
|
NotificationInfo notificationInfo, |
||||
|
IEnumerable<UserIdentifier> subscriptionUserIdentifiers) |
||||
|
{ |
||||
|
Logger.LogDebug($"Sending notification with provider {provider.Name}"); |
||||
|
var notifacationDataMapping = Options.NotificationDataMappings |
||||
|
.GetMapItemOrDefault(provider.Name, notificationInfo.Name); |
||||
|
if (notifacationDataMapping != null) |
||||
|
{ |
||||
|
notificationInfo.Data = notifacationDataMapping.MappingFunc(notificationInfo.Data); |
||||
|
} |
||||
|
// 发布
|
||||
|
await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); |
||||
|
|
||||
|
Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\modules\wx-pusher\LINGYUN.Abp.Notifications.WxPusher\LINGYUN.Abp.Notifications.WxPusher.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.WxPusher.Tests\LINGYUN.Abp.WxPusher.Tests.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Notifications.Tests\LINGYUN.Abp.Notifications.Tests.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,7 @@ |
|||||
|
using LINGYUN.Abp.Tests; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.WxPusher; |
||||
|
|
||||
|
public abstract class AbpNotificationsWxPusherTestBase : AbpTestsBase<AbpNotificationsWxPusherTestModule> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using LINGYUN.Abp.WxPusher; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.WxPusher; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpNotificationsWxPusherModule), |
||||
|
typeof(AbpWxPusherTestModule), |
||||
|
typeof(AbpNotificationsTestsModule))] |
||||
|
public class AbpNotificationsWxPusherTestModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,77 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.WxPusher; |
||||
|
|
||||
|
public class NotificationSenderTests : AbpNotificationsWxPusherTestBase |
||||
|
{ |
||||
|
protected INotificationSender NotificationSender { get; } |
||||
|
|
||||
|
public NotificationSenderTests() |
||||
|
{ |
||||
|
NotificationSender = GetRequiredService<INotificationSender>(); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData( |
||||
|
"Title from the Xunit unit test", |
||||
|
"Text content from the Xunit unit test. \r\n Click the link at the top to redirect baidu site.")] |
||||
|
public async Task Send_Text_Test( |
||||
|
string title, |
||||
|
string message) |
||||
|
{ |
||||
|
var notificationData = new NotificationData(); |
||||
|
notificationData.WriteStandardData( |
||||
|
title, |
||||
|
message, |
||||
|
DateTime.Now, |
||||
|
"xUnit Test"); |
||||
|
notificationData.SetUrl("https://www.baidu.com/"); |
||||
|
|
||||
|
await NotificationSender.SendNofiterAsync( |
||||
|
NotificationsTestsNames.Test1, |
||||
|
notificationData); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData( |
||||
|
"Title from the Xunit unit test", |
||||
|
"<h>Html content from the Xunit unit test.</h> <br /> <a href=\"https://www.baidu.com/\">Click to redirect baidu site.</a>")] |
||||
|
public async Task Send_Html_Test( |
||||
|
string title, |
||||
|
string message) |
||||
|
{ |
||||
|
var notificationData = new NotificationData(); |
||||
|
notificationData.WriteStandardData( |
||||
|
title, |
||||
|
message, |
||||
|
DateTime.Now, |
||||
|
"xUnit Test"); |
||||
|
notificationData.SetUrl("https://www.baidu.com/"); |
||||
|
|
||||
|
await NotificationSender.SendNofiterAsync( |
||||
|
NotificationsTestsNames.Test2, |
||||
|
notificationData); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData( |
||||
|
"Title from the Xunit unit test", |
||||
|
"**Markdown content from the Xunit unit test.** <br /> <a href=\"https://www.baidu.com/\">Click to redirect baidu site.</a>")] |
||||
|
public async Task Send_Markdown_Test( |
||||
|
string title, |
||||
|
string message) |
||||
|
{ |
||||
|
var notificationData = new NotificationData(); |
||||
|
notificationData.WriteStandardData( |
||||
|
title, |
||||
|
message, |
||||
|
DateTime.Now, |
||||
|
"xUnit Test"); |
||||
|
notificationData.SetUrl("https://www.baidu.com/"); |
||||
|
|
||||
|
await NotificationSender.SendNofiterAsync( |
||||
|
NotificationsTestsNames.Test3, |
||||
|
notificationData); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using LINGYUN.Abp.WxPusher.Messages; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Notifications.WxPusher; |
||||
|
|
||||
|
public class NotificationsWxPusherTestsDefinitionProvider : NotificationDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(INotificationDefinitionContext context) |
||||
|
{ |
||||
|
var group = context.GetGroupOrNull(NotificationsTestsNames.GroupName); |
||||
|
|
||||
|
var nt1 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test1)); |
||||
|
nt1.WithProviders(WxPusherNotificationPublishProvider.ProviderName) |
||||
|
.WithContentType(MessageContentType.Text) |
||||
|
.WithTopics(new List<int> { 7182 }); |
||||
|
|
||||
|
var nt2 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test2)); |
||||
|
nt2.WithProviders(WxPusherNotificationPublishProvider.ProviderName) |
||||
|
.WithContentType(MessageContentType.Html) |
||||
|
.WithTopics(new List<int> { 7182 }); |
||||
|
|
||||
|
var nt3 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test3)); |
||||
|
nt3.WithProviders(WxPusherNotificationPublishProvider.ProviderName) |
||||
|
.WithContentType(MessageContentType.Markdown) |
||||
|
.WithTopics(new List<int> { 7182 }); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
global using Xunit; |
||||
|
global using Shouldly; |
||||
Loading…
Reference in new issue