Browse Source

集成阿里云短信服务实现短信接口;IdentityServer增加短信认证功能;升级abp到2.8.0版本

pull/1/head
cKey 6 years ago
parent
commit
c22d2264b0
  1. 5
      .gitignore
  2. 26
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj
  3. 27
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs
  4. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs
  5. 31
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterVerifyDto.cs
  6. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs
  7. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs
  8. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json
  9. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
  10. 18
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj
  11. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs
  12. 187
      aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs
  13. 12
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj
  14. 19
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs
  15. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs
  16. 19
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs
  17. 9
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs
  18. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs
  19. 26
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj
  20. 25
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs
  21. 33
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountSettingDefinitionProvider.cs
  22. 12
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/IIdentityUserRepository.cs
  23. 11
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/en.json
  24. 11
      aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json
  25. 16
      aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj
  26. 20
      aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs
  27. 36
      aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs
  28. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj
  29. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj
  30. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj
  31. 4
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj
  32. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj
  33. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj
  34. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj
  35. 22
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs
  36. 10
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj
  37. 158
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
  38. 7
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/AbpCAPEventBusModule.cs
  39. 79
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs
  40. 9
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs
  41. 25
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj
  42. 35
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs
  43. 46
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs
  44. 76
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsResponse.cs
  45. 115
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
  46. 7
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSuccessResponse.cs
  47. 9
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/AliyunSmsResource.cs
  48. 29
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/en.json
  49. 29
      aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json
  50. 2
      aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj
  51. 4
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj
  52. 2
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj
  53. 8
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs
  54. 92
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs
  55. 2
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj
  56. 26
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj
  57. 37
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmValidatorModule.cs
  58. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json
  59. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json
  60. 100
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs
  61. 13
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsValidatorConsts.cs
  62. 4
      aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj
  63. 4
      aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj
  64. 13
      aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs
  65. 4
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj
  66. 2
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj
  67. 2
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj
  68. 4
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj
  69. 2
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj
  70. 2
      aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj
  71. 11
      aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
  72. 19
      aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj
  73. 38
      aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
  74. 8
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj
  75. 10
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj
  76. 27
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs
  77. 44
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantDeleteEventHandler.cs
  78. 40
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  79. 12
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs
  80. 4
      vueJs/src/api/users.ts
  81. 204
      vueJs/src/views/admin/users/components/UserCreateForm.vue
  82. 65
      vueJs/src/views/admin/users/components/UserEditForm.vue
  83. 67
      vueJs/src/views/admin/users/index.vue
  84. 14
      vueJs/start-vue-admin.bat

5
.gitignore

@ -4,6 +4,11 @@ node_modules
vue.config.js
.env.production
task
obj
bin
Logs
appsettings.json
appsettings.*.json
/tests/e2e/videos/
/tests/e2e/screenshots/

26
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj" />
</ItemGroup>
</Project>

27
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs

@ -0,0 +1,27 @@
using Volo.Abp.Account.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account
{
[DependsOn(typeof(AbpAccountDomainSharedModule))]
public class AbpAccountApplicationContractsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountApplicationContractsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<Localization.AccountResource>()
.AddBaseTypes(typeof(AccountResource))
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources");
});
}
}
}

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
public class RegisterDto
{
[Required]
[Phone]
[StringLength(IdentityUserConsts.MaxPhoneNumberLength)]
public string PhoneNumber { get; set; }
}
}

31
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterVerifyDto.cs

@ -0,0 +1,31 @@
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
public class RegisterVerifyDto
{
[Required]
[Phone]
[StringLength(IdentityUserConsts.MaxPhoneNumberLength)]
public string PhoneNumber { get; set; }
[StringLength(IdentityUserConsts.MaxUserNameLength)]
public string UserName { get; set; }
[EmailAddress]
[StringLength(IdentityUserConsts.MaxEmailLength)]
public string EmailAddress { get; set; }
[Required]
[StringLength(IdentityUserConsts.MaxPasswordLength)]
[DataType(DataType.Password)]
[DisableAuditing]
public string Password { get; set; }
[Required]
[StringLength(6)]
public string VerifyCode { get; set; }
}
}

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.Account
{
public class VerifyDto
{
[Required]
[Phone]
public string PhoneNumber { get; set; }
[Required]
public PhoneNumberVerifyType VerifyType { get; set; }
}
}

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs

@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
public interface IAccountAppService : IApplicationService
{
Task<IdentityUserDto> RegisterAsync(RegisterVerifyDto input);
Task VerifyPhoneNumberAsync(VerifyDto input);
}
}

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json

@ -0,0 +1,8 @@
{
"culture": "en",
"texts": {
"PhoneNumberNotRegisterd": "The registered mobile phone number is not registered!",
"PhoneVerifyCodeInvalid": "The phone verification code is invalid or expired!",
"PhoneVerifyCodeNotRepeatSend": "Phone verification code cannot be sent repeatedly within {0} minutes!"
}
}

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json

@ -0,0 +1,8 @@
{
"culture": "zh-Hans",
"texts": {
"PhoneNumberNotRegisterd": "手机号码未注册!",
"PhoneVerifyCodeInvalid": "手机验证码无效或已经过期!",
"PhoneVerifyCodeNotRepeatSend": "手机验证码不能在 {0} 分钟内重复发送!"
}
}

18
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Account.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Sms" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Account.Domain\LINGYUN.Abp.Account.Domain.csproj" />
</ItemGroup>
</Project>

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs

@ -0,0 +1,13 @@
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(
typeof(AbpAccountDomainModule),
typeof(Volo.Abp.Account.AbpAccountApplicationModule),
typeof(AbpAccountApplicationContractsModule))]
public class AbpAccountApplicationModule : AbpModule
{
}
}

187
aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs

@ -0,0 +1,187 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Identity;
using Volo.Abp.Settings;
using Volo.Abp.Sms;
namespace LINGYUN.Abp.Account
{
/// <summary>
/// 用户注册服务
/// </summary>
public class AccountAppService : ApplicationService, IAccountAppService
{
protected ISmsSender SmsSender { get; }
protected IdentityUserManager UserManager { get; }
protected IIdentityUserRepository UserRepository { get; }
protected IDistributedCache<AccountRegisterVerifyCacheItem> Cache { get; }
protected PhoneNumberTokenProvider<IdentityUser> PhoneNumberTokenProvider { get; }
public AccountAppService(
ISmsSender smsSender,
IdentityUserManager userManager,
IIdentityUserRepository userRepository,
IDistributedCache<AccountRegisterVerifyCacheItem> cache,
PhoneNumberTokenProvider<IdentityUser> phoneNumberTokenProvider)
{
Cache = cache;
SmsSender = smsSender;
UserManager = userManager;
UserRepository = userRepository;
PhoneNumberTokenProvider = phoneNumberTokenProvider;
LocalizationResource = typeof(Localization.AccountResource);
}
/// <summary>
/// 用户注册
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <remarks>
/// 用户通过VerifyPhoneNumber接口发送到手机的验证码,传递注册信息注册用户
/// 如果没有此手机号的缓存记录或验证码不匹配,抛出验证码无效的异常
/// 用户注册成功,清除缓存的验证码记录
/// </remarks>
public virtual async Task<IdentityUserDto> RegisterAsync(RegisterVerifyDto input)
{
var phoneVerifyCacheKey = NormalizeCacheKey(input.PhoneNumber);
var phoneVerifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey);
if(phoneVerifyCacheItem == null || !phoneVerifyCacheItem.VerifyCode.Equals(input.VerifyCode))
{
throw new UserFriendlyException(L["PhoneVerifyCodeInvalid"]);
}
await CheckSelfRegistrationAsync();
var userEmail = input.EmailAddress ?? input.PhoneNumber + "@abp.io";
var userName = input.UserName ?? input.PhoneNumber;
var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id);
(await UserManager.CreateAsync(user, input.Password)).CheckErrors();
await UserManager.SetPhoneNumberAsync(user, input.PhoneNumber);
await UserManager.SetEmailAsync(user, userEmail);
await UserManager.AddDefaultRolesAsync(user);
await Cache.RemoveAsync(phoneVerifyCacheKey);
return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
}
/// <summary>
/// 验证手机号码
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <remarks>
/// 用户传递手机号码及认证类型
/// 1、如果认证类型为注册:
/// 先查询是否存在此手机号的缓存验证码信息,如果存在,抛出不能重复发送验证码异常
/// 随机生成6位纯数字验证码,通过短信接口服务发送到用户手机,并缓存验证码,设定一个有效时长
///
/// 2、如果认证类型为登录:
/// 先查询是否存在此手机号的缓存验证码信息,如果存在,抛出不能重复发送验证码异常
/// 通过手机号查询用户信息,如果用户不存在,抛出手机号未注册异常
/// 调用PhoneNumberTokenProvider接口生成6位手机验证码,用途为 phone_verify
/// 发送手机验证码到用户手机,并缓存验证码,设定一个有效时长
///
/// 用户调用 IdentityServer4/connect/token 登录系统(需要引用LINGYUN.Abp.IdentityServer.SmsValidator模块)
/// 参数1:grant_type=phone_verify
/// 参数2:phone_number=手机号码
/// 参数3:phone_verify_code=手机验证码
/// 参数4:client_id=客户端标识
/// 参数5:client_secret=客户端密钥
/// </remarks>
public virtual async Task VerifyPhoneNumberAsync(VerifyDto input)
{
var verifyCodeExpiration = await SettingProvider.GetAsync<int>(AccountSettingNames.PhoneVerifyCodeExpiration);
var phoneVerifyCacheKey = NormalizeCacheKey(input.PhoneNumber);
var verifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey);
if (verifyCacheItem != null)
{
throw new UserFriendlyException(L["PhoneVerifyCodeNotRepeatSend", verifyCodeExpiration]);
}
verifyCacheItem = new AccountRegisterVerifyCacheItem
{
PhoneNumber = input.PhoneNumber,
};
if (input.VerifyType == PhoneNumberVerifyType.Register)
{
var phoneVerifyCode = new Random().Next(100000, 999999);
verifyCacheItem.VerifyCode = phoneVerifyCode.ToString();
var templateCode = await SettingProvider.GetOrNullAsync(AccountSettingNames.SmsRegisterTemplateCode);
await SendPhoneVerifyMessageAsync(templateCode, input.PhoneNumber, phoneVerifyCode.ToString());
}
else
{
var phoneVerifyCode = await SendSigninVerifyCodeAsync(input.PhoneNumber);
verifyCacheItem.VerifyCode = phoneVerifyCode;
}
var cacheOptions = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(verifyCodeExpiration)
};
await Cache.SetAsync(phoneVerifyCacheKey, verifyCacheItem, cacheOptions);
}
/// <summary>
/// 发送登录验证码
/// </summary>
/// <param name="phoneNumber">手机号</param>
/// <returns>返回登录验证码</returns>
protected virtual async Task<string> SendSigninVerifyCodeAsync(string phoneNumber)
{
// 查找用户信息
var user = await UserRepository.FindByPhoneNumberAsync(phoneNumber);
if (user == null)
{
throw new UserFriendlyException(L["PhoneNumberNotRegisterd"]);
}
// 获取登录验证码模板号
var templateCode = await SettingProvider.GetOrNullAsync(AccountSettingNames.SmsSigninTemplateCode);
// 生成手机验证码
var phoneVerifyCode = await PhoneNumberTokenProvider.GenerateAsync("phone_verify", UserManager, user);
// 发送短信验证码
await SendPhoneVerifyMessageAsync(templateCode, user.PhoneNumber, phoneVerifyCode);
return phoneVerifyCode;
}
/// <summary>
/// 检查是否允许用户注册
/// </summary>
/// <returns></returns>
protected virtual async Task CheckSelfRegistrationAsync()
{
if (!await SettingProvider.IsTrueAsync(Volo.Abp.Account.Settings.AccountSettingNames.IsSelfRegistrationEnabled))
{
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
}
}
/// <summary>
/// 发送短信验证码
/// </summary>
/// <param name="templateCode"></param>
/// <param name="phoneNumber"></param>
/// <param name="verifyCode"></param>
/// <returns></returns>
protected virtual async Task SendPhoneVerifyMessageAsync(string templateCode, string phoneNumber, string verifyCode)
{
var sendMessage = new SmsMessage(phoneNumber, "SendSmsMessage");
sendMessage.Properties.Add("code", verifyCode);
sendMessage.Properties.Add("TemplateCode", templateCode);
await SmsSender.SendAsync(sendMessage);
}
/// <summary>
/// 格式化缓存主键
/// </summary>
/// <param name="phoneNumber">手机号码</param>
/// <returns></returns>
protected string NormalizeCacheKey(string phoneNumber)
{
return $"ACCOUNT-PHONE:{phoneNumber}";
}
}
}

12
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="2.8.0" />
</ItemGroup>
</Project>

19
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs

@ -0,0 +1,19 @@
using LINGYUN.Abp.Account.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(typeof(AbpLocalizationModule))]
public class AbpAccountDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AccountResource>("zh-Hans");
});
}
}
}

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs

@ -0,0 +1,8 @@
namespace LINGYUN.Abp.Account
{
public class AccountRegisterVerifyCacheItem
{
public string PhoneNumber { get; set; }
public string VerifyCode { get; set; }
}
}

19
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs

@ -0,0 +1,19 @@
namespace LINGYUN.Abp.Account
{
public class AccountSettingNames
{
public const string GroupName = "Abp.Account";
/// <summary>
/// 短信验证码过期时间
/// </summary>
public const string PhoneVerifyCodeExpiration = GroupName + ".PhoneVerifyCodeExpiration";
/// <summary>
/// 用户注册短信验证码模板号
/// </summary>
public const string SmsRegisterTemplateCode = GroupName + ".SmsRegisterTemplateCode";
/// <summary>
/// 用户登录短信验证码模板号
/// </summary>
public const string SmsSigninTemplateCode = GroupName + ".SmsSigninTemplateCode";
}
}

9
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Account.Localization
{
[LocalizationResourceName("LINYUNAbpAccount")]
public class AccountResource
{
}
}

8
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs

@ -0,0 +1,8 @@
namespace LINGYUN.Abp.Account
{
public enum PhoneNumberVerifyType : sbyte
{
Register = 0,
Signin = 10
}
}

26
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Identity.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj" />
</ItemGroup>
</Project>

25
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs

@ -0,0 +1,25 @@
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account
{
[DependsOn(typeof(AbpAccountDomainSharedModule))]
public class AbpAccountDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountDomainModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<Localization.AccountResource>()
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources");
});
}
}
}

33
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountSettingDefinitionProvider.cs

@ -0,0 +1,33 @@
using LINGYUN.Abp.Account.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account
{
public class AbpAccountSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(GetAccountSettings());
}
protected SettingDefinition[] GetAccountSettings()
{
return new SettingDefinition[]
{
new SettingDefinition(AccountSettingNames.SmsRegisterTemplateCode,
"SMS_190728520", L("DisplayName:SmsRegisterTemplateCode"), L("Description:SmsRegisterTemplateCode")),
new SettingDefinition(AccountSettingNames.SmsSigninTemplateCode,
"SMS_190728516", L("DisplayName:SmsSigninTemplateCode"), L("Description:SmsSigninTemplateCode")),
new SettingDefinition(AccountSettingNames.PhoneVerifyCodeExpiration,
"3", L("DisplayName:PhoneVerifyCodeExpiration"), L("Description:PhoneVerifyCodeExpiration")),
};
}
protected LocalizableString L(string name)
{
return LocalizableString.Create<AccountResource>(name);
}
}
}

12
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/IIdentityUserRepository.cs

@ -0,0 +1,12 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
public interface IIdentityUserRepository : IReadOnlyRepository<IdentityUser, Guid>
{
Task<IdentityUser> FindByPhoneNumberAsync(string phoneNumber);
}
}

11
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/en.json

@ -0,0 +1,11 @@
{
"culture": "en",
"texts": {
"DisplayName:SmsRegisterTemplateCode": "Register sms template",
"Description:SmsRegisterTemplateCode": "When the user registers, he/she should send the template number of the SMS verification code and fill in the template number of the corresponding cloud platform registration",
"DisplayName:SmsSigninTemplateCode": "Signin sms template",
"Description:SmsSigninTemplateCode": "When the user logs in, he/she should send the template number of the SMS verification code and fill in the template number of the corresponding cloud platform registration",
"DisplayName:PhoneVerifyCodeExpiration": "SMS verification code validity",
"Description:PhoneVerifyCodeExpiration": "The valid time for the user to send SMS verification code, unit m, default 3m"
}
}

11
aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json

@ -0,0 +1,11 @@
{
"culture": "zh-Hans",
"texts": {
"DisplayName:SmsRegisterTemplateCode": "用户注册短信模板",
"Description:SmsRegisterTemplateCode": "用户注册时发送短信验证码的模板号,填写对应云平台注册的模板号",
"DisplayName:SmsSigninTemplateCode": "用户登录短信模板",
"Description:SmsSigninTemplateCode": "用户登录时发送短信验证码的模板号,填写对应云平台注册的模板号",
"DisplayName:PhoneVerifyCodeExpiration": "短信验证码有效期",
"Description:PhoneVerifyCodeExpiration": "用户发送短信验证码的有效时长,单位m,默认3m"
}
}

16
aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj" />
</ItemGroup>
</Project>

20
aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs

@ -0,0 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Account
{
[DependsOn(
typeof(AbpAccountApplicationContractsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpAccountHttpApiModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly);
});
}
}
}

36
aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs

@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.Account
{
[RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)]
[Area("account")]
[Route("api/account/phone")]
public class AccountController : AbpController, IAccountAppService
{
protected IAccountAppService AccountAppService { get; }
public AccountController(
IAccountAppService accountAppService)
{
AccountAppService = accountAppService;
}
[HttpPost]
[Route("register")]
public virtual async Task<IdentityUserDto> RegisterAsync(RegisterVerifyDto input)
{
return await AccountAppService.RegisterAsync(input);
}
[HttpPost]
[Route("verify")]
public virtual async Task VerifyPhoneNumberAsync(VerifyDto input)
{
await AccountAppService.VerifyPhoneNumberAsync(input);
}
}
}

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj

@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj

@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Localization" Version="2.8.0" />
</ItemGroup>
</Project>

4
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj

@ -7,8 +7,8 @@
<ItemGroup>
<PackageReference Include="DotNetCore.CAP" Version="3.0.3" />
<PackageReference Include="Volo.Abp.Caching" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Caching" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Http.Client" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

22
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs

@ -11,12 +11,21 @@ using Volo.Abp.EventBus.Distributed;
namespace DotNetCore.CAP
{
/// <summary>
/// 消费者查找器
/// </summary>
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
[ExposeServices(typeof(IConsumerServiceSelector), typeof(ConsumerServiceSelector))]
public class ConsumerServiceSelector : Internal.ConsumerServiceSelector
{
/// <summary>
/// Abp分布式事件配置
/// </summary>
protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; }
/// <summary>
/// 服务提供者
/// </summary>
protected IServiceProvider ServiceProvider { get; }
/// <summary>
@ -27,7 +36,11 @@ namespace DotNetCore.CAP
ServiceProvider = serviceProvider;
AbpDistributedEventBusOptions = distributedEventBusOptions.Value;
}
/// <summary>
/// 查找消费者集合
/// </summary>
/// <param name="provider"></param>
/// <returns></returns>
protected override IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromInterfaceTypes(IServiceProvider provider)
{
var executorDescriptorList =
@ -55,7 +68,12 @@ namespace DotNetCore.CAP
}
return executorDescriptorList;
}
/// <summary>
/// 获取事件处理器集合
/// </summary>
/// <param name="eventType"></param>
/// <param name="typeInfo"></param>
/// <returns></returns>
protected virtual IEnumerable<ConsumerExecutorDescriptor> GetHandlerDescription(Type eventType, Type typeInfo)
{
var serviceTypeInfo = typeof(IDistributedEventHandler<>)

10
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj

@ -3,11 +3,19 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Version>2.8.0</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>D:\LocalNuget</OutputPath>
<DocumentationFile>D:\Projects\MicroService\CRM\Vue\vue-abp\aspnet-core\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.CAP" Version="3.0.3" />
<PackageReference Include="Volo.Abp.EventBus" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EventBus" Version="2.8.0" />
</ItemGroup>
</Project>

158
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml

@ -0,0 +1,158 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>LINGYUN.Abp.EventBus.CAP</name>
</assembly>
<members>
<member name="T:DotNetCore.CAP.ConsumerServiceSelector">
<summary>
消费者查找器
</summary>
</member>
<member name="P:DotNetCore.CAP.ConsumerServiceSelector.AbpDistributedEventBusOptions">
<summary>
Abp分布式事件配置
</summary>
</member>
<member name="P:DotNetCore.CAP.ConsumerServiceSelector.ServiceProvider">
<summary>
服务提供者
</summary>
</member>
<member name="M:DotNetCore.CAP.ConsumerServiceSelector.#ctor(System.IServiceProvider,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions})">
<summary>
Creates a new <see cref="T:DotNetCore.CAP.Internal.ConsumerServiceSelector" />.
</summary>
</member>
<member name="M:DotNetCore.CAP.ConsumerServiceSelector.FindConsumersFromInterfaceTypes(System.IServiceProvider)">
<summary>
查找消费者集合
</summary>
<param name="provider"></param>
<returns></returns>
</member>
<member name="M:DotNetCore.CAP.ConsumerServiceSelector.GetHandlerDescription(System.Type,System.Type)">
<summary>
获取事件处理器集合
</summary>
<param name="eventType"></param>
<param name="typeInfo"></param>
<returns></returns>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.AbpCAPEventBusModule">
<summary>
AbpCAPEventBusModule
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPEventBusModule.ConfigureServices(Volo.Abp.Modularity.ServiceConfigurationContext)">
<summary>
ConfigureServices
</summary>
<param name="context"></param>
</member>
<member name="T:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus">
<summary>
CAP分布式事件总线
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.AbpDistributedEventBusOptions">
<summary>
Abp分布式事件总线配置
</summary>
</member>
<member name="F:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.CapPublisher">
<summary>
CAP消息发布接口
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.HandlerFactories">
<summary>
本地事件处理器工厂对象集合
</summary>
</member>
<member name="P:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.EventTypes">
<summary>
本地事件集合
</summary>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.#ctor(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory,Microsoft.Extensions.Options.IOptions{Volo.Abp.EventBus.Distributed.AbpDistributedEventBusOptions},DotNetCore.CAP.ICapPublisher)">
<summary>
constructor
</summary>
<param name="serviceScopeFactory"></param>
<param name="distributedEventBusOptions"></param>
<param name="capPublisher"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Subscribe(System.Type,Volo.Abp.EventBus.IEventHandlerFactory)">
<summary>
订阅事件
</summary>
<param name="eventType"></param>
<param name="factory"></param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Unsubscribe``1(System.Func{``0,System.Threading.Tasks.Task})">
<summary>
退订事件
</summary>
<typeparam name="TEvent">事件类型</typeparam>
<param name="action"></param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Unsubscribe(System.Type,Volo.Abp.EventBus.IEventHandler)">
<summary>
退订事件
</summary>
<param name="eventType">事件类型</param>
<param name="handler">事件处理器</param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Unsubscribe(System.Type,Volo.Abp.EventBus.IEventHandlerFactory)">
<summary>
退订事件
</summary>
<param name="eventType">事件类型</param>
<param name="factory">事件处理器工厂</param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.UnsubscribeAll(System.Type)">
<summary>
退订所有事件
</summary>
<param name="eventType">事件类型</param>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.Subscribe``1(Volo.Abp.EventBus.Distributed.IDistributedEventHandler{``0})">
<summary>
订阅事件
</summary>
<typeparam name="TEvent">事件类型</typeparam>
<param name="handler">事件处理器</param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.PublishAsync(System.Type,System.Object)">
<summary>
发布事件
</summary>
<param name="eventType">事件类型</param>
<param name="eventData">事件数据对象</param>
<returns></returns>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.CAPDistributedEventBus.GetHandlerFactories(System.Type)">
<summary>
获取事件处理器工厂列表
</summary>
<param name="eventType"></param>
<returns></returns>
</member>
<member name="T:Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions">
<summary>
CAP ServiceCollectionExtensions
</summary>
</member>
<member name="M:Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.AddCAPEventBus(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{DotNetCore.CAP.CapOptions})">
<summary>
Adds and configures the consistence services for the consistency.
</summary>
<param name="services"></param>
<param name="capAction"></param>
<returns></returns>
</member>
</members>
</doc>

7
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/AbpCAPEventBusModule.cs

@ -5,9 +5,16 @@ using Volo.Abp.Modularity;
namespace LINGYUN.Abp.EventBus.CAP
{
/// <summary>
/// AbpCAPEventBusModule
/// </summary>
[DependsOn(typeof(AbpEventBusModule))]
public class AbpCAPEventBusModule : AbpModule
{
/// <summary>
/// ConfigureServices
/// </summary>
/// <param name="context"></param>
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();

79
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs

@ -14,17 +14,36 @@ using Volo.Abp.Threading;
namespace LINGYUN.Abp.EventBus.CAP
{
/// <summary>
/// CAP分布式事件总线
/// </summary>
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
[ExposeServices(typeof(IDistributedEventBus), typeof(CAPDistributedEventBus))]
public class CAPDistributedEventBus : EventBusBase, IDistributedEventBus
{
/// <summary>
/// Abp分布式事件总线配置
/// </summary>
protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; }
/// <summary>
/// CAP消息发布接口
/// </summary>
protected readonly ICapPublisher CapPublisher;
//TODO: Accessing to the List<IEventHandlerFactory> may not be thread-safe!
/// <summary>
/// 本地事件处理器工厂对象集合
/// </summary>
protected ConcurrentDictionary<Type, List<IEventHandlerFactory>> HandlerFactories { get; }
/// <summary>
/// 本地事件集合
/// </summary>
protected ConcurrentDictionary<string, Type> EventTypes { get; }
/// <summary>
/// constructor
/// </summary>
/// <param name="serviceScopeFactory"></param>
/// <param name="distributedEventBusOptions"></param>
/// <param name="capPublisher"></param>
public CAPDistributedEventBus(IServiceScopeFactory serviceScopeFactory,
IOptions<AbpDistributedEventBusOptions> distributedEventBusOptions,
ICapPublisher capPublisher) : base(serviceScopeFactory)
@ -34,13 +53,22 @@ namespace LINGYUN.Abp.EventBus.CAP
HandlerFactories = new ConcurrentDictionary<Type, List<IEventHandlerFactory>>();
EventTypes = new ConcurrentDictionary<string, Type>();
}
/// <summary>
/// 订阅事件
/// </summary>
/// <param name="eventType"></param>
/// <param name="factory"></param>
/// <returns></returns>
public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory)
{
//This is handled by CAP ConsumerServiceSelector
throw new NotImplementedException();
}
/// <summary>
/// 退订事件
/// </summary>
/// <typeparam name="TEvent">事件类型</typeparam>
/// <param name="action"></param>
public override void Unsubscribe<TEvent>(Func<TEvent, Task> action)
{
Check.NotNull(action, nameof(action));
@ -51,14 +79,12 @@ namespace LINGYUN.Abp.EventBus.CAP
factories.RemoveAll(
factory =>
{
var singleInstanceFactory = factory as SingleInstanceHandlerFactory;
if (singleInstanceFactory == null)
if (!(factory is SingleInstanceHandlerFactory singleInstanceFactory))
{
return false;
}
var actionHandler = singleInstanceFactory.HandlerInstance as ActionEventHandler<TEvent>;
if (actionHandler == null)
if (!(singleInstanceFactory.HandlerInstance is ActionEventHandler<TEvent> actionHandler))
{
return false;
}
@ -67,7 +93,11 @@ namespace LINGYUN.Abp.EventBus.CAP
});
});
}
/// <summary>
/// 退订事件
/// </summary>
/// <param name="eventType">事件类型</param>
/// <param name="handler">事件处理器</param>
public override void Unsubscribe(Type eventType, IEventHandler handler)
{
GetOrCreateHandlerFactories(eventType)
@ -80,29 +110,50 @@ namespace LINGYUN.Abp.EventBus.CAP
);
});
}
/// <summary>
/// 退订事件
/// </summary>
/// <param name="eventType">事件类型</param>
/// <param name="factory">事件处理器工厂</param>
public override void Unsubscribe(Type eventType, IEventHandlerFactory factory)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory));
}
/// <summary>
/// 退订所有事件
/// </summary>
/// <param name="eventType">事件类型</param>
public override void UnsubscribeAll(Type eventType)
{
GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear());
}
/// <summary>
/// 订阅事件
/// </summary>
/// <typeparam name="TEvent">事件类型</typeparam>
/// <param name="handler">事件处理器</param>
/// <returns></returns>
public IDisposable Subscribe<TEvent>(IDistributedEventHandler<TEvent> handler) where TEvent : class
{
return Subscribe(typeof(TEvent), handler);
}
/// <summary>
/// 发布事件
/// </summary>
/// <param name="eventType">事件类型</param>
/// <param name="eventData">事件数据对象</param>
/// <returns></returns>
public override async Task PublishAsync(Type eventType, object eventData)
{
var eventName = EventNameAttribute.GetNameOrDefault(eventType);
await CapPublisher.PublishAsync(eventName, eventData);
}
/// <summary>
/// 获取事件处理器工厂列表
/// </summary>
/// <param name="eventType"></param>
/// <returns></returns>
protected override IEnumerable<EventTypeWithEventHandlerFactories> GetHandlerFactories(Type eventType)
{
var handlerFactoryList = new List<EventTypeWithEventHandlerFactories>();

9
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs

@ -3,8 +3,17 @@ using System;
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// CAP ServiceCollectionExtensions
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds and configures the consistence services for the consistency.
/// </summary>
/// <param name="services"></param>
/// <param name="capAction"></param>
/// <returns></returns>
public static IServiceCollection AddCAPEventBus(this IServiceCollection services, Action<CapOptions> capAction)
{
services.AddCap(capAction);

25
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINYUN\Abp\Sms\Aliyun\Localization\Resources\en.json" />
<None Remove="LINYUN\Abp\Sms\Aliyun\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINYUN\Abp\Sms\Aliyun\Localization\Resources\en.json" />
<EmbeddedResource Include="LINYUN\Abp\Sms\Aliyun\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="aliyun-net-sdk-core" Version="1.5.6" />
<PackageReference Include="Volo.Abp.Json" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Localization" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Sms" Version="2.8.0" />
</ItemGroup>
</Project>

35
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs

@ -0,0 +1,35 @@
using LINYUN.Abp.Sms.Aliyun.Localization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Sms;
using Volo.Abp.VirtualFileSystem;
namespace LINYUN.Abp.Sms.Aliyun
{
[DependsOn(
typeof(AbpSmsModule),
typeof(AbpJsonModule),
typeof(AbpLocalizationModule))]
public class AbpAliyunSmsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AliyunSmsOptions>(configuration.GetSection("Aliyun:Sms"));
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAliyunSmsModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AliyunSmsResource>("en")
.AddVirtualJson("/LINYUN/Abp/Sms/Aliyun/Localization/Resources");
});
}
}
}

46
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs

@ -0,0 +1,46 @@
namespace LINYUN.Abp.Sms.Aliyun
{
public class AliyunSmsOptions
{
/// <summary>
/// 区域Id
/// </summary>
public string RegionId { get; set; } = "default";
/// <summary>
/// 阿里云sms服务域名
/// </summary>
public string Domain { get; set; } = "dysmsapi.aliyuncs.com";
/// <summary>
/// 调用方法名称
/// </summary>
public string ActionName { get; set; } = "SendSms";
/// <summary>
/// ApiKey
/// </summary>
public string AccessKeyId { get; set; }
/// <summary>
/// Api密钥
/// </summary>
public string AccessKeySecret { get; set; }
/// <summary>
/// 默认版本号
/// </summary>
public string DefaultVersion { get; set; } = "2017-05-25";
/// <summary>
/// 默认签名
/// </summary>
public string DefaultSignName { get; set; }
/// <summary>
/// 默认短信模板号
/// </summary>
public string DefaultTemplateCode { get; set; }
/// <summary>
/// 开发人员号码,当应用处于开发模式时,默认所有信息都会发送到此号码
/// </summary>
public string DeveloperPhoneNumber { get; set; } = "13800138000";
/// <summary>
/// 展示错误给客户端
/// </summary>
public bool VisableErrorToClient { get; set; } = false;
}
}

76
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsResponse.cs

@ -0,0 +1,76 @@
using LINYUN.Abp.Sms.Aliyun.Localization;
using System;
using Volo.Abp;
using Volo.Abp.Localization;
namespace LINYUN.Abp.Sms.Aliyun
{
public class AliyunSmsResponse
{
public string Code { get; set; }
public string Message { get; set; }
public string RequestId { get; set; }
public bool IsSuccess()
{
return "ok".Equals(Code, StringComparison.CurrentCultureIgnoreCase);
}
public ILocalizableString GetErrorMessage()
{
Check.NotNullOrWhiteSpace(Code, nameof(Code));
switch (Code)
{
case "isv.SMS_TEMPLATE_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("SMS_TEMPLATE_ILLEGAL");
case "isv.SMS_SIGNATURE_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("SMS_SIGNATURE_ILLEGAL");
case "isv.MOBILE_NUMBER_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("MOBILE_NUMBER_ILLEGAL");
case "isv.TEMPLATE_MISSING_PARAMETERS":
return LocalizableString.Create<AliyunSmsResource>("TEMPLATE_MISSING_PARAMETERS");
case "isv.EXTEND_CODE_ERROR":
return LocalizableString.Create<AliyunSmsResource>("EXTEND_CODE_ERROR");
case "isv.DOMESTIC_NUMBER_NOT_SUPPORTED":
return LocalizableString.Create<AliyunSmsResource>("DOMESTIC_NUMBER_NOT_SUPPORTED");
case "isv.DAY_LIMIT_CONTROL":
return LocalizableString.Create<AliyunSmsResource>("DAY_LIMIT_CONTROL");
case "isv.SMS_CONTENT_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("SMS_CONTENT_ILLEGAL");
case "isv.SMS_SIGN_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("SMS_SIGN_ILLEGAL");
case "isp.RAM_PERMISSION_DENY":
return LocalizableString.Create<AliyunSmsResource>("RAM_PERMISSION_DENY");
case "isp.OUT_OF_SERVICE":
return LocalizableString.Create<AliyunSmsResource>("OUT_OF_SERVICE");
case "isv.PRODUCT_UN_SUBSCRIPT":
return LocalizableString.Create<AliyunSmsResource>("PRODUCT_UN_SUBSCRIPT");
case "isv.PRODUCT_UNSUBSCRIBE":
return LocalizableString.Create<AliyunSmsResource>("PRODUCT_UNSUBSCRIBE");
case "isv.ACCOUNT_NOT_EXISTS":
return LocalizableString.Create<AliyunSmsResource>("ACCOUNT_NOT_EXISTS");
case "isv.ACCOUNT_ABNORMAL":
return LocalizableString.Create<AliyunSmsResource>("ACCOUNT_ABNORMAL");
case "isv.INVALID_PARAMETERS":
return LocalizableString.Create<AliyunSmsResource>("INVALID_PARAMETERS");
case "isv.SYSTEM_ERROR":
return LocalizableString.Create<AliyunSmsResource>("SYSTEM_ERROR");
case "isv.INVALID_JSON_PARAM":
return LocalizableString.Create<AliyunSmsResource>("INVALID_JSON_PARAM");
case "isv.BLACK_KEY_CONTROL_LIMIT":
return LocalizableString.Create<AliyunSmsResource>("BLACK_KEY_CONTROL_LIMIT");
case "isv.PARAM_LENGTH_LIMIT":
return LocalizableString.Create<AliyunSmsResource>("PARAM_LENGTH_LIMIT");
case "isv.PARAM_NOT_SUPPORT_URL":
return LocalizableString.Create<AliyunSmsResource>("PARAM_NOT_SUPPORT_URL");
case "isv.AMOUNT_NOT_ENOUGH":
return LocalizableString.Create<AliyunSmsResource>("AMOUNT_NOT_ENOUGH");
case "isv.TEMPLATE_PARAMS_ILLEGAL":
return LocalizableString.Create<AliyunSmsResource>("TEMPLATE_PARAMS_ILLEGAL");
default:
throw new AbpException("no error code define!");
}
}
}
}

115
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs

@ -0,0 +1,115 @@
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Exceptions;
using Aliyun.Acs.Core.Http;
using Aliyun.Acs.Core.Profile;
using LINYUN.Abp.Sms.Aliyun.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Localization;
using Volo.Abp.Sms;
namespace LINYUN.Abp.Sms.Aliyun
{
[Dependency(ServiceLifetime.Singleton)]
[ExposeServices(typeof(ISmsSender), typeof(AliyunSmsSender))]
public class AliyunSmsSender : ISmsSender
{
protected AliyunSmsOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IHostEnvironment Environment { get; }
protected IServiceProvider ServiceProvider { get; }
public AliyunSmsSender(
IHostEnvironment environment,
IJsonSerializer jsonSerializer,
IServiceProvider serviceProvider,
IOptions<AliyunSmsOptions> options)
{
Options = options.Value;
Environment = environment;
JsonSerializer = jsonSerializer;
ServiceProvider = serviceProvider;
}
public Task SendAsync(SmsMessage smsMessage)
{
CommonRequest request = new CommonRequest
{
Method = MethodType.POST,
Domain = Options.Domain,
Action = Options.ActionName,
Version = Options.DefaultVersion
};
if (smsMessage.Properties.TryGetValue("TemplateCode", out object template))
{
request.AddQueryParameters("TemplateCode", template.ToString());
smsMessage.Properties.Remove("TemplateCode");
}
else
{
Check.NotNullOrWhiteSpace(Options.DefaultTemplateCode, nameof(Options.DefaultTemplateCode));
request.AddQueryParameters("TemplateCode", Options.DefaultTemplateCode);
}
if (smsMessage.Properties.TryGetValue("SignName", out object signName))
{
request.AddQueryParameters("SignName", signName.ToString());
smsMessage.Properties.Remove("SignName");
}
else
{
Check.NotNullOrWhiteSpace(Options.DefaultSignName, nameof(Options.DefaultSignName));
request.AddQueryParameters("SignName", Options.DefaultSignName);
}
if (Environment.IsDevelopment())
{
Check.NotNullOrWhiteSpace(Options.DeveloperPhoneNumber, nameof(Options.DeveloperPhoneNumber));
request.AddQueryParameters("PhoneNumbers", Options.DeveloperPhoneNumber);
}
else
{
request.AddQueryParameters("PhoneNumbers", smsMessage.PhoneNumber);
}
var queryParamJson = JsonSerializer.Serialize(smsMessage.Properties);
request.AddQueryParameters("TemplateParam", queryParamJson);
try
{
IClientProfile profile = DefaultProfile.GetProfile(Options.RegionId, Options.AccessKeyId, Options.AccessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonResponse response = client.GetCommonResponse(request);
var responseContent = Encoding.Default.GetString(response.HttpResponse.Content);
var aliyunResponse = JsonSerializer.Deserialize<AliyunSmsResponse>(responseContent);
if (!aliyunResponse.IsSuccess())
{
var localizerFactory = ServiceProvider.GetRequiredService<IStringLocalizerFactory>();
var localizerError = aliyunResponse.GetErrorMessage().Localize(localizerFactory);
if (Options.VisableErrorToClient)
{
var localizer = ServiceProvider.GetRequiredService<IStringLocalizer<AliyunSmsResource>>();
localizerError = localizer["SendMessageFailed", localizerError];
throw new UserFriendlyException(localizerError);
}
throw new AbpException($"Text message sending failed:{localizerError}!");
}
}
catch(ServerException se)
{
throw new AbpException("Sending text messages to aliyun server is abnormal", se);
}
catch(ClientException ce)
{
throw new AbpException("A client exception occurred in sending SMS messages", ce);
}
return Task.CompletedTask;
}
}
}

7
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSuccessResponse.cs

@ -0,0 +1,7 @@
namespace LINYUN.Abp.Sms.Aliyun
{
public class AliyunSmsSuccessResponse : AliyunSmsResponse
{
public string BizId { get; set; }
}
}

9
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/AliyunSmsResource.cs

@ -0,0 +1,9 @@
using Volo.Abp.Localization;
namespace LINYUN.Abp.Sms.Aliyun.Localization
{
[LocalizationResourceName("AliyunSms")]
public class AliyunSmsResource
{
}
}

29
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/en.json

@ -0,0 +1,29 @@
{
"culture": "en",
"texts": {
"SendMessageFailed": "Text message sending failed:{0}",
"SMS_TEMPLATE_ILLEGAL": "template is not valid (not present or blocked)",
"SMS_SIGNATURE_ILLEGAL": "the signature is not valid (not present or blocked)",
"MOBILE_NUMBER_ILLEGAL": "invalid phone number ",
"TEMPLATE_MISSING_PARAMETERS": "template variable missing corresponding parameter value ",
"EXTEND_CODE_ERROR": "Error using extension code",
"DOMESTIC_NUMBER_NOT_SUPPORTED": "the template for international/Hong Kong, Macao and Taiwan messages does not support the sending of domestic Numbers",
"DAY_LIMIT_CONTROL": "trigger daily send limit ",
"SMS_CONTENT_ILLEGAL": "SMS content contains prohibited content ",
"SMS_SIGN_ILLEGAL": "signature is not allowed ",
"RAM_PERMISSION_DENY": "RAM permission DENY",
"OUT_OF_SERVICE": "business down ",
"PRODUCT_UN_SUBSCRIPT": "ali cloud customers who have not opened cloud communication products",
"PRODUCT_UNSUBSCRIBE": "product not opened ",
"ACCOUNT_NOT_EXISTS": "the account does not exist ",
"ACCOUNT_ABNORMAL": "account abnormal ",
"INVALID_PARAMETERS": "parameter exception ",
"SYSTEM_ERROR": "system error ",
"INVALID_JSON_PARAM": "invalid JSON parameter, only accept string value ",
"BLACK_KEY_CONTROL_LIMIT": "blacklist control ",
"PARAM_LENGTH_LIMIT": "the parameter exceeds the length limit ",
"PARAM_NOT_SUPPORT_URL": "unsupported URL",
"AMOUNT_NOT_ENOUGH": "insufficient account balance ",
"TEMPLATE_PARAMS_ILLEGAL": "template variable contains illegal keyword"
}
}

29
aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json

@ -0,0 +1,29 @@
{
"culture": "zh-Hans",
"texts": {
"SendMessageFailed": "发送短信错误:{0}",
"SMS_TEMPLATE_ILLEGAL": "模板不合法(不存在或被拉黑)",
"SMS_SIGNATURE_ILLEGAL": "签名不合法(不存在或被拉黑)",
"MOBILE_NUMBER_ILLEGAL": "无效的电话号码",
"TEMPLATE_MISSING_PARAMETERS": "模板变量缺少对应参数值",
"EXTEND_CODE_ERROR": "扩展码使用错误",
"DOMESTIC_NUMBER_NOT_SUPPORTED": "国际/港澳台消息模板不支持发送境内号码",
"DAY_LIMIT_CONTROL": "触发日发送限额",
"SMS_CONTENT_ILLEGAL": "短信内容包含禁止发送内容",
"SMS_SIGN_ILLEGAL": "签名禁止使用",
"RAM_PERMISSION_DENY": "没有访问权限",
"OUT_OF_SERVICE": "业务停机",
"PRODUCT_UN_SUBSCRIPT": "未开通云通信产品的阿里云客户",
"PRODUCT_UNSUBSCRIBE": "产品未开通",
"ACCOUNT_NOT_EXISTS": "账户不存在",
"ACCOUNT_ABNORMAL": "账户异常",
"INVALID_PARAMETERS": "参数异常",
"SYSTEM_ERROR": "系统错误",
"INVALID_JSON_PARAM": "JSON参数不合法,只接受字符串值",
"BLACK_KEY_CONTROL_LIMIT": "黑名单管控",
"PARAM_LENGTH_LIMIT": "参数超出长度限制",
"PARAM_NOT_SUPPORT_URL": "不支持URL",
"AMOUNT_NOT_ENOUGH": "账户余额不足",
"TEMPLATE_PARAMS_ILLEGAL": "模版变量里包含非法关键字"
}
}

2
aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EventBus" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EventBus" Version="2.8.0" />
</ItemGroup>
</Project>

4
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj

@ -16,8 +16,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="2.8.0" />
</ItemGroup>
</Project>

2
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="2.7.0" />
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

8
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs

@ -47,9 +47,11 @@ namespace LINGYUN.Abp.IdentityServer.ApiResources
throw new UserFriendlyException(L[AbpIdentityServerErrorConsts.ApiResourceNameExisted, apiResourceCreate.Name]);
}
var apiResource = new ApiResource(GuidGenerator.Create(), apiResourceCreate.Name,
apiResourceCreate.DisplayName, apiResourceCreate.Description);
apiResource.Enabled = apiResourceCreate.Enabled;
foreach(var userClaim in apiResourceCreate.UserClaims)
apiResourceCreate.DisplayName, apiResourceCreate.Description)
{
Enabled = apiResourceCreate.Enabled
};
foreach (var userClaim in apiResourceCreate.UserClaims)
{
apiResource.AddUserClaim(userClaim.Type);
}

92
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs

@ -87,10 +87,12 @@ namespace LINGYUN.Abp.IdentityServer.Clients
{
throw new UserFriendlyException(L[AbpIdentityServerErrorConsts.ClientIdExisted, clientCreate.ClientId]);
}
var client = new Client(GuidGenerator.Create(), clientCreate.ClientId);
client.ClientName = clientCreate.ClientName;
client.Description = clientCreate.Description;
foreach(var grantType in clientCreate.AllowedGrantTypes)
var client = new Client(GuidGenerator.Create(), clientCreate.ClientId)
{
ClientName = clientCreate.ClientName,
Description = clientCreate.Description
};
foreach (var grantType in clientCreate.AllowedGrantTypes)
{
client.AddGrantType(grantType.GrantType);
}
@ -295,46 +297,48 @@ namespace LINGYUN.Abp.IdentityServer.Clients
}
var srcClient = await ClientRepository.GetAsync(clientCloneInput.SourceClientId);
var client = new Client(GuidGenerator.Create(), clientCloneInput.ClientId);
client.ClientName = clientCloneInput.ClientName;
client.Description = clientCloneInput.Description;
client.AbsoluteRefreshTokenLifetime = srcClient.AbsoluteRefreshTokenLifetime;
client.AccessTokenLifetime = srcClient.AccessTokenLifetime;
client.AccessTokenType = srcClient.AccessTokenType;
client.AllowAccessTokensViaBrowser = srcClient.AllowAccessTokensViaBrowser;
client.AllowOfflineAccess = srcClient.AllowOfflineAccess;
client.AllowPlainTextPkce = srcClient.AllowPlainTextPkce;
client.AllowRememberConsent = srcClient.AllowRememberConsent;
client.AlwaysIncludeUserClaimsInIdToken = srcClient.AlwaysIncludeUserClaimsInIdToken;
client.AlwaysSendClientClaims = srcClient.AlwaysSendClientClaims;
client.AuthorizationCodeLifetime = srcClient.AuthorizationCodeLifetime;
client.BackChannelLogoutSessionRequired = srcClient.BackChannelLogoutSessionRequired;
client.BackChannelLogoutUri = srcClient.BackChannelLogoutUri;
client.ClientClaimsPrefix = srcClient.ClientClaimsPrefix;
client.ConsentLifetime = srcClient.ConsentLifetime;
client.DeviceCodeLifetime = srcClient.DeviceCodeLifetime;
client.Enabled = srcClient.Enabled;
client.EnableLocalLogin = srcClient.EnableLocalLogin;
client.FrontChannelLogoutSessionRequired = srcClient.FrontChannelLogoutSessionRequired;
client.FrontChannelLogoutUri = srcClient.FrontChannelLogoutUri;
client.IdentityTokenLifetime = srcClient.IdentityTokenLifetime;
client.IncludeJwtId = srcClient.IncludeJwtId;
client.LogoUri = srcClient.LogoUri;
client.PairWiseSubjectSalt = srcClient.PairWiseSubjectSalt;
client.ProtocolType = srcClient.ProtocolType;
client.RefreshTokenExpiration = srcClient.RefreshTokenExpiration;
client.RefreshTokenUsage = srcClient.RefreshTokenUsage;
client.RequireClientSecret = srcClient.RequireClientSecret;
client.RequireConsent = srcClient.RequireConsent;
client.RequirePkce = srcClient.RequirePkce;
client.SlidingRefreshTokenLifetime = srcClient.SlidingRefreshTokenLifetime;
client.UpdateAccessTokenClaimsOnRefresh = srcClient.UpdateAccessTokenClaimsOnRefresh;
client.UserCodeType = srcClient.UserCodeType;
client.UserSsoLifetime = srcClient.UserSsoLifetime;
var client = new Client(GuidGenerator.Create(), clientCloneInput.ClientId)
{
ClientName = clientCloneInput.ClientName,
Description = clientCloneInput.Description,
AbsoluteRefreshTokenLifetime = srcClient.AbsoluteRefreshTokenLifetime,
AccessTokenLifetime = srcClient.AccessTokenLifetime,
AccessTokenType = srcClient.AccessTokenType,
AllowAccessTokensViaBrowser = srcClient.AllowAccessTokensViaBrowser,
AllowOfflineAccess = srcClient.AllowOfflineAccess,
AllowPlainTextPkce = srcClient.AllowPlainTextPkce,
AllowRememberConsent = srcClient.AllowRememberConsent,
AlwaysIncludeUserClaimsInIdToken = srcClient.AlwaysIncludeUserClaimsInIdToken,
AlwaysSendClientClaims = srcClient.AlwaysSendClientClaims,
AuthorizationCodeLifetime = srcClient.AuthorizationCodeLifetime,
BackChannelLogoutSessionRequired = srcClient.BackChannelLogoutSessionRequired,
BackChannelLogoutUri = srcClient.BackChannelLogoutUri,
ClientClaimsPrefix = srcClient.ClientClaimsPrefix,
ConsentLifetime = srcClient.ConsentLifetime,
DeviceCodeLifetime = srcClient.DeviceCodeLifetime,
Enabled = srcClient.Enabled,
EnableLocalLogin = srcClient.EnableLocalLogin,
FrontChannelLogoutSessionRequired = srcClient.FrontChannelLogoutSessionRequired,
FrontChannelLogoutUri = srcClient.FrontChannelLogoutUri,
IdentityTokenLifetime = srcClient.IdentityTokenLifetime,
IncludeJwtId = srcClient.IncludeJwtId,
LogoUri = srcClient.LogoUri,
PairWiseSubjectSalt = srcClient.PairWiseSubjectSalt,
ProtocolType = srcClient.ProtocolType,
RefreshTokenExpiration = srcClient.RefreshTokenExpiration,
RefreshTokenUsage = srcClient.RefreshTokenUsage,
RequireClientSecret = srcClient.RequireClientSecret,
RequireConsent = srcClient.RequireConsent,
RequirePkce = srcClient.RequirePkce,
SlidingRefreshTokenLifetime = srcClient.SlidingRefreshTokenLifetime,
UpdateAccessTokenClaimsOnRefresh = srcClient.UpdateAccessTokenClaimsOnRefresh,
UserCodeType = srcClient.UserCodeType,
UserSsoLifetime = srcClient.UserSsoLifetime
};
if (clientCloneInput.CopyAllowedCorsOrigin)
{

2
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

26
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\IdentityServer\Localization\Resources\en.json" />
<None Remove="LINGYUN\Abp\IdentityServer\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\account\LINGYUN.Abp.Account.Domain\LINGYUN.Abp.Account.Domain.csproj" />
</ItemGroup>
</Project>

37
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmValidatorModule.cs

@ -0,0 +1,37 @@
using LINGYUN.Abp.IdentityServer.SmsValidator;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.IdentityServer
{
[DependsOn(typeof(AbpIdentityServerDomainModule))]
public class AbpIdentityServerSmValidatorModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddExtensionGrantValidator<SmsTokenGrantValidator>();
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIdentityServerSmValidatorModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpIdentityServerResource>()
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/Resources");
});
}
}
}

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json

@ -0,0 +1,9 @@
{
"culture": "en",
"texts": {
"InvalidGrant:GrantTypeInvalid": "Type of authorization not allowed!",
"InvalidGrant:PhoneVerifyInvalid": "phone verification code failed!",
"InvalidGrant:PhoneOrTokenCodeNotFound": "Phone number or verify code not found!",
"InvalidGrant:PhoneNumberNotRegister": "The registered mobile phone number is not registered!"
}
}

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json

@ -0,0 +1,9 @@
{
"culture": "zh-Hans",
"texts": {
"InvalidGrant:GrantTypeInvalid": "不被允许的授权类型!",
"InvalidGrant:PhoneVerifyInvalid": "手机验证码无效或已过期!",
"InvalidGrant:PhoneOrTokenCodeNotFound": "手机号码或手机验证码未输入!",
"InvalidGrant:PhoneNumberNotRegister": "登录的手机号码未注册!"
}
}

100
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs

@ -0,0 +1,100 @@
using IdentityModel;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using LINGYUN.Abp.Account;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Security.Claims;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.SmsValidator
{
public class SmsTokenGrantValidator : IExtensionGrantValidator
{
protected ILogger<SmsTokenGrantValidator> Logger { get; }
protected IEventService EventService { get; }
protected IIdentityUserRepository UserRepository { get; }
protected UserManager<IdentityUser> UserManager { get; }
protected SignInManager<IdentityUser> SignInManager { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
protected PhoneNumberTokenProvider<IdentityUser> PhoneNumberTokenProvider { get; }
public SmsTokenGrantValidator(
IEventService eventService,
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
IIdentityUserRepository userRepository,
IStringLocalizer<AbpIdentityServerResource> stringLocalizer,
PhoneNumberTokenProvider<IdentityUser> phoneNumberTokenProvider,
ILogger<SmsTokenGrantValidator> logger)
{
Logger = logger;
EventService = eventService;
UserManager = userManager;
SignInManager = signInManager;
Localizer = stringLocalizer;
UserRepository = userRepository;
PhoneNumberTokenProvider = phoneNumberTokenProvider;
}
public string GrantType => SmsValidatorConsts.SmsValidatorGrantTypeName;
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var raw = context.Request.Raw;
var credential = raw.Get(OidcConstants.TokenRequest.GrantType);
if (credential == null || !credential.Equals(GrantType))
{
Logger.LogWarning("Invalid grant type: not allowed");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:GrantTypeInvalid"]);
return;
}
var phoneNumber = raw.Get(SmsValidatorConsts.SmsValidatorParamName);
var phoneToken = raw.Get(SmsValidatorConsts.SmsValidatorTokenName);
if (phoneNumber.IsNullOrWhiteSpace() || phoneToken.IsNullOrWhiteSpace())
{
Logger.LogWarning("Invalid grant type: phone number or token code not found");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:PhoneOrTokenCodeNotFound"]);
return;
}
var currentUser = await UserRepository.FindByPhoneNumberAsync(phoneNumber);
if(currentUser == null)
{
Logger.LogWarning("Invalid grant type: phone number not register");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:PhoneNumberNotRegister"]);
return;
}
var validResult = await PhoneNumberTokenProvider.ValidateAsync(SmsValidatorConsts.SmsValidatorPurpose, phoneToken, UserManager, currentUser);
if (!validResult)
{
Logger.LogWarning("Authentication failed for token: {0}, reason: invalid token", phoneToken);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:PhoneVerifyInvalid"]);
await EventService.RaiseAsync(new UserLoginFailureEvent(currentUser.UserName, $"invalid phone verify code {phoneToken}", false));
return;
}
var sub = await UserManager.GetUserIdAsync(currentUser);
var additionalClaims = new List<Claim>();
if (currentUser.TenantId.HasValue)
{
additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString()));
}
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, phoneNumber, null));
context.Result = new GrantValidationResult(sub, OidcConstants.AuthenticationMethods.ConfirmationBySms, additionalClaims.ToArray());
}
}
}

13
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsValidatorConsts.cs

@ -0,0 +1,13 @@
namespace LINGYUN.Abp.IdentityServer.SmsValidator
{
public class SmsValidatorConsts
{
public const string SmsValidatorGrantTypeName = "phone_verify";
public const string SmsValidatorParamName = "phone_number";
public const string SmsValidatorTokenName = "phone_verify_code";
public const string SmsValidatorPurpose = "phone_verify";
}
}

4
aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj

@ -6,8 +6,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Shared" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Shared" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

4
aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj

@ -6,8 +6,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.PermissionManagement.Domain" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="2.8.0" />
</ItemGroup>
</Project>

13
aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
@ -21,13 +22,16 @@ namespace LINGYUN.Abp.PermissionManagement
public class PermissionAppService : ApplicationService, IPermissionAppService
{
protected PermissionManagementOptions Options { get; }
protected IDistributedCache<PermissionGrantCacheItem> Cache { get; }
protected IPermissionGrantRepository PermissionGrantRepository { get; }
protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
public PermissionAppService(
IDistributedCache<PermissionGrantCacheItem> cache,
IPermissionGrantRepository permissionGrantRepository,
IPermissionDefinitionManager permissionDefinitionManager,
IOptions<PermissionManagementOptions> options)
{
Cache = cache;
Options = options.Value;
PermissionGrantRepository = permissionGrantRepository;
PermissionDefinitionManager = permissionDefinitionManager;
@ -140,6 +144,10 @@ namespace LINGYUN.Abp.PermissionManagement
await PermissionGrantRepository.DeleteAsync(editPermission.Id);
}
}
// 同步变更缓存里的权限配置
var cacheKey = CalculateCacheKey(permission.Name, providerName, providerKey);
var cacheItem = new PermissionGrantCacheItem(permission.Name, permission.IsGranted);
await Cache.SetAsync(cacheKey, cacheItem);
}
}
@ -153,5 +161,10 @@ namespace LINGYUN.Abp.PermissionManagement
await AuthorizationService.CheckAsync(policyName);
}
protected virtual string CalculateCacheKey(string name, string providerName, string providerKey)
{
return PermissionGrantCacheItem.CalculateCacheKey(name, providerName, providerKey);
}
}
}

4
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj

@ -16,8 +16,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Domain.Shared" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Domain.Shared" Version="2.8.0" />
</ItemGroup>
</Project>

2
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="2.7.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

4
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj

@ -6,8 +6,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="2.8.0" />
</ItemGroup>
</Project>

2
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.TenantManagement.Domain" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

2
aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

11
aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs

@ -1,5 +1,6 @@
using DotNetCore.CAP;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.IdentityServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
@ -27,6 +28,7 @@ using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading;
namespace AuthServer.Host
{
[DependsOn(
@ -34,6 +36,7 @@ namespace AuthServer.Host
typeof(AbpAutofacModule),
typeof(AbpCAPEventBusModule),
typeof(AbpIdentityAspNetCoreModule),
typeof(AbpIdentityServerSmValidatorModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpIdentityServerEntityFrameworkCoreModule),
@ -149,12 +152,8 @@ namespace AuthServer.Host
{
AsyncHelper.RunSync(async () =>
{
using (var scope = context.ServiceProvider.CreateScope())
{
await scope.ServiceProvider
.GetRequiredService<IDataSeeder>()
.SeedAsync();
}
using var scope = context.ServiceProvider.CreateScope();
await scope.ServiceProvider.GetRequiredService<IDataSeeder>().SeedAsync();
});
}
}

19
aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj

@ -20,20 +20,21 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Volo.Abp.Autofac" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Identity.AspNetCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySql" Version="2.7.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Identity.AspNetCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.8.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySql" Version="2.8.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Common.EventBus\LINGYUN.Common.EventBus.csproj" />
<ProjectReference Include="..\..\..\modules\identityServer\LINGYUN.Abp.IdentityServer.SmsValidator\LINGYUN.Abp.IdentityServer.SmsValidator.csproj" />
</ItemGroup>
<ItemGroup>

38
aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs

@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
namespace AuthServer.Host.EntityFrameworkCore.Identity
{
public class EfCoreIdentityUserRepository : EfCoreRepository<IdentityDbContext, IdentityUser, Guid>, LINGYUN.Abp.Account.IIdentityUserRepository,
ITransientDependency
{
public EfCoreIdentityUserRepository(
IDbContextProvider<IdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<IdentityUser> FindByPhoneNumberAsync(string phoneNumber)
{
return await WithDetails()
.Where(usr => usr.PhoneNumber.Equals(phoneNumber))
.FirstOrDefaultAsync();
}
public override IQueryable<IdentityUser> WithDetails()
{
return DbSet
.Include(x => x.Claims)
.Include(x => x.Roles)
.Include(x => x.Logins)
.Include(x => x.Tokens);
}
}
}

8
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj

@ -17,10 +17,10 @@
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AspNetCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

10
aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj

@ -28,11 +28,11 @@
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.8.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>

27
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs

@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
namespace LINGYUN.Platform.EntityFrameworkCore.Identity
{
public class EfCoreIdentityUserRepository : EfCoreRepository<IdentityDbContext, IdentityUser, Guid>, Abp.Account.IIdentityUserRepository,
ITransientDependency
{
public EfCoreIdentityUserRepository(
IDbContextProvider<IdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<IdentityUser> FindByPhoneNumberAsync(string phoneNumber)
{
return await DbSet.Where(usr => usr.PhoneNumber.Equals(phoneNumber)).FirstOrDefaultAsync();
}
}
}

44
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantDeleteEventHandler.cs

@ -33,33 +33,31 @@ namespace LINGYUN.Platform.EventBus.Handlers
public async Task HandleEventAsync(DeleteEventData eventData)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
using var unitOfWork = UnitOfWorkManager.Begin();
// 订阅租户删除事件,删除管理员角色所有权限
// TODO: 租户貌似不存在了,删除应该会失败
using (CurrentTenant.Change(eventData.Id))
{
// 订阅租户删除事件,删除管理员角色所有权限
// TODO: 租户貌似不存在了,删除应该会失败
using (CurrentTenant.Change(eventData.Id))
{
// var grantPermissions = await PermissionGrantRepository.GetListAsync("R", "admin");
// var grantPermissions = await PermissionGrantRepository.GetListAsync("R", "admin");
// EfCore MySql 批量删除还是一条一条的语句?
// PermissionGrantRepository.GetDbSet().RemoveRange(grantPermissions);
var permissionEntityType = PermissionGrantRepository.GetDbContext().Model.FindEntityType(typeof(PermissionGrant));
var permissionTableName = permissionEntityType.GetTableName();
var batchRmovePermissionSql = string.Empty;
if (PermissionGrantRepository.GetDbContext().Database.IsMySql())
{
batchRmovePermissionSql = BuildMySqlBatchDeleteScript(permissionTableName, eventData.Id);
}
else
{
batchRmovePermissionSql = BuildSqlServerBatchDeleteScript(permissionTableName, eventData.Id);
}
// EfCore MySql 批量删除还是一条一条的语句?
// PermissionGrantRepository.GetDbSet().RemoveRange(grantPermissions);
var permissionEntityType = PermissionGrantRepository.GetDbContext().Model.FindEntityType(typeof(PermissionGrant));
var permissionTableName = permissionEntityType.GetTableName();
var batchRmovePermissionSql = string.Empty;
if (PermissionGrantRepository.GetDbContext().Database.IsMySql())
{
batchRmovePermissionSql = BuildMySqlBatchDeleteScript(permissionTableName, eventData.Id);
}
else
{
batchRmovePermissionSql = BuildSqlServerBatchDeleteScript(permissionTableName, eventData.Id);
}
await PermissionGrantRepository.GetDbContext().Database
.ExecuteSqlRawAsync(batchRmovePermissionSql);
await PermissionGrantRepository.GetDbContext().Database
.ExecuteSqlRawAsync(batchRmovePermissionSql);
await unitOfWork.CompleteAsync();
}
await unitOfWork.CompleteAsync();
}
}

40
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj

@ -22,29 +22,33 @@
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.7.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Identity.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Account.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Account.HttpApi" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="2.7.0" />
<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.7.0" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="2.8.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="2.8.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Identity.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Identity.HttpApi" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Account.Application" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Account.HttpApi" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.Identity" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.HttpApi" Version="2.8.0" />
<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="2.8.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\modules\account\LINGYUN.Abp.Account.Application\LINGYUN.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\modules\account\LINGYUN.Abp.Account.HttpApi\LINGYUN.Abp.Account.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\apigateway\LINGYUN.ApiGateway.Application.Contracts\LINGYUN.ApiGateway.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj" />
<ProjectReference Include="..\..\..\modules\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj" />
<ProjectReference Include="..\..\..\modules\identityServer\LINGYUN.Abp.IdentityServer.Application\LINGYUN.Abp.IdentityServer.Application.csproj" />
<ProjectReference Include="..\..\..\modules\identityServer\LINGYUN.Abp.IdentityServer.HttpApi\LINGYUN.Abp.IdentityServer.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\identityServer\LINGYUN.Abp.IdentityServer.SmsValidator\LINGYUN.Abp.IdentityServer.SmsValidator.csproj" />
<ProjectReference Include="..\..\..\modules\permissions\LINGYUN.Abp.PermissionManagement.Application\LINGYUN.Abp.PermissionManagement.Application.csproj" />
<ProjectReference Include="..\..\..\modules\settings\LINGYUN.Abp.SettingManagement.Application\LINGYUN.Abp.SettingManagement.Application.csproj" />
<ProjectReference Include="..\..\..\modules\settings\LINGYUN.Abp.SettingManagement.HttpApi\LINGYUN.Abp.SettingManagement.HttpApi.csproj" />
@ -52,8 +56,4 @@
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.TenantManagement.HttpApi\LINGYUN.Abp.TenantManagement.HttpApi.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="EntityFrameworkCore\" />
</ItemGroup>
</Project>

12
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs

@ -6,9 +6,11 @@ using LINGYUN.Abp.SettingManagement;
using LINGYUN.Abp.TenantManagement;
using LINGYUN.ApiGateway;
using LINGYUN.Platform.MultiTenancy;
using LINYUN.Abp.Sms.Aliyun;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -47,6 +49,8 @@ namespace LINGYUN.Platform
typeof(ApiGatewayApplicationContractsModule),
typeof(AbpIdentityHttpApiModule),
typeof(AbpIdentityApplicationModule),
typeof(Abp.Account.AbpAccountApplicationModule),
typeof(Abp.Account.AbpAccountHttpApiModule),
typeof(AbpAccountApplicationModule),
typeof(AbpAccountHttpApiModule),
typeof(AbpIdentityServerApplicationModule),
@ -65,6 +69,7 @@ namespace LINGYUN.Platform
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpCAPEventBusModule),
typeof(AbpAliyunSmsModule),
typeof(AbpAutofacModule)
)]
public class PlatformHttpApiHostModule : AbpModule
@ -82,6 +87,11 @@ namespace LINGYUN.Platform
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions);
});
});
PreConfigure<IdentityBuilder>(builder =>
{
builder.AddDefaultTokenProviders();
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
@ -176,7 +186,7 @@ namespace LINGYUN.Platform
// 审计日志
app.UseAuditing();
// 路由
app.UseMvcWithDefaultRouteAndArea();
app.UseConfiguredEndpoints();
}
}
}

4
vueJs/src/api/users.ts

@ -263,7 +263,7 @@ export class UserUpdateDto implements IUserData {
/** 用户账户 */
userName!: string;
/** 用户简称 */
surname!: string;
surname?: string;
/** 邮件地址 */
email!: string;
/** 联系方式 */
@ -319,7 +319,7 @@ export interface IUserData {
/** 用户账户 */
userName: string
/** 用户简称 */
surname: string
surname?: string
/** 邮件地址 */
email: string
/** 联系方式 */

204
vueJs/src/views/admin/users/components/UserCreateForm.vue

@ -0,0 +1,204 @@
<template>
<el-form
ref="formCreateUser"
label-width="110px"
:model="createUser"
:rules="createUserRules"
>
<el-tabs v-model="activedTabPane">
<el-tab-pane
:label="$t('userProfile.basic')"
name="basic"
>
<el-form-item
prop="userName"
:label="$t('users.userName')"
>
<el-input
v-model="createUser.userName"
:placeholder="$t('userProfile.pleaseInputUserName')"
/>
</el-form-item>
<el-form-item
prop="name"
:label="$t('users.name')"
>
<el-input
v-model="createUser.name"
:placeholder="$t('userProfile.pleaseInputName')"
/>
</el-form-item>
<el-form-item
prop="surname"
:label="$t('users.surname')"
>
<el-input
v-model="createUser.surname"
:placeholder="$t('userProfile.pleaseInputSurname')"
/>
</el-form-item>
<el-form-item
prop="phoneNumber"
:label="$t('users.phoneNumber')"
>
<el-input
v-model="createUser.phoneNumber"
:placeholder="$t('userProfile.pleaseInputPhoneNumber')"
/>
</el-form-item>
<el-form-item
prop="email"
:label="$t('users.email')"
>
<el-input
v-model="createUser.email"
:placeholder="$t('userProfile.pleaseInputEmail')"
/>
</el-form-item>
</el-tab-pane>
<el-tab-pane
:label="$t('userProfile.security')"
name="security"
>
<el-form-item
prop="password"
label-width="100px"
:label="$t('userProfile.password')"
>
<el-input
v-model="createUser.password"
type="password"
:placeholder="$t('userProfile.pleaseInputPassword')"
/>
</el-form-item>
<el-form-item
prop="twoFactorEnabled"
label-width="100px"
:label="$t('users.twoFactorEnabled')"
>
<el-switch v-model="createUser.twoFactorEnabled" />
</el-form-item>
<el-form-item
prop="lockoutEnabled"
label-width="100px"
:label="$t('users.lockoutEnabled')"
>
<el-switch v-model="createUser.lockoutEnabled" />
</el-form-item>
</el-tab-pane>
</el-tabs>
<el-form-item>
<el-button
class="cancel"
style="width:100px"
@click="onCancel"
>
{{ $t('table.cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
@click="onSubmit"
>
{{ $t('table.confirm') }}
</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import UserApiService, { UserCreateDto } from '@/api/users'
import { checkPermission } from '@/utils/permission'
@Component({
name: 'UserProfile',
methods: {
checkPermission
}
})
export default class extends Vue {
private createUser: UserCreateDto
private activedTabPane: string
constructor() {
super()
this.activedTabPane = 'basic'
this.createUser = new UserCreateDto()
}
private validatePhoneNumberValue = (rule: any, value: string, callback: any) => {
const phoneReg = /^1[34578]\d{9}$/
if (!value || !phoneReg.test(value)) {
callback(new Error(this.l('global.pleaseInputBy', { key: this.l('global.correctPhoneNumber') })))
} else {
callback()
}
}
private createUserRules = {
userName: [
{ required: true, message: this.l('userProfile.pleaseInputUserName'), trigger: 'blur' },
{ min: 3, max: 20, message: this.l('global.charLengthRange', { min: 3, max: 20 }), trigger: 'blur' }
],
name: [
{ required: true, message: this.l('userProfile.pleaseInputName'), trigger: 'blur' },
{ min: 3, max: 50, message: this.l('global.charLengthRange', { min: 3, max: 50 }), trigger: 'blur' }
],
email: [
{ required: true, message: this.l('userProfile.pleaseInputEmail'), trigger: 'blur' },
{ type: 'email', message: this.l('global.pleaseInputBy', { key: this.l('global.correctEmailAddress') }), trigger: ['blur', 'change'] }
],
password: [
{ required: true, message: this.l('userProfile.pleaseInputPassword'), trigger: 'blur' },
{ min: 6, max: 15, message: this.l('global.charLengthRange', { min: 6, max: 15 }), trigger: 'blur' }
],
phoneNumber: [
{ required: true, validator: this.validatePhoneNumberValue, trigger: 'blur' }
]
}
private onSubmit() {
const frmCreateUser = this.$refs.formCreateUser as any
frmCreateUser.validate(async(valid: boolean) => {
if (valid) {
UserApiService.createUser(this.createUser).then(user => {
this.$message.success(this.l('users.createUserSuccess', { name: user.name }))
this.$emit('onUserProfileChanged', user.id)
this.resetForm()
this.onCancel()
})
}
})
}
private onCancel() {
this.resetForm()
this.$emit('onClose')
}
private resetForm() {
this.activedTabPane = 'basic'
this.createUser = new UserCreateDto()
const frmCreateUser = this.$refs.formCreateUser as any
frmCreateUser.resetFields()
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
right: 10px;
}
.cancel {
position: absolute;
right: 120px;
}
</style>

65
vueJs/src/views/admin/users/components/UserProfile.vue → vueJs/src/views/admin/users/components/UserEditForm.vue

@ -1,6 +1,6 @@
<template>
<el-form
ref="profile"
ref="formEditUser"
label-width="110px"
:model="userProfile"
:rules="userProfileRules"
@ -60,18 +60,6 @@
:label="$t('userProfile.security')"
name="security"
>
<el-form-item
v-if="!hasEditUser"
prop="password"
label-width="100px"
:label="$t('userProfile.password')"
>
<el-input
v-model="userPassword"
type="password"
:placeholder="$t('userProfile.pleaseInputPassword')"
/>
</el-form-item>
<el-form-item
prop="twoFactorEnabled"
label-width="100px"
@ -122,7 +110,7 @@
class="confirm"
type="primary"
style="width:100px"
@click="onSubmit('profile')"
@click="onSubmit"
>
{{ $t('table.confirm') }}
</el-button>
@ -134,8 +122,7 @@
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import UserApiService, {
UserDataDto,
UserUpdateDto,
UserCreateDto
UserUpdateDto
} from '@/api/users'
import RoleService from '@/api/roles'
import PermissionService, { PermissionDto, UpdatePermissionsDto } from '@/api/permission'
@ -157,10 +144,9 @@ export default class extends Vue {
private roleList: {key: string, label: string, disabled: boolean}[]
/** 用户组 */
private userRoles: string[]
private userPassword: string
private hasEditUser: boolean
private userRolesChanged: boolean
private userProfile: UserDataDto
private userProfile: any
/** 是否加载用户权限 */
private hasLoadPermission: boolean
/** 用户权限数据 */
@ -175,7 +161,6 @@ export default class extends Vue {
constructor() {
super()
this.activedTabPane = 'basic'
this.userPassword = ''
this.hasEditUser = false
this.userRolesChanged = false
this.hasLoadPermission = false
@ -274,8 +259,6 @@ export default class extends Vue {
this.userRoles = userRoleDto.items.map(r => r.name)
//
this.$watch('userRoles', this.onUserRolesChanged)
// const data = await getSettings('U', UserModule.id)
// console.log(data)
}
private async handleGetUserPermissions(id: string) {
@ -290,20 +273,14 @@ export default class extends Vue {
this.editUserPermissions = permissions
}
private onSubmit(formName: string) {
const userProfileForm = this.$refs[formName] as any
userProfileForm.validate(async(valid: boolean) => {
private onSubmit() {
const frmEditUser = this.$refs.formEditUser as any
frmEditUser.validate(async(valid: boolean) => {
if (valid) {
if (!this.hasEditUser) {
const createUserInput = this.createAddUserDto()
this.userProfile = await UserApiService.createUser(createUserInput)
this.$message.success(this.$t('users.createUserSuccess', { name: this.userProfile.name }).toString())
} else {
const updateUserInput = this.createEditUserDto()
const user = await UserApiService.updateUser(this.userProfile.id, updateUserInput)
this.userProfile = user
this.$message.success(this.$t('users.updateUserSuccess', { name: this.userProfile.name }).toString())
}
const updateUserInput = this.createEditUserDto()
const user = await UserApiService.updateUser(this.userProfile.id, updateUserInput)
this.userProfile = user
this.$message.success(this.l('users.updateUserSuccess', { name: this.userProfile.name }))
if (this.userRolesChanged) {
await UserApiService.setUserRoles(this.userProfile.id, this.userRoles)
}
@ -312,7 +289,7 @@ export default class extends Vue {
setUserPermissions.permissions = this.editUserPermissions
await PermissionService.setPermissionsByKey('U', this.userProfile.id, setUserPermissions)
}
userProfileForm.resetFields()
frmEditUser.resetFields()
this.$emit('onUserProfileChanged', this.userProfile.id)
this.onCancel()
} else {
@ -329,8 +306,8 @@ export default class extends Vue {
private resetForm() {
this.activedTabPane = 'basic'
this.userRoles = new Array<string>()
const userProfileForm = this.$refs.profile as any
userProfileForm.resetFields()
const frmEditUser = this.$refs.formEditUser as any
frmEditUser.resetFields()
if (this.hasLoadPermission) {
const userPermission = this.$refs.permissionTree as PermissionTree
userPermission.resetPermissions()
@ -338,20 +315,6 @@ export default class extends Vue {
}
}
private createAddUserDto() {
const createUserInput = new UserCreateDto()
createUserInput.name = this.userProfile.name
createUserInput.userName = this.userProfile.userName
createUserInput.password = this.userPassword
createUserInput.surname = this.userProfile.surname
createUserInput.email = this.userProfile.email
createUserInput.phoneNumber = this.userProfile.phoneNumber
createUserInput.twoFactorEnabled = this.userProfile.twoFactorEnabled
createUserInput.lockoutEnabled = this.userProfile.lockoutEnabled
createUserInput.roleNames = this.userRoles
return createUserInput
}
private createEditUserDto() {
const updateUserInput = new UserUpdateDto()
updateUserInput.name = this.userProfile.name

67
vueJs/src/views/admin/users/index.vue

@ -115,7 +115,7 @@
:disabled="!checkPermission(['AbpIdentity.Users.Update'])"
size="mini"
type="primary"
@click="handleShowUserProfile(row)"
@click="handleShowEditUserForm(row)"
>
{{ $t('users.updateUser') }}
</el-button>
@ -159,13 +159,25 @@
/>
<el-dialog
:visible.sync="showUserProfile"
:visible.sync="showEditUserDialog"
custom-class="profile"
:title="userProfileTitle"
:title="$t('users.updateUserBy', {name: editUser.name})"
:show-close="false"
>
<UserProfile
:user-id="editUserId"
<UserEditForm
:user-id="editUser.id"
@onClose="handleCloseUserProfile"
@onUserProfileChanged="handleUserProfileChanged"
/>
</el-dialog>
<el-dialog
:visible.sync="showCreateUserDialog"
custom-class="profile"
:title="$t('users.createUser')"
:show-close="false"
>
<UserCreateForm
@onClose="handleCloseUserProfile"
@onUserProfileChanged="handleUserProfileChanged"
/>
@ -178,14 +190,16 @@ import { Component, Vue } from 'vue-property-decorator'
import Pagination from '@/components/Pagination/index.vue'
import { dateFormat } from '@/utils'
import UserApiService, { UserDataDto, UsersGetPagedDto } from '@/api/users'
import UserProfile from './components/UserProfile.vue'
import UserCreateForm from './components/UserCreateForm.vue'
import UserEditForm from './components/UserEditForm.vue'
import { checkPermission } from '@/utils/permission'
@Component({
name: 'UserList',
components: {
Pagination,
UserProfile
UserEditForm,
UserCreateForm
},
filters: {
dateTimeFilter(datetime: string) {
@ -205,26 +219,26 @@ export default class extends Vue {
/** 最大用户数量 */
private totalCount: number
/** 当前编辑用户 */
private editUserId: string
/** 是否显示用户详情页 */
private showUserProfile: boolean
/** 用户详情页标题 */
private userProfileTitle: any
private editUser: UserDataDto
/** 排序组别 */
private sortRule: { prop: string, sort: string }
/** 查询用户过滤参数 */
private getUserQuery: UsersGetPagedDto
private showCreateUserDialog: boolean
private showEditUserDialog: boolean
constructor() {
super()
this.totalCount = 0
this.editUserId = ''
this.showUserProfile = false
this.editUser = new UserDataDto()
this.userListLoading = false
this.userProfileTitle = ''
this.sortRule = { prop: '', sort: '' }
this.getUserQuery = new UsersGetPagedDto()
this.userList = new Array<UserDataDto>()
this.showEditUserDialog = false
this.showCreateUserDialog = false
}
mounted() {
@ -248,31 +262,24 @@ export default class extends Vue {
console.log('handleLockUser' + row.id)
}
/**
* @param row 操作行数据,可以转换为 UserDataDto 对象
*/
private handleShowUserProfile(row: any) {
this.editUserId = row.id
this.userProfileTitle = this.$t('users.updateUser', { namec: row.name })
this.showUserProfile = true
private handleShowEditUserForm(row: UserDataDto) {
this.editUser = row
this.showEditUserDialog = true
}
/** 响应用户详情页关闭事件 */
private handleCloseUserProfile() {
this.editUserId = ''
this.showUserProfile = false
this.editUser = new UserDataDto()
this.showCreateUserDialog = false
this.showEditUserDialog = false
}
/** 响应用户详情页变更事件 */
private handleUserProfileChanged() {
this.handleGetUsers()
}
/** 新增用户事件,打开用户详情页 */
private handleCreateUser() {
this.editUserId = ''
this.userProfileTitle = this.$t('users.createUser')
this.showUserProfile = true
this.editUser = new UserDataDto()
this.showCreateUserDialog = true
}
/** 响应更多操作命令 */

14
vueJs/start-vue-admin.bat

@ -0,0 +1,14 @@
@echo off
cls
chcp 65001
echo. 启动后台管理UI
if '%1' equ '--run' goto run
if '%1' equ '' goto run
exit
:run
npm run serve-nomock
pause
exit
Loading…
Cancel
Save