diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index 0d1e59be7..e1baa131a 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -428,7 +428,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Localization", "modules\localization\LINGYUN.Abp.AspNetCore.Mvc.Localization\LINGYUN.Abp.AspNetCore.Mvc.Localization.csproj", "{995DB1CE-A2FC-4468-A521-4207FD587EC5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Domain.Shared", "modules\account\LINGYUN.Abp.Account.Domain.Shared\LINGYUN.Abp.Account.Domain.Shared.csproj", "{446852ED-D80C-450F-8383-6B1ADCA08A59}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Templates", "modules\account\LINGYUN.Abp.Account.Templates\LINGYUN.Abp.Account.Templates.csproj", "{AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1112,10 +1112,10 @@ Global {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU {995DB1CE-A2FC-4468-A521-4207FD587EC5}.Release|Any CPU.Build.0 = Release|Any CPU - {446852ED-D80C-450F-8383-6B1ADCA08A59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {446852ED-D80C-450F-8383-6B1ADCA08A59}.Debug|Any CPU.Build.0 = Debug|Any CPU - {446852ED-D80C-450F-8383-6B1ADCA08A59}.Release|Any CPU.ActiveCfg = Release|Any CPU - {446852ED-D80C-450F-8383-6B1ADCA08A59}.Release|Any CPU.Build.0 = Release|Any CPU + {AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1325,7 +1325,7 @@ Global {A53FE09E-6B1C-46C0-9422-C313D14AE9E4} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} {0CE035CF-2D8A-4559-93EC-ADBEC4237C61} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} {995DB1CE-A2FC-4468-A521-4207FD587EC5} = {90E88EAC-4291-4406-8D88-EFDF61B11292} - {446852ED-D80C-450F-8383-6B1ADCA08A59} = {9E72FEB9-A626-4312-892B-CDD043879758} + {AFFBE8EE-1B92-4CDF-8A4F-4000B78A0154} = {9E72FEB9-A626-4312-892B-CDD043879758} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} 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 index 95bc1f9ba..219323cd0 100644 --- 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 @@ -9,11 +9,15 @@ - + - + + + + + 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 index 6044f4a04..2eca54a66 100644 --- 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 @@ -1,11 +1,27 @@ -using Volo.Abp.Modularity; - +using Volo.Abp.Account.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + namespace LINGYUN.Abp.Account { [DependsOn( - typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule), - typeof(AbpAccountDomainSharedModule))] + typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule))] public class AbpAccountApplicationContractsModule : 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.Application.Contracts/LINGYUN/Abp/Account/Dto/ConfirmEmailInput.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/ConfirmEmailInput.cs new file mode 100644 index 000000000..c8d697a2d --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/ConfirmEmailInput.cs @@ -0,0 +1,13 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.Account; + +public class ConfirmEmailInput +{ + [Required] + public Guid UserId { get; set; } + + [Required] + public string ConfirmToken { get; set; } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendEmailConfirmCodeDto.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendEmailConfirmCodeDto.cs new file mode 100644 index 000000000..61f906755 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Dto/SendEmailConfirmCodeDto.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Identity; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.Account; + +public class SendEmailConfirmCodeDto +{ + [Required] + [EmailAddress] + [Display(Name = "EmailAddress")] + [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))] + public string Email { get; set; } + + [Required] + public string AppName { get; set; } + + public string ReturnUrl { get; set; } + + public string ReturnUrlHash { get; set; } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IMyProfileAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IMyProfileAppService.cs index 099033936..0f15f3e46 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IMyProfileAppService.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/IMyProfileAppService.cs @@ -31,5 +31,17 @@ namespace LINGYUN.Abp.Account /// 需二次认证,主要是为了无法用到重定向页面修改相关信息的地方(点名微信小程序) /// Task ChangePhoneNumberAsync(ChangePhoneNumberInput input); + /// + /// 发送确认邮件验证码 + /// + /// + /// + Task SendEmailConfirmLinkAsync(SendEmailConfirmCodeDto input); + /// + /// 确认邮件地址 + /// + /// + /// + Task ConfirmEmailAsync(ConfirmEmailInput input); } } diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json similarity index 68% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json index 136e680a1..275cc6314 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/en.json +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/en.json @@ -4,6 +4,7 @@ "UserNotRegisterd": "The user account is not registered!", "UserEmailNotConfirmed": "The user's email address is not confirmed!", "SendRepeatSmsVerifyCode": "Phone verification code cannot be sent repeatedly within {0} minutes!", + "SendRepeatEmailVerifyCode": "Email verification code cannot be sent repeatedly within {0} minutes!", "DuplicatePhoneNumber": "The phone number already exists!", "PhoneNumberNotRegisterd": "The registered mobile phone number is not registered!", "InvalidVerifyCode": "The verification code is invalid or expired!", @@ -24,11 +25,6 @@ "VerifyAuthenticatorCode": "Authentication code", "RememberBrowser": "Remember me in the browser", "TwoFactorAuthenticationInvaidUser": "Authentication failed. Your session is invalid. Please re login try again!", - "InvaidGenerateTwoFactorToken": "Verification code generation failed. Please contact your administrator!", - "TextTemplate:Abp.Account.MailSecurityVerifyLink": "Mail security validation template", - "MailSecurityVerify": "Mail security verification", - "VerifyMyEmailAddress": "Hello {0}

Your email security verification code is as follows. Please enter the verification code to proceed to the next step.

If not operated by you, please ignore this email.

", - "MailSecurityVerifyRemarks": "

(If it is not in the form of a link, copy the address to the browser address bar for further access)

Thank you for your visit and have a good time!

", - "ClickToValidation": "Click link verification" + "InvaidGenerateTwoFactorToken": "Verification code generation failed. Please contact your administrator!" } } \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/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 similarity index 74% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application.Contracts/LINGYUN/Abp/Account/Localization/Resources/zh-Hans.json index b6bebfa3f..83572a44d 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/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 @@ -4,6 +4,7 @@ "UserNotRegisterd": "用户账号未注册!", "UserEmailNotConfirmed": "用户邮件地址未确认!", "SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!", + "SendRepeatEmailVerifyCode": "邮件验证码不能在 {0} 分钟内重复发送!", "DuplicatePhoneNumber": "手机号已经存在!", "PhoneNumberNotRegisterd": "手机号码未注册!", "InvalidVerifyCode": "验证码无效或已经过期!", @@ -24,11 +25,6 @@ "VerifyAuthenticatorCode": "验证身份代码", "RememberBrowser": "在浏览器中记住我", "TwoFactorAuthenticationInvaidUser": "认证失败,您的会话已失效,请程序登录!", - "InvaidGenerateTwoFactorToken": "验证码生成失败,请联系管理员!", - "TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件安全验证模板", - "MailSecurityVerify": "邮件安全验证", - "VerifyMyEmailAddress": "您好

您此次邮件安全验证码如下,请输入验证码进行下一步操作。

如非你本人操作,请忽略此邮件。

", - "MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。", - "ClickToValidation": "点击进行验证" + "InvaidGenerateTwoFactorToken": "验证码生成失败,请联系管理员!" } } \ 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 index ed0f8353c..ab8949116 100644 --- 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 @@ -18,6 +18,11 @@ + + + + + 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 index 8300e99a3..ffc9998b0 100644 --- 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 @@ -1,16 +1,31 @@ -using LINGYUN.Abp.Identity; +using LINGYUN.Abp.Account.Templates; +using LINGYUN.Abp.Identity; using LINGYUN.Abp.WeChat.MiniProgram; using Volo.Abp.Modularity; - +using Volo.Abp.UI.Navigation.Urls; +using Volo.Abp.VirtualFileSystem; + namespace LINGYUN.Abp.Account { [DependsOn( typeof(Volo.Abp.Account.AbpAccountApplicationModule), typeof(AbpAccountApplicationContractsModule), + typeof(AbpAccountTemplatesModule), typeof(AbpIdentityDomainModule), typeof(AbpWeChatMiniProgramModule))] public class AbpAccountApplicationModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Applications["MVC"].Urls[AccountUrlNames.EmailConfirm] = "Account/EmailConfirm"; + }); + } } } 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 index 9eafcc55b..dd557cd26 100644 --- 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 @@ -30,18 +30,18 @@ namespace LINGYUN.Abp.Account { protected ITotpService TotpService { get; } protected IIdentityUserRepository UserRepository { get; } - protected IUserSecurityCodeSender SecurityCodeSender { get; } + protected IAccountSmsSecurityCodeSender SecurityCodeSender { get; } protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } - protected IDistributedCache SecurityTokenCache { get; } + protected IDistributedCache SecurityTokenCache { get; } public AccountAppService( ITotpService totpService, IWeChatOpenIdFinder weChatOpenIdFinder, IIdentityUserRepository userRepository, - IUserSecurityCodeSender securityCodeSender, - IDistributedCache securityTokenCache, + IAccountSmsSecurityCodeSender securityCodeSender, + IDistributedCache securityTokenCache, AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory, IdentitySecurityLogManager identitySecurityLogManager) { @@ -108,7 +108,7 @@ namespace LINGYUN.Abp.Account await CheckSelfRegistrationAsync(); await CheckNewUserPhoneNumberNotBeUsedAsync(input.PhoneNumber); - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.PhoneNumber, "SmsVerifyCode"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1); @@ -123,9 +123,9 @@ namespace LINGYUN.Abp.Account var securityToken = GuidGenerator.Create().ToString("N"); var code = TotpService.GenerateCode(Encoding.Unicode.GetBytes(securityToken), securityTokenCacheKey); - securityTokenCacheItem = new SmsSecurityTokenCacheItem(code.ToString(), securityToken); + securityTokenCacheItem = new SecurityTokenCacheItem(code.ToString(), securityToken); - await SecurityCodeSender.SendPhoneConfirmedCodeAsync( + await SecurityCodeSender.SendSmsCodeAsync( input.PhoneNumber, securityTokenCacheItem.Token, template); await SecurityTokenCache @@ -142,7 +142,7 @@ namespace LINGYUN.Abp.Account await IdentityOptions.SetAsync(); await CheckNewUserPhoneNumberNotBeUsedAsync(input.PhoneNumber); - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.PhoneNumber, "SmsVerifyCode"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); if (securityTokenCacheItem == null) { @@ -216,7 +216,7 @@ namespace LINGYUN.Abp.Account throw new BusinessException(code: Volo.Abp.Identity.IdentityErrorCodes.ExternalUserPasswordChange); } - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.PhoneNumber, "SmsVerifyCode"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1); // 能查询到缓存就是重复发送 @@ -229,9 +229,9 @@ namespace LINGYUN.Abp.Account // 生成二次认证码 var code = await UserManager.GenerateTwoFactorTokenAsync(user, TokenOptions.DefaultPhoneProvider); // 发送短信验证码 - await SecurityCodeSender.SendPhoneConfirmedCodeAsync(input.PhoneNumber, code, template); + await SecurityCodeSender.SendSmsCodeAsync(input.PhoneNumber, code, template); // 缓存这个手机号的记录,防重复 - securityTokenCacheItem = new SmsSecurityTokenCacheItem(code, user.SecurityStamp); + securityTokenCacheItem = new SecurityTokenCacheItem(code, user.SecurityStamp); await SecurityTokenCache .SetAsync(securityTokenCacheKey, securityTokenCacheItem, new DistributedCacheEntryOptions @@ -242,7 +242,7 @@ namespace LINGYUN.Abp.Account public virtual async Task ResetPasswordAsync(PhoneResetPasswordDto input) { - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.PhoneNumber, "SmsVerifyCode"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); if (securityTokenCacheItem == null) { @@ -283,7 +283,7 @@ namespace LINGYUN.Abp.Account public virtual async Task SendPhoneSigninCodeAsync(SendPhoneSigninCodeDto input) { - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.PhoneNumber, "SmsVerifyCode"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.PhoneNumber, "SmsVerifyCode"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); var interval = await SettingProvider.GetAsync(IdentitySettingNames.User.SmsRepetInterval, 1); if (securityTokenCacheItem != null) @@ -296,9 +296,9 @@ namespace LINGYUN.Abp.Account var template = await SettingProvider.GetOrNullAsync(IdentitySettingNames.User.SmsUserSignin); // 发送登录验证码短信 - await SecurityCodeSender.SendPhoneConfirmedCodeAsync(input.PhoneNumber, code, template); + await SecurityCodeSender.SendSmsCodeAsync(input.PhoneNumber, code, template); // 缓存登录验证码状态,防止同一手机号重复发送 - securityTokenCacheItem = new SmsSecurityTokenCacheItem(code, user.SecurityStamp); + securityTokenCacheItem = new SecurityTokenCacheItem(code, user.SecurityStamp); await SecurityTokenCache .SetAsync(securityTokenCacheKey, securityTokenCacheItem, new DistributedCacheEntryOptions diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountSmsSecurityCodeSender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountSmsSecurityCodeSender.cs new file mode 100644 index 000000000..551bb10a2 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountSmsSecurityCodeSender.cs @@ -0,0 +1,32 @@ +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Sms; + +namespace LINGYUN.Abp.Account; + +public class AccountSmsSecurityCodeSender : IAccountSmsSecurityCodeSender, ITransientDependency +{ + protected ISmsSender SmsSender { get; } + + public AccountSmsSecurityCodeSender(ISmsSender smsSender) + { + SmsSender = smsSender; + } + + public async virtual Task SendSmsCodeAsync( + string phone, + string token, + string template, + CancellationToken cancellation = default) + { + Check.NotNullOrWhiteSpace(template, nameof(template)); + + var smsMessage = new SmsMessage(phone, token); + smsMessage.Properties.Add("code", token); + smsMessage.Properties.Add("TemplateCode", template); + + await SmsSender.SendAsync(smsMessage); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountUrlNames.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountUrlNames.cs new file mode 100644 index 000000000..b096a0ba8 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/AccountUrlNames.cs @@ -0,0 +1,6 @@ +namespace LINGYUN.Abp.Account; + +public static class AccountUrlNames +{ + public const string EmailConfirm = "Abp.Account.EmailConfirm"; +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/AccountEmailSender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/AccountEmailSender.cs new file mode 100644 index 000000000..de699ed62 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/AccountEmailSender.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.Account.Emailing.Templates; +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Volo.Abp.Account.Emailing; +using Volo.Abp.Account.Localization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Emailing; +using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TextTemplating; +using Volo.Abp.UI.Navigation.Urls; + +namespace LINGYUN.Abp.Account.Emailing; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(IAccountEmailConfirmSender), + typeof(IAccountEmailVerifySender), + typeof(IAccountEmailer), + typeof(AccountEmailSender))] +public class AccountEmailSender : + AccountEmailer, + IAccountEmailConfirmSender, + IAccountEmailVerifySender, + ITransientDependency +{ + public AccountEmailSender( + IEmailSender emailSender, + ITemplateRenderer templateRenderer, + IStringLocalizer accountLocalizer, + IAppUrlProvider appUrlProvider, + ICurrentTenant currentTenant) + : base(emailSender, templateRenderer, accountLocalizer, appUrlProvider, currentTenant) + { + } + + public async virtual Task SendMailLoginVerifyCodeAsync( + string code, + string userName, + string emailAddress) + { + var emailContent = await TemplateRenderer.RenderAsync( + AccountEmailTemplates.MailSecurityVerifyLink, + new { code = code, user = userName } + ); + + await EmailSender.SendAsync( + emailAddress, + StringLocalizer["MailSecurityVerify"], + emailContent + ); + } + + public async virtual Task SendEmailConfirmLinkAsync( + IdentityUser user, + string confirmToken, + string appName, + string returnUrl = null, + string returnUrlHash = null) + { + Debug.Assert(CurrentTenant.Id == user.TenantId, "This method can only work for current tenant!"); + + var url = await AppUrlProvider.GetUrlAsync(appName, AccountUrlNames.EmailConfirm); + + var link = $"{url}?userId={user.Id}&{TenantResolverConsts.DefaultTenantKey}={user.TenantId}&confirmToken={UrlEncoder.Default.Encode(confirmToken)}"; + + if (!returnUrl.IsNullOrEmpty()) + { + link += "&returnUrl=" + NormalizeReturnUrl(returnUrl); + } + + if (!returnUrlHash.IsNullOrEmpty()) + { + link += "&returnUrlHash=" + returnUrlHash; + } + + var emailContent = await TemplateRenderer.RenderAsync( + AccountEmailTemplates.MailConfirmLink, + new { link = link } + ); + + await EmailSender.SendAsync( + user.Email, + StringLocalizer["EmailConfirm"], + emailContent + ); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/IAccountEmailConfirmSender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/IAccountEmailConfirmSender.cs new file mode 100644 index 000000000..36a2427a9 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/IAccountEmailConfirmSender.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Identity; + +namespace LINGYUN.Abp.Account.Emailing; + +public interface IAccountEmailConfirmSender +{ + Task SendEmailConfirmLinkAsync( + IdentityUser user, + string confirmToken, + string appName, + string returnUrl = null, + string returnUrlHash = null + ); +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs similarity index 100% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/Emailing/IAccountEmailVerifySender.cs diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/IAccountSmsSecurityCodeSender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/IAccountSmsSecurityCodeSender.cs new file mode 100644 index 000000000..e4b31e783 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/IAccountSmsSecurityCodeSender.cs @@ -0,0 +1,14 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Account +{ + public interface IAccountSmsSecurityCodeSender + { + Task SendSmsCodeAsync( + string phone, + string token, + string template, // 传递模板号 + CancellationToken cancellation = default); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs index b4494b0ba..64c908270 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Application/LINGYUN/Abp/Account/MyProfileAppService.cs @@ -1,12 +1,15 @@ -using LINGYUN.Abp.Identity; +using LINGYUN.Abp.Account.Emailing; +using LINGYUN.Abp.Identity; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Account.Localization; using Volo.Abp.Caching; +using Volo.Abp.Identity; using Volo.Abp.Settings; namespace LINGYUN.Abp.Account @@ -14,17 +17,20 @@ namespace LINGYUN.Abp.Account [Authorize] public class MyProfileAppService : AccountApplicationServiceBase, IMyProfileAppService { - protected IDistributedCache SecurityTokenCache { get; } - protected IUserSecurityCodeSender SecurityCodeSender { get; } + protected IDistributedCache SecurityTokenCache { get; } + protected IAccountSmsSecurityCodeSender SecurityCodeSender { get; } protected Identity.IIdentityUserRepository UserRepository { get; } + protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } public MyProfileAppService( Identity.IIdentityUserRepository userRepository, - IUserSecurityCodeSender securityCodeSender, - IDistributedCache securityTokenCache) + IAccountSmsSecurityCodeSender securityCodeSender, + IdentitySecurityLogManager identitySecurityLogManager, + IDistributedCache securityTokenCache) { UserRepository = userRepository; SecurityCodeSender = securityCodeSender; + IdentitySecurityLogManager = identitySecurityLogManager; SecurityTokenCache = securityTokenCache; LocalizationResource = typeof(AccountResource); @@ -57,7 +63,7 @@ namespace LINGYUN.Abp.Account public virtual async Task SendChangePhoneNumberCodeAsync(SendChangePhoneNumberCodeInput input) { - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.NewPhoneNumber, "SmsChangePhoneNumber"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.NewPhoneNumber, "SmsChangePhoneNumber"); var securityTokenCacheItem = await SecurityTokenCache.GetAsync(securityTokenCacheKey); var interval = await SettingProvider.GetAsync(Identity.Settings.IdentitySettingNames.User.SmsRepetInterval, 1); if (securityTokenCacheItem != null) @@ -75,9 +81,9 @@ namespace LINGYUN.Abp.Account var template = await SettingProvider.GetOrNullAsync(Identity.Settings.IdentitySettingNames.User.SmsPhoneNumberConfirmed); var token = await UserManager.GenerateChangePhoneNumberTokenAsync(user, input.NewPhoneNumber); // 发送验证码 - await SecurityCodeSender.SendPhoneConfirmedCodeAsync(input.NewPhoneNumber, token, template); + await SecurityCodeSender.SendSmsCodeAsync(input.NewPhoneNumber, token, template); - securityTokenCacheItem = new SmsSecurityTokenCacheItem(token, user.ConcurrencyStamp); + securityTokenCacheItem = new SecurityTokenCacheItem(token, user.ConcurrencyStamp); await SecurityTokenCache .SetAsync(securityTokenCacheKey, securityTokenCacheItem, new DistributedCacheEntryOptions @@ -99,8 +105,48 @@ namespace LINGYUN.Abp.Account await CurrentUnitOfWork.SaveChangesAsync(); - var securityTokenCacheKey = SmsSecurityTokenCacheItem.CalculateCacheKey(input.NewPhoneNumber, "SmsChangePhoneNumber"); + var securityTokenCacheKey = SecurityTokenCacheItem.CalculateSmsCacheKey(input.NewPhoneNumber, "SmsChangePhoneNumber"); await SecurityTokenCache.RemoveAsync(securityTokenCacheKey); } + + public async virtual Task SendEmailConfirmLinkAsync(SendEmailConfirmCodeDto input) + { + var user = await UserManager.FindByEmailAsync(input.Email); + + if (user == null) + { + throw new UserFriendlyException(L["Volo.Account:InvalidEmailAddress", input.Email]); + } + + if (user.EmailConfirmed) + { + throw new BusinessException(Identity.IdentityErrorCodes.DuplicateConfirmEmailAddress); + } + + var token = await UserManager.GenerateEmailConfirmationTokenAsync(user); + var sender = LazyServiceProvider.LazyGetRequiredService(); + + await sender.SendEmailConfirmLinkAsync( + user, + token, + input.AppName, + input.ReturnUrl, + input.ReturnUrlHash); + } + + public async virtual Task ConfirmEmailAsync(ConfirmEmailInput input) + { + await IdentityOptions.SetAsync(); + + var user = await UserManager.GetByIdAsync(input.UserId); + + (await UserManager.ConfirmEmailAsync(user, input.ConfirmToken)).CheckErrors(); + + await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext + { + Identity = IdentitySecurityLogIdentityConsts.Identity, + Action = "ConfirmEmail" + }); + } } } 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 deleted file mode 100644 index ec56918ac..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/AbpAccountDomainSharedModule.cs +++ /dev/null @@ -1,28 +0,0 @@ -using LINGYUN.Abp.Account.Localization; -using Volo.Abp.Emailing; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileSystem; - -namespace LINGYUN.Abp.Account -{ - [DependsOn( - typeof(AbpEmailingModule))] - public class AbpAccountDomainSharedModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.FileSets.AddEmbedded(); - }); - - Configure(options => - { - options.Resources - .Add("en") - .AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); - }); - } - } -} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/AccountEmailVerifySender.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/AccountEmailVerifySender.cs deleted file mode 100644 index 4d959f55b..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/AccountEmailVerifySender.cs +++ /dev/null @@ -1,44 +0,0 @@ -using LINGYUN.Abp.Account.Localization; -using LY.MicroService.IdentityServer.Emailing.Templates; -using Microsoft.Extensions.Localization; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Emailing; -using Volo.Abp.TextTemplating; - -namespace LINGYUN.Abp.Account.Emailing; - -public class AccountEmailVerifySender : IAccountEmailVerifySender, ITransientDependency -{ - protected IEmailSender EmailSender { get; } - protected ITemplateRenderer TemplateRenderer { get; } - - protected IStringLocalizer StringLocalizer { get; } - - public AccountEmailVerifySender( - IEmailSender emailSender, - ITemplateRenderer templateRenderer, - IStringLocalizer stringLocalizer) - { - EmailSender = emailSender; - TemplateRenderer = templateRenderer; - StringLocalizer = stringLocalizer; - } - - public async virtual Task SendMailLoginVerifyCodeAsync( - string code, - string userName, - string emailAddress) - { - var emailContent = await TemplateRenderer.RenderAsync( - AccountEmailTemplates.MailSecurityVerifyLink, - new { code = code, user = userName } - ); - - await EmailSender.SendAsync( - emailAddress, - StringLocalizer["MailSecurityVerify"], - emailContent - ); - } -} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs deleted file mode 100644 index 4e3f2a87a..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplateDefinitionProvider.cs +++ /dev/null @@ -1,22 +0,0 @@ -using LINGYUN.Abp.Account.Localization; -using Volo.Abp.Emailing.Templates; -using Volo.Abp.Localization; -using Volo.Abp.TextTemplating; - -namespace LY.MicroService.IdentityServer.Emailing.Templates; - -public class AccountEmailTemplateDefinitionProvider : TemplateDefinitionProvider -{ - public override void Define(ITemplateDefinitionContext context) - { - context.Add( - new TemplateDefinition( - AccountEmailTemplates.MailSecurityVerifyLink, - displayName: LocalizableString.Create( - $"TextTemplate:{AccountEmailTemplates.MailSecurityVerifyLink}"), - layout: StandardEmailTemplates.Layout, - localizationResource: typeof(AbpAccountResource) - ).WithVirtualFilePath("/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl", true) - ); - } -} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AbpAccountResource.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AbpAccountResource.cs deleted file mode 100644 index ebc24bbb6..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Localization/AbpAccountResource.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Volo.Abp.Localization; - -namespace LINGYUN.Abp.Account.Localization; - -[LocalizationResourceName("AbpAccountResource")] -public class AbpAccountResource -{ -} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/FodyWeavers.xml b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/FodyWeavers.xml deleted file mode 100644 index 1715698cc..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file 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 deleted file mode 100644 index 27e95404c..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN.Abp.Account.Domain.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - 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 deleted file mode 100644 index 5226add4a..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.Account -{ - [DependsOn(typeof(AbpAccountDomainSharedModule))] - public class AbpAccountDomainModule : AbpModule - { - } -} 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 deleted file mode 100644 index 360c2f22b..000000000 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/IIdentityUserRepository.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; - -namespace LINGYUN.Abp.Account -{ - public interface IIdentityUserRepository : IReadOnlyRepository - { - Task PhoneNumberHasRegistedAsync(string phoneNumber); - - Task FindByPhoneNumberAsync(string phoneNumber); - - Task GetIdByPhoneNumberAsync(string phoneNumber); - } -} 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 index 78771e56b..66ae75ed2 100644 --- 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 @@ -1,8 +1,6 @@ -using LINGYUN.Abp.Account.Localization; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Account.Localization; using Volo.Abp.AspNetCore.Mvc.Localization; -using Volo.Abp.Localization; using Volo.Abp.Modularity; namespace LINGYUN.Abp.Account @@ -26,15 +24,5 @@ namespace LINGYUN.Abp.Account mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountHttpApiModule).Assembly); }); } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Resources - .Get() - .AddBaseTypes(typeof(AbpAccountResource)); - }); - } } } diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/MyProfileController.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/MyProfileController.cs index 20024bd43..c290eb5b6 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/MyProfileController.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.HttpApi/LINGYUN/Abp/Account/MyProfileController.cs @@ -47,5 +47,19 @@ namespace LINGYUN.Abp.Account { await MyProfileAppService.ChangePhoneNumberAsync(input); } + + [HttpPut] + [Route("send-email-confirm-link")] + public async virtual Task SendEmailConfirmLinkAsync(SendEmailConfirmCodeDto input) + { + await MyProfileAppService.SendEmailConfirmLinkAsync(input); + } + + [HttpPut] + [Route("confirm-email")] + public async virtual Task ConfirmEmailAsync(ConfirmEmailInput input) + { + await MyProfileAppService.ConfirmEmailAsync(input); + } } } diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xml b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/FodyWeavers.xml similarity index 100% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xml rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/FodyWeavers.xml diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xsd b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/FodyWeavers.xsd similarity index 100% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/FodyWeavers.xsd rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/FodyWeavers.xsd 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.Templates/LINGYUN.Abp.Account.Templates.csproj similarity index 61% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN.Abp.Account.Templates.csproj index f5931fa38..756b911bc 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN.Abp.Account.Domain.Shared.csproj +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN.Abp.Account.Templates.csproj @@ -1,25 +1,29 @@ - - - - - - - netstandard2.0 - - - - - - - - - - - - - - - - - - + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs similarity index 50% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs index 9b9f500f8..4415d1452 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountEmailTemplates.cs @@ -1,7 +1,11 @@ -namespace LY.MicroService.IdentityServer.Emailing.Templates; +namespace LINGYUN.Abp.Account.Emailing.Templates; public static class AccountEmailTemplates { + /// + /// 邮件地址确认 + /// + public const string MailConfirmLink = "Abp.Account.MailConfirmLink"; /// /// 邮件安全验证 /// diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountTemplateDefinitionProvider.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountTemplateDefinitionProvider.cs new file mode 100644 index 000000000..265c8879b --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/AccountTemplateDefinitionProvider.cs @@ -0,0 +1,32 @@ +using Volo.Abp.Account.Localization; +using Volo.Abp.Emailing.Templates; +using Volo.Abp.Localization; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.Account.Emailing.Templates; + +public class AccountTemplateDefinitionProvider : TemplateDefinitionProvider +{ + public override void Define(ITemplateDefinitionContext context) + { + context.Add( + new TemplateDefinition( + AccountEmailTemplates.MailSecurityVerifyLink, + displayName: L($"TextTemplate:{AccountEmailTemplates.MailSecurityVerifyLink}"), + layout: StandardEmailTemplates.Layout, + localizationResource: typeof(AccountResource) + ).WithVirtualFilePath("/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl", true), + new TemplateDefinition( + AccountEmailTemplates.MailConfirmLink, + displayName: L($"TextTemplate:{AccountEmailTemplates.MailConfirmLink}"), + layout: StandardEmailTemplates.Layout, + localizationResource: typeof(AccountResource) + ).WithVirtualFilePath("/LINGYUN/Abp/Account/Emailing/Templates/MailConfirm.tpl", true) + ); + } + + private static ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/MailConfirm.tpl b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/MailConfirm.tpl new file mode 100644 index 000000000..49bdcf0f8 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/MailConfirm.tpl @@ -0,0 +1,7 @@ +

{{L "EmailConfirm"}}

+ +

{{L "EmailConfirmInfo"}}

+ + \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl similarity index 100% rename from aspnet-core/modules/account/LINGYUN.Abp.Account.Domain.Shared/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl rename to aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/AbpAccountTemplatesModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/AbpAccountTemplatesModule.cs new file mode 100644 index 000000000..9588fd2bc --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/AbpAccountTemplatesModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Emailing; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Account.Templates +{ + [DependsOn( + typeof(AbpEmailingModule), + typeof(AbpAccountApplicationContractsModule))] + public class AbpAccountTemplatesModule : AbpModule + { + + } +} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/en.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/en.json new file mode 100644 index 000000000..ff2ebb3ca --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/en.json @@ -0,0 +1,16 @@ +{ + "culture": "en", + "texts": { + "TextTemplate:Abp.Account.MailSecurityVerifyLink": "Mail security validation template", + "TextTemplate:Abp.Account.MailConfirmLink": "Mail confirm template", + "MailSecurityVerify": "Mail security verification", + "VerifyMyEmailAddress": "Hello {0}

Your email security verification code is as follows. Please enter the verification code to proceed to the next step.

If not operated by you, please ignore this email.

", + "MailSecurityVerifyRemarks": "

(If it is not in the form of a link, copy the address to the browser address bar for further access)

Thank you for your visit and have a good time!

", + "ClickToValidation": "Click link verification", + "Validation": "Validation", + "EmailConfirm": "Email confirm", + "EmailConfirmInfo": "We received an email confirmation request! If you initiated this request, please click the link below to confirm the email address.", + "ConfirmMyEmail": "Bind my email address", + "YourEmailIsSuccessfullyConfirm": "Your email address was bound successfully." + } +} \ No newline at end of file diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/zh-Hans.json b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..bf4fe71f5 --- /dev/null +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Templates/LINGYUN/Abp/Account/Templates/Localization/Resources/zh-Hans.json @@ -0,0 +1,16 @@ +{ + "culture": "zh-Hans", + "texts": { + "TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件验证模板", + "TextTemplate:Abp.Account.MailConfirmLink": "邮件确认模板", + "MailSecurityVerify": "邮件安全验证", + "VerifyMyEmailAddress": "您好

您此次邮件安全验证码如下,请输入验证码进行下一步操作。

如非你本人操作,请忽略此邮件。

", + "MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。", + "ClickToValidation": "点击进行验证", + "Validation": "验证", + "EmailConfirm": "邮件确认", + "EmailConfirmInfo": "我们收到了邮件确认请求!如果你发起了此请求,请单击以下链接以确认邮件地址.", + "ConfirmMyEmail": "绑定我的邮箱地址", + "YourEmailIsSuccessfullyConfirm": "您的邮件地址绑定成功." + } +} \ No newline at end of file diff --git a/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj b/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj index 483321c99..e9a34c828 100644 --- a/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj +++ b/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj @@ -5,7 +5,7 @@ Exe net6.0 - 5.3.0 + 5.3.2 colin Use LINGYUN.MicroService.Templates command line true diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj index 7f4ee0e53..74a8efec3 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj @@ -1,4 +1,4 @@ - + diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IUserSecurityCodeSender.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IUserSecurityCodeSender.cs deleted file mode 100644 index 7ec4aeacb..000000000 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IUserSecurityCodeSender.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace LINGYUN.Abp.Identity -{ - public interface IUserSecurityCodeSender - { - Task SendPhoneConfirmedCodeAsync( - string phone, - string token, - string template, // 传递模板号 - CancellationToken cancellation = default); - - Task SendEmailConfirmedCodeAsync( - string userName, - string email, - string token, - CancellationToken cancellation = default); - } -} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityErrorCodes.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityErrorCodes.cs index 9af0aee7b..31cea94a7 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityErrorCodes.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityErrorCodes.cs @@ -22,5 +22,9 @@ /// 你不能修改你的邮件绑定信息 /// public const string UsersCanNotChangeEmailAddress = "Volo.Abp.Identity:020009"; + /// + /// 重复确认的邮件地址 + /// + public const string DuplicateConfirmEmailAddress = "Volo.Abp.Identity:020010"; } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json index bce5b9dc3..dc8915354 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json @@ -46,6 +46,7 @@ "Volo.Abp.Identity:020007": "The phone number is already tied to another user!", "Volo.Abp.Identity:020008": "You can't modify your phone's binding information!", "Volo.Abp.Identity:020009": "You cannot modify your email binding information!", + "Volo.Abp.Identity:020010": "The email address is bound!", "Volo.Abp.Identity:DuplicatePhoneNumber": "Phone number '{0}' is already taken.", "DisplayName:Abp.Identity.User.SmsNewUserRegister": "Register sms template", "Description:Abp.Identity.User.SmsNewUserRegister": "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", diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json index e332ca4a2..a0882dc0d 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json @@ -46,6 +46,7 @@ "Volo.Abp.Identity:020007": "手机号码已被其他用户绑定!", "Volo.Abp.Identity:020008": "你不能修改你的手机绑定信息!", "Volo.Abp.Identity:020009": "你不能修改你的邮件绑定信息!", + "Volo.Abp.Identity:020010": "邮件地址已绑定!", "Volo.Abp.Identity:DuplicatePhoneNumber": "手机号 '{0}' 已存在.", "DisplayName:Abp.Identity.User.SmsNewUserRegister": "新用户注册模板", "Description:Abp.Identity.User.SmsNewUserRegister": "新用户通过手机注册账号验证码模板", @@ -55,8 +56,8 @@ "Description:Abp.Identity.User.SmsResetPassword": "用户通过手机找回密码验证码模板", "DisplayName:Abp.Identity.User.SmsPhoneNumberConfirmed": "手机确认模板", "Description:Abp.Identity.User.SmsPhoneNumberConfirmed": "用户确认手机号验证码模板", - "DisplayName:Abp.Identity.User.SmsRepetInterval": "重复发送间隔时间(min)", - "Description:Abp.Identity.User.SmsRepetInterval": "验证码重复发送的最小时间差,单位为分", + "DisplayName:Abp.Identity.User.SmsRepetInterval": "短信验证码重复发送间隔时间(min)", + "Description:Abp.Identity.User.SmsRepetInterval": "短信验证码验证码重复发送的最小时间差,单位为分", "DisplayName:SmsVerifyCode": "短信验证码", "DisplayName:EmailVerifyCode": "邮件验证码", "DisplayName:WeChatCode": "微信登录凭证", diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingNames.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingNames.cs index ec7d9f94c..e2ab5405b 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingNames.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingNames.cs @@ -23,7 +23,7 @@ /// public const string SmsResetPassword = UserPrefix + ".SmsResetPassword"; /// - /// 验证码重复间隔时间 + /// 短信验证码重复间隔时间 /// public const string SmsRepetInterval = UserPrefix + ".SmsRepetInterval"; } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SmsSecurityTokenCacheItem.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SecurityTokenCacheItem.cs similarity index 53% rename from aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SmsSecurityTokenCacheItem.cs rename to aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SecurityTokenCacheItem.cs index 1a866787d..8cc8f747e 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SmsSecurityTokenCacheItem.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/SecurityTokenCacheItem.cs @@ -1,9 +1,9 @@ namespace LINGYUN.Abp.Identity { /// - /// 短信安全令牌验证缓存 + /// 安全令牌验证缓存 /// - public class SmsSecurityTokenCacheItem + public class SecurityTokenCacheItem { /// /// 用于验证的Token @@ -14,12 +14,12 @@ /// public string SecurityToken { get; set; } - public SmsSecurityTokenCacheItem() + public SecurityTokenCacheItem() { } - public SmsSecurityTokenCacheItem(string token, string securityToken) + public SecurityTokenCacheItem(string token, string securityToken) { Token = token; SecurityToken = securityToken; @@ -31,9 +31,20 @@ /// 手机号 /// 安全令牌用途 /// - public static string CalculateCacheKey(string phoneNumber, string purpose) + public static string CalculateSmsCacheKey(string phoneNumber, string purpose) { return "Totp:" + purpose + ";p:" + phoneNumber; } + + /// + /// 生成查询Key + /// + /// 邮件地址 + /// 安全令牌用途 + /// + public static string CalculateEmailCacheKey(string email, string purpose) + { + return "Totp:" + purpose + ";e:" + email; + } } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateDto.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateDto.cs index 4b79f11ef..f2896541d 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateDto.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateDto.cs @@ -5,8 +5,6 @@ namespace LINGYUN.Platform.Menus { public class MenuCreateDto : MenuCreateOrUpdateDto { - public Guid? ParentId { get; set; } - [Required] public Guid LayoutId { get; set; } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateOrUpdateDto.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateOrUpdateDto.cs index 433ea5085..8b59081bb 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateOrUpdateDto.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Application.Contracts/LINGYUN/Platform/Menus/Dto/MenuCreateOrUpdateDto.cs @@ -1,4 +1,5 @@ using LINGYUN.Platform.Routes; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Volo.Abp.Validation; @@ -7,6 +8,8 @@ namespace LINGYUN.Platform.Menus { public class MenuCreateOrUpdateDto { + public Guid? ParentId { get; set; } + [Required] [DynamicStringLength(typeof(RouteConsts), nameof(RouteConsts.MaxNameLength))] public string Name { get; set; } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs index 6aa72fbc2..8b0b6c896 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Application/LINGYUN/Platform/Menus/MenuAppService.cs @@ -211,6 +211,7 @@ namespace LINGYUN.Platform.Menus menu.Component = input.Component; } + menu.ParentId = input.ParentId; menu.IsPublic = input.IsPublic; await MenuManager.UpdateAsync(menu); diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobExecutedFailedProvider.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobExecutedFailedProvider.cs index 93109f646..9db8784f6 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobExecutedFailedProvider.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobExecutedFailedProvider.cs @@ -98,9 +98,9 @@ public class JobExecutedFailedProvider : JobExecutedProvider, ITransientDependen { Title = subject, Id = context.Event.EventData.Key, - Group = context.Action.Paramters.GetOrDefault(nameof(JobInfo.Group)) ?? context.Event.EventData.Group, - Name = context.Action.Paramters.GetOrDefault(nameof(JobInfo.Name)) ?? context.Event.EventData.Name, - Type = context.Action.Paramters.GetOrDefault(nameof(JobInfo.Type)) ?? context.Event.EventData.Type.Name, + Group = context.Event.EventData.Args.GetOrDefault(nameof(JobInfo.Group)) ?? context.Event.EventData.Group, + Name = context.Event.EventData.Args.GetOrDefault(nameof(JobInfo.Name)) ?? context.Event.EventData.Name, + Type = context.Event.EventData.Args.GetOrDefault(nameof(JobInfo.Type)) ?? context.Event.EventData.Type.Name, Triggertime = context.Event.EventData.RunTime.ToString("yyyy-MM-dd HH:mm:ss"), Message = errorMessage, Tenantname = context.Action.Paramters.GetOrDefault(nameof(IMultiTenant.TenantId)), diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl deleted file mode 100644 index 157f51bb5..000000000 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/EmailConfirmed.tpl +++ /dev/null @@ -1,5 +0,0 @@ -
- {{L "EmailConfirmed" model.user}} -

{{model.code}}

- {{L "EmailConfirmedRemarks"}} -
\ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs deleted file mode 100644 index 4d45a8841..000000000 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplateDefinitionProvider.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp.Emailing.Templates; -using Volo.Abp.Localization; -using Volo.Abp.TextTemplating; -using Volo.Abp.Identity.Localization; - -namespace LY.MicroService.IdentityServer.Emailing.Templates -{ - public class IdentityEmailTemplateDefinitionProvider : TemplateDefinitionProvider - { - public override void Define(ITemplateDefinitionContext context) - { - context.Add( - new TemplateDefinition( - IdentityEmailTemplates.EmailConfirmed, - displayName: LocalizableString.Create($"TextTemplate:{IdentityEmailTemplates.EmailConfirmed}"), - layout: StandardEmailTemplates.Layout, - localizationResource: typeof(IdentityResource) - ).WithVirtualFilePath("/LINGYUN/Abp/IdentityServer4/Emailing/Templates/EmailConfirmed.tpl", true) - ); - } - } -} diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs deleted file mode 100644 index 59b8f8cdd..000000000 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Emailing/Templates/IdentityEmailTemplates.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace LY.MicroService.IdentityServer.Emailing.Templates -{ - public static class IdentityEmailTemplates - { - public const string EmailConfirmed = "Abp.Identity.EmailConfirmed"; - } -} diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/LY.MicroService.identityServer.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/LY.MicroService.identityServer.HttpApi.Host.csproj index 715b5fbf8..67e8a0764 100644 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/LY.MicroService.identityServer.HttpApi.Host.csproj +++ b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/LY.MicroService.identityServer.HttpApi.Host.csproj @@ -10,11 +10,6 @@ - - - - - diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/UserSecurityCodeSender.cs b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/UserSecurityCodeSender.cs deleted file mode 100644 index 7d6cd4a5b..000000000 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/UserSecurityCodeSender.cs +++ /dev/null @@ -1,65 +0,0 @@ -using LINGYUN.Abp.Identity; -using LY.MicroService.IdentityServer.Emailing.Templates; -using Microsoft.Extensions.Localization; -using System.Threading; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Emailing; -using Volo.Abp.Identity.Localization; -using Volo.Abp.Sms; -using Volo.Abp.TextTemplating; - -namespace LY.MicroService.IdentityServer; - -public class UserSecurityCodeSender : IUserSecurityCodeSender, ITransientDependency -{ - protected IEmailSender EmailSender { get; } - protected ITemplateRenderer TemplateRenderer { get; } - protected IStringLocalizer Localizer { get; } - - protected ISmsSender SmsSender { get; } - - public UserSecurityCodeSender( - ISmsSender smsSender, - IEmailSender emailSender, - ITemplateRenderer templateRenderer, - IStringLocalizer localizer) - { - SmsSender = smsSender; - EmailSender = emailSender; - TemplateRenderer = templateRenderer; - Localizer = localizer; - } - - public virtual async Task SendEmailConfirmedCodeAsync( - string userName, - string email, - string token, - CancellationToken cancellation = default) - { - var emailContent = await TemplateRenderer.RenderAsync( - IdentityEmailTemplates.EmailConfirmed, - new { user = userName, code = token }); - - await EmailSender.SendAsync( - email, - Localizer["EmailConfirmed"], - emailContent); - } - - public virtual async Task SendPhoneConfirmedCodeAsync( - string phone, - string token, - string template, - CancellationToken cancellation = default) - { - Check.NotNullOrWhiteSpace(template, nameof(template)); - - var smsMessage = new SmsMessage(phone, token); - smsMessage.Properties.Add("code", token); - smsMessage.Properties.Add("TemplateCode", template); - - await SmsSender.SendAsync(smsMessage); - } -} diff --git a/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs b/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs index dd693f9e5..0b6814cd5 100644 --- a/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.Configure.cs @@ -1,5 +1,4 @@ using DotNetCore.CAP; -using LINGYUN.Abp.Account.Localization; using LINGYUN.Abp.IdentityServer.IdentityResources; using LINGYUN.Abp.Localization.CultureMap; using LINGYUN.Abp.Serilog.Enrichers.Application; @@ -180,7 +179,6 @@ public partial class IdentityServerModule options.Resources .Get() - .AddBaseTypes(typeof(AbpAccountResource)) .AddVirtualJson("/Localization/Resources"); }); @@ -209,8 +207,10 @@ public partial class IdentityServerModule Configure(options => { options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; - // 邮件登录地址 + options.Applications["VUE"].RootUrl = configuration["App:VueUrl"]; + options.Applications["MVC"].Urls["EmailVerifyLogin"] = "Account/VerifyCode"; + options.Applications["MVC"].Urls["EmailConfirm"] = "Account/EmailConfirm"; }); } private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false) diff --git a/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs b/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs index 04e632358..8a9f2b367 100644 --- a/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs +++ b/aspnet-core/services/LY.MicroService.identityServer/IdentityServerModule.cs @@ -20,7 +20,6 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Volo.Abp; -using Volo.Abp.Account; using Volo.Abp.Account.Web; using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; @@ -45,7 +44,6 @@ namespace LY.MicroService.IdentityServer; typeof(AbpAspNetCoreSerilogModule), typeof(AbpAccountWebIdentityServerModule), typeof(AbpAccountApplicationModule), - typeof(AbpAccountDomainSharedModule), typeof(AbpAspNetCoreMvcUiBasicThemeModule), typeof(AbpAutofacModule), typeof(AbpCachingStackExchangeRedisModule), diff --git a/aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj b/aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj index 4617d0424..53d9ed700 100644 --- a/aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj +++ b/aspnet-core/services/LY.MicroService.identityServer/LY.MicroService.IdentityServer.csproj @@ -45,7 +45,7 @@ - + diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml new file mode 100644 index 000000000..6f70e6921 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml @@ -0,0 +1,56 @@ +@using Volo.Abp.Account.Localization +@using Volo.Abp.Users +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@using Volo.Abp.Identity.Settings +@using Volo.Abp.Settings +@inject IHtmlLocalizer L +@inject ICurrentUser CurrentUser +@inject ISettingProvider SettingManager +@inject IThemeManager ThemeManager +@model Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo.AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel +@{ + var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true", + StringComparison.OrdinalIgnoreCase); + + var isEmailUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsEmailUpdateEnabled), "true", + StringComparison.OrdinalIgnoreCase); +} + +

@L["PersonalSettings"]


+
+ + + + + + + + + + + + + + + + + + + + + @if (CurrentUser.EmailVerified) + { + + } + else + { + @L["Validation"].Value + } + + + + + + + diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js new file mode 100644 index 000000000..55a88e52e --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js @@ -0,0 +1,28 @@ +(function ($) { + $(function () { + var l = abp.localization.getResource("AbpAccount"); + + $('#PersonalSettingsForm').submit(function (e) { + e.preventDefault(); + + if (!$('#PersonalSettingsForm').valid()) { + return false; + } + + var input = $('#PersonalSettingsForm').serializeFormToObject(); + + volo.abp.account.profile.update(input).then(function (result) { + abp.notify.success(l('PersonalSettingsSaved')); + updateConcurrencyStamp(); + }); + }); + }); + + abp.event.on('passwordChanged', updateConcurrencyStamp); + + function updateConcurrencyStamp(){ + volo.abp.account.profile.get().then(function(profile){ + $("#ConcurrencyStamp").val(profile.concurrencyStamp); + }); + } +})(jQuery); diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml new file mode 100644 index 000000000..eb9fcd2e6 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml @@ -0,0 +1,17 @@ +@page +@inject IHtmlLocalizer L +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.Account.Localization +@model LY.MicroService.IdentityServer.Pages.Account.EmailConfirmModel +@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout +
+
+

@L["EmailConfirm"]

+
+ + + @L["Cancel"] + + +
+
diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml.cs b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml.cs new file mode 100644 index 000000000..44a4ea6ce --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirm.cshtml.cs @@ -0,0 +1,75 @@ +using LINGYUN.Abp.Account; +using Microsoft.AspNetCore.Mvc; +using System; +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Volo.Abp.Account.Localization; +using Volo.Abp.Account.Web.Pages.Account; +using Volo.Abp.Identity; +using Volo.Abp.Validation; + +namespace LY.MicroService.IdentityServer.Pages.Account +{ + public class EmailConfirmModel : AccountPageModel + { + [Required] + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid UserId { get; set; } + + [Required] + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string ConfirmToken { get; set; } + + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string ReturnUrl { get; set; } + + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string ReturnUrlHash { get; set; } + + public IMyProfileAppService MyProfileAppService { get; set; } + + public EmailConfirmModel() + { + LocalizationResourceType = typeof(AccountResource); + } + + public async virtual Task OnPostAsync() + { + try + { + ValidateModel(); + + await MyProfileAppService.ConfirmEmailAsync( + new ConfirmEmailInput + { + UserId = UserId, + ConfirmToken = ConfirmToken, + }); + } + catch (AbpIdentityResultException e) + { + if (!string.IsNullOrWhiteSpace(e.Message)) + { + Alerts.Warning(GetLocalizeExceptionMessage(e)); + return Page(); + } + + throw; + } + catch (AbpValidationException) + { + return Page(); + } + + return RedirectToPage("./ConfirmEmailConfirmation", new + { + returnUrl = ReturnUrl, + returnUrlHash = ReturnUrlHash + }); + } + } +} diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml new file mode 100644 index 000000000..39b14ef6b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml @@ -0,0 +1,13 @@ +@page +@model LY.MicroService.IdentityServer.Pages.Account.EmailConfirmConfirmationModel +@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.Account.Localization +@inject IHtmlLocalizer L +
+
+

@L["EmailConfirm"]

+

@L["YourEmailIsSuccessfullyConfirm"]

+ @L["GoToTheApplication"] +
+
diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml.cs b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml.cs new file mode 100644 index 000000000..592ac73be --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/EmailConfirmConfirmation.cshtml.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp.Account.Web.Pages.Account; + +namespace LY.MicroService.IdentityServer.Pages.Account; + +[AllowAnonymous] +public class EmailConfirmConfirmationModel : AccountPageModel +{ + [BindProperty(SupportsGet = true)] + public string ReturnUrl { get; set; } + + [BindProperty(SupportsGet = true)] + public string ReturnUrlHash { get; set; } + + public virtual Task OnGetAsync() + { + ReturnUrl = GetRedirectUrl(ReturnUrl, ReturnUrlHash); + + return Task.FromResult(Page()); + } +} diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml new file mode 100644 index 000000000..7c4e9e79e --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml @@ -0,0 +1,16 @@ +@page +@inject IHtmlLocalizer L +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.Account.Localization +@model LY.MicroService.IdentityServer.Pages.Account.SendEmailConfirmModel +@inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout +
+
+

@L["EmailConfirm"]

+
+ + @L["Cancel"] + + +
+
diff --git a/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml.cs b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml.cs new file mode 100644 index 000000000..046edbeaa --- /dev/null +++ b/aspnet-core/services/LY.MicroService.identityServer/Pages/Account/SendEmailConfirm.cshtml.cs @@ -0,0 +1,75 @@ +using LINGYUN.Abp.Account; +using Microsoft.AspNetCore.Mvc; +using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; +using Volo.Abp.Account.Localization; +using Volo.Abp.Account.Web.Pages.Account; +using Volo.Abp.Identity; +using Volo.Abp.Validation; + +namespace LY.MicroService.IdentityServer.Pages.Account +{ + public class SendEmailConfirmModel : AccountPageModel + { + [BindProperty(SupportsGet = true)] + public string Email { get; set; } + + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string ReturnUrl { get; set; } + + [HiddenInput] + [BindProperty(SupportsGet = true)] + public string ReturnUrlHash { get; set; } + + public IMyProfileAppService MyProfileAppService { get; set; } + + public SendEmailConfirmModel() + { + LocalizationResourceType = typeof(AccountResource); + } + + public virtual Task OnGetAsync() + { + Email = CurrentUser.Email; + + return Task.FromResult(Page()); + } + + public async virtual Task OnPostAsync() + { + try + { + ValidateModel(); + + await MyProfileAppService.SendEmailConfirmLinkAsync( + new SendEmailConfirmCodeDto + { + Email = Email, + AppName = "MVC", + ReturnUrl = ReturnUrl, + ReturnUrlHash = ReturnUrlHash + }); + } + catch (AbpIdentityResultException e) + { + if (!string.IsNullOrWhiteSpace(e.Message)) + { + Alerts.Warning(GetLocalizeExceptionMessage(e)); + return Page(); + } + + throw; + } + catch (AbpValidationException) + { + return Page(); + } + + return RedirectToPage("~/Account/Manage", new + { + returnUrl = ReturnUrl + }); + } + } +} diff --git a/aspnet-core/services/LY.MicroService.identityServer/appsettings.Development.json b/aspnet-core/services/LY.MicroService.identityServer/appsettings.Development.json index 4dd7e1adc..d9959f072 100644 --- a/aspnet-core/services/LY.MicroService.identityServer/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.identityServer/appsettings.Development.json @@ -10,6 +10,7 @@ "App": { "TrackingEntitiesChanged": true, "SelfUrl": "http://127.0.0.1:44385/", + "VueUrl": "http://127.0.0.1:3100/", "CorsOrigins": "http://127.0.0.1:3100" }, "AppSelfUrl": "http://127.0.0.1:44385/", diff --git a/build/modules.dependencies.json b/build/modules.dependencies.json index 70bfd6eb9..4d01194c0 100644 --- a/build/modules.dependencies.json +++ b/build/modules.dependencies.json @@ -56,6 +56,7 @@ "path": "/../aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Modules/", "depPath": "/../aspnet-core/LocalNuget/netstandard2.0/", "dependencies": [ + "LINGYUN.Abp.Account.Templates.dll", "LINGYUN.Abp.Features.LimitValidation.dll", "LINGYUN.Abp.Features.LimitValidation.Redis.dll", "LINGYUN.Abp.WorkflowManagement.Application.Contracts.dll",