68 changed files with 810 additions and 387 deletions
@ -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 |
namespace LINGYUN.Abp.Account |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule), |
typeof(Volo.Abp.Account.AbpAccountApplicationContractsModule))] |
||||
typeof(AbpAccountDomainSharedModule))] |
|
||||
public class AbpAccountApplicationContractsModule : AbpModule |
public class AbpAccountApplicationContractsModule : AbpModule |
||||
{ |
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpAccountApplicationContractsModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<AccountResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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; } |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
@ -1,16 +1,31 @@ |
|||||
using LINGYUN.Abp.Identity; |
using LINGYUN.Abp.Account.Templates; |
||||
|
using LINGYUN.Abp.Identity; |
||||
using LINGYUN.Abp.WeChat.MiniProgram; |
using LINGYUN.Abp.WeChat.MiniProgram; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.UI.Navigation.Urls; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
namespace LINGYUN.Abp.Account |
namespace LINGYUN.Abp.Account |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(Volo.Abp.Account.AbpAccountApplicationModule), |
typeof(Volo.Abp.Account.AbpAccountApplicationModule), |
||||
typeof(AbpAccountApplicationContractsModule), |
typeof(AbpAccountApplicationContractsModule), |
||||
|
typeof(AbpAccountTemplatesModule), |
||||
typeof(AbpIdentityDomainModule), |
typeof(AbpIdentityDomainModule), |
||||
typeof(AbpWeChatMiniProgramModule))] |
typeof(AbpWeChatMiniProgramModule))] |
||||
public class AbpAccountApplicationModule : AbpModule |
public class AbpAccountApplicationModule : AbpModule |
||||
{ |
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpAccountApplicationModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AppUrlOptions>(options => |
||||
|
{ |
||||
|
options.Applications["MVC"].Urls[AccountUrlNames.EmailConfirm] = "Account/EmailConfirm"; |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace LINGYUN.Abp.Account; |
||||
|
|
||||
|
public static class AccountUrlNames |
||||
|
{ |
||||
|
public const string EmailConfirm = "Abp.Account.EmailConfirm"; |
||||
|
} |
||||
@ -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<AccountResource> 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 |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
); |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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<AbpVirtualFileSystemOptions>(options => |
|
||||
{ |
|
||||
options.FileSets.AddEmbedded<AbpAccountDomainSharedModule>(); |
|
||||
}); |
|
||||
|
|
||||
Configure<AbpLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.Resources |
|
||||
.Add<AbpAccountResource>("en") |
|
||||
.AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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<AbpAccountResource> StringLocalizer { get; } |
|
||||
|
|
||||
public AccountEmailVerifySender( |
|
||||
IEmailSender emailSender, |
|
||||
ITemplateRenderer templateRenderer, |
|
||||
IStringLocalizer<AbpAccountResource> 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 |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
@ -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<AbpAccountResource>( |
|
||||
$"TextTemplate:{AccountEmailTemplates.MailSecurityVerifyLink}"), |
|
||||
layout: StandardEmailTemplates.Layout, |
|
||||
localizationResource: typeof(AbpAccountResource) |
|
||||
).WithVirtualFilePath("/LINGYUN/Abp/Account/Emailing/Templates/MailSecurityVerify.tpl", true) |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
@ -1,8 +0,0 @@ |
|||||
using Volo.Abp.Localization; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Account.Localization; |
|
||||
|
|
||||
[LocalizationResourceName("AbpAccountResource")] |
|
||||
public class AbpAccountResource |
|
||||
{ |
|
||||
} |
|
||||
@ -1,3 +0,0 @@ |
|||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|
||||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|
||||
</Weavers> |
|
||||
@ -1,18 +0,0 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
|
||||
|
|
||||
<Import Project="..\..\..\common.props" /> |
|
||||
|
|
||||
<PropertyGroup> |
|
||||
<TargetFramework>netstandard2.0</TargetFramework> |
|
||||
<RootNamespace /> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<PackageReference Include="Volo.Abp.Identity.Domain" Version="4.4.0" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<Folder Include="Microsoft\AspNetCore\Identity\" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
</Project> |
|
||||
@ -1,9 +0,0 @@ |
|||||
using Volo.Abp.Modularity; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Account |
|
||||
{ |
|
||||
[DependsOn(typeof(AbpAccountDomainSharedModule))] |
|
||||
public class AbpAccountDomainModule : AbpModule |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -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<IdentityUser, Guid> |
|
||||
{ |
|
||||
Task<bool> PhoneNumberHasRegistedAsync(string phoneNumber); |
|
||||
|
|
||||
Task<IdentityUser> FindByPhoneNumberAsync(string phoneNumber); |
|
||||
|
|
||||
Task<Guid?> GetIdByPhoneNumberAsync(string phoneNumber); |
|
||||
} |
|
||||
} |
|
||||
@ -1,25 +1,29 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<Import Project="..\..\..\configureawait.props" /> |
<Import Project="..\..\..\configureawait.props" /> |
||||
<Import Project="..\..\..\common.props" /> |
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
<PropertyGroup> |
<PropertyGroup> |
||||
<TargetFramework>netstandard2.0</TargetFramework> |
<TargetFramework>netstandard2.0</TargetFramework> |
||||
<RootNamespace /> |
<RootNamespace /> |
||||
</PropertyGroup> |
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<None Remove="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" /> |
<None Remove="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" /> |
||||
<None Remove="LINGYUN\Abp\Account\Localization\Resources\*.json" /> |
<None Remove="LINGYUN\Abp\Account\Templates\Localization\Resources\*.json" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<EmbeddedResource Include="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" /> |
<EmbeddedResource Include="LINGYUN\Abp\Account\Emailing\Templates\*.tpl" /> |
||||
<EmbeddedResource Include="LINGYUN\Abp\Account\Localization\Resources\*.json" /> |
<EmbeddedResource Include="LINGYUN\Abp\Account\Templates\Localization\Resources\*.json" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" /> |
<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
</Project> |
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -1,7 +1,11 @@ |
|||||
namespace LY.MicroService.IdentityServer.Emailing.Templates; |
namespace LINGYUN.Abp.Account.Emailing.Templates; |
||||
|
|
||||
public static class AccountEmailTemplates |
public static class AccountEmailTemplates |
||||
{ |
{ |
||||
|
/// <summary>
|
||||
|
/// 邮件地址确认
|
||||
|
/// </summary>
|
||||
|
public const string MailConfirmLink = "Abp.Account.MailConfirmLink"; |
||||
/// <summary>
|
/// <summary>
|
||||
/// 邮件安全验证
|
/// 邮件安全验证
|
||||
/// </summary>
|
/// </summary>
|
||||
@ -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<AccountResource>(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
<h3>{{L "EmailConfirm"}}</h3> |
||||
|
|
||||
|
<p>{{L "EmailConfirmInfo"}}</p> |
||||
|
|
||||
|
<div> |
||||
|
<a href="{{model.link}}">{{L "ConfirmMyEmail"}}</a> |
||||
|
</div> |
||||
@ -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 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -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}<br/><p>Your email security verification code is as follows. Please enter the verification code to proceed to the next step.</p><p>If not operated by you, please ignore this email.</p>", |
||||
|
"MailSecurityVerifyRemarks": "<p>(If it is not in the form of a link, copy the address to the browser address bar for further access)</p><p>Thank you for your visit and have a good time!</p>", |
||||
|
"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." |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"TextTemplate:Abp.Account.MailSecurityVerifyLink": "邮件验证模板", |
||||
|
"TextTemplate:Abp.Account.MailConfirmLink": "邮件确认模板", |
||||
|
"MailSecurityVerify": "邮件安全验证", |
||||
|
"VerifyMyEmailAddress": "您好<br/><p>您此次邮件安全验证码如下,请输入验证码进行下一步操作。</p><p>如非你本人操作,请忽略此邮件。</p>", |
||||
|
"MailSecurityVerifyRemarks": "此邮件为系统所发,请勿直接回复。", |
||||
|
"ClickToValidation": "点击进行验证", |
||||
|
"Validation": "验证", |
||||
|
"EmailConfirm": "邮件确认", |
||||
|
"EmailConfirmInfo": "我们收到了邮件确认请求!如果你发起了此请求,请单击以下链接以确认邮件地址.", |
||||
|
"ConfirmMyEmail": "绑定我的邮箱地址", |
||||
|
"YourEmailIsSuccessfullyConfirm": "您的邮件地址绑定成功." |
||||
|
} |
||||
|
} |
||||
@ -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); |
|
||||
} |
|
||||
} |
|
||||
@ -1,5 +0,0 @@ |
|||||
<div style="position: absolute;"> |
|
||||
<span>{{L "EmailConfirmed" model.user}}</span> |
|
||||
<p style="display:block; padding:0 50px; width: 150px; height:48px; line-height:48px; color:#cc0000; font-size:26px; background:#9c9797; font-weight:bold;">{{model.code}}</p> |
|
||||
<span>{{L "EmailConfirmedRemarks"}}</span> |
|
||||
</div> |
|
||||
@ -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<IdentityResource>($"TextTemplate:{IdentityEmailTemplates.EmailConfirmed}"), |
|
||||
layout: StandardEmailTemplates.Layout, |
|
||||
localizationResource: typeof(IdentityResource) |
|
||||
).WithVirtualFilePath("/LINGYUN/Abp/IdentityServer4/Emailing/Templates/EmailConfirmed.tpl", true) |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
namespace LY.MicroService.IdentityServer.Emailing.Templates |
|
||||
{ |
|
||||
public static class IdentityEmailTemplates |
|
||||
{ |
|
||||
public const string EmailConfirmed = "Abp.Identity.EmailConfirmed"; |
|
||||
} |
|
||||
} |
|
||||
@ -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<IdentityResource> Localizer { get; } |
|
||||
|
|
||||
protected ISmsSender SmsSender { get; } |
|
||||
|
|
||||
public UserSecurityCodeSender( |
|
||||
ISmsSender smsSender, |
|
||||
IEmailSender emailSender, |
|
||||
ITemplateRenderer templateRenderer, |
|
||||
IStringLocalizer<IdentityResource> 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); |
|
||||
} |
|
||||
} |
|
||||
@ -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<AccountResource> 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); |
||||
|
} |
||||
|
|
||||
|
<h4>@L["PersonalSettings"]</h4><hr/> |
||||
|
<form method="post" id="PersonalSettingsForm"> |
||||
|
|
||||
|
<input asp-for="ConcurrencyStamp" /> |
||||
|
|
||||
|
<abp-input asp-for="UserName" readonly="!isUserNameUpdateEnabled"/> |
||||
|
|
||||
|
<abp-row> |
||||
|
<abp-column size-md="_6"> |
||||
|
<abp-input asp-for="Name"/> |
||||
|
</abp-column> |
||||
|
<abp-column size-md="_6"> |
||||
|
<abp-input asp-for="Surname"/> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
|
||||
|
<abp-row> |
||||
|
<abp-column size-md="_9"> |
||||
|
<abp-input asp-for="Email" readonly="!isEmailUpdateEnabled"/> |
||||
|
</abp-column> |
||||
|
<abp-column size-md="_3"> |
||||
|
|
||||
|
@if (CurrentUser.EmailVerified) |
||||
|
{ |
||||
|
<abp-button button-type="Success" text="@L["Confirmed"].Value"/> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<a href="/Account/SendEmailConfirm">@L["Validation"].Value</a> |
||||
|
} |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
|
||||
|
<abp-input asp-for="PhoneNumber"/> |
||||
|
|
||||
|
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/> |
||||
|
</form> |
||||
@ -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); |
||||
@ -0,0 +1,17 @@ |
|||||
|
@page |
||||
|
@inject IHtmlLocalizer<AccountResource> 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 |
||||
|
<div class="card mt-3 shadow-sm rounded"> |
||||
|
<div class="card-body p-5"> |
||||
|
<h4>@L["EmailConfirm"]</h4> |
||||
|
<form method="post"> |
||||
|
<abp-input asp-for="UserId"/> |
||||
|
<abp-input asp-for="ConfirmToken"/> |
||||
|
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a> |
||||
|
<abp-button type="submit" button-type="Primary" text="@L["Submit"].Value"/> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
@ -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<IActionResult> 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 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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<AccountResource> L |
||||
|
<div class="card mt-3 shadow-sm rounded"> |
||||
|
<div class="card-body p-5"> |
||||
|
<h4>@L["EmailConfirm"]</h4> |
||||
|
<p>@L["YourEmailIsSuccessfullyConfirm"]</p> |
||||
|
<a abp-button="Primary" href="@Url.Content(Model.ReturnUrl)">@L["GoToTheApplication"]</a> |
||||
|
</div> |
||||
|
</div> |
||||
@ -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<IActionResult> OnGetAsync() |
||||
|
{ |
||||
|
ReturnUrl = GetRedirectUrl(ReturnUrl, ReturnUrlHash); |
||||
|
|
||||
|
return Task.FromResult<IActionResult>(Page()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
@page |
||||
|
@inject IHtmlLocalizer<AccountResource> 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 |
||||
|
<div class="card mt-3 shadow-sm rounded"> |
||||
|
<div class="card-body p-5"> |
||||
|
<h4>@L["EmailConfirm"]</h4> |
||||
|
<form method="post"> |
||||
|
<abp-input asp-for="Email" readonly="true" /> |
||||
|
<a abp-button="Secondary" asp-page="./Login">@L["Cancel"]</a> |
||||
|
<abp-button type="submit" button-type="Primary" text="@L["ClickToValidation"].Value"/> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
@ -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<IActionResult> OnGetAsync() |
||||
|
{ |
||||
|
Email = CurrentUser.Email; |
||||
|
|
||||
|
return Task.FromResult<IActionResult>(Page()); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<IActionResult> 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 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue