82 changed files with 3145 additions and 8 deletions
			
			
		| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,18 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\Sanhe.Abp.Identity.Domain.Shared\Sanhe.Abp.Identity.Domain.Shared.csproj" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,15 @@ | ||||
| using Volo.Abp.Authorization; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn( | ||||
|         typeof(Volo.Abp.Identity.AbpIdentityApplicationContractsModule), | ||||
|         typeof(AbpIdentityDomainSharedModule), | ||||
|         typeof(AbpAuthorizationModule) | ||||
|         )] | ||||
|     public class AbpIdentityApplicationContractsModule : AbpModule | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| using System; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimDto : EntityDto<Guid> | ||||
|     { | ||||
|         public string ClaimType { get; set; } | ||||
| 
 | ||||
|         public string ClaimValue { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimTypeCreateDto : IdentityClaimTypeCreateOrUpdateBaseDto | ||||
|     { | ||||
|         [Required] | ||||
|         [DynamicStringLength(typeof(IdentityClaimTypeConsts), nameof(IdentityClaimTypeConsts.MaxNameLength))] | ||||
|         public string Name { get; set; } | ||||
| 
 | ||||
|         public bool IsStatic { get; set; } | ||||
| 
 | ||||
|         public IdentityClaimValueType ValueType { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.ObjectExtending; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimTypeCreateOrUpdateBaseDto : ExtensibleObject | ||||
|     { | ||||
|         public bool Required { get; set; } | ||||
| 
 | ||||
|         [DynamicStringLength(typeof(IdentityClaimTypeConsts), nameof(IdentityClaimTypeConsts.MaxRegexLength))] | ||||
|         public string Regex { get; set; } | ||||
| 
 | ||||
|         [DynamicStringLength(typeof(IdentityClaimTypeConsts), nameof(IdentityClaimTypeConsts.MaxRegexDescriptionLength))] | ||||
|         public string RegexDescription { get; set; } | ||||
| 
 | ||||
|         [DynamicStringLength(typeof(IdentityClaimTypeConsts), nameof(IdentityClaimTypeConsts.MaxDescriptionLength))] | ||||
|         public string Description { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| using System; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimTypeDto : ExtensibleEntityDto<Guid> | ||||
|     { | ||||
|         public string Name { get; set; } | ||||
| 
 | ||||
|         public bool Required { get; set; } | ||||
| 
 | ||||
|         public bool IsStatic { get; set; } | ||||
| 
 | ||||
|         public string Regex { get; set; } | ||||
| 
 | ||||
|         public string RegexDescription { get; set; } | ||||
| 
 | ||||
|         public string Description { get; set; } | ||||
| 
 | ||||
|         public IdentityClaimValueType ValueType { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimTypeGetByPagedDto : PagedAndSortedResultRequestDto | ||||
|     { | ||||
|         public string Filter { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityClaimTypeUpdateDto : IdentityClaimTypeCreateOrUpdateBaseDto | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| using System; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityRoleAddOrRemoveOrganizationUnitDto | ||||
|     { | ||||
|         [Required] | ||||
|         public Guid[] OrganizationUnitIds { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityRoleClaimCreateDto | ||||
|     { | ||||
|         [Required] | ||||
|         [DynamicMaxLength(typeof(IdentityRoleClaimConsts), nameof(IdentityRoleClaimConsts.MaxClaimTypeLength))] | ||||
|         public string ClaimType { get; set; } | ||||
| 
 | ||||
|         [Required] | ||||
|         [DynamicMaxLength(typeof(IdentityRoleClaimConsts), nameof(IdentityRoleClaimConsts.MaxClaimValueLength))] | ||||
|         public string ClaimValue { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityRoleClaimDeleteDto : IdentityRoleClaimCreateDto | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityRoleClaimUpdateDto : IdentityRoleClaimCreateDto | ||||
|     { | ||||
|         [Required] | ||||
|         [DynamicMaxLength(typeof(IdentityRoleClaimConsts), nameof(IdentityRoleClaimConsts.MaxClaimValueLength))] | ||||
|         public string NewClaimValue { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityUserClaimCreateDto : IdentityUserClaimCreateOrUpdateDto | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public abstract class IdentityUserClaimCreateOrUpdateDto | ||||
|     { | ||||
|         [Required] | ||||
|         [DynamicMaxLength(typeof(IdentityUserClaimConsts), nameof(IdentityUserClaimConsts.MaxClaimTypeLength))] | ||||
|         public string ClaimType { get; set; } | ||||
| 
 | ||||
|         [DynamicMaxLength(typeof(IdentityUserClaimConsts), nameof(IdentityUserClaimConsts.MaxClaimValueLength))] | ||||
|         public string ClaimValue { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityUserClaimDeleteDto : IdentityUserClaimCreateDto | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityUserClaimUpdateDto : IdentityUserClaimCreateOrUpdateDto | ||||
|     { | ||||
|         [DynamicMaxLength(typeof(IdentityUserClaimConsts), nameof(IdentityUserClaimConsts.MaxClaimValueLength))] | ||||
|         public string NewClaimValue { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| using System; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class IdentityUserOrganizationUnitUpdateDto | ||||
|     { | ||||
|         [Required] | ||||
|         public Guid[] OrganizationUnitIds { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitAddRoleDto | ||||
|     { | ||||
|         [Required] | ||||
|         public List<Guid> RoleIds { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitAddUserDto | ||||
|     { | ||||
|         [Required] | ||||
|         public List<Guid> UserIds { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| using System; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.ObjectExtending; | ||||
| using Volo.Abp.Validation; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitCreateDto : ExtensibleObject | ||||
|     { | ||||
|         [Required] | ||||
|         [DynamicStringLength(typeof(OrganizationUnitConsts), nameof(OrganizationUnitConsts.MaxDisplayNameLength))] | ||||
|         public string DisplayName { get; set; } | ||||
| 
 | ||||
|         public Guid? ParentId { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,12 @@ | ||||
| using System; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitDto : ExtensibleAuditedEntityDto<Guid> | ||||
|     { | ||||
|         public Guid? ParentId { get; set; } | ||||
|         public string Code { get; set; } | ||||
|         public string DisplayName { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitGetByPagedDto : PagedAndSortedResultRequestDto | ||||
|     { | ||||
|         public string Filter { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| using System; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitGetChildrenDto : IEntityDto<Guid> | ||||
|     { | ||||
|         [Required] | ||||
|         public Guid Id { get; set; } | ||||
|         public bool Recursive { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitGetUnaddedRoleByPagedDto : PagedAndSortedResultRequestDto | ||||
|     { | ||||
| 
 | ||||
|         public string Filter { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| using Volo.Abp.Application.Dtos; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitGetUnaddedUserByPagedDto : PagedAndSortedResultRequestDto | ||||
|     { | ||||
|         public string Filter { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| using System; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitMoveDto | ||||
|     { | ||||
|         public Guid? ParentId { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| using Volo.Abp.ObjectExtending; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class OrganizationUnitUpdateDto : ExtensibleObject | ||||
|     { | ||||
|         public string DisplayName { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| namespace Sanhe.Abp.Identity.Dto | ||||
| { | ||||
|     public class TwoFactorEnabledDto | ||||
|     { | ||||
|         public bool Enabled { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Application.Services; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IIdentityClaimTypeAppService : ICrudAppService< | ||||
|         IdentityClaimTypeDto, | ||||
|         Guid, | ||||
|         IdentityClaimTypeGetByPagedDto, | ||||
|         IdentityClaimTypeCreateDto, | ||||
|         IdentityClaimTypeUpdateDto> | ||||
|     { | ||||
|         Task<ListResultDto<IdentityClaimTypeDto>> GetAllListAsync(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Application.Services; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IIdentityRoleAppService : IApplicationService | ||||
|     { | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
|         Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id); | ||||
| 
 | ||||
|         Task SetOrganizationUnitsAsync(Guid id, IdentityRoleAddOrRemoveOrganizationUnitDto input); | ||||
| 
 | ||||
|         Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId); | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region ClaimType | ||||
| 
 | ||||
|         Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id); | ||||
| 
 | ||||
|         Task AddClaimAsync(Guid id, IdentityRoleClaimCreateDto input); | ||||
| 
 | ||||
|         Task UpdateClaimAsync(Guid id, IdentityRoleClaimUpdateDto input); | ||||
| 
 | ||||
|         Task DeleteClaimAsync(Guid id, IdentityRoleClaimDeleteDto input); | ||||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Application.Services; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IIdentityUserAppService : IApplicationService | ||||
|     { | ||||
| 
 | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
|         Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id); | ||||
| 
 | ||||
|         Task SetOrganizationUnitsAsync(Guid id, IdentityUserOrganizationUnitUpdateDto input); | ||||
| 
 | ||||
|         Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId); | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region ClaimType | ||||
| 
 | ||||
|         Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id); | ||||
| 
 | ||||
|         Task AddClaimAsync(Guid id, IdentityUserClaimCreateDto input); | ||||
| 
 | ||||
|         Task UpdateClaimAsync(Guid id, IdentityUserClaimUpdateDto input); | ||||
| 
 | ||||
|         Task DeleteClaimAsync(Guid id, IdentityUserClaimDeleteDto input); | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 变更用户双因素验证选项 | ||||
|         /// </summary> | ||||
|         /// <param name="id"></param> | ||||
|         /// <param name="input"></param> | ||||
|         /// <returns></returns> | ||||
|         Task ChangeTwoFactorEnabledAsync(Guid id, TwoFactorEnabledDto input); | ||||
|         /// <summary> | ||||
|         /// 变更用户密码 | ||||
|         /// </summary> | ||||
|         /// <param name="id"></param> | ||||
|         /// <param name="input"></param> | ||||
|         /// <returns></returns> | ||||
|         /// TODO: 移除api,改为重置用户密码 | ||||
|         // Task ChangePasswordAsync(Guid id, ChangePasswordInput input); | ||||
|         /// <summary> | ||||
|         /// 锁定 | ||||
|         /// </summary> | ||||
|         /// <param name="id"></param> | ||||
|         /// <param name="seconds">锁定时长</param> | ||||
|         /// <returns></returns> | ||||
|         Task LockAsync(Guid id, int seconds); | ||||
|         /// <summary> | ||||
|         /// 解除锁定 | ||||
|         /// </summary> | ||||
|         /// <param name="id"></param> | ||||
|         /// <returns></returns> | ||||
|         Task UnLockAsync(Guid id); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,41 @@ | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Application.Services; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IOrganizationUnitAppService : ICrudAppService< | ||||
|         OrganizationUnitDto, | ||||
|         Guid, | ||||
|         OrganizationUnitGetByPagedDto, | ||||
|         OrganizationUnitCreateDto, | ||||
|         OrganizationUnitUpdateDto> | ||||
|     { | ||||
|         Task<ListResultDto<OrganizationUnitDto>> GetAllListAsync(); | ||||
| 
 | ||||
|         Task<OrganizationUnitDto> GetLastChildOrNullAsync(Guid? parentId); | ||||
| 
 | ||||
|         Task MoveAsync(Guid id, OrganizationUnitMoveDto input); | ||||
| 
 | ||||
|         Task<ListResultDto<OrganizationUnitDto>> GetRootAsync(); | ||||
| 
 | ||||
|         Task<ListResultDto<OrganizationUnitDto>> FindChildrenAsync(OrganizationUnitGetChildrenDto input); | ||||
| 
 | ||||
|         Task<ListResultDto<string>> GetRoleNamesAsync(Guid id); | ||||
| 
 | ||||
|         Task<PagedResultDto<IdentityRoleDto>> GetUnaddedRolesAsync(Guid id, OrganizationUnitGetUnaddedRoleByPagedDto input); | ||||
| 
 | ||||
|         Task<PagedResultDto<IdentityRoleDto>> GetRolesAsync(Guid id, PagedAndSortedResultRequestDto input); | ||||
| 
 | ||||
|         Task AddRolesAsync(Guid id, OrganizationUnitAddRoleDto input); | ||||
| 
 | ||||
|         Task<PagedResultDto<IdentityUserDto>> GetUnaddedUsersAsync(Guid id, OrganizationUnitGetUnaddedUserByPagedDto input); | ||||
| 
 | ||||
|         Task<PagedResultDto<IdentityUserDto>> GetUsersAsync(Guid id, GetIdentityUsersInput input); | ||||
| 
 | ||||
|         Task AddUsersAsync(Guid id, OrganizationUnitAddUserDto input); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,50 @@ | ||||
| using Volo.Abp.Authorization.Permissions; | ||||
| using Volo.Abp.Identity.Localization; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.MultiTenancy; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public class IdentityPermissionDefinitionProvider : PermissionDefinitionProvider | ||||
|     { | ||||
|         public override void Define(IPermissionDefinitionContext context) | ||||
|         { | ||||
|             var identityGroup = context.GetGroupOrNull(Volo.Abp.Identity.IdentityPermissions.GroupName); | ||||
|             if (identityGroup != null) | ||||
|             { | ||||
|                 var userPermission = identityGroup.GetPermissionOrNull(Volo.Abp.Identity.IdentityPermissions.Users.Default); | ||||
|                 if (userPermission != null) | ||||
|                 { | ||||
|                     userPermission.AddChild(IdentityPermissions.Users.ManageClaims, L("Permission:ManageClaims")); | ||||
|                     userPermission.AddChild(IdentityPermissions.Users.ManageOrganizationUnits, L("Permission:ManageOrganizationUnits")); | ||||
|                 } | ||||
| 
 | ||||
|                 var rolePermission = identityGroup.GetPermissionOrNull(Volo.Abp.Identity.IdentityPermissions.Roles.Default); | ||||
|                 if (rolePermission != null) | ||||
|                 { | ||||
|                     rolePermission.AddChild(IdentityPermissions.Roles.ManageClaims, L("Permission:ManageClaims")); | ||||
|                     rolePermission.AddChild(IdentityPermissions.Roles.ManageOrganizationUnits, L("Permission:ManageOrganizationUnits")); | ||||
|                 } | ||||
| 
 | ||||
|                 var organizationUnitPermission = identityGroup.AddPermission(IdentityPermissions.OrganizationUnits.Default, L("Permission:OrganizationUnitManagement")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.Create, L("Permission:Create")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.Update, L("Permission:Edit")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.Delete, L("Permission:Delete")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.ManageRoles, L("Permission:ManageRoles")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.ManageUsers, L("Permission:ManageUsers")); | ||||
|                 organizationUnitPermission.AddChild(IdentityPermissions.OrganizationUnits.ManagePermissions, L("Permission:ChangePermissions")); | ||||
| 
 | ||||
|                 // 2020-10-23 修复Bug 租户用户也必须能查询自定义的声明, 管理权限只能为主机 | ||||
|                 var identityClaimType = identityGroup.AddPermission(IdentityPermissions.IdentityClaimType.Default, L("Permission:IdentityClaimTypeManagement")); | ||||
|                 identityClaimType.AddChild(IdentityPermissions.IdentityClaimType.Create, L("Permission:Create"), MultiTenancySides.Host); | ||||
|                 identityClaimType.AddChild(IdentityPermissions.IdentityClaimType.Update, L("Permission:Edit"), MultiTenancySides.Host); | ||||
|                 identityClaimType.AddChild(IdentityPermissions.IdentityClaimType.Delete, L("Permission:Delete"), MultiTenancySides.Host); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private static LocalizableString L(string name) | ||||
|         { | ||||
|             return LocalizableString.Create<IdentityResource>(name); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| using Volo.Abp.Reflection; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public class IdentityPermissions | ||||
|     { | ||||
|         public static class Roles | ||||
|         { | ||||
|             public const string ManageClaims = Volo.Abp.Identity.IdentityPermissions.Roles.Default + ".ManageClaims"; | ||||
|             public const string ManageOrganizationUnits = Volo.Abp.Identity.IdentityPermissions.Roles.Default + ".ManageOrganizationUnits"; | ||||
|         } | ||||
| 
 | ||||
|         public static class Users | ||||
|         { | ||||
|             public const string ManageClaims = Volo.Abp.Identity.IdentityPermissions.Users.Default + ".ManageClaims"; | ||||
|             public const string ManageOrganizationUnits = Volo.Abp.Identity.IdentityPermissions.Users.Default + ".ManageOrganizationUnits"; | ||||
|         } | ||||
| 
 | ||||
|         public static class OrganizationUnits | ||||
|         { | ||||
|             public const string Default = Volo.Abp.Identity.IdentityPermissions.GroupName + ".OrganizationUnits"; | ||||
|             public const string Create = Default + ".Create"; | ||||
|             public const string Update = Default + ".Update"; | ||||
|             public const string Delete = Default + ".Delete"; | ||||
|             public const string ManageUsers = Default + ".ManageUsers"; | ||||
|             public const string ManageRoles = Default + ".ManageRoles"; | ||||
|             public const string ManagePermissions = Default + ".ManagePermissions"; | ||||
|         } | ||||
| 
 | ||||
|         public static class IdentityClaimType | ||||
|         { | ||||
|             public const string Default = Volo.Abp.Identity.IdentityPermissions.GroupName + ".IdentityClaimTypes"; | ||||
|             public const string Create = Default + ".Create"; | ||||
|             public const string Update = Default + ".Update"; | ||||
|             public const string Delete = Default + ".Delete"; | ||||
|         } | ||||
| 
 | ||||
|         public static string[] GetAll() | ||||
|         { | ||||
|             return ReflectionHelper.GetPublicConstantsRecursively(typeof(IdentityPermissions)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,20 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 	 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
|     <TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
|   </PropertyGroup> | ||||
| 
 | ||||
| 		<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.Application" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup>	 | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\Sanhe.Abp.Identity.Application.Contracts\Sanhe.Abp.Identity.Application.Contracts.csproj" /> | ||||
| 	  <ProjectReference Include="..\Sanhe.Abp.Identity.Domain\Sanhe.Abp.Identity.Domain.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| </Project> | ||||
| @ -0,0 +1,42 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Volo.Abp.AutoMapper; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn( | ||||
|         typeof(Volo.Abp.Identity.AbpIdentityApplicationModule), | ||||
|         typeof(AbpIdentityApplicationContractsModule), | ||||
|         typeof(AbpIdentityDomainModule))] | ||||
|     public class AbpIdentityApplicationModule : AbpModule | ||||
|     { | ||||
|         // private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             context.Services.AddAutoMapperObjectMapper<AbpIdentityApplicationModule>(); | ||||
| 
 | ||||
|             Configure<AbpAutoMapperOptions>(options => | ||||
|             { | ||||
|                 options.AddProfile<AbpIdentityApplicationModuleAutoMapperProfile>(validate: true); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         //public override void PostConfigureServices(ServiceConfigurationContext context) | ||||
|         //{ | ||||
|         //    OneTimeRunner.Run(() => | ||||
|         //    { | ||||
|         //        ObjectExtensionManager.Instance | ||||
|         //            .AddOrUpdateProperty<string>( | ||||
|         //                new[] | ||||
|         //                { | ||||
|         //                    typeof(IdentityUserDto), | ||||
|         //                    typeof(IdentityUserCreateDto), | ||||
|         //                    typeof(IdentityUserUpdateDto), | ||||
|         //                    typeof(ProfileDto), | ||||
|         //                    typeof(UpdateProfileDto) | ||||
|         //                }, | ||||
|         //                ExtensionIdentityUserConsts.AvatarUrlField); | ||||
|         //    }); | ||||
|         //} | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| using AutoMapper; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public class AbpIdentityApplicationModuleAutoMapperProfile : Profile | ||||
|     { | ||||
|         public AbpIdentityApplicationModuleAutoMapperProfile() | ||||
|         { | ||||
|             CreateMap<IdentityClaimType, IdentityClaimTypeDto>() | ||||
|                 .MapExtraProperties(); | ||||
|             CreateMap<IdentityUserClaim, IdentityClaimDto>(); | ||||
|             CreateMap<IdentityRoleClaim, IdentityClaimDto>(); | ||||
| 
 | ||||
|             CreateMap<IdentityUser, IdentityUserDto>() | ||||
|                 .MapExtraProperties(); | ||||
| 
 | ||||
|             CreateMap<IdentityRole, IdentityRoleDto>() | ||||
|                 .MapExtraProperties(); | ||||
| 
 | ||||
|             CreateMap<OrganizationUnit, OrganizationUnitDto>() | ||||
|                 .MapExtraProperties(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,130 @@ | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [Authorize(IdentityPermissions.IdentityClaimType.Default)] | ||||
|     public class IdentityClaimTypeAppService : IdentityAppServiceBase, IIdentityClaimTypeAppService | ||||
|     { | ||||
|         protected IdentityClaimTypeManager IdentityClaimTypeManager { get; } | ||||
| 
 | ||||
|         protected IIdentityClaimTypeRepository IdentityClaimTypeRepository { get; } | ||||
| 
 | ||||
|         public IdentityClaimTypeAppService( | ||||
|             IdentityClaimTypeManager identityClaimTypeManager, | ||||
|             IIdentityClaimTypeRepository identityClaimTypeRepository) | ||||
|         { | ||||
|             IdentityClaimTypeManager = identityClaimTypeManager; | ||||
|             IdentityClaimTypeRepository = identityClaimTypeRepository; | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.IdentityClaimType.Create)] | ||||
|         public virtual async Task<IdentityClaimTypeDto> CreateAsync(IdentityClaimTypeCreateDto input) | ||||
|         { | ||||
|             if (await IdentityClaimTypeRepository.AnyAsync(input.Name)) | ||||
|             { | ||||
|                 throw new UserFriendlyException(L["IdentityClaimTypeAlreadyExists", input.Name]); | ||||
|             } | ||||
|             var identityClaimType = new IdentityClaimType( | ||||
|                 GuidGenerator.Create(), | ||||
|                 input.Name, | ||||
|                 input.Required, | ||||
|                 input.IsStatic, | ||||
|                 input.Regex, | ||||
|                 input.RegexDescription, | ||||
|                 input.Description, | ||||
|                 input.ValueType | ||||
|             ); | ||||
|             identityClaimType = await IdentityClaimTypeManager.CreateAsync(identityClaimType); | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
| 
 | ||||
|             return ObjectMapper.Map<IdentityClaimType, IdentityClaimTypeDto>(identityClaimType); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.IdentityClaimType.Delete)] | ||||
|         public virtual async Task DeleteAsync(Guid id) | ||||
|         { | ||||
|             var identityClaimType = await IdentityClaimTypeRepository.FindAsync(id); | ||||
|             if (identityClaimType == null) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             CheckDeletionClaimType(identityClaimType); | ||||
|             await IdentityClaimTypeRepository.DeleteAsync(identityClaimType); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<IdentityClaimTypeDto> GetAsync(Guid id) | ||||
|         { | ||||
|             var identityClaimType = await IdentityClaimTypeRepository.FindAsync(id); | ||||
| 
 | ||||
|             return ObjectMapper.Map<IdentityClaimType, IdentityClaimTypeDto>(identityClaimType); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<IdentityClaimTypeDto>> GetAllListAsync() | ||||
|         { | ||||
|             var identityClaimTypes = await IdentityClaimTypeRepository | ||||
|                 .GetListAsync(); | ||||
| 
 | ||||
|             return new ListResultDto<IdentityClaimTypeDto>( | ||||
|                 ObjectMapper.Map<List<IdentityClaimType>, List<IdentityClaimTypeDto>>(identityClaimTypes)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<PagedResultDto<IdentityClaimTypeDto>> GetListAsync(IdentityClaimTypeGetByPagedDto input) | ||||
|         { | ||||
|             var identityClaimTypeCount = await IdentityClaimTypeRepository.GetCountAsync(input.Filter); | ||||
| 
 | ||||
|             var identityClaimTypes = await IdentityClaimTypeRepository | ||||
|                 .GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter); | ||||
| 
 | ||||
|             return new PagedResultDto<IdentityClaimTypeDto>(identityClaimTypeCount, | ||||
|                 ObjectMapper.Map<List<IdentityClaimType>, List<IdentityClaimTypeDto>>(identityClaimTypes)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.IdentityClaimType.Update)] | ||||
|         public virtual async Task<IdentityClaimTypeDto> UpdateAsync(Guid id, IdentityClaimTypeUpdateDto input) | ||||
|         { | ||||
|             var identityClaimType = await IdentityClaimTypeRepository.GetAsync(id); | ||||
|             CheckChangingClaimType(identityClaimType); | ||||
|             identityClaimType.Required = input.Required; | ||||
|             if (!string.Equals(identityClaimType.Regex, input.Regex, StringComparison.InvariantCultureIgnoreCase)) | ||||
|             { | ||||
|                 identityClaimType.Regex = input.Regex; | ||||
|             } | ||||
|             if (!string.Equals(identityClaimType.RegexDescription, input.RegexDescription, StringComparison.InvariantCultureIgnoreCase)) | ||||
|             { | ||||
|                 identityClaimType.RegexDescription = input.RegexDescription; | ||||
|             } | ||||
|             if (!string.Equals(identityClaimType.Description, input.Description, StringComparison.InvariantCultureIgnoreCase)) | ||||
|             { | ||||
|                 identityClaimType.Description = input.Description; | ||||
|             } | ||||
| 
 | ||||
|             identityClaimType = await IdentityClaimTypeManager.UpdateAsync(identityClaimType); | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
| 
 | ||||
|             return ObjectMapper.Map<IdentityClaimType, IdentityClaimTypeDto>(identityClaimType); | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void CheckChangingClaimType(IdentityClaimType claimType) | ||||
|         { | ||||
|             if (claimType.IsStatic) | ||||
|             { | ||||
|                 throw new BusinessException(IdentityErrorCodes.StaticClaimTypeChange); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         protected virtual void CheckDeletionClaimType(IdentityClaimType claimType) | ||||
|         { | ||||
|             if (claimType.IsStatic) | ||||
|             { | ||||
|                 throw new BusinessException(IdentityErrorCodes.StaticClaimTypeDeletion); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,124 @@ | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Security.Claims; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [Authorize(Volo.Abp.Identity.IdentityPermissions.Roles.Default)] | ||||
|     public class IdentityRoleAppService : IdentityAppServiceBase, IIdentityRoleAppService | ||||
|     { | ||||
|         protected IIdentityRoleRepository IdentityRoleRepository { get; } | ||||
|         protected OrganizationUnitManager OrganizationUnitManager { get; } | ||||
|         protected IOrganizationUnitRepository OrganizationUnitRepository { get; } | ||||
|         public IdentityRoleAppService( | ||||
|             IIdentityRoleRepository roleRepository, | ||||
|             OrganizationUnitManager organizationUnitManager) | ||||
|         { | ||||
|             OrganizationUnitManager = organizationUnitManager; | ||||
|             IdentityRoleRepository = roleRepository; | ||||
|         } | ||||
| 
 | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageOrganizationUnits)] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id) | ||||
|         { | ||||
|             var organizationUnits = await IdentityRoleRepository.GetOrganizationUnitsAsync(id); | ||||
| 
 | ||||
|             return new ListResultDto<OrganizationUnitDto>( | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(organizationUnits)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageOrganizationUnits)] | ||||
|         public virtual async Task SetOrganizationUnitsAsync(Guid id, IdentityRoleAddOrRemoveOrganizationUnitDto input) | ||||
|         { | ||||
|             var organizationUnits = await IdentityRoleRepository.GetOrganizationUnitsAsync(id, true); | ||||
| 
 | ||||
|             var notInRoleOuIds = input.OrganizationUnitIds.Where(ouid => !organizationUnits.Any(ou => ou.Id.Equals(ouid))); | ||||
| 
 | ||||
|             foreach (var ouId in notInRoleOuIds) | ||||
|             { | ||||
|                 await OrganizationUnitManager.AddRoleToOrganizationUnitAsync(id, ouId); | ||||
|             } | ||||
| 
 | ||||
|             var removeRoleOriganzationUnits = organizationUnits.Where(ou => !input.OrganizationUnitIds.Contains(ou.Id)); | ||||
|             foreach (var origanzationUnit in removeRoleOriganzationUnits) | ||||
|             { | ||||
|                 origanzationUnit.RemoveRole(id); | ||||
|             } | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageOrganizationUnits)] | ||||
|         public virtual async Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId) | ||||
|         { | ||||
|             await OrganizationUnitManager.RemoveRoleFromOrganizationUnitAsync(id, ouId); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region ClaimType | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id) | ||||
|         { | ||||
|             var role = await IdentityRoleRepository.GetAsync(id); | ||||
| 
 | ||||
|             return new ListResultDto<IdentityClaimDto>(ObjectMapper.Map<ICollection<IdentityRoleClaim>, List<IdentityClaimDto>>(role.Claims)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageClaims)] | ||||
|         public virtual async Task AddClaimAsync(Guid id, IdentityRoleClaimCreateDto input) | ||||
|         { | ||||
|             var role = await IdentityRoleRepository.GetAsync(id); | ||||
|             var claim = new Claim(input.ClaimType, input.ClaimValue); | ||||
|             if (role.FindClaim(claim) != null) | ||||
|             { | ||||
|                 throw new UserFriendlyException(L["RoleClaimAlreadyExists"]); | ||||
|             } | ||||
| 
 | ||||
|             role.AddClaim(GuidGenerator, claim); | ||||
|             await IdentityRoleRepository.UpdateAsync(role); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageClaims)] | ||||
|         public virtual async Task UpdateClaimAsync(Guid id, IdentityRoleClaimUpdateDto input) | ||||
|         { | ||||
|             var role = await IdentityRoleRepository.GetAsync(id); | ||||
|             var oldClaim = role.FindClaim(new Claim(input.ClaimType, input.ClaimValue)); | ||||
|             if (oldClaim != null) | ||||
|             { | ||||
|                 role.RemoveClaim(oldClaim.ToClaim()); | ||||
|                 role.AddClaim(GuidGenerator, new Claim(input.ClaimType, input.NewClaimValue)); | ||||
| 
 | ||||
|                 await IdentityRoleRepository.UpdateAsync(role); | ||||
| 
 | ||||
|                 await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Roles.ManageClaims)] | ||||
|         public virtual async Task DeleteClaimAsync(Guid id, IdentityRoleClaimDeleteDto input) | ||||
|         { | ||||
|             var role = await IdentityRoleRepository.GetAsync(id); | ||||
|             role.RemoveClaim(new Claim(input.ClaimType, input.ClaimValue)); | ||||
| 
 | ||||
|             await IdentityRoleRepository.UpdateAsync(role); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,151 @@ | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Identity; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Security.Claims; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Default)] | ||||
|     public class IdentityUserAppService : IdentityAppServiceBase, IIdentityUserAppService | ||||
|     { | ||||
|         protected IdentityUserManager UserManager { get; } | ||||
|         protected IOptions<IdentityOptions> IdentityOptions { get; } | ||||
|         public IdentityUserAppService( | ||||
|             IdentityUserManager userManager, | ||||
|             IOptions<IdentityOptions> identityOptions) | ||||
|         { | ||||
|             UserManager = userManager; | ||||
|             IdentityOptions = identityOptions; | ||||
|         } | ||||
| 
 | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageOrganizationUnits)] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
| 
 | ||||
|             var organizationUnits = await UserManager.GetOrganizationUnitsAsync(user); | ||||
| 
 | ||||
|             return new ListResultDto<OrganizationUnitDto>( | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(organizationUnits)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageOrganizationUnits)] | ||||
|         public virtual async Task SetOrganizationUnitsAsync(Guid id, IdentityUserOrganizationUnitUpdateDto input) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
| 
 | ||||
|             await UserManager.SetOrganizationUnitsAsync(user, input.OrganizationUnitIds); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageOrganizationUnits)] | ||||
|         public virtual async Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId) | ||||
|         { | ||||
|             await UserManager.RemoveFromOrganizationUnitAsync(id, ouId); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Claim | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
| 
 | ||||
|             return new ListResultDto<IdentityClaimDto>(ObjectMapper.Map<ICollection<IdentityUserClaim>, List<IdentityClaimDto>>(user.Claims)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageClaims)] | ||||
|         public virtual async Task AddClaimAsync(Guid id, IdentityUserClaimCreateDto input) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
|             var claim = new Claim(input.ClaimType, input.ClaimValue); | ||||
|             if (user.FindClaim(claim) != null) | ||||
|             { | ||||
|                 throw new UserFriendlyException(L["UserClaimAlreadyExists"]); | ||||
|             } | ||||
|             user.AddClaim(GuidGenerator, claim); | ||||
|             (await UserManager.UpdateAsync(user)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageClaims)] | ||||
|         public virtual async Task UpdateClaimAsync(Guid id, IdentityUserClaimUpdateDto input) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
|             var oldClaim = new Claim(input.ClaimType, input.ClaimValue); | ||||
|             var newClaim = new Claim(input.ClaimType, input.NewClaimValue); | ||||
|             user.ReplaceClaim(oldClaim, newClaim); | ||||
|             (await UserManager.UpdateAsync(user)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.Users.ManageClaims)] | ||||
|         public virtual async Task DeleteClaimAsync(Guid id, IdentityUserClaimDeleteDto input) | ||||
|         { | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
|             user.RemoveClaim(new Claim(input.ClaimType, input.ClaimValue)); | ||||
|             (await UserManager.UpdateAsync(user)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Update)] | ||||
|         public virtual async Task ChangeTwoFactorEnabledAsync(Guid id, TwoFactorEnabledDto input) | ||||
|         { | ||||
|             var user = await GetUserAsync(id); | ||||
| 
 | ||||
|             (await UserManager.SetTwoFactorEnabledWithAccountConfirmedAsync(user, input.Enabled)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Update)] | ||||
|         public virtual async Task LockAsync(Guid id, int seconds) | ||||
|         { | ||||
|             var user = await GetUserAsync(id); | ||||
|             //if (!UserManager.SupportsUserLockout) | ||||
|             //{ | ||||
|             //    throw new UserFriendlyException(L["Volo.Abp.Identity:UserLockoutNotEnabled"]); | ||||
|             //} | ||||
|             var endDate = new DateTimeOffset(Clock.Now).AddSeconds(seconds); | ||||
|             (await UserManager.SetLockoutEndDateAsync(user, endDate)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(Volo.Abp.Identity.IdentityPermissions.Users.Update)] | ||||
|         public virtual async Task UnLockAsync(Guid id) | ||||
|         { | ||||
|             var user = await GetUserAsync(id); | ||||
|             (await UserManager.SetLockoutEndDateAsync(user, null)).CheckErrors(); | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         protected virtual async Task<IdentityUser> GetUserAsync(Guid id) | ||||
|         { | ||||
|             await IdentityOptions.SetAsync(); | ||||
|             var user = await UserManager.GetByIdAsync(id); | ||||
| 
 | ||||
|             return user; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,236 @@ | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.ObjectExtending; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [Authorize(IdentityPermissions.OrganizationUnits.Default)] | ||||
|     public class OrganizationUnitAppService : IdentityAppServiceBase, IOrganizationUnitAppService | ||||
|     { | ||||
|         protected OrganizationUnitManager OrganizationUnitManager { get; } | ||||
|         protected IOrganizationUnitRepository OrganizationUnitRepository { get; } | ||||
| 
 | ||||
|         protected IdentityUserManager UserManager { get; } | ||||
|         protected IIdentityRoleRepository RoleRepository { get; } | ||||
|         protected IIdentityUserRepository UserRepository { get; } | ||||
| 
 | ||||
|         public OrganizationUnitAppService( | ||||
|             IdentityUserManager userManager, | ||||
|             IIdentityRoleRepository roleRepository, | ||||
|             IIdentityUserRepository userRepository, | ||||
|             OrganizationUnitManager organizationUnitManager, | ||||
|             IOrganizationUnitRepository organizationUnitRepository) | ||||
|         { | ||||
|             UserManager = userManager; | ||||
|             RoleRepository = roleRepository; | ||||
|             UserRepository = userRepository; | ||||
|             OrganizationUnitManager = organizationUnitManager; | ||||
|             OrganizationUnitRepository = organizationUnitRepository; | ||||
| 
 | ||||
|             ObjectMapperContext = typeof(AbpIdentityApplicationModule); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.Create)] | ||||
|         public virtual async Task<OrganizationUnitDto> CreateAsync(OrganizationUnitCreateDto input) | ||||
|         { | ||||
|             var organizationUnit = new OrganizationUnit( | ||||
|                 GuidGenerator.Create(), input.DisplayName, input.ParentId, CurrentTenant.Id) | ||||
|             { | ||||
|                 CreationTime = Clock.Now | ||||
|             }; | ||||
|             input.MapExtraPropertiesTo(organizationUnit); | ||||
| 
 | ||||
|             await OrganizationUnitManager.CreateAsync(organizationUnit); | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
| 
 | ||||
|             return ObjectMapper.Map<OrganizationUnit, OrganizationUnitDto>(organizationUnit); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.Delete)] | ||||
|         public virtual async Task DeleteAsync(Guid id) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.FindAsync(id); | ||||
|             if (organizationUnit == null) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             await OrganizationUnitManager.DeleteAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetRootAsync() | ||||
|         { | ||||
|             var rootorganizationUnits = await OrganizationUnitManager.FindChildrenAsync(null, recursive: false); | ||||
| 
 | ||||
|             return new ListResultDto<OrganizationUnitDto>( | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(rootorganizationUnits)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> FindChildrenAsync(OrganizationUnitGetChildrenDto input) | ||||
|         { | ||||
|             var organizationUnitChildren = await OrganizationUnitManager.FindChildrenAsync(input.Id, input.Recursive); | ||||
| 
 | ||||
|             return new ListResultDto<OrganizationUnitDto>( | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(organizationUnitChildren)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<OrganizationUnitDto> GetAsync(Guid id) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.FindAsync(id); | ||||
| 
 | ||||
|             return ObjectMapper.Map<OrganizationUnit, OrganizationUnitDto>(organizationUnit); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<OrganizationUnitDto> GetLastChildOrNullAsync(Guid? parentId) | ||||
|         { | ||||
|             var organizationUnitLastChildren = await OrganizationUnitManager.GetLastChildOrNullAsync(parentId); | ||||
| 
 | ||||
|             return ObjectMapper.Map<OrganizationUnit, OrganizationUnitDto>(organizationUnitLastChildren); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetAllListAsync() | ||||
|         { | ||||
|             var organizationUnits = await OrganizationUnitRepository.GetListAsync(false); | ||||
| 
 | ||||
|             return new ListResultDto<OrganizationUnitDto>( | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(organizationUnits)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<PagedResultDto<OrganizationUnitDto>> GetListAsync(OrganizationUnitGetByPagedDto input) | ||||
|         { | ||||
|             var organizationUnitCount = await OrganizationUnitRepository.GetCountAsync(); | ||||
|             var organizationUnits = await OrganizationUnitRepository | ||||
|                 .GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, false); | ||||
| 
 | ||||
|             return new PagedResultDto<OrganizationUnitDto>(organizationUnitCount, | ||||
|                 ObjectMapper.Map<List<OrganizationUnit>, List<OrganizationUnitDto>>(organizationUnits)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageRoles)] | ||||
|         public virtual async Task<ListResultDto<string>> GetRoleNamesAsync(Guid id) | ||||
|         { | ||||
|             var inOrignizationUnitRoleNames = await UserRepository.GetRoleNamesInOrganizationUnitAsync(id); | ||||
|             return new ListResultDto<string>(inOrignizationUnitRoleNames); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageRoles)] | ||||
|         public virtual async Task<PagedResultDto<IdentityRoleDto>> GetUnaddedRolesAsync(Guid id, OrganizationUnitGetUnaddedRoleByPagedDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
| 
 | ||||
|             var organizationUnitRoleCount = await OrganizationUnitRepository | ||||
|                 .GetUnaddedRolesCountAsync(organizationUnit, input.Filter); | ||||
| 
 | ||||
|             var organizationUnitRoles = await OrganizationUnitRepository | ||||
|                 .GetUnaddedRolesAsync(organizationUnit, | ||||
|                 input.Sorting, input.MaxResultCount, | ||||
|                 input.SkipCount, input.Filter); | ||||
| 
 | ||||
|             return new PagedResultDto<IdentityRoleDto>(organizationUnitRoleCount, | ||||
|                 ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(organizationUnitRoles)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageRoles)] | ||||
|         public virtual async Task<PagedResultDto<IdentityRoleDto>> GetRolesAsync(Guid id, PagedAndSortedResultRequestDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
| 
 | ||||
|             var organizationUnitRoleCount = await OrganizationUnitRepository | ||||
|                 .GetRolesCountAsync(organizationUnit); | ||||
| 
 | ||||
|             var organizationUnitRoles = await OrganizationUnitRepository | ||||
|                 .GetRolesAsync(organizationUnit, | ||||
|                 input.Sorting, input.MaxResultCount, | ||||
|                 input.SkipCount); | ||||
| 
 | ||||
|             return new PagedResultDto<IdentityRoleDto>(organizationUnitRoleCount, | ||||
|                 ObjectMapper.Map<List<IdentityRole>, List<IdentityRoleDto>>(organizationUnitRoles)); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageUsers)] | ||||
|         public virtual async Task<PagedResultDto<IdentityUserDto>> GetUnaddedUsersAsync(Guid id, OrganizationUnitGetUnaddedUserByPagedDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
| 
 | ||||
|             var organizationUnitUserCount = await OrganizationUnitRepository | ||||
|                 .GetUnaddedUsersCountAsync(organizationUnit, input.Filter); | ||||
|             var organizationUnitUsers = await OrganizationUnitRepository | ||||
|                 .GetUnaddedUsersAsync(organizationUnit, | ||||
|                 input.Sorting, input.MaxResultCount, | ||||
|                 input.SkipCount, input.Filter); | ||||
| 
 | ||||
|             return new PagedResultDto<IdentityUserDto>(organizationUnitUserCount, | ||||
|                 ObjectMapper.Map<List<IdentityUser>, List<IdentityUserDto>>(organizationUnitUsers)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageUsers)] | ||||
|         public virtual async Task<PagedResultDto<IdentityUserDto>> GetUsersAsync(Guid id, GetIdentityUsersInput input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
| 
 | ||||
|             var organizationUnitUserCount = await OrganizationUnitRepository | ||||
|                 .GetMembersCountAsync(organizationUnit, input.Filter); | ||||
|             var organizationUnitUsers = await OrganizationUnitRepository | ||||
|                 .GetMembersAsync(organizationUnit, | ||||
|                 input.Sorting, input.MaxResultCount, | ||||
|                 input.SkipCount, input.Filter); | ||||
| 
 | ||||
|             return new PagedResultDto<IdentityUserDto>(organizationUnitUserCount, | ||||
|                 ObjectMapper.Map<List<IdentityUser>, List<IdentityUserDto>>(organizationUnitUsers)); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.Update)] | ||||
|         public virtual async Task MoveAsync(Guid id, OrganizationUnitMoveDto input) | ||||
|         { | ||||
|             await OrganizationUnitManager.MoveAsync(id, input.ParentId); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.Update)] | ||||
|         public virtual async Task<OrganizationUnitDto> UpdateAsync(Guid id, OrganizationUnitUpdateDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
|             organizationUnit.DisplayName = input.DisplayName; | ||||
|             input.MapExtraPropertiesTo(organizationUnit); | ||||
| 
 | ||||
|             await OrganizationUnitManager.UpdateAsync(organizationUnit); | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
| 
 | ||||
|             return ObjectMapper.Map<OrganizationUnit, OrganizationUnitDto>(organizationUnit); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageUsers)] | ||||
|         public virtual async Task AddUsersAsync(Guid id, OrganizationUnitAddUserDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
|             var users = await UserRepository.GetListByIdListAsync(input.UserIds, includeDetails: true); | ||||
| 
 | ||||
|             // 调用内部方法设置用户组织机构 | ||||
|             foreach (var user in users) | ||||
|             { | ||||
|                 await UserManager.AddToOrganizationUnitAsync(user, organizationUnit); | ||||
|             } | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [Authorize(IdentityPermissions.OrganizationUnits.ManageRoles)] | ||||
|         public virtual async Task AddRolesAsync(Guid id, OrganizationUnitAddRoleDto input) | ||||
|         { | ||||
|             var organizationUnit = await OrganizationUnitRepository.GetAsync(id); | ||||
| 
 | ||||
|             var roles = await RoleRepository.GetListByIdListAsync(input.RoleIds, includeDetails: true); | ||||
| 
 | ||||
|             foreach (var role in roles) | ||||
|             { | ||||
|                 await OrganizationUnitManager.AddRoleToOrganizationUnitAsync(role, organizationUnit); | ||||
|             } | ||||
| 
 | ||||
|             await CurrentUnitOfWork.SaveChangesAsync(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,27 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <None Remove="Sanhe\Abp\Identity\Localization\en.json" /> | ||||
| 	  <None Remove="Sanhe\Abp\Identity\Localization\zh-Hans.json" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\Identity\Localization\en.json" /> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\Identity\Localization\zh-Hans.json" /> | ||||
| 	</ItemGroup> | ||||
| 	 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.Domain.Shared" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,26 @@ | ||||
| using Volo.Abp.Identity.Localization; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.Modularity; | ||||
| using Volo.Abp.VirtualFileSystem; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn(typeof(Volo.Abp.Identity.AbpIdentityDomainSharedModule))] | ||||
|     public class AbpIdentityDomainSharedModule : AbpModule | ||||
|     { | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             Configure<AbpVirtualFileSystemOptions>(options => | ||||
|             { | ||||
|                 options.FileSets.AddEmbedded<AbpIdentityDomainSharedModule>(); | ||||
|             }); | ||||
| 
 | ||||
|             Configure<AbpLocalizationOptions>(options => | ||||
|             { | ||||
|                 options.Resources | ||||
|                     .Get<IdentityResource>() | ||||
|                     .AddVirtualJson("/Sanhe/Abp/Identity/Localization"); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IUserSecurityCodeSender | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 发送手机确认码 | ||||
|         /// </summary> | ||||
|         /// <param name="phone">手机号</param> | ||||
|         /// <param name="token">令牌</param> | ||||
|         /// <param name="template">模板号</param> | ||||
|         /// <param name="cancellation"></param> | ||||
|         /// <returns></returns> | ||||
|         Task SendPhoneConfirmedCodeAsync( | ||||
|             string phone, | ||||
|             string token, | ||||
|             string template, // 传递模板号 | ||||
|             CancellationToken cancellation = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 发送邮箱确认码 | ||||
|         /// </summary> | ||||
|         /// <param name="userName">用户名</param> | ||||
|         /// <param name="email">邮箱</param> | ||||
|         /// <param name="token">令牌</param> | ||||
|         /// <param name="cancellation"></param> | ||||
|         /// <returns></returns> | ||||
|         Task SendEmailConfirmedCodeAsync( | ||||
|             string userName, | ||||
|             string email, | ||||
|             string token, | ||||
|             CancellationToken cancellation = default); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,15 @@ | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public static class IdentityConsts | ||||
|     { | ||||
|         public static class ClaimType | ||||
|         { | ||||
|             public static class Avatar | ||||
|             { | ||||
|                 public static string Name { get; set; } = "avatarUrl"; | ||||
|                 public static string DisplayName { get; set; } = "Your avatar url"; | ||||
|                 public static string Description { get; set; } = "Your avatar url"; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public static class IdentityErrorCodes | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 无法变更静态声明类型 | ||||
|         /// </summary> | ||||
|         public const string StaticClaimTypeChange = "Volo.Abp.Identity:020005"; | ||||
|         /// <summary> | ||||
|         /// 无法删除静态声明类型 | ||||
|         /// </summary> | ||||
|         public const string StaticClaimTypeDeletion = "Volo.Abp.Identity:020006"; | ||||
|         /// <summary> | ||||
|         /// 手机号码已被使用 | ||||
|         /// </summary> | ||||
|         public const string DuplicatePhoneNumber = "Volo.Abp.Identity:020007"; | ||||
|         /// <summary> | ||||
|         /// 你不能修改你的手机绑定信息 | ||||
|         /// </summary> | ||||
|         public const string UsersCanNotChangePhoneNumber = "Volo.Abp.Identity:020008"; | ||||
|         /// <summary> | ||||
|         /// 你不能修改你的邮件绑定信息 | ||||
|         /// </summary> | ||||
|         public const string UsersCanNotChangeEmailAddress = "Volo.Abp.Identity:020009"; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using System.Runtime.Serialization; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Logging; | ||||
| 
 | ||||
| namespace Sanhe.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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| { | ||||
|   "culture": "en", | ||||
|   "texts": { | ||||
|     "Permission:OrganizationUnitManagement": "Organization unit management", | ||||
|     "Permission:ManageRoles": "Management roles", | ||||
|     "Permission:ManageUsers": "Management users", | ||||
|     "Permission:ManageClaims": "Management claims", | ||||
|     "Permission:ManageOrganizationUnits": "Management organization units", | ||||
|     "Permission:IdentityClaimTypeManagement": "Management claim types", | ||||
|     "OrganizationUnit:Tree": "Organization tree", | ||||
|     "OrganizationUnit:New": "Add New", | ||||
|     "OrganizationUnit:Members": "Organization Members", | ||||
|     "OrganizationUnit:AddRoot": "Add Root", | ||||
|     "OrganizationUnit:AddChildren": "Add Children", | ||||
|     "OrganizationUnit:AddMember": "Add Member", | ||||
|     "OrganizationUnit:AddRole": "Add Role", | ||||
|     "OrganizationUnit:DisplayName": "Display Name", | ||||
|     "OrganizationUnit:WillDelete": "Organization: {0} will be deleted", | ||||
|     "OrganizationUnit:AreYouSureRemoveUser": "Are you sure you want to delete user {0} from your organization?", | ||||
|     "OrganizationUnit:AreYouSureRemoveRole": "Are you sure you want to remove the role {0} from the organization?", | ||||
|     "OrganizationUnit:SelectUsers": "Select Users", | ||||
|     "OrganizationUnit:SelectRoles": "Select Roles", | ||||
|     "IdentityClaimTypeAlreadyExists": "The identity claim type {0} already exists!", | ||||
|     "UserClaimAlreadyExists": "User claim with the same parameters have been added!", | ||||
|     "RoleClaimAlreadyExists": "Role claim with the same parameters has been added!", | ||||
|     "DisplayName:ClaimType": "Type", | ||||
|     "DisplayName:ClaimValue": "Value", | ||||
|     "ClaimSubject": "Claim - {0}", | ||||
|     "RoleSubject": "Role - {0}", | ||||
|     "AddClaim": "Add claim", | ||||
|     "UpdateClaim": "Update claim", | ||||
|     "DeleteClaim": "Delete claim", | ||||
|     "WillDeleteClaim": "Pending deletion claim type: {0}", | ||||
|     "ManageClaim": "Management claim", | ||||
|     "IdentityClaim:New": "New claim", | ||||
|     "IdentityClaim:Name": "Name", | ||||
|     "IdentityClaim:Required": "Required", | ||||
|     "IdentityClaim:IsStatic": "Is static", | ||||
|     "IdentityClaim:Regex": "Regex", | ||||
|     "IdentityClaim:RegexDescription": "Regex description", | ||||
|     "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: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: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", | ||||
|     "DisplayName:Abp.Identity.User.SmsUserSignin": "Signin sms template", | ||||
|     "Description:Abp.Identity.User.SmsUserSignin": "When the user logs in, he/she should send the template number of the SMS verification code and fill in the template number of the corresponding cloud platform registration", | ||||
|     "DisplayName:Abp.Identity.User.SmsResetPassword": "Reset password sms template", | ||||
|     "Description:Abp.Identity.User.SmsResetPassword": "When the user resets the password, he/she sends the template number of SMS verification code and fills in the template number registered on the cloud platform", | ||||
|     "DisplayName:Abp.Identity.User.SmsPhoneNumberConfirmed": "Phone number confirmation template", | ||||
|     "Description:Abp.Identity.User.SmsPhoneNumberConfirmed": "The user confirms the mobile phone verification code template", | ||||
|     "DisplayName:Abp.Identity.User.SmsRepeatInterval": "SMS verification code validity(min)", | ||||
|     "Description:Abp.Identity.User.SmsRepeatInterval": "The valid time for the user to send SMS verification code, unit m, default 3min", | ||||
|     "DisplayName:SmsVerifyCode": "SMS verification code", | ||||
|     "DisplayName:EmailVerifyCode": "Mail verification code", | ||||
|     "DisplayName:WeChatCode": "Wechat login code", | ||||
|     "SendRepeatSmsVerifyCode": "Phone verification code cannot be sent repeatedly within {0} minutes!" | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| { | ||||
|   "culture": "zh-Hans", | ||||
|   "texts": { | ||||
|     "Permission:OrganizationUnitManagement": "组织机构管理", | ||||
|     "Permission:ManageRoles": "管理角色", | ||||
|     "Permission:ManageUsers": "管理用户", | ||||
|     "Permission:ManageClaims": "管理声明", | ||||
|     "Permission:ManageOrganizationUnits": "管理组织机构", | ||||
|     "Permission:IdentityClaimTypeManagement": "管理声明类型", | ||||
|     "OrganizationUnit:Tree": "组织机构树", | ||||
|     "OrganizationUnit:New": "新组织结构", | ||||
|     "OrganizationUnit:Members": "机构成员", | ||||
|     "OrganizationUnit:AddRoot": "添加根机构", | ||||
|     "OrganizationUnit:AddChildren": "添加子机构", | ||||
|     "OrganizationUnit:AddMember": "添加成员", | ||||
|     "OrganizationUnit:AddRole": "添加角色", | ||||
|     "OrganizationUnit:DisplayName": "显示名称", | ||||
|     "OrganizationUnit:WillDelete": "组织机构: {0} 将被删除", | ||||
|     "OrganizationUnit:AreYouSureRemoveUser": "你确定要从组织机构中删除用户 {0} 吗?", | ||||
|     "OrganizationUnit:AreYouSureRemoveRole": "你确定要从组织机构中删除角色 {0} 吗?", | ||||
|     "OrganizationUnit:SelectUsers": "选择用户", | ||||
|     "OrganizationUnit:SelectRoles": "选择角色", | ||||
|     "IdentityClaimTypeAlreadyExists": "声明类型 {0} 已经存在!", | ||||
|     "UserClaimAlreadyExists": "已经添加相同参数的用户声明!", | ||||
|     "RoleClaimAlreadyExists": "已经添加相同参数的角色声明", | ||||
|     "DisplayName:ClaimType": "声明类型", | ||||
|     "DisplayName:ClaimValue": "声明值", | ||||
|     "ClaimSubject": "声明 - {0}", | ||||
|     "RoleSubject": "角色 - {0}", | ||||
|     "AddClaim": "添加声明", | ||||
|     "UpdateClaim": "变更声明", | ||||
|     "DeleteClaim": "删除声明", | ||||
|     "WillDeleteClaim": "声明类型: {0} 将被删除", | ||||
|     "ManageClaim": "管理声明", | ||||
|     "IdentityClaim:New": "新声明类型", | ||||
|     "IdentityClaim:Name": "名称", | ||||
|     "IdentityClaim:Required": "是否必须", | ||||
|     "IdentityClaim:IsStatic": "是否静态", | ||||
|     "IdentityClaim:Regex": "正则", | ||||
|     "IdentityClaim:RegexDescription": "正则描述", | ||||
|     "IdentityClaim:Description": "描述", | ||||
|     "IdentityClaim:ValueType": "值类型", | ||||
|     "Volo.Abp.Identity:020005": "无法变更静态声明类型!", | ||||
|     "Volo.Abp.Identity:020006": "无法删除静态声明类型!", | ||||
|     "Volo.Abp.Identity:020007": "手机号码已被其他用户绑定!", | ||||
|     "Volo.Abp.Identity:020008": "你不能修改你的手机绑定信息!", | ||||
|     "Volo.Abp.Identity:020009": "你不能修改你的邮件绑定信息!", | ||||
|     "Volo.Abp.Identity:DuplicatePhoneNumber": "手机号 '{0}' 已存在.", | ||||
|     "DisplayName:Abp.Identity.User.SmsNewUserRegister": "新用户注册模板", | ||||
|     "Description:Abp.Identity.User.SmsNewUserRegister": "新用户通过手机注册账号验证码模板", | ||||
|     "DisplayName:Abp.Identity.User.SmsUserSignin": "用户登录模板", | ||||
|     "Description:Abp.Identity.User.SmsUserSignin": "用户通过手机登录验证码模板", | ||||
|     "DisplayName:Abp.Identity.User.SmsResetPassword": "密码找回模板", | ||||
|     "Description:Abp.Identity.User.SmsResetPassword": "用户通过手机找回密码验证码模板", | ||||
|     "DisplayName:Abp.Identity.User.SmsPhoneNumberConfirmed": "手机确认模板", | ||||
|     "Description:Abp.Identity.User.SmsPhoneNumberConfirmed": "用户确认手机号验证码模板", | ||||
|     "DisplayName:Abp.Identity.User.SmsRepeatInterval": "重复发送间隔时间(min)", | ||||
|     "Description:Abp.Identity.User.SmsRepeatInterval": "验证码重复发送的最小时间差,单位为分", | ||||
|     "DisplayName:SmsVerifyCode": "短信验证码", | ||||
|     "DisplayName:EmailVerifyCode": "邮件验证码", | ||||
|     "DisplayName:WeChatCode": "微信登录凭证", | ||||
|     "SendRepeatSmsVerifyCode": "手机验证码不能在 {0} 分钟内重复发送!" | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,121 @@ | ||||
| using System; | ||||
| using System.Diagnostics; | ||||
| using System.Net; | ||||
| using System.Security.Cryptography; | ||||
| using System.Text; | ||||
| using Volo.Abp.DependencyInjection; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Security | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 微软的实现 | ||||
|     /// See: Microsoft.AspNetCore.Identity.Rfc6238AuthenticationService | ||||
|     /// </summary> | ||||
|     internal class DefaultTotpService : ITotpService, ISingletonDependency | ||||
|     { | ||||
|         private static readonly TimeSpan _timestep = TimeSpan.FromMinutes(3); | ||||
|         private static readonly Encoding _encoding = new UTF8Encoding(false, true); | ||||
| #if NETSTANDARD2_0 | ||||
|         private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | ||||
|         private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create(); | ||||
| #endif | ||||
| 
 | ||||
|         // Generates a new 80-bit security token | ||||
|         public static byte[] GenerateRandomKey() | ||||
|         { | ||||
|             var bytes = new byte[20]; | ||||
| #if NETSTANDARD2_0 | ||||
|             _rng.GetBytes(bytes); | ||||
| #else | ||||
|             RandomNumberGenerator.Fill(bytes); | ||||
| #endif | ||||
|             return bytes; | ||||
|         } | ||||
| 
 | ||||
|         internal static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier) | ||||
|         { | ||||
|             // # of 0's = length of pin | ||||
|             const int Mod = 1000000; | ||||
| 
 | ||||
|             // See https://tools.ietf.org/html/rfc4226 | ||||
|             // We can add an optional modifier | ||||
|             var timestepAsBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber)); | ||||
|             var hash = hashAlgorithm.ComputeHash(ApplyModifier(timestepAsBytes, modifier)); | ||||
| 
 | ||||
|             // Generate DT string | ||||
|             var offset = hash[hash.Length - 1] & 0xf; | ||||
|             Debug.Assert(offset + 4 < hash.Length); | ||||
|             var binaryCode = (hash[offset] & 0x7f) << 24 | ||||
|                              | (hash[offset + 1] & 0xff) << 16 | ||||
|                              | (hash[offset + 2] & 0xff) << 8 | ||||
|                              | hash[offset + 3] & 0xff; | ||||
| 
 | ||||
|             return binaryCode % Mod; | ||||
|         } | ||||
| 
 | ||||
|         private static byte[] ApplyModifier(byte[] input, string modifier) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(modifier)) | ||||
|             { | ||||
|                 return input; | ||||
|             } | ||||
| 
 | ||||
|             var modifierBytes = _encoding.GetBytes(modifier); | ||||
|             var combined = new byte[checked(input.Length + modifierBytes.Length)]; | ||||
|             Buffer.BlockCopy(input, 0, combined, 0, input.Length); | ||||
|             Buffer.BlockCopy(modifierBytes, 0, combined, input.Length, modifierBytes.Length); | ||||
|             return combined; | ||||
|         } | ||||
| 
 | ||||
|         // More info: https://tools.ietf.org/html/rfc6238#section-4 | ||||
|         private static ulong GetCurrentTimeStepNumber() | ||||
|         { | ||||
| #if NETSTANDARD2_0 | ||||
|             var delta = DateTime.UtcNow - _unixEpoch; | ||||
| #else | ||||
|             var delta = DateTimeOffset.UtcNow - DateTimeOffset.UnixEpoch; | ||||
| #endif | ||||
|             return (ulong)(delta.Ticks / _timestep.Ticks); | ||||
|         } | ||||
| 
 | ||||
|         public int GenerateCode(byte[] securityToken, string modifier = null) | ||||
|         { | ||||
|             if (securityToken == null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(securityToken)); | ||||
|             } | ||||
| 
 | ||||
|             // Allow a variance of no greater than 9 minutes in either direction | ||||
|             var currentTimeStep = GetCurrentTimeStepNumber(); | ||||
|             using (var hashAlgorithm = new HMACSHA1(securityToken)) | ||||
|             { | ||||
|                 return ComputeTotp(hashAlgorithm, currentTimeStep, modifier); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public bool ValidateCode(byte[] securityToken, int code, string modifier = null) | ||||
|         { | ||||
|             if (securityToken == null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(securityToken)); | ||||
|             } | ||||
| 
 | ||||
|             // Allow a variance of no greater than 9 minutes in either direction | ||||
|             var currentTimeStep = GetCurrentTimeStepNumber(); | ||||
|             using (var hashAlgorithm = new HMACSHA1(securityToken)) | ||||
|             { | ||||
|                 for (var i = -2; i <= 2; i++) | ||||
|                 { | ||||
|                     var computedTotp = ComputeTotp(hashAlgorithm, (ulong)((long)currentTimeStep + i), modifier); | ||||
|                     if (computedTotp == code) | ||||
|                     { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // No match | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| namespace Sanhe.Abp.Identity.Security | ||||
| { | ||||
|     /// <summary> | ||||
|     /// totp算法服务 | ||||
|     /// </summary> | ||||
|     public interface ITotpService | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 生成 | ||||
|         /// </summary> | ||||
|         /// <param name="securityToken"></param> | ||||
|         /// <param name="modifier"></param> | ||||
|         /// <returns></returns> | ||||
|         int GenerateCode(byte[] securityToken, string modifier = null); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 验证 | ||||
|         /// </summary> | ||||
|         /// <param name="securityToken"></param> | ||||
|         /// <param name="code"></param> | ||||
|         /// <param name="modifier"></param> | ||||
|         /// <returns></returns> | ||||
|         bool ValidateCode(byte[] securityToken, int code, string modifier = null); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,75 @@ | ||||
| using Volo.Abp.Identity.Localization; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.Settings; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.Settings | ||||
| { | ||||
|     public class IdentitySettingDefinitionProvider : SettingDefinitionProvider | ||||
|     { | ||||
|         public override void Define(ISettingDefinitionContext context) | ||||
|         { | ||||
|             context.Add( | ||||
|                 new SettingDefinition( | ||||
|                     name: IdentitySettingNames.User.SmsNewUserRegister, | ||||
|                     defaultValue: "", | ||||
|                     displayName: L("DisplayName:Abp.Identity.User.SmsNewUserRegister"), | ||||
|                     description: L("Description:Abp.Identity.User.SmsNewUserRegister"), | ||||
|                     isVisibleToClients: true) | ||||
|                 .WithProviders( | ||||
|                     DefaultValueSettingValueProvider.ProviderName, | ||||
|                     ConfigurationSettingValueProvider.ProviderName, | ||||
|                     GlobalSettingValueProvider.ProviderName, | ||||
|                     TenantSettingValueProvider.ProviderName), | ||||
|                 new SettingDefinition( | ||||
|                     name: IdentitySettingNames.User.SmsUserSignin, | ||||
|                     defaultValue: "", | ||||
|                     displayName: L("DisplayName:Abp.Identity.User.SmsUserSignin"), | ||||
|                     description: L("Description:Abp.Identity.User.SmsUserSignin"), | ||||
|                     isVisibleToClients: true) | ||||
|                 .WithProviders( | ||||
|                     DefaultValueSettingValueProvider.ProviderName, | ||||
|                     ConfigurationSettingValueProvider.ProviderName, | ||||
|                     GlobalSettingValueProvider.ProviderName, | ||||
|                     TenantSettingValueProvider.ProviderName), | ||||
|                 new SettingDefinition( | ||||
|                     name: IdentitySettingNames.User.SmsResetPassword, | ||||
|                     defaultValue: "", | ||||
|                     displayName: L("DisplayName:Abp.Identity.User.SmsResetPassword"), | ||||
|                     description: L("Description:Abp.Identity.User.SmsResetPassword"), | ||||
|                     isVisibleToClients: true) | ||||
|                 .WithProviders( | ||||
|                     DefaultValueSettingValueProvider.ProviderName, | ||||
|                     ConfigurationSettingValueProvider.ProviderName, | ||||
|                     GlobalSettingValueProvider.ProviderName, | ||||
|                     TenantSettingValueProvider.ProviderName), | ||||
|                 new SettingDefinition( | ||||
|                     name: IdentitySettingNames.User.SmsPhoneNumberConfirmed, | ||||
|                     defaultValue: "", | ||||
|                     displayName: L("DisplayName:Abp.Identity.User.SmsPhoneNumberConfirmed"), | ||||
|                     description: L("Description:Abp.Identity.User.SmsPhoneNumberConfirmed"), | ||||
|                     isVisibleToClients: true) | ||||
|                 .WithProviders( | ||||
|                     DefaultValueSettingValueProvider.ProviderName, | ||||
|                     ConfigurationSettingValueProvider.ProviderName, | ||||
|                     GlobalSettingValueProvider.ProviderName, | ||||
|                     TenantSettingValueProvider.ProviderName), | ||||
|                 new SettingDefinition( | ||||
|                     name: IdentitySettingNames.User.SmsRepeatInterval, | ||||
|                     defaultValue: "5", | ||||
|                     displayName: L("DisplayName:Abp.Identity.User.SmsRepeatInterval"), | ||||
|                     description: L("Description:Abp.Identity.User.SmsRepeatInterval"), | ||||
|                     isVisibleToClients: true) | ||||
|                 .WithProviders( | ||||
|                     DefaultValueSettingValueProvider.ProviderName, | ||||
|                     ConfigurationSettingValueProvider.ProviderName, | ||||
|                     GlobalSettingValueProvider.ProviderName, | ||||
|                     TenantSettingValueProvider.ProviderName) | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         private static LocalizableString L(string name) | ||||
|         { | ||||
|             return LocalizableString.Create<IdentityResource>(name); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| namespace Sanhe.Abp.Identity.Settings | ||||
| { | ||||
|     public static class IdentitySettingNames | ||||
|     { | ||||
|         private const string Prefix = "Abp.Identity"; | ||||
| 
 | ||||
|         public static class User | ||||
|         { | ||||
|             private const string UserPrefix = Prefix + ".User"; | ||||
|             /// <summary> | ||||
|             /// 用户手机验证短信模板 | ||||
|             /// </summary> | ||||
|             public const string SmsPhoneNumberConfirmed = UserPrefix + ".SmsPhoneNumberConfirmed"; | ||||
|             /// <summary> | ||||
|             /// 用户注册短信验证码模板号 | ||||
|             /// </summary> | ||||
|             public const string SmsNewUserRegister = UserPrefix + ".SmsNewUserRegister"; | ||||
|             /// <summary> | ||||
|             /// 用户登录短信验证码模板号 | ||||
|             /// </summary> | ||||
|             public const string SmsUserSignin = UserPrefix + ".SmsUserSignin"; | ||||
|             /// <summary> | ||||
|             /// 用户重置密码短信验证码模板号 | ||||
|             /// </summary> | ||||
|             public const string SmsResetPassword = UserPrefix + ".SmsResetPassword"; | ||||
|             /// <summary> | ||||
|             /// 验证码重复间隔时间 | ||||
|             /// </summary> | ||||
|             public const string SmsRepeatInterval = UserPrefix + ".SmsRepeatInterval"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -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<IdentityResult> SetTwoFactorEnabledWithAccountConfirmedAsync<TUser>( | ||||
|             [NotNull] this UserManager<TUser> 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 Sanhe.Abp.Identity.IdentityException( | ||||
|                         IdentityErrorCodes.CanNotChangeTwoFactor, | ||||
|                         details: phoneNumberConfirmed ? "phone number not confirmed" : "email address not confirmed"); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return await userManager.SetTwoFactorEnabledAsync(user, enabled); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,58 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Localization; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.DependencyInjection; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Identity.Localization; | ||||
| using IIdentityUserRepository = Sanhe.Abp.Identity.IIdentityUserRepository; | ||||
| 
 | ||||
| namespace Microsoft.AspNetCore.Identity | ||||
| { | ||||
|     [Dependency(ServiceLifetime.Scoped, ReplaceServices = true)] | ||||
|     [ExposeServices(typeof(IUserValidator<IdentityUser>))] | ||||
|     public class PhoneNumberUserValidator : UserValidator<IdentityUser> | ||||
|     { | ||||
|         private readonly IStringLocalizer _stringLocalizer; | ||||
|         private readonly IIdentityUserRepository _userRepository; | ||||
| 
 | ||||
|         public PhoneNumberUserValidator( | ||||
|             IIdentityUserRepository userRepository, | ||||
|             IStringLocalizer<IdentityResource> stringLocalizer) | ||||
|         { | ||||
|             _userRepository = userRepository; | ||||
|             _stringLocalizer = stringLocalizer; | ||||
|         } | ||||
| 
 | ||||
|         public async override Task<IdentityResult> ValidateAsync(UserManager<IdentityUser> manager, IdentityUser user) | ||||
|         { | ||||
|             var errors = new List<IdentityError>(); | ||||
|             await ValidatePhoneNumberAsync(manager, user, errors); | ||||
| 
 | ||||
|             return (errors.Count > 0)  | ||||
|                 ? IdentityResult.Failed(errors.ToArray())  | ||||
|                 : await base.ValidateAsync(manager, user); | ||||
|         } | ||||
| 
 | ||||
|         protected async virtual Task ValidatePhoneNumberAsync(UserManager<IdentityUser> manager, IdentityUser user, ICollection<IdentityError> errors) | ||||
|         { | ||||
|             var phoneNumber = await manager.GetPhoneNumberAsync(user); | ||||
|             if (phoneNumber.IsNullOrWhiteSpace()) | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
|             var findUser = await _userRepository.FindByPhoneNumberAsync(phoneNumber, false); | ||||
|             if (findUser != null && !findUser.Id.Equals(user.Id)) | ||||
|             { | ||||
|                 //errors.Add(new IdentityError | ||||
|                 //{ | ||||
|                 //    Code = "DuplicatePhoneNumber", | ||||
|                 //    Description = _stringLocalizer["DuplicatePhoneNumber", phoneNumber] | ||||
|                 //}); | ||||
|                 throw new UserFriendlyException(_stringLocalizer["Volo.Abp.Identity:DuplicatePhoneNumber", phoneNumber]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,18 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\Sanhe.Abp.Identity.Domain.Shared\Sanhe.Abp.Identity.Domain.Shared.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.Domain" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,11 @@ | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn( | ||||
|         typeof(AbpIdentityDomainSharedModule), | ||||
|         typeof(Volo.Abp.Identity.AbpIdentityDomainModule))] | ||||
|     public class AbpIdentityDomainModule : AbpModule | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IIdentityRoleRepository : Volo.Abp.Identity.IIdentityRoleRepository | ||||
|     { | ||||
|         Task<List<IdentityRole>> GetListByIdListAsync( | ||||
|             List<Guid> roleIds, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             Guid id, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             IEnumerable<string> roleNames, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityRole>> GetRolesInOrganizationUnitAsync( | ||||
|             Guid organizationUnitId, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityRole>> GetRolesInOrganizationsListAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityRole>> GetRolesInOrganizationUnitWithChildrenAsync( | ||||
|             string code, | ||||
|             CancellationToken cancellationToken = default); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,128 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     public interface IIdentityUserRepository : Volo.Abp.Identity.IIdentityUserRepository | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 手机号是否已被使用 | ||||
|         /// </summary> | ||||
|         /// <param name="phoneNumber"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<bool> IsPhoneNumberUedAsync( | ||||
|             string phoneNumber, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 手机号是否已确认(绑定) | ||||
|         /// </summary> | ||||
|         /// <param name="phoneNumber"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<bool> IsPhoneNumberConfirmedAsync( | ||||
|             string phoneNumber, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 邮件地址是否已确认(绑定) | ||||
|         /// </summary> | ||||
|         /// <param name="normalizedEmail"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<bool> IsNormalizedEmailConfirmedAsync( | ||||
|            string normalizedEmail, | ||||
|            CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 通过手机号查询用户 | ||||
|         /// </summary> | ||||
|         /// <param name="phoneNumber">手机号码</param> | ||||
|         /// <param name="isConfirmed">是否已确认过</param> | ||||
|         /// <param name="includeDetails"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<IdentityUser> FindByPhoneNumberAsync( | ||||
|             string phoneNumber, | ||||
|             bool isConfirmed = true, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 通过用户主键列表获取用户 | ||||
|         /// </summary> | ||||
|         /// <param name="userIds"></param> | ||||
|         /// <param name="includeDetails"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<List<IdentityUser>> GetListByIdListAsync( | ||||
|             List<Guid> userIds, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 获取用户所有的组织机构列表 | ||||
|         /// </summary> | ||||
|         /// <param name="userId"></param> | ||||
|         /// <param name="filter"></param> | ||||
|         /// <param name="includeDetails"></param> | ||||
|         /// <param name="skipCount"></param> | ||||
|         /// <param name="maxResultCount"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             Guid userId, | ||||
|             string filter = null, | ||||
|             bool includeDetails = false, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         ///  | ||||
|         /// </summary> | ||||
|         /// <param name="organizationUnitId"></param> | ||||
|         /// <param name="filter"></param> | ||||
|         /// <param name="cancellationToken"></param> | ||||
|         /// <returns></returns> | ||||
|         Task<long> GetUsersInOrganizationUnitCountAsync( | ||||
|             Guid organizationUnitId, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityUser>> GetUsersInOrganizationUnitAsync( | ||||
|             Guid organizationUnitId, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<long> GetUsersInOrganizationsListCountAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityUser>> GetUsersInOrganizationsListAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<long> GetUsersInOrganizationUnitWithChildrenCountAsync( | ||||
|             string code, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default); | ||||
| 
 | ||||
|         Task<List<IdentityUser>> GetUsersInOrganizationUnitWithChildrenAsync( | ||||
|             string code, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,39 @@ | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 短信安全令牌验证缓存 | ||||
|     /// </summary> | ||||
|     public class SmsSecurityTokenCacheItem | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// 用于验证的Token | ||||
|         /// </summary> | ||||
|         public string Token { get; set; } | ||||
|         /// <summary> | ||||
|         /// 用于验证的安全令牌 | ||||
|         /// </summary> | ||||
|         public string SecurityToken { get; set; } | ||||
| 
 | ||||
|         public SmsSecurityTokenCacheItem() | ||||
|         { | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         public SmsSecurityTokenCacheItem(string token, string securityToken) | ||||
|         { | ||||
|             Token = token; | ||||
|             SecurityToken = securityToken; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// 生成查询Key | ||||
|         /// </summary> | ||||
|         /// <param name="phoneNumber">手机号</param> | ||||
|         /// <param name="purpose">安全令牌用途</param> | ||||
|         /// <returns></returns> | ||||
|         public static string CalculateCacheKey(string phoneNumber, string purpose) | ||||
|         { | ||||
|             return "Totp:" + purpose + ";p:" + phoneNumber; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,19 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 	 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>net6.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\Sanhe.Abp.Identity.Domain\Sanhe.Abp.Identity.Domain.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| </Project> | ||||
| @ -0,0 +1,37 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Identity.EntityFrameworkCore; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.EntityFrameworkCore | ||||
| { | ||||
|     [DependsOn(typeof(AbpIdentityDomainModule))] | ||||
|     [DependsOn(typeof(Volo.Abp.Identity.EntityFrameworkCore.AbpIdentityEntityFrameworkCoreModule))] | ||||
|     public class AbpIdentityEntityFrameworkCoreModule : AbpModule | ||||
|     { | ||||
|         // private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); | ||||
| 
 | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             context.Services.AddAbpDbContext<IdentityDbContext>(options => | ||||
|             { | ||||
|                 options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>(); | ||||
|                 options.AddRepository<IdentityUser, EfCoreIdentityUserRepository>(); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         //public override void PostConfigureServices(ServiceConfigurationContext context) | ||||
|         //{ | ||||
|         //    OneTimeRunner.Run(() => | ||||
|         //    { | ||||
|         //        ObjectExtensionManager.Instance | ||||
|         //            .MapEfCoreProperty<IdentityUser, string>( | ||||
|         //                ExtensionIdentityUserConsts.AvatarUrlField, | ||||
|         //                (etb, prop) => | ||||
|         //                { | ||||
|         //                    prop.HasMaxLength(ExtensionIdentityUserConsts.MaxAvatarUrlLength); | ||||
|         //                }); | ||||
|         //    }); | ||||
|         //} | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,97 @@ | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Linq.Dynamic.Core; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.EntityFrameworkCore; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Identity.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.EntityFrameworkCore | ||||
| { | ||||
|     public class EfCoreIdentityRoleRepository : Volo.Abp.Identity.EntityFrameworkCore.EfCoreIdentityRoleRepository, IIdentityRoleRepository | ||||
|     { | ||||
|         public EfCoreIdentityRoleRepository( | ||||
|             IDbContextProvider<IIdentityDbContext> dbContextProvider) | ||||
|             : base(dbContextProvider) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityRole>> GetListByIdListAsync( | ||||
|             List<Guid> roleIds, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default | ||||
|             ) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(includeDetails) | ||||
|                 .Where(role => roleIds.Contains(role.Id)) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             Guid id, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from roleOU in dbContext.Set<OrganizationUnitRole>() | ||||
|                         join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) on roleOU.OrganizationUnitId equals ou.Id | ||||
|                         where roleOU.RoleId == id | ||||
|                         select ou; | ||||
| 
 | ||||
|             return await query.ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             IEnumerable<string> roleNames, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from roleOU in dbContext.Set<OrganizationUnitRole>() | ||||
|                         join role in dbContext.Roles on roleOU.RoleId equals role.Id | ||||
|                         join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) on roleOU.OrganizationUnitId equals ou.Id | ||||
|                         where roleNames.Contains(role.Name) | ||||
|                         select ou; | ||||
| 
 | ||||
|             return await query.ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityRole>> GetRolesInOrganizationsListAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             var query = from roleOu in (await GetDbContextAsync()).Set<OrganizationUnitRole>() | ||||
|                         join user in await GetDbSetAsync() on roleOu.RoleId equals user.Id | ||||
|                         where organizationUnitIds.Contains(roleOu.OrganizationUnitId) | ||||
|                         select user; | ||||
|             return await query.ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityRole>> GetRolesInOrganizationUnitAsync( | ||||
|             Guid organizationUnitId, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             var query = from roleOu in (await GetDbContextAsync()).Set<OrganizationUnitRole>() | ||||
|                         join user in await GetDbSetAsync() on roleOu.RoleId equals user.Id | ||||
|                         where roleOu.OrganizationUnitId == organizationUnitId | ||||
|                         select user; | ||||
|             return await query.ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityRole>> GetRolesInOrganizationUnitWithChildrenAsync( | ||||
|             string code, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from roleOU in dbContext.Set<OrganizationUnitRole>() | ||||
|                         join user in await GetDbSetAsync() on roleOU.RoleId equals user.Id | ||||
|                         join ou in dbContext.Set<OrganizationUnit>() on roleOU.OrganizationUnitId equals ou.Id | ||||
|                         where ou.Code.StartsWith(code) | ||||
|                         select user; | ||||
|             return await query.ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,238 @@ | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Linq.Dynamic.Core; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.EntityFrameworkCore; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Identity.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity.EntityFrameworkCore | ||||
| { | ||||
|     public class EfCoreIdentityUserRepository : Volo.Abp.Identity.EntityFrameworkCore.EfCoreIdentityUserRepository, IIdentityUserRepository | ||||
|     { | ||||
|         public EfCoreIdentityUserRepository( | ||||
|             IDbContextProvider<IIdentityDbContext> dbContextProvider) | ||||
|             : base(dbContextProvider) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<bool> IsPhoneNumberUedAsync( | ||||
|             string phoneNumber, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(false) | ||||
|                 .AnyAsync(user => user.PhoneNumber == phoneNumber, | ||||
|                     GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<bool> IsPhoneNumberConfirmedAsync( | ||||
|             string phoneNumber, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(false) | ||||
|                 .AnyAsync(user => user.PhoneNumber == phoneNumber && user.PhoneNumberConfirmed, | ||||
|                     GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<bool> IsNormalizedEmailConfirmedAsync( | ||||
|            string normalizedEmail, | ||||
|            CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(false) | ||||
|                 .AnyAsync(user => user.NormalizedEmail == normalizedEmail && user.EmailConfirmed, | ||||
|                     GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<IdentityUser> FindByPhoneNumberAsync( | ||||
|             string phoneNumber, | ||||
|             bool isConfirmed = true, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(includeDetails) | ||||
|                .Where(user => user.PhoneNumber == phoneNumber && user.PhoneNumberConfirmed == isConfirmed) | ||||
|                .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityUser>> GetListByIdListAsync( | ||||
|             List<Guid> userIds, | ||||
|             bool includeDetails = false, | ||||
|             CancellationToken cancellationToken = default | ||||
|             ) | ||||
|         { | ||||
|             return await (await GetDbSetAsync()).IncludeDetails(includeDetails) | ||||
|                 .Where(user => userIds.Contains(user.Id)) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<OrganizationUnit>> GetOrganizationUnitsAsync( | ||||
|             Guid id, | ||||
|             string filter = null, | ||||
|             bool includeDetails = false, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             //var userUoDbSet = dbContext.Set<IdentityUserOrganizationUnit>(); | ||||
|             //var roleUoDbSet = dbContext.Set<OrganizationUnitRole>(); | ||||
|             //var userRoleDbSet = dbContext.Set<IdentityUserRole>(); | ||||
| 
 | ||||
|             //var userUo = from usrUo in userUoDbSet | ||||
|             //             join usr in dbContext.Users on usrUo.UserId equals usr.Id | ||||
|             //             join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) | ||||
|             //                on usrUo.OrganizationUnitId equals ou.Id | ||||
|             //             where usr.Id == id | ||||
|             //             select ou; | ||||
| 
 | ||||
|             //var roleUo = from urol in userRoleDbSet | ||||
|             //             join rol in dbContext.Roles on urol.RoleId equals rol.Id | ||||
|             //             join rolUo in roleUoDbSet on rol.Id equals rolUo.RoleId | ||||
|             //             join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) | ||||
|             //                on rolUo.OrganizationUnitId equals ou.Id | ||||
|             //             where urol.UserId == id | ||||
|             //             select ou; | ||||
| 
 | ||||
|             var query = from userOU in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join ro in dbContext.Set<IdentityUserRole>() on userOU.UserId equals ro.UserId | ||||
|                         join ou in dbContext.OrganizationUnits.IncludeDetails(includeDetails) | ||||
|                             on userOU.OrganizationUnitId equals ou.Id | ||||
|                         where userOU.UserId == id | ||||
|                         select ou; | ||||
| 
 | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), ou => ou.Code.Contains(filter) || ou.DisplayName.Contains(filter)) | ||||
|                 .PageBy(skipCount, maxResultCount) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<long> GetUsersInOrganizationUnitCountAsync( | ||||
|             Guid organizationUnitId, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         where userOu.OrganizationUnitId == organizationUnitId | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .LongCountAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityUser>> GetUsersInOrganizationUnitAsync( | ||||
|             Guid organizationUnitId, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         where userOu.OrganizationUnitId == organizationUnitId | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .PageBy(skipCount, maxResultCount) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<long> GetUsersInOrganizationsListCountAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         where organizationUnitIds.Contains(userOu.OrganizationUnitId) | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .LongCountAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityUser>> GetUsersInOrganizationsListAsync( | ||||
|             List<Guid> organizationUnitIds, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         where organizationUnitIds.Contains(userOu.OrganizationUnitId) | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .PageBy(skipCount, maxResultCount) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<long> GetUsersInOrganizationUnitWithChildrenCountAsync( | ||||
|             string code, | ||||
|             string filter = null, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         join ou in dbContext.Set<OrganizationUnit>() on userOu.OrganizationUnitId equals ou.Id | ||||
|                         where ou.Code.StartsWith(code) | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .LongCountAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
| 
 | ||||
|         public virtual async Task<List<IdentityUser>> GetUsersInOrganizationUnitWithChildrenAsync( | ||||
|             string code, | ||||
|             string filter = null, | ||||
|             int skipCount = 1, | ||||
|             int maxResultCount = 10, | ||||
|             CancellationToken cancellationToken = default | ||||
|         ) | ||||
|         { | ||||
|             var dbContext = await GetDbContextAsync(); | ||||
|             var query = from userOu in dbContext.Set<IdentityUserOrganizationUnit>() | ||||
|                         join user in await GetDbSetAsync() on userOu.UserId equals user.Id | ||||
|                         join ou in dbContext.Set<OrganizationUnit>() on userOu.OrganizationUnitId equals ou.Id | ||||
|                         where ou.Code.StartsWith(code) | ||||
|                         select user; | ||||
|             return await query | ||||
|                 .WhereIf(!filter.IsNullOrWhiteSpace(), | ||||
|                     user => user.Name.Contains(filter) || user.UserName.Contains(filter) || | ||||
|                         user.Surname.Contains(filter) || user.Email.Contains(filter) || | ||||
|                         user.PhoneNumber.Contains(filter)) | ||||
|                 .PageBy(skipCount, maxResultCount) | ||||
|                 .ToListAsync(GetCancellationToken(cancellationToken)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,19 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.HttpApi.Client" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\Sanhe.Abp.Identity.Application.Contracts\Sanhe.Abp.Identity.Application.Contracts.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| </Project> | ||||
| @ -0,0 +1,20 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Volo.Abp.Identity; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn( | ||||
|         typeof(Volo.Abp.Identity.AbpIdentityHttpApiClientModule), | ||||
|         typeof(AbpIdentityApplicationContractsModule))] | ||||
|     public class AbpIdentityHttpApiClientModule : AbpModule | ||||
|     { | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             context.Services.AddHttpClientProxies( | ||||
|                 typeof(AbpIdentityApplicationContractsModule).Assembly, | ||||
|                 IdentityRemoteServiceConsts.RemoteServiceName | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,19 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>net6.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 		<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\Sanhe.Abp.Identity.Application.Contracts\Sanhe.Abp.Identity.Application.Contracts.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Identity.HttpApi" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,27 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Volo.Abp.AspNetCore.Mvc.Localization; | ||||
| using Volo.Abp.Identity.Localization; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [DependsOn( | ||||
|         typeof(Volo.Abp.Identity.AbpIdentityHttpApiModule), | ||||
|         typeof(AbpIdentityApplicationContractsModule))] | ||||
|     public class AbpIdentityHttpApiModule : AbpModule | ||||
|     { | ||||
|         public override void PreConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => | ||||
|             { | ||||
|                 options.AddAssemblyResource(typeof(IdentityResource), typeof(AbpIdentityApplicationContractsModule).Assembly); | ||||
|                 options.AddAssemblyResource(typeof(IdentityResource), typeof(Volo.Abp.Identity.AbpIdentityApplicationContractsModule).Assembly); | ||||
|             }); | ||||
| 
 | ||||
|             PreConfigure<IMvcBuilder>(mvcBuilder => | ||||
|             { | ||||
|                 mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpIdentityHttpApiModule).Assembly); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.AspNetCore.Mvc; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [RemoteService(true, Name = IdentityRemoteServiceConsts.RemoteServiceName)] | ||||
|     [Area("identity")] | ||||
|     [ControllerName("ClaimType")] | ||||
|     [Route("api/identity/claim-types")] | ||||
|     public class IdentityClaimTypeController : AbpController, IIdentityClaimTypeAppService | ||||
|     { | ||||
|         protected IIdentityClaimTypeAppService IdentityClaimTypeAppService { get; } | ||||
|         public IdentityClaimTypeController(IIdentityClaimTypeAppService identityClaimTypeAppService) | ||||
|         { | ||||
|             IdentityClaimTypeAppService = identityClaimTypeAppService; | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         public virtual async Task<IdentityClaimTypeDto> CreateAsync(IdentityClaimTypeCreateDto input) | ||||
|         { | ||||
|             return await IdentityClaimTypeAppService.CreateAsync(input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task DeleteAsync(Guid id) | ||||
|         { | ||||
|             await IdentityClaimTypeAppService.DeleteAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("actived-list")] | ||||
|         public virtual async Task<ListResultDto<IdentityClaimTypeDto>> GetAllListAsync() | ||||
|         { | ||||
|             return await IdentityClaimTypeAppService.GetAllListAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task<IdentityClaimTypeDto> GetAsync(Guid id) | ||||
|         { | ||||
|             return await IdentityClaimTypeAppService.GetAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         public virtual async Task<PagedResultDto<IdentityClaimTypeDto>> GetListAsync(IdentityClaimTypeGetByPagedDto input) | ||||
|         { | ||||
|             return await IdentityClaimTypeAppService.GetListAsync(input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task<IdentityClaimTypeDto> UpdateAsync(Guid id, IdentityClaimTypeUpdateDto input) | ||||
|         { | ||||
|             return await IdentityClaimTypeAppService.UpdateAsync(id, input); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,82 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.AspNetCore.Mvc; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [RemoteService(true, Name = IdentityRemoteServiceConsts.RemoteServiceName)] | ||||
|     [Area("identity")] | ||||
|     [ControllerName("Role")] | ||||
|     [Route("api/identity/roles")] | ||||
|     public class IdentityRoleController : AbpController, IIdentityRoleAppService | ||||
|     { | ||||
|         protected IIdentityRoleAppService RoleAppService { get; } | ||||
|         public IdentityRoleController( | ||||
|             IIdentityRoleAppService roleAppService) | ||||
|         { | ||||
|             RoleAppService = roleAppService; | ||||
|         } | ||||
| 
 | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/organization-units")] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id) | ||||
|         { | ||||
|             return await RoleAppService.GetOrganizationUnitsAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/organization-units")] | ||||
|         public virtual async Task SetOrganizationUnitsAsync(Guid id, IdentityRoleAddOrRemoveOrganizationUnitDto input) | ||||
|         { | ||||
|             await RoleAppService.SetOrganizationUnitsAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}/organization-units/{ouId}")] | ||||
|         public virtual async Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId) | ||||
|         { | ||||
|             await RoleAppService.RemoveOrganizationUnitsAsync(id, ouId); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Claim | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id) | ||||
|         { | ||||
|             return await RoleAppService.GetClaimsAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task AddClaimAsync(Guid id, IdentityRoleClaimCreateDto input) | ||||
|         { | ||||
|             await RoleAppService.AddClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task UpdateClaimAsync(Guid id, IdentityRoleClaimUpdateDto input) | ||||
|         { | ||||
|             await RoleAppService.UpdateClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task DeleteClaimAsync(Guid id, IdentityRoleClaimDeleteDto input) | ||||
|         { | ||||
|             await RoleAppService.DeleteClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,104 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.AspNetCore.Mvc; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [RemoteService(true, Name = IdentityRemoteServiceConsts.RemoteServiceName)] | ||||
|     [Area("identity")] | ||||
|     [ControllerName("User")] | ||||
|     [Route("api/identity/users")] | ||||
|     public class IdentityUserController : AbpController, IIdentityUserAppService | ||||
|     { | ||||
|         protected IIdentityUserAppService UserAppService { get; } | ||||
|         public IdentityUserController( | ||||
|             IIdentityUserAppService userAppService) | ||||
|         { | ||||
|             UserAppService = userAppService; | ||||
|         } | ||||
| 
 | ||||
|         #region OrganizationUnit | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/organization-units")] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetOrganizationUnitsAsync(Guid id) | ||||
|         { | ||||
|             return await UserAppService.GetOrganizationUnitsAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/organization-units")] | ||||
|         public virtual async Task SetOrganizationUnitsAsync(Guid id, IdentityUserOrganizationUnitUpdateDto input) | ||||
|         { | ||||
|             await UserAppService.SetOrganizationUnitsAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}/organization-units/{ouId}")] | ||||
|         public virtual async Task RemoveOrganizationUnitsAsync(Guid id, Guid ouId) | ||||
|         { | ||||
|             await UserAppService.RemoveOrganizationUnitsAsync(id, ouId); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
|         #region Claim | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task<ListResultDto<IdentityClaimDto>> GetClaimsAsync(Guid id) | ||||
|         { | ||||
|             return await UserAppService.GetClaimsAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task AddClaimAsync(Guid id, IdentityUserClaimCreateDto input) | ||||
|         { | ||||
|             await UserAppService.AddClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task UpdateClaimAsync(Guid id, IdentityUserClaimUpdateDto input) | ||||
|         { | ||||
|             await UserAppService.UpdateClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}/claims")] | ||||
|         public virtual async Task DeleteClaimAsync(Guid id, IdentityUserClaimDeleteDto input) | ||||
|         { | ||||
|             await UserAppService.DeleteClaimAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         #endregion | ||||
| 
 | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("change-two-factor")] | ||||
|         public virtual async Task ChangeTwoFactorEnabledAsync(Guid id, TwoFactorEnabledDto input) | ||||
|         { | ||||
|             await UserAppService.ChangeTwoFactorEnabledAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/lock/{seconds}")] | ||||
|         public virtual async Task LockAsync(Guid id, int seconds) | ||||
|         { | ||||
|             await UserAppService.LockAsync(id, seconds); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/unlock")] | ||||
|         public virtual async Task UnLockAsync(Guid id) | ||||
|         { | ||||
|             await UserAppService.UnLockAsync(id); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,143 @@ | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Sanhe.Abp.Identity.Dto; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp; | ||||
| using Volo.Abp.Application.Dtos; | ||||
| using Volo.Abp.AspNetCore.Mvc; | ||||
| using Volo.Abp.Identity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.Identity | ||||
| { | ||||
|     [RemoteService(Name = IdentityRemoteServiceConsts.RemoteServiceName)] | ||||
|     [Area("identity")] | ||||
|     [ControllerName("organization-units")] | ||||
|     [Route("api/identity/organization-units")] | ||||
|     public class OrganizationUnitController : AbpController, IOrganizationUnitAppService | ||||
|     { | ||||
|         protected IOrganizationUnitAppService OrganizationUnitAppService { get; } | ||||
| 
 | ||||
|         public OrganizationUnitController( | ||||
|             IOrganizationUnitAppService organizationUnitAppService) | ||||
|         { | ||||
|             OrganizationUnitAppService = organizationUnitAppService; | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         public virtual async Task<OrganizationUnitDto> CreateAsync(OrganizationUnitCreateDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.CreateAsync(input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpDelete] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task DeleteAsync(Guid id) | ||||
|         { | ||||
|             await OrganizationUnitAppService.DeleteAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("find-children")] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> FindChildrenAsync(OrganizationUnitGetChildrenDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.FindChildrenAsync(input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task<OrganizationUnitDto> GetAsync(Guid id) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("root-node")] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetRootAsync() | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetRootAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("last-children")] | ||||
|         public virtual async Task<OrganizationUnitDto> GetLastChildOrNullAsync(Guid? parentId) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetLastChildOrNullAsync(parentId); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("all")] | ||||
|         public virtual async Task<ListResultDto<OrganizationUnitDto>> GetAllListAsync() | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetAllListAsync(); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         public virtual async Task<PagedResultDto<OrganizationUnitDto>> GetListAsync(OrganizationUnitGetByPagedDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetListAsync(input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/role-names")] | ||||
|         public virtual async Task<ListResultDto<string>> GetRoleNamesAsync(Guid id) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetRoleNamesAsync(id); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/unadded-roles")] | ||||
|         public virtual async Task<PagedResultDto<IdentityRoleDto>> GetUnaddedRolesAsync(Guid id, OrganizationUnitGetUnaddedRoleByPagedDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetUnaddedRolesAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/roles")] | ||||
|         public virtual async Task<PagedResultDto<IdentityRoleDto>> GetRolesAsync(Guid id, PagedAndSortedResultRequestDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetRolesAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/unadded-users")] | ||||
|         public virtual async Task<PagedResultDto<IdentityUserDto>> GetUnaddedUsersAsync(Guid id, OrganizationUnitGetUnaddedUserByPagedDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetUnaddedUsersAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpGet] | ||||
|         [Route("{id}/users")] | ||||
|         public virtual async Task<PagedResultDto<IdentityUserDto>> GetUsersAsync(Guid id, GetIdentityUsersInput input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.GetUsersAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         [Route("{id}/users")] | ||||
|         public virtual async Task AddUsersAsync(Guid id, OrganizationUnitAddUserDto input) | ||||
|         { | ||||
|             await OrganizationUnitAppService.AddUsersAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPost] | ||||
|         [Route("{id}/roles")] | ||||
|         public virtual async Task AddRolesAsync(Guid id, OrganizationUnitAddRoleDto input) | ||||
|         { | ||||
|             await OrganizationUnitAppService.AddRolesAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}/move")] | ||||
|         public virtual async Task MoveAsync(Guid id, OrganizationUnitMoveDto input) | ||||
|         { | ||||
|             await OrganizationUnitAppService.MoveAsync(id, input); | ||||
|         } | ||||
| 
 | ||||
|         [HttpPut] | ||||
|         [Route("{id}")] | ||||
|         public virtual async Task<OrganizationUnitDto> UpdateAsync(Guid id, OrganizationUnitUpdateDto input) | ||||
|         { | ||||
|             return await OrganizationUnitAppService.UpdateAsync(id, input); | ||||
|         } | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue