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