diff --git a/.gitignore b/.gitignore index 051ce9c8b..ca7fae3fc 100644 --- a/.gitignore +++ b/.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/ diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj new file mode 100644 index 000000000..aa212cfed --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN.Abp.Account.Application.Contracts.csproj @@ -0,0 +1,26 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/AbpAccountApplicationContractsModule.cs new file mode 100644 index 000000000..72a42a84f --- /dev/null +++ b/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(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes(typeof(AccountResource)) + .AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterDto.cs new file mode 100644 index 000000000..55a67a068 --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterVerifyDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/RegisterVerifyDto.cs new file mode 100644 index 000000000..dce404f29 --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/VerifyDto.cs new file mode 100644 index 000000000..03bcd2eda --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IAccountAppService.cs new file mode 100644 index 000000000..031b76359 --- /dev/null +++ b/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 RegisterAsync(RegisterVerifyDto input); + + Task VerifyPhoneNumberAsync(VerifyDto input); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json new file mode 100644 index 000000000..b61468521 --- /dev/null +++ b/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!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..f054a8048 --- /dev/null +++ b/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} 分钟内重复发送!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj new file mode 100644 index 000000000..3ddea3d7a --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN.Abp.Account.Application.csproj @@ -0,0 +1,18 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AbpAccountApplicationModule.cs new file mode 100644 index 000000000..a0c4d6f9f --- /dev/null +++ b/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 + { + + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountAppService.cs new file mode 100644 index 000000000..7a824cb11 --- /dev/null +++ b/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 +{ + /// + /// 用户注册服务 + /// + public class AccountAppService : ApplicationService, IAccountAppService + { + protected ISmsSender SmsSender { get; } + protected IdentityUserManager UserManager { get; } + protected IIdentityUserRepository UserRepository { get; } + protected IDistributedCache Cache { get; } + protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; } + public AccountAppService( + ISmsSender smsSender, + IdentityUserManager userManager, + IIdentityUserRepository userRepository, + IDistributedCache cache, + PhoneNumberTokenProvider phoneNumberTokenProvider) + { + Cache = cache; + SmsSender = smsSender; + UserManager = userManager; + UserRepository = userRepository; + PhoneNumberTokenProvider = phoneNumberTokenProvider; + LocalizationResource = typeof(Localization.AccountResource); + } + /// + /// 用户注册 + /// + /// + /// + /// + /// 用户通过VerifyPhoneNumber接口发送到手机的验证码,传递注册信息注册用户 + /// 如果没有此手机号的缓存记录或验证码不匹配,抛出验证码无效的异常 + /// 用户注册成功,清除缓存的验证码记录 + /// + public virtual async Task 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(user); + } + /// + /// 验证手机号码 + /// + /// + /// + /// + /// 用户传递手机号码及认证类型 + /// 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=客户端密钥 + /// + public virtual async Task VerifyPhoneNumberAsync(VerifyDto input) + { + var verifyCodeExpiration = await SettingProvider.GetAsync(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); + } + + /// + /// 发送登录验证码 + /// + /// 手机号 + /// 返回登录验证码 + protected virtual async Task 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; + } + /// + /// 检查是否允许用户注册 + /// + /// + protected virtual async Task CheckSelfRegistrationAsync() + { + if (!await SettingProvider.IsTrueAsync(Volo.Abp.Account.Settings.AccountSettingNames.IsSelfRegistrationEnabled)) + { + throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]); + } + } + /// + /// 发送短信验证码 + /// + /// + /// + /// + /// + 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); + } + /// + /// 格式化缓存主键 + /// + /// 手机号码 + /// + protected string NormalizeCacheKey(string phoneNumber) + { + return $"ACCOUNT-PHONE:{phoneNumber}"; + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj new file mode 100644 index 000000000..815f27437 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs new file mode 100644 index 000000000..b30dde284 --- /dev/null +++ b/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(options => + { + options.Resources + .Add("zh-Hans"); + }); + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountRegisterVerifyCacheItem.cs new file mode 100644 index 000000000..faf78244a --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AccountSettingNames.cs new file mode 100644 index 000000000..d3bf2abd9 --- /dev/null +++ b/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"; + /// + /// 短信验证码过期时间 + /// + public const string PhoneVerifyCodeExpiration = GroupName + ".PhoneVerifyCodeExpiration"; + /// + /// 用户注册短信验证码模板号 + /// + public const string SmsRegisterTemplateCode = GroupName + ".SmsRegisterTemplateCode"; + /// + /// 用户登录短信验证码模板号 + /// + public const string SmsSigninTemplateCode = GroupName + ".SmsSigninTemplateCode"; + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AccountResource.cs new file mode 100644 index 000000000..c132a9b9b --- /dev/null +++ b/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 + { + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/PhoneNumberVerifyType.cs new file mode 100644 index 000000000..3fb05ebcd --- /dev/null +++ b/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 + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj new file mode 100644 index 000000000..74d1df10d --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj @@ -0,0 +1,26 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs new file mode 100644 index 000000000..0ad58c817 --- /dev/null +++ b/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(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountSettingDefinitionProvider.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountSettingDefinitionProvider.cs new file mode 100644 index 000000000..b8f347730 --- /dev/null +++ b/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(name); + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/IIdentityUserRepository.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/IIdentityUserRepository.cs new file mode 100644 index 000000000..54817fc92 --- /dev/null +++ b/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 + { + Task FindByPhoneNumberAsync(string phoneNumber); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/en.json new file mode 100644 index 000000000..b49a3d2b8 --- /dev/null +++ b/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" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..c7a2c1df6 --- /dev/null +++ b/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" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj new file mode 100644 index 000000000..b2242b858 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN.Abp.Account.HttpApi.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AbpAccountHttpApiModule.cs new file mode 100644 index 000000000..fb49e8866 --- /dev/null +++ b/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(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly); + }); + } + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/AccountController.cs new file mode 100644 index 000000000..f1cc98255 --- /dev/null +++ b/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 RegisterAsync(RegisterVerifyDto input) + { + return await AccountAppService.RegisterAsync(input); + } + + [HttpPost] + [Route("verify")] + public virtual async Task VerifyPhoneNumberAsync(VerifyDto input) + { + await AccountAppService.VerifyPhoneNumberAsync(input); + } + } +} diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj index 6e2e554f6..a66598500 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN.ApiGateway.Application.Contracts.csproj @@ -16,7 +16,7 @@ - + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj index 9251af785..e87e99db2 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN.ApiGateway.Application.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj index 8a56afa78..f6eb8b1c0 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain.Shared/LINGYUN.ApiGateway.Domain.Shared.csproj @@ -16,7 +16,7 @@ - + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj index 1732dc330..72e481122 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN.ApiGateway.Domain.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj index 43738db7d..ab90b85d8 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN.ApiGateway.EntityFrameworkCore.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj index b6916c730..9239a7892 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi.Client/LINGYUN.ApiGateway.HttpApi.Client.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj index e5939dd48..a9dc687be 100644 --- a/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj +++ b/aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN.ApiGateway.HttpApi.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs index 89f3b75a6..17a965873 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/DotNetCore/CAP/ConsumerServiceSelector.cs @@ -11,12 +11,21 @@ using Volo.Abp.EventBus.Distributed; namespace DotNetCore.CAP { + /// + /// 消费者查找器 + /// [Dependency(ServiceLifetime.Singleton, ReplaceServices = true)] [ExposeServices(typeof(IConsumerServiceSelector), typeof(ConsumerServiceSelector))] public class ConsumerServiceSelector : Internal.ConsumerServiceSelector { + /// + /// Abp分布式事件配置 + /// protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } + /// + /// 服务提供者 + /// protected IServiceProvider ServiceProvider { get; } /// @@ -27,7 +36,11 @@ namespace DotNetCore.CAP ServiceProvider = serviceProvider; AbpDistributedEventBusOptions = distributedEventBusOptions.Value; } - + /// + /// 查找消费者集合 + /// + /// + /// protected override IEnumerable FindConsumersFromInterfaceTypes(IServiceProvider provider) { var executorDescriptorList = @@ -55,7 +68,12 @@ namespace DotNetCore.CAP } return executorDescriptorList; } - + /// + /// 获取事件处理器集合 + /// + /// + /// + /// protected virtual IEnumerable GetHandlerDescription(Type eventType, Type typeInfo) { var serviceTypeInfo = typeof(IDistributedEventHandler<>) diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj index ca43fecff..e55aa8625 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.csproj @@ -3,11 +3,19 @@ netstandard2.0 + true + false + 2.8.0 + + + + D:\LocalNuget + D:\Projects\MicroService\CRM\Vue\vue-abp\aspnet-core\modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.xml - + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml new file mode 100644 index 000000000..3cb756744 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml @@ -0,0 +1,158 @@ + + + + LINGYUN.Abp.EventBus.CAP + + + + + 消费者查找器 + + + + + Abp分布式事件配置 + + + + + 服务提供者 + + + + + Creates a new . + + + + + 查找消费者集合 + + + + + + + 获取事件处理器集合 + + + + + + + + AbpCAPEventBusModule + + + + + ConfigureServices + + + + + + CAP分布式事件总线 + + + + + Abp分布式事件总线配置 + + + + + CAP消息发布接口 + + + + + 本地事件处理器工厂对象集合 + + + + + 本地事件集合 + + + + + constructor + + + + + + + + 订阅事件 + + + + + + + + 退订事件 + + 事件类型 + + + + + 退订事件 + + 事件类型 + 事件处理器 + + + + 退订事件 + + 事件类型 + 事件处理器工厂 + + + + 退订所有事件 + + 事件类型 + + + + 订阅事件 + + 事件类型 + 事件处理器 + + + + + 发布事件 + + 事件类型 + 事件数据对象 + + + + + 获取事件处理器工厂列表 + + + + + + + CAP ServiceCollectionExtensions + + + + + Adds and configures the consistence services for the consistency. + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/AbpCAPEventBusModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/AbpCAPEventBusModule.cs index 9bb24ef87..3bf6ebb55 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/AbpCAPEventBusModule.cs +++ b/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 { + /// + /// AbpCAPEventBusModule + /// [DependsOn(typeof(AbpEventBusModule))] public class AbpCAPEventBusModule : AbpModule { + /// + /// ConfigureServices + /// + /// public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs index 8dd564da1..e67f0bf8d 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs +++ b/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 { + /// + /// CAP分布式事件总线 + /// [Dependency(ServiceLifetime.Singleton, ReplaceServices = true)] [ExposeServices(typeof(IDistributedEventBus), typeof(CAPDistributedEventBus))] public class CAPDistributedEventBus : EventBusBase, IDistributedEventBus { + /// + /// Abp分布式事件总线配置 + /// protected AbpDistributedEventBusOptions AbpDistributedEventBusOptions { get; } + /// + /// CAP消息发布接口 + /// protected readonly ICapPublisher CapPublisher; - //TODO: Accessing to the List may not be thread-safe! + /// + /// 本地事件处理器工厂对象集合 + /// protected ConcurrentDictionary> HandlerFactories { get; } + /// + /// 本地事件集合 + /// protected ConcurrentDictionary EventTypes { get; } - + /// + /// constructor + /// + /// + /// + /// public CAPDistributedEventBus(IServiceScopeFactory serviceScopeFactory, IOptions distributedEventBusOptions, ICapPublisher capPublisher) : base(serviceScopeFactory) @@ -34,13 +53,22 @@ namespace LINGYUN.Abp.EventBus.CAP HandlerFactories = new ConcurrentDictionary>(); EventTypes = new ConcurrentDictionary(); } - + /// + /// 订阅事件 + /// + /// + /// + /// public override IDisposable Subscribe(Type eventType, IEventHandlerFactory factory) { //This is handled by CAP ConsumerServiceSelector throw new NotImplementedException(); } - + /// + /// 退订事件 + /// + /// 事件类型 + /// public override void Unsubscribe(Func 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; - if (actionHandler == null) + if (!(singleInstanceFactory.HandlerInstance is ActionEventHandler actionHandler)) { return false; } @@ -67,7 +93,11 @@ namespace LINGYUN.Abp.EventBus.CAP }); }); } - + /// + /// 退订事件 + /// + /// 事件类型 + /// 事件处理器 public override void Unsubscribe(Type eventType, IEventHandler handler) { GetOrCreateHandlerFactories(eventType) @@ -80,29 +110,50 @@ namespace LINGYUN.Abp.EventBus.CAP ); }); } - + /// + /// 退订事件 + /// + /// 事件类型 + /// 事件处理器工厂 public override void Unsubscribe(Type eventType, IEventHandlerFactory factory) { GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Remove(factory)); } - + /// + /// 退订所有事件 + /// + /// 事件类型 public override void UnsubscribeAll(Type eventType) { GetOrCreateHandlerFactories(eventType).Locking(factories => factories.Clear()); } - + /// + /// 订阅事件 + /// + /// 事件类型 + /// 事件处理器 + /// public IDisposable Subscribe(IDistributedEventHandler handler) where TEvent : class { return Subscribe(typeof(TEvent), handler); } - + /// + /// 发布事件 + /// + /// 事件类型 + /// 事件数据对象 + /// public override async Task PublishAsync(Type eventType, object eventData) { var eventName = EventNameAttribute.GetNameOrDefault(eventType); await CapPublisher.PublishAsync(eventName, eventData); } - + /// + /// 获取事件处理器工厂列表 + /// + /// + /// protected override IEnumerable GetHandlerFactories(Type eventType) { var handlerFactoryList = new List(); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs index 0b77dce6f..d6a9afd09 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/Microsoft/Extensions/DependencyInjection/ServiceCollectionExtensions.cs @@ -3,8 +3,17 @@ using System; namespace Microsoft.Extensions.DependencyInjection { + /// + /// CAP ServiceCollectionExtensions + /// public static class ServiceCollectionExtensions { + /// + /// Adds and configures the consistence services for the consistency. + /// + /// + /// + /// public static IServiceCollection AddCAPEventBus(this IServiceCollection services, Action capAction) { services.AddCap(capAction); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj new file mode 100644 index 000000000..64736c78d --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs new file mode 100644 index 000000000..e36a96c42 --- /dev/null +++ b/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(configuration.GetSection("Aliyun:Sms")); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/LINYUN/Abp/Sms/Aliyun/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs new file mode 100644 index 000000000..e4abc6eaa --- /dev/null +++ b/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 + { + /// + /// 区域Id + /// + public string RegionId { get; set; } = "default"; + /// + /// 阿里云sms服务域名 + /// + public string Domain { get; set; } = "dysmsapi.aliyuncs.com"; + /// + /// 调用方法名称 + /// + public string ActionName { get; set; } = "SendSms"; + /// + /// ApiKey + /// + public string AccessKeyId { get; set; } + /// + /// Api密钥 + /// + public string AccessKeySecret { get; set; } + /// + /// 默认版本号 + /// + public string DefaultVersion { get; set; } = "2017-05-25"; + /// + /// 默认签名 + /// + public string DefaultSignName { get; set; } + /// + /// 默认短信模板号 + /// + public string DefaultTemplateCode { get; set; } + /// + /// 开发人员号码,当应用处于开发模式时,默认所有信息都会发送到此号码 + /// + public string DeveloperPhoneNumber { get; set; } = "13800138000"; + /// + /// 展示错误给客户端 + /// + public bool VisableErrorToClient { get; set; } = false; + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsResponse.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsResponse.cs new file mode 100644 index 000000000..66e623ffa --- /dev/null +++ b/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("SMS_TEMPLATE_ILLEGAL"); + case "isv.SMS_SIGNATURE_ILLEGAL": + return LocalizableString.Create("SMS_SIGNATURE_ILLEGAL"); + case "isv.MOBILE_NUMBER_ILLEGAL": + return LocalizableString.Create("MOBILE_NUMBER_ILLEGAL"); + case "isv.TEMPLATE_MISSING_PARAMETERS": + return LocalizableString.Create("TEMPLATE_MISSING_PARAMETERS"); + case "isv.EXTEND_CODE_ERROR": + return LocalizableString.Create("EXTEND_CODE_ERROR"); + case "isv.DOMESTIC_NUMBER_NOT_SUPPORTED": + return LocalizableString.Create("DOMESTIC_NUMBER_NOT_SUPPORTED"); + case "isv.DAY_LIMIT_CONTROL": + return LocalizableString.Create("DAY_LIMIT_CONTROL"); + case "isv.SMS_CONTENT_ILLEGAL": + return LocalizableString.Create("SMS_CONTENT_ILLEGAL"); + case "isv.SMS_SIGN_ILLEGAL": + return LocalizableString.Create("SMS_SIGN_ILLEGAL"); + case "isp.RAM_PERMISSION_DENY": + return LocalizableString.Create("RAM_PERMISSION_DENY"); + case "isp.OUT_OF_SERVICE": + return LocalizableString.Create("OUT_OF_SERVICE"); + case "isv.PRODUCT_UN_SUBSCRIPT": + return LocalizableString.Create("PRODUCT_UN_SUBSCRIPT"); + case "isv.PRODUCT_UNSUBSCRIBE": + return LocalizableString.Create("PRODUCT_UNSUBSCRIBE"); + case "isv.ACCOUNT_NOT_EXISTS": + return LocalizableString.Create("ACCOUNT_NOT_EXISTS"); + case "isv.ACCOUNT_ABNORMAL": + return LocalizableString.Create("ACCOUNT_ABNORMAL"); + case "isv.INVALID_PARAMETERS": + return LocalizableString.Create("INVALID_PARAMETERS"); + case "isv.SYSTEM_ERROR": + return LocalizableString.Create("SYSTEM_ERROR"); + case "isv.INVALID_JSON_PARAM": + return LocalizableString.Create("INVALID_JSON_PARAM"); + case "isv.BLACK_KEY_CONTROL_LIMIT": + return LocalizableString.Create("BLACK_KEY_CONTROL_LIMIT"); + case "isv.PARAM_LENGTH_LIMIT": + return LocalizableString.Create("PARAM_LENGTH_LIMIT"); + case "isv.PARAM_NOT_SUPPORT_URL": + return LocalizableString.Create("PARAM_NOT_SUPPORT_URL"); + case "isv.AMOUNT_NOT_ENOUGH": + return LocalizableString.Create("AMOUNT_NOT_ENOUGH"); + case "isv.TEMPLATE_PARAMS_ILLEGAL": + return LocalizableString.Create("TEMPLATE_PARAMS_ILLEGAL"); + default: + throw new AbpException("no error code define!"); + + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs new file mode 100644 index 000000000..d17888502 --- /dev/null +++ b/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 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(responseContent); + if (!aliyunResponse.IsSuccess()) + { + var localizerFactory = ServiceProvider.GetRequiredService(); + var localizerError = aliyunResponse.GetErrorMessage().Localize(localizerFactory); + if (Options.VisableErrorToClient) + { + var localizer = ServiceProvider.GetRequiredService>(); + 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; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSuccessResponse.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSuccessResponse.cs new file mode 100644 index 000000000..4d0ad74c7 --- /dev/null +++ b/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; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/AliyunSmsResource.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/AliyunSmsResource.cs new file mode 100644 index 000000000..b1220263e --- /dev/null +++ b/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 + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/en.json b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/en.json new file mode 100644 index 000000000..2f947f883 --- /dev/null +++ b/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" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..a56cd5852 --- /dev/null +++ b/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": "模版变量里包含非法关键字" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj b/aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj index fb24e3e53..7b0206dd6 100644 --- a/aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj +++ b/aspnet-core/modules/common/LINGYUN.Common.EventBus/LINGYUN.Common.EventBus.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj index 936e1ad68..0e784b770 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN.Abp.IdentityServer.Application.Contracts.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj index 21e931179..86577be15 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN.Abp.IdentityServer.Application.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs index 2b35871ed..21c238f41 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs @@ -46,10 +46,12 @@ 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) + var apiResource = new ApiResource(GuidGenerator.Create(), apiResourceCreate.Name, + apiResourceCreate.DisplayName, apiResourceCreate.Description) + { + Enabled = apiResourceCreate.Enabled + }; + foreach (var userClaim in apiResourceCreate.UserClaims) { apiResource.AddUserClaim(userClaim.Type); } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs index 01af8f7e4..8dd96466d 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs +++ b/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) { diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj index b9615fd30..9c4eafc5c 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.HttpApi/LINGYUN.Abp.IdentityServer.HttpApi.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj new file mode 100644 index 000000000..e79d7fe1b --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN.Abp.IdentityServer.SmsValidator.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmValidatorModule.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerSmValidatorModule.cs new file mode 100644 index 000000000..1a1bb6fe4 --- /dev/null +++ b/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(builder => + { + builder.AddExtensionGrantValidator(); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json new file mode 100644 index 000000000..dd09cb2a5 --- /dev/null +++ b/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!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..c75aaff38 --- /dev/null +++ b/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": "登录的手机号码未注册!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsTokenGrantValidator.cs new file mode 100644 index 000000000..95ddd848d --- /dev/null +++ b/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 Logger { get; } + protected IEventService EventService { get; } + protected IIdentityUserRepository UserRepository { get; } + protected UserManager UserManager { get; } + protected SignInManager SignInManager { get; } + protected IStringLocalizer Localizer { get; } + protected PhoneNumberTokenProvider PhoneNumberTokenProvider { get; } + + + public SmsTokenGrantValidator( + IEventService eventService, + UserManager userManager, + SignInManager signInManager, + IIdentityUserRepository userRepository, + IStringLocalizer stringLocalizer, + PhoneNumberTokenProvider phoneNumberTokenProvider, + ILogger 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(); + 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()); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsValidatorConsts.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.SmsValidator/LINGYUN/Abp/IdentityServer/SmsValidator/SmsValidatorConsts.cs new file mode 100644 index 000000000..91ff74fb0 --- /dev/null +++ b/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"; + } +} diff --git a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj b/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj index 7b26376aa..e904bdfa4 100644 --- a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj +++ b/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application.Contracts/LINGYUN.Abp.PermissionManagement.Application.Contracts.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj b/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj index ad598bac1..1485e2519 100644 --- a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj +++ b/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN.Abp.PermissionManagement.Application.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs b/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs index 0561c1b08..c100c9030 100644 --- a/aspnet-core/modules/permissions/LINGYUN.Abp.PermissionManagement.Application/LINGYUN/Abp/PermissionManagement/PermissionAppService.cs +++ b/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 Cache { get; } protected IPermissionGrantRepository PermissionGrantRepository { get; } protected IPermissionDefinitionManager PermissionDefinitionManager { get; } public PermissionAppService( + IDistributedCache cache, IPermissionGrantRepository permissionGrantRepository, IPermissionDefinitionManager permissionDefinitionManager, IOptions 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); + } } } diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj index eed9ff929..15a6eb018 100644 --- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN.Abp.SettingManagement.Application.Contracts.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj index 9611d9e3b..a4667a898 100644 --- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj @@ -5,7 +5,7 @@ - + diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj index 2064be3f3..5dba8495c 100644 --- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN.Abp.SettingManagement.HttpApi.csproj @@ -5,7 +5,7 @@ - + diff --git a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj index b631f522e..77e7ab38d 100644 --- a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj +++ b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application.Contracts/LINGYUN.Abp.TenantManagement.Application.Contracts.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj index 0ab5dc32a..447d25c85 100644 --- a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj +++ b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN.Abp.TenantManagement.Application.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj index 30322f5c6..2a0839fe6 100644 --- a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj +++ b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.HttpApi/LINGYUN.Abp.TenantManagement.HttpApi.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs index b70f9ad10..e370d890d 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs +++ b/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() - .SeedAsync(); - } + using var scope = context.ServiceProvider.CreateScope(); + await scope.ServiceProvider.GetRequiredService().SeedAsync(); }); } } diff --git a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj index 0d343a9f4..a938bac49 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj +++ b/aspnet-core/services/account/AuthServer.Host/AuthServer.Host.csproj @@ -20,20 +20,21 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - + + + + + + + + + + diff --git a/aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs b/aspnet-core/services/account/AuthServer.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs new file mode 100644 index 000000000..62593211a --- /dev/null +++ b/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, LINGYUN.Abp.Account.IIdentityUserRepository, + ITransientDependency + { + public EfCoreIdentityUserRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindByPhoneNumberAsync(string phoneNumber) + { + return await WithDetails() + .Where(usr => usr.PhoneNumber.Equals(phoneNumber)) + .FirstOrDefaultAsync(); + } + + public override IQueryable WithDetails() + { + return DbSet + .Include(x => x.Claims) + .Include(x => x.Roles) + .Include(x => x.Logins) + .Include(x => x.Tokens); + } + } +} diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj index c2e62ed48..9578d5f3b 100644 --- a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj +++ b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj @@ -17,10 +17,10 @@ - - - - + + + + diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj index 65062cd60..a0ab01d18 100644 --- a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj +++ b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/LINGYUN.ApiGateway.HttpApi.Host.csproj @@ -28,11 +28,11 @@ - - - - - + + + + + diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EntityFrameworkCore/Identity/EfCoreIdentityUserExtensionRepository.cs new file mode 100644 index 000000000..7809d6795 --- /dev/null +++ b/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, Abp.Account.IIdentityUserRepository, + ITransientDependency + { + public EfCoreIdentityUserRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task FindByPhoneNumberAsync(string phoneNumber) + { + return await DbSet.Where(usr => usr.PhoneNumber.Equals(phoneNumber)).FirstOrDefaultAsync(); + } + } +} diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantDeleteEventHandler.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantDeleteEventHandler.cs index 7eb8fafd1..aae3df09a 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/EventBus/Handlers/TenantDeleteEventHandler.cs +++ b/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(); } } diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj index c0aa074f3..61d1a2047 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj +++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj @@ -22,29 +22,33 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -52,8 +56,4 @@ - - - - diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs index 04a4bade1..02fa0c688 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs +++ b/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(builder => + { + builder.AddDefaultTokenProviders(); + }); } public override void ConfigureServices(ServiceConfigurationContext context) @@ -176,7 +186,7 @@ namespace LINGYUN.Platform // 审计日志 app.UseAuditing(); // 路由 - app.UseMvcWithDefaultRouteAndArea(); + app.UseConfiguredEndpoints(); } } } diff --git a/vueJs/src/api/users.ts b/vueJs/src/api/users.ts index f31625227..5c6442986 100644 --- a/vueJs/src/api/users.ts +++ b/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 /** 联系方式 */ diff --git a/vueJs/src/views/admin/users/components/UserCreateForm.vue b/vueJs/src/views/admin/users/components/UserCreateForm.vue new file mode 100644 index 000000000..6196fe1ec --- /dev/null +++ b/vueJs/src/views/admin/users/components/UserCreateForm.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/vueJs/src/views/admin/users/components/UserProfile.vue b/vueJs/src/views/admin/users/components/UserEditForm.vue similarity index 82% rename from vueJs/src/views/admin/users/components/UserProfile.vue rename to vueJs/src/views/admin/users/components/UserEditForm.vue index 0f2ae3e39..23454383c 100644 --- a/vueJs/src/views/admin/users/components/UserProfile.vue +++ b/vueJs/src/views/admin/users/components/UserEditForm.vue @@ -1,6 +1,6 @@