diff --git a/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln b/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln index 355d4ca4f..043bf0498 100644 --- a/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln +++ b/aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln @@ -55,6 +55,30 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{7EE965 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.Authorization", "modules\wechat\LINGYUN.Abp.WeChat.Authorization\LINGYUN.Abp.WeChat.Authorization.csproj", "{F61FA8AA-4248-4F2B-87E0-73CD2C027783}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD48-8F84-4924-BBAF-52080AB32267}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{23536755-4F00-4929-9C5E-D4CABD1CC513}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Emailing", "modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj", "{986B0610-4AC3-499A-AB81-DF15EA06F4D1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{53E90646-2933-4381-9386-6BC6ED16E71A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Authorization", "modules\common\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj", "{720120B4-76F6-4701-9426-611BB8F84515}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Aliyun", "modules\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj", "{D89ECB96-3349-4E77-B884-C18B30289D0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{39B77454-52AB-43BE-AB33-7680719415A6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{99B60A42-29DA-4D91-9255-B90F53BC6D6E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.DbFinder", "modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj", "{70C4FA43-0526-48E3-B852-A21395502604}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,6 +165,46 @@ Global {F61FA8AA-4248-4F2B-87E0-73CD2C027783}.Debug|Any CPU.Build.0 = Debug|Any CPU {F61FA8AA-4248-4F2B-87E0-73CD2C027783}.Release|Any CPU.ActiveCfg = Release|Any CPU {F61FA8AA-4248-4F2B-87E0-73CD2C027783}.Release|Any CPU.Build.0 = Release|Any CPU + {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.Build.0 = Release|Any CPU + {23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.Build.0 = Release|Any CPU + {80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.Build.0 = Release|Any CPU + {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.Build.0 = Release|Any CPU + {53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.Build.0 = Release|Any CPU + {720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.Build.0 = Debug|Any CPU + {720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.ActiveCfg = Release|Any CPU + {720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.Build.0 = Release|Any CPU + {D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.Build.0 = Release|Any CPU + {39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.Build.0 = Release|Any CPU + {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.Build.0 = Release|Any CPU + {70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -170,6 +234,18 @@ Global {177B6CD3-1690-416D-9B37-A821093DEFBD} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {7EE9651C-17B0-4343-A2ED-92439F8C9019} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {F61FA8AA-4248-4F2B-87E0-73CD2C027783} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} + {FD2DDD48-8F84-4924-BBAF-52080AB32267} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} + {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {23536755-4F00-4929-9C5E-D4CABD1CC513} = {BD964040-90B2-4179-A5EB-5830F5C7E073} + {80A418EB-6149-4684-80EF-D8574B91FE2B} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {986B0610-4AC3-499A-AB81-DF15EA06F4D1} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {53E90646-2933-4381-9386-6BC6ED16E71A} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} + {720120B4-76F6-4701-9426-611BB8F84515} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {D89ECB96-3349-4E77-B884-C18B30289D0D} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {39B77454-52AB-43BE-AB33-7680719415A6} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} + {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} + {99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} + {70C4FA43-0526-48E3-B852-A21395502604} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228} 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 c1f648440..938ceaa01 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 @@ -48,14 +48,14 @@ namespace LINGYUN.Abp.Account var wehchatOpenId = await WeChatOpenIdFinder.FindAsync(input.Code); - var user = await UserManager.FindByLoginAsync("WeChat", wehchatOpenId.OpenId); + var user = await UserManager.FindByLoginAsync(AbpWeChatAuthorizationConsts.ProviderKey, wehchatOpenId.OpenId); if (user != null) { // 应该要抛出微信号已注册异常,而不是直接返回注册用户数据,否则造成用户信息泄露 throw new UserFriendlyException(L["DuplicateWeChat"]); } - var userName = input.UserName ?? wehchatOpenId.OpenId; - var userEmail = input.EmailAddress ?? $"{userName}@default.io";//如果邮件地址不验证,随意写入一个 + var userName = input.UserName ?? "wx-" + wehchatOpenId.OpenId; + var userEmail = input.EmailAddress ?? $"{userName}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个 user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id) { @@ -65,7 +65,7 @@ namespace LINGYUN.Abp.Account (await UserManager.AddDefaultRolesAsync(user)).CheckErrors(); - var userLogin = new UserLoginInfo("WeChat", wehchatOpenId.OpenId, "微信认证登录"); + var userLogin = new UserLoginInfo(AbpWeChatAuthorizationConsts.ProviderKey, wehchatOpenId.OpenId, AbpWeChatAuthorizationConsts.DisplayName); (await UserManager.AddLoginAsync(user, userLogin)).CheckErrors(); return ObjectMapper.Map(user); @@ -101,7 +101,7 @@ namespace LINGYUN.Abp.Account // } //} - var userEmail = input.EmailAddress ?? $"{input.PhoneNumber}@default.io";//如果邮件地址不验证,随意写入一个 + var userEmail = input.EmailAddress ?? $"{input.PhoneNumber}@{CurrentTenant.Name ?? "default"}.io";//如果邮件地址不验证,随意写入一个 var userName = input.UserName ?? input.PhoneNumber; var user = new IdentityUser(GuidGenerator.Create(), userName, userEmail, CurrentTenant.Id) { @@ -173,6 +173,8 @@ namespace LINGYUN.Abp.Account /// public virtual async Task VerifyPhoneNumberAsync(VerifyDto input) { + // TODO: 借用TOTP算法生成6位动态验证码 + var verifyCodeExpiration = await SettingProvider.GetAsync(AccountSettingNames.PhoneVerifyCodeExpiration); var phoneVerifyCacheKey = NormalizeCacheKey(input.PhoneNumber); var verifyCacheItem = await Cache.GetAsync(phoneVerifyCacheKey); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Settings/Volo/Abp/Settings/ISettingProviderExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Settings/Volo/Abp/Settings/ISettingProviderExtensions.cs index fda1463bb..2094283bc 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Settings/Volo/Abp/Settings/ISettingProviderExtensions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Settings/Volo/Abp/Settings/ISettingProviderExtensions.cs @@ -24,5 +24,7 @@ namespace Volo.Abp.Settings } return value; } + + } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN.Abp.Identity.Application.Contracts.csproj b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN.Abp.Identity.Application.Contracts.csproj index 410ab8f28..cb8da47c5 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN.Abp.Identity.Application.Contracts.csproj +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN.Abp.Identity.Application.Contracts.csproj @@ -8,17 +8,11 @@ - - - - - - - + - + diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/AbpIdentityApplicationContractsModule.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/AbpIdentityApplicationContractsModule.cs index d249bc291..1f08d07cb 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/AbpIdentityApplicationContractsModule.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/AbpIdentityApplicationContractsModule.cs @@ -1,32 +1,16 @@ using Volo.Abp.Application; using Volo.Abp.Authorization; -using Volo.Abp.Identity.Localization; -using Volo.Abp.Localization; using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileSystem; namespace LINGYUN.Abp.Identity { [DependsOn( typeof(Volo.Abp.Identity.AbpIdentityApplicationContractsModule), + typeof(AbpIdentityDomainSharedModule), typeof(AbpAuthorizationModule), typeof(AbpDddApplicationModule) )] public class AbpIdentityApplicationContractsModule : AbpModule { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.FileSets.AddEmbedded(); - }); - - Configure(options => - { - options.Resources - .Get() - .AddVirtualJson("/LINGYUN/Abp/Identity/Localization"); - }); - } } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangeEmailAddressInput.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangeEmailAddressInput.cs new file mode 100644 index 000000000..10b873607 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangeEmailAddressInput.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Auditing; +using Volo.Abp.Identity; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.Identity +{ + public class ChangeEmailAddressInput + { + /// + /// 新邮件地址 + /// + [Required] + [EmailAddress] + [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))] + public string NewEmailAddress { get; set; } + /// + /// 安全验证码 + /// + [DisableAuditing] + [StringLength(6)] + public string Code { get; set; } + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangePhoneNumberInput.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangePhoneNumberInput.cs new file mode 100644 index 000000000..4d432971c --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/ChangePhoneNumberInput.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Auditing; +using Volo.Abp.Identity; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.Identity +{ + public class ChangePhoneNumberInput + { + /// + /// 新手机号 + /// + [Required] + [Phone] + [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPhoneNumberLength))] + public string NewPhoneNumber { get; set; } + /// + /// 安全验证码 + /// + [DisableAuditing] + [StringLength(6)] + public string Code { get; set; } + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/IdentityUserTwoFactorEnabledDto.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/IdentityUserTwoFactorEnabledDto.cs new file mode 100644 index 000000000..0450be9f6 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Dto/IdentityUserTwoFactorEnabledDto.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.Identity +{ + public class IdentityUserTwoFactorEnabledDto + { + public bool Enabled { get; set; } + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IIdentityUserAppService.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IIdentityUserAppService.cs index df9159134..204f10fab 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IIdentityUserAppService.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IIdentityUserAppService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; +using Volo.Abp.Identity; namespace LINGYUN.Abp.Identity { @@ -30,5 +31,19 @@ namespace LINGYUN.Abp.Identity #endregion + /// + /// 变更用户双因素验证选项 + /// + /// + /// + /// + Task ChangeTwoFactorEnabledAsync(Guid id, IdentityUserTwoFactorEnabledDto input); + /// + /// 变更用户密码 + /// + /// + /// + /// + Task ChangePasswordAsync(Guid id, ChangePasswordInput input); } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IMyProfileAppService.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IMyProfileAppService.cs new file mode 100644 index 000000000..f600f2a64 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IMyProfileAppService.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.Identity +{ + public interface IMyProfileAppService : IApplicationService + { + /// + /// 变更双因素验证 + /// + /// + /// + Task ChangeTwoFactorEnabledAsync(IdentityUserTwoFactorEnabledDto input); + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IdentityErrorCodes.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IdentityErrorCodes.cs deleted file mode 100644 index df419bf9a..000000000 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/IdentityErrorCodes.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace LINGYUN.Abp.Identity -{ - public class IdentityErrorCodes - { - public const string StaticClaimTypeChange = "Volo.Abp.Identity:020005"; - public const string StaticClaimTypeDeletion = "Volo.Abp.Identity:020006"; - } -} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN.Abp.Identity.Application.csproj b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN.Abp.Identity.Application.csproj index 528fa5588..92b8149ef 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN.Abp.Identity.Application.csproj +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN.Abp.Identity.Application.csproj @@ -1,4 +1,4 @@ - + diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/AbpIdentityApplicationModule.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/AbpIdentityApplicationModule.cs index 3da3d702e..c7de0f249 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/AbpIdentityApplicationModule.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/AbpIdentityApplicationModule.cs @@ -6,7 +6,8 @@ namespace LINGYUN.Abp.Identity { [DependsOn( typeof(Volo.Abp.Identity.AbpIdentityApplicationModule), - typeof(AbpIdentityApplicationContractsModule))] + typeof(AbpIdentityApplicationContractsModule), + typeof(AbpIdentityDomainModule))] public class AbpIdentityApplicationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/IdentityUserAppService.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/IdentityUserAppService.cs index a84bd9b4a..2c69f05e6 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/IdentityUserAppService.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/IdentityUserAppService.cs @@ -102,5 +102,35 @@ namespace LINGYUN.Abp.Identity } #endregion + + [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Update)] + public virtual async Task ChangePasswordAsync(Guid id, ChangePasswordInput input) + { + var user = await UserManager.GetByIdAsync(id); + + if (user.IsExternal) + { + throw new BusinessException(code: Volo.Abp.Identity.IdentityErrorCodes.ExternalUserPasswordChange); + } + + if (user.PasswordHash == null) + { + (await UserManager.AddPasswordAsync(user, input.NewPassword)).CheckErrors(); + + return; + } + + (await UserManager.ChangePasswordAsync(user, input.CurrentPassword, input.NewPassword)).CheckErrors(); + } + + [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Update)] + public virtual async Task ChangeTwoFactorEnabledAsync(Guid id, IdentityUserTwoFactorEnabledDto input) + { + var user = await UserManager.GetByIdAsync(id); + + (await UserManager.SetTwoFactorEnabledWithAccountConfirmedAsync(user, input.Enabled)).CheckErrors(); + + await CurrentUnitOfWork.SaveChangesAsync(); + } } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/MyProfileAppService.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/MyProfileAppService.cs new file mode 100644 index 000000000..41f8fefea --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application/LINGYUN/Abp/Identity/MyProfileAppService.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using System.Threading.Tasks; +using Volo.Abp.Identity; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.Identity +{ + [Authorize] + public class MyProfileAppService : IdentityAppServiceBase, IMyProfileAppService + { + protected IdentityUserManager UserManager { get; } + protected IIdentityUserRepository UserRepository { get; } + + public MyProfileAppService( + IdentityUserManager userManager, + IIdentityUserRepository userRepository) + { + UserManager = userManager; + UserRepository = userRepository; + } + + public virtual async Task ChangeTwoFactorEnabledAsync(IdentityUserTwoFactorEnabledDto input) + { + var user = await UserManager.GetByIdAsync(CurrentUser.GetId()); + + (await UserManager.SetTwoFactorEnabledWithAccountConfirmedAsync(user, input.Enabled)).CheckErrors(); + + await CurrentUnitOfWork.SaveChangesAsync(); + } + } +} 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 new file mode 100644 index 000000000..bed1350ca --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN.Abp.Identity.Domain.Shared.csproj @@ -0,0 +1,24 @@ + + + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/AbpIdentityDomainSharedModule.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/AbpIdentityDomainSharedModule.cs new file mode 100644 index 000000000..2cd968b9c --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/AbpIdentityDomainSharedModule.cs @@ -0,0 +1,26 @@ +using Volo.Abp.Identity.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.Identity +{ + [DependsOn(typeof(Volo.Abp.Identity.AbpIdentityDomainSharedModule))] + public class AbpIdentityDomainSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/Identity/Localization"); + }); + } + } +} 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 new file mode 100644 index 000000000..b79a7c77e --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityErrorCodes.cs @@ -0,0 +1,18 @@ +namespace LINGYUN.Abp.Identity +{ + public class IdentityErrorCodes + { + /// + /// 无法变更静态声明类型 + /// + public const string StaticClaimTypeChange = "Volo.Abp.Identity:020005"; + /// + /// 无法删除静态声明类型 + /// + public const string StaticClaimTypeDeletion = "Volo.Abp.Identity:020006"; + /// + /// 手机号码已被使用 + /// + public const string DuplicatePhoneNumber = "Volo.Abp.Identity:020007"; + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityException.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityException.cs new file mode 100644 index 000000000..97df568a1 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/IdentityException.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Runtime.Serialization; +using Volo.Abp; +using Volo.Abp.Logging; + +namespace LINGYUN.Abp.Identity +{ + public class IdentityException : BusinessException, IExceptionWithSelfLogging + { + public IdentityException( + SerializationInfo serializationInfo, + StreamingContext context) + : base(serializationInfo, context) + { + } + + public IdentityException( + string code = null, + string message = null, + string details = null, + Exception innerException = null, + LogLevel logLevel = LogLevel.Warning) + : base(code, message, details, innerException, logLevel) + { + } + + public virtual void Log(ILogger logger) + { + logger.Log( + LogLevel, + "An id error occurred,code: {0}, Message: {1}, Details: {2}", + Code, + Message, + Details); + } + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/en.json b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json similarity index 96% rename from aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/en.json rename to aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json index 33568e7c2..f74341346 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/en.json +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/en.json @@ -40,6 +40,7 @@ "IdentityClaim:Description": "Description", "IdentityClaim:ValueType": "Value type", "Volo.Abp.Identity:020005": "The static claim type cannot be changed!", - "Volo.Abp.Identity:020006": "Unable to delete static claim type!" + "Volo.Abp.Identity:020006": "Unable to delete static claim type!", + "Volo.Abp.Identity:020007": "The phone number is already tied to another user!" } } \ No newline at end of file diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/zh-Hans.json b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json similarity index 96% rename from aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/zh-Hans.json rename to aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json index c068c63b4..86bffcc92 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Application.Contracts/LINGYUN/Abp/Identity/Localization/zh-Hans.json +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Localization/zh-Hans.json @@ -41,6 +41,7 @@ "IdentityClaim:Description": "描述", "IdentityClaim:ValueType": "值类型", "Volo.Abp.Identity:020005": "无法变更静态声明类型!", - "Volo.Abp.Identity:020006": "无法删除静态声明类型!" + "Volo.Abp.Identity:020006": "无法删除静态声明类型!", + "Volo.Abp.Identity:020007": "手机号码已被其他用户绑定!" } } \ No newline at end of file diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingDefinitionProvider.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingDefinitionProvider.cs new file mode 100644 index 000000000..5951a8e07 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingDefinitionProvider.cs @@ -0,0 +1,18 @@ +using Volo.Abp.Identity.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.Identity.Settings +{ + public class IdentitySettingDefinitionProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} 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 new file mode 100644 index 000000000..ee74f105d --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain.Shared/LINGYUN/Abp/Identity/Settings/IdentitySettingNames.cs @@ -0,0 +1,6 @@ +namespace LINGYUN.Abp.Identity.Settings +{ + public static class IdentitySettingNames + { + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN.Abp.Identity.Domain.csproj b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN.Abp.Identity.Domain.csproj index 56fc090c6..42a7d33a4 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN.Abp.Identity.Domain.csproj +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN.Abp.Identity.Domain.csproj @@ -1,4 +1,4 @@ - + @@ -11,4 +11,8 @@ + + + + diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs index 9004ff3f5..c5e114d30 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/AbpIdentityDomainModule.cs @@ -2,7 +2,9 @@ namespace LINGYUN.Abp.Identity { - [DependsOn(typeof(Volo.Abp.Identity.AbpIdentityDomainModule))] + [DependsOn( + typeof(AbpIdentityDomainSharedModule), + typeof(Volo.Abp.Identity.AbpIdentityDomainModule))] public class AbpIdentityDomainModule : AbpModule { } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/IdentityUserManagerExtensions.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/IdentityUserManagerExtensions.cs new file mode 100644 index 000000000..42a79f545 --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/IdentityUserManagerExtensions.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Identity; + +namespace Microsoft.AspNetCore.Identity +{ + public static class IdentityUserManagerExtensions + { + public static async Task SetTwoFactorEnabledWithAccountConfirmedAsync( + [NotNull] this UserManager userManager, + [NotNull] TUser user, + bool enabled) + where TUser : class + { + Check.NotNull(userManager, nameof(userManager)); + Check.NotNull(user, nameof(user)); + + if (enabled) + { + var phoneNumberConfirmed = await userManager.IsPhoneNumberConfirmedAsync(user); + var emailAddressConfirmed = await userManager.IsEmailConfirmedAsync(user); + // 如果其中一个安全选项未确认,无法启用双因素验证 + if (!phoneNumberConfirmed && !emailAddressConfirmed) + { + // TODO: 返回标准的 IdentityResult + //var error = new IdentityError(); + //return IdentityResult.Failed(error); + + throw new LINGYUN.Abp.Identity.IdentityException( + IdentityErrorCodes.CanNotChangeTwoFactor, + details: phoneNumberConfirmed ? "phone number not confirmed" : "email address not confirmed"); + } + } + + return await userManager.SetTwoFactorEnabledAsync(user, enabled); + } + } +} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/IdentityUserController.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/IdentityUserController.cs index f58862868..4b021748b 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/IdentityUserController.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/IdentityUserController.cs @@ -77,5 +77,19 @@ namespace LINGYUN.Abp.Identity } #endregion + + [HttpPut] //TODO: Post? + [Route("change-password")] + public virtual async Task ChangePasswordAsync(Guid id, ChangePasswordInput input) + { + await UserAppService.ChangePasswordAsync(id, input); + } + + [HttpPut] + [Route("change-two-factor")] + public virtual async Task ChangeTwoFactorEnabledAsync(Guid id, IdentityUserTwoFactorEnabledDto input) + { + await UserAppService.ChangeTwoFactorEnabledAsync(id, input); + } } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/MyProfileController.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/MyProfileController.cs new file mode 100644 index 000000000..1ba29ec1b --- /dev/null +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.HttpApi/LINGYUN/Abp/Identity/MyProfileController.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Identity; + +namespace LINGYUN.Abp.Identity +{ + [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] + [Area("identity")] + [ControllerName("Profile")] + [Route("/api/identity/my-profile")] + public class MyProfileController : AbpController, IMyProfileAppService + { + protected IMyProfileAppService MyProfileAppService { get; } + + public MyProfileController( + IMyProfileAppService myProfileAppService) + { + MyProfileAppService = myProfileAppService; + } + + [HttpPut] + [Route("change-two-factor")] + public virtual async Task ChangeTwoFactorEnabledAsync(IdentityUserTwoFactorEnabledDto input) + { + await MyProfileAppService.ChangeTwoFactorEnabledAsync(input); + } + } +}