diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs index 3cd71e3af..d412353b4 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.IdentityServer.Localization; using Volo.Abp.Localization; @@ -13,6 +10,7 @@ namespace LINGYUN.Abp.IdentityServer { var identityServerGroup = context.AddGroup(AbpIdentityServerPermissions.GroupName, L("Permissions:IdentityServer")); + // 客户端权限 var clientPermissions = identityServerGroup.AddPermission(AbpIdentityServerPermissions.Clients.Default, L("Permissions:Clients")); clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Create, L("Permissions:Create")); clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Update, L("Permissions:Update")); @@ -21,20 +19,41 @@ namespace LINGYUN.Abp.IdentityServer clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Delete, L("Permissions:Delete")); clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.ManagePermissions, L("Permissions:ManagePermissions")); + // 客户端声明权限 var clientClaimPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Claims.Default, L("Permissions:Clients:Claims")); clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Create, L("Permissions:Create")); clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Update, L("Permissions:Update")); clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Delete, L("Permissions:Delete")); + // 客户端密钥权限 var clientSecretPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Default, L("Permissions:Clients:Secrets")); clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Create, L("Permissions:Create")); clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Update, L("Permissions:Update")); clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Delete, L("Permissions:Delete")); + // 客户端属性权限 var clientPropertyPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Properties.Default, L("Permissions:Clients:Properties")); clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Create, L("Permissions:Create")); clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Update, L("Permissions:Update")); clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Delete, L("Permissions:Delete")); + + // Api资源权限 + var apiResourcePermissions = identityServerGroup.AddPermission(AbpIdentityServerPermissions.ApiResources.Default, L("Permissions:ApiResources")); + apiResourcePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Create, L("Permissions:Create")); + apiResourcePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Update, L("Permissions:Update")); + apiResourcePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Delete, L("Permissions:Delete")); + + // Api作用域权限 + var apiResourceScopePermissions = apiResourcePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Scope.Default, L("Permissions:ApiResources:Scope")); + apiResourceScopePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Scope.Create, L("Permissions:Create")); + apiResourceScopePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Scope.Update, L("Permissions:Update")); + apiResourceScopePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Scope.Delete, L("Permissions:Delete")); + + // Api密钥权限 + var apiResourceSecretPermissions = apiResourcePermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Secrets.Default, L("Permissions:ApiResources:Secrets")); + apiResourceSecretPermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Secrets.Create, L("Permissions:Create")); + apiResourceSecretPermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Secrets.Update, L("Permissions:Update")); + apiResourceSecretPermissions.AddChild(AbpIdentityServerPermissions.ApiResources.Secrets.Delete, L("Permissions:Delete")); } protected virtual LocalizableString L(string name) diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs index 2bf4a5964..b825716e4 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs @@ -38,5 +38,28 @@ public const string Delete = Default + ".Delete"; } } + + public static class ApiResources + { + public const string Default = GroupName + ".ApiResources"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + public static class Scope + { + public const string Default = ApiResources.Default + ".Scope"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + } + + public static class Secrets + { + public const string Default = ApiResources.Default + ".Secrets"; + public const string Create = Default + ".Create"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + } + } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceClaimDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceClaimDto.cs new file mode 100644 index 000000000..220a9d8b6 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceClaimDto.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceClaimDto + { + public string Type { get; set; } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceCreateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceCreateDto.cs new file mode 100644 index 000000000..c468b0ff3 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceCreateDto.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.IdentityServer.ApiResources; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceCreateDto + { + [Required] + [StringLength(ApiResourceConsts.NameMaxLength)] + public string Name { get; set; } + + [StringLength(ApiResourceConsts.DisplayNameMaxLength)] + public string DisplayName { get; set; } + + [StringLength(ApiResourceConsts.DescriptionMaxLength)] + public string Description { get; set; } + + public bool Enabled { get; set; } + + public List UserClaims { get; set; } + public ApiResourceCreateDto() + { + Enabled = true; + UserClaims = new List(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceDto.cs new file mode 100644 index 000000000..094218d6f --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceDto.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceDto : FullAuditedEntityDto + { + public string Name { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public bool Enabled { get; set; } + + public List Secrets { get; set; } + + public List Scopes { get; set; } + + public List UserClaims { get; set; } + + public ApiResourceDto() + { + Scopes = new List(); + Secrets = new List(); + UserClaims = new List(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByIdInputDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByIdInputDto.cs new file mode 100644 index 000000000..e331fce50 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByIdInputDto.cs @@ -0,0 +1,9 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceGetByIdInputDto : EntityDto + { + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByPagedInputDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByPagedInputDto.cs new file mode 100644 index 000000000..b961408af --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByPagedInputDto.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceGetByPagedInputDto : PagedAndSortedResultRequestDto + { + public string Filter { get; set; } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceUpdateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceUpdateDto.cs new file mode 100644 index 000000000..c88f785ad --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceUpdateDto.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; +using Volo.Abp.IdentityServer.ApiResources; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiResourceUpdateDto + { + [Required] + public Guid Id { get; set; } + + [StringLength(ApiResourceConsts.DisplayNameMaxLength)] + public string DisplayName { get; set; } + + [StringLength(ApiResourceConsts.DescriptionMaxLength)] + public string Description { get; set; } + + public bool Enabled { get; set; } + + public List UserClaims { get; set; } + + public ApiResourceUpdateDto() + { + UserClaims = new List(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeClaimDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeClaimDto.cs new file mode 100644 index 000000000..09ce3df47 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeClaimDto.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiScopeClaimDto + { + public string Type { get; set; } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeCreateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeCreateDto.cs new file mode 100644 index 000000000..25470b601 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeCreateDto.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.IdentityServer.ApiResources; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiScopeCreateDto + { + [Required] + public Guid ApiResourceId { get; set; } + + [Required] + [StringLength(ApiScopeConsts.NameMaxLength)] + public string Name { get; set; } + + [StringLength(ApiScopeConsts.DisplayNameMaxLength)] + public string DisplayName { get; set; } + + [StringLength(ApiScopeConsts.DescriptionMaxLength)] + public string Description { get; set; } + + public bool Required { get; set; } + + public bool Emphasize { get; set; } + + public bool ShowInDiscoveryDocument { get; set; } + + public List UserClaims { get; set; } + + public ApiScopeCreateDto() + { + UserClaims = new List(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeDto.cs new file mode 100644 index 000000000..6e6a99f87 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeDto.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiScopeDto + { + public string Name { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public bool Required { get; set; } + + public bool Emphasize { get; set; } + + public bool ShowInDiscoveryDocument { get; set; } + + public List UserClaims { get; set; } + + public ApiScopeDto() + { + UserClaims = new List(); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeGetByNameInputDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeGetByNameInputDto.cs new file mode 100644 index 000000000..d306a5b07 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeGetByNameInputDto.cs @@ -0,0 +1,16 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.IdentityServer.ApiResources; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiScopeGetByNameInputDto + { + [Required] + public Guid ApiResourceId { get; set; } + + [Required] + [StringLength(ApiScopeConsts.NameMaxLength)] + public string Name { get; set; } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretCreateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretCreateDto.cs new file mode 100644 index 000000000..733d44137 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretCreateDto.cs @@ -0,0 +1,32 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.IdentityServer; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiSecretCreateDto + { + [Required] + public Guid ApiResourceId { get; set; } + + [Required] + [StringLength(SecretConsts.TypeMaxLength)] + public string Type { get; set; } + + public HashType HashType { get; set; } + + [Required] + [StringLength(SecretConsts.ValueMaxLength)] + public string Value { get; set; } + + [StringLength(SecretConsts.DescriptionMaxLength)] + public string Description { get; set; } + + public DateTime? Expiration { get; set; } + + public ApiSecretCreateDto() + { + HashType = 0; + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretDto.cs new file mode 100644 index 000000000..86293223a --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretDto.cs @@ -0,0 +1,6 @@ +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiSecretDto : SecretBaseDto + { + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretGetByTypeInputDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretGetByTypeInputDto.cs new file mode 100644 index 000000000..273ac0b34 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretGetByTypeInputDto.cs @@ -0,0 +1,20 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Volo.Abp.IdentityServer; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public class ApiSecretGetByTypeInputDto + { + [Required] + public Guid ApiResourceId { get; set; } + + [Required] + [StringLength(SecretConsts.TypeMaxLength)] + public string Type { get; set; } + + [Required] + [StringLength(SecretConsts.ValueMaxLength)] + public string Value { get; set; } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/IApiResourceAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/IApiResourceAppService.cs new file mode 100644 index 000000000..152582492 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/IApiResourceAppService.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + public interface IApiResourceAppService : IApplicationService + { + Task GetAsync(ApiResourceGetByIdInputDto apiResourceGetById); + + Task> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged); + + Task CreateAsync(ApiResourceCreateDto apiResourceCreate); + + Task UpdateAsync(ApiResourceUpdateDto apiResourceUpdate); + + Task DeleteAsync(ApiResourceGetByIdInputDto apiResourceGetById); + + Task AddSecretAsync(ApiSecretCreateDto apiSecretCreate); + + Task DeleteSecretAsync(ApiSecretGetByTypeInputDto apiSecretGetByType); + + Task AddScopeAsync(ApiScopeCreateDto apiScopeCreate); + + Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName); + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretCreateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretCreateDto.cs index e915f0de3..e4fb660e4 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretCreateDto.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretCreateDto.cs @@ -13,6 +13,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients [StringLength(SecretConsts.TypeMaxLength)] public string Type { get; set; } + public HashType HashType { get; set; } + [Required] [StringLength(SecretConsts.ValueMaxLength)] public string Value { get; set; } @@ -21,5 +23,10 @@ namespace LINGYUN.Abp.IdentityServer.Clients public string Description { get; set; } public DateTime? Expiration { get; set; } + + public ClientSecretCreateDto() + { + HashType = 0; + } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretUpdateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretUpdateDto.cs index 1442776e7..3d2096544 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretUpdateDto.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretUpdateDto.cs @@ -13,6 +13,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients [StringLength(SecretConsts.TypeMaxLength)] public string Type { get; set; } + public HashType HashType { get; set; } + [Required] [StringLength(SecretConsts.ValueMaxLength)] public string Value { get; set; } diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/HashType.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/HashType.cs new file mode 100644 index 000000000..b012beea2 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/HashType.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.IdentityServer +{ + public enum HashType + { + Sha256, + Sha512 + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json index 5758db3cb..d854559a2 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json @@ -12,6 +12,9 @@ "Permissions:Clients:Claims": "Client claim", "Permissions:Clients:Secrets": "Client secret", "Permissions:Clients:Properties": "Client property", + "Permissions:ApiResources": "ApiResources", + "Permissions:ApiResources:Scope": "Api scope", + "Permissions:ApiResources:Secrets": "Api secret", "ClientIdExisted": "Client id: {0} already exists!", "ClientClaimNotFound": "Client claim: {0} not found!", "ClientSecretNotFound": "Client secret: {0} not found!", diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json index 5088e5cb2..1d9082e91 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json @@ -12,6 +12,9 @@ "Permissions:Clients:Secrets": "客户端密钥", "Permissions:Clients:Properties": "客户端属性", "Permissions:Clients:Claims": "客户端声明", + "Permissions:ApiResources": "Api资源管理", + "Permissions:ApiResources:Scope": "授权范围", + "Permissions:ApiResources:Secrets": "Api密钥", "ClientIdExisted": "客户端标识: {0} 已经存在!", "ClientClaimNotFound": "客户端声明: {0} 不存在!", "ClientSecretNotFound": "客户端密钥: {0} 不存在!", diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs index 5679a5faa..db5bdfd9e 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs @@ -1,5 +1,7 @@ using AutoMapper; +using LINGYUN.Abp.IdentityServer.ApiResources; using LINGYUN.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; namespace LINGYUN.Abp.IdentityServer @@ -18,6 +20,12 @@ namespace LINGYUN.Abp.IdentityServer CreateMap(); CreateMap(); CreateMap(); + + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs new file mode 100644 index 000000000..2356b7492 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs @@ -0,0 +1,132 @@ +using IdentityServer4; +using IdentityServer4.Models; +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.IdentityServer.ApiResources; +using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + [Authorize(AbpIdentityServerPermissions.ApiResources.Default)] + public class ApiResourceAppService : AbpIdentityServerAppServiceBase, IApiResourceAppService + { + protected IApiResourceRepository ApiResourceRepository { get; } + + public ApiResourceAppService( + IApiResourceRepository apiResourceRepository) + { + ApiResourceRepository = apiResourceRepository; + } + + public virtual async Task GetAsync(ApiResourceGetByIdInputDto apiResourceGetById) + { + var apiResource = await ApiResourceRepository.GetAsync(apiResourceGetById.Id); + + return ObjectMapper.Map(apiResource); + } + + public virtual async Task> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged) + { + var apiResources = await ApiResourceRepository.GetListAsync(apiResourceGetByPaged.Sorting, + apiResourceGetByPaged.SkipCount, apiResourceGetByPaged.MaxResultCount); + var apiResourceCount = await ApiResourceRepository.GetCountAsync(); + + return new PagedResultDto(apiResourceCount, + ObjectMapper.Map, List>(apiResources)); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Create)] + public virtual async Task CreateAsync(ApiResourceCreateDto apiResourceCreate) + { + var apiResource = new ApiResource(GuidGenerator.Create(), apiResourceCreate.Name, + apiResourceCreate.DisplayName, apiResourceCreate.Description); + apiResource.Enabled = apiResourceCreate.Enabled; + foreach(var userClaim in apiResourceCreate.UserClaims) + { + apiResource.AddUserClaim(userClaim.Type); + } + apiResource = await ApiResourceRepository.InsertAsync(apiResource); + return ObjectMapper.Map(apiResource); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Update)] + public virtual async Task UpdateAsync(ApiResourceUpdateDto apiResourceUpdate) + { + var apiResource = await ApiResourceRepository.GetAsync(apiResourceUpdate.Id); + apiResource.DisplayName = apiResourceUpdate.DisplayName ?? apiResource.DisplayName; + apiResource.Description = apiResourceUpdate.Description ?? apiResource.Description; + apiResource.Enabled = apiResourceUpdate.Enabled; + + apiResource.RemoveAllUserClaims(); + foreach (var userClaim in apiResourceUpdate.UserClaims) + { + apiResource.AddUserClaim(userClaim.Type); + } + apiResource = await ApiResourceRepository.UpdateAsync(apiResource); + return ObjectMapper.Map(apiResource); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Delete)] + public virtual async Task DeleteAsync(ApiResourceGetByIdInputDto apiResourceGetById) + { + var apiResource = await ApiResourceRepository.GetAsync(apiResourceGetById.Id); + await ApiResourceRepository.DeleteAsync(apiResource); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Secrets.Create)] + public virtual async Task AddSecretAsync(ApiSecretCreateDto apiSecretCreate) + { + var apiResource = await ApiResourceRepository.GetAsync(apiSecretCreate.ApiResourceId); + var apiSecretValue = apiSecretCreate.Value; + var apiResourceSecret = apiResource.FindSecret(apiSecretValue, apiSecretCreate.Type); + if(apiResourceSecret == null) + { + if (IdentityServerConstants.SecretTypes.SharedSecret.Equals(apiSecretCreate.Type)) + { + if (apiSecretCreate.HashType == HashType.Sha256) + { + apiSecretValue = apiSecretCreate.Value.Sha256(); + } + else if (apiSecretCreate.HashType == HashType.Sha512) + { + apiSecretValue = apiSecretCreate.Value.Sha512(); + } + } + apiResource.AddSecret(apiSecretValue, apiSecretCreate.Expiration, apiSecretCreate.Type, apiSecretCreate.Description); + apiResourceSecret = apiResource.FindSecret(apiSecretValue, apiSecretCreate.Type); + } + + return ObjectMapper.Map(apiResourceSecret); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Secrets.Delete)] + public virtual async Task DeleteSecretAsync(ApiSecretGetByTypeInputDto apiSecretGetByType) + { + var apiResource = await ApiResourceRepository.GetAsync(apiSecretGetByType.ApiResourceId); + apiResource.RemoveSecret(apiSecretGetByType.Value, apiSecretGetByType.Type); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Scope.Create)] + public virtual async Task AddScopeAsync(ApiScopeCreateDto apiScopeCreate) + { + var apiResource = await ApiResourceRepository.GetAsync(apiScopeCreate.ApiResourceId); + var apiResourceScope = apiResource.FindScope(apiScopeCreate.Name); + if (apiResourceScope == null) + { + apiResource.AddScope(apiScopeCreate.Name, apiScopeCreate.DisplayName, apiScopeCreate.Description, + apiScopeCreate.Required, apiScopeCreate.Emphasize, apiScopeCreate.ShowInDiscoveryDocument); + apiResourceScope = apiResource.FindScope(apiScopeCreate.Name); + } + return ObjectMapper.Map(apiResourceScope); + } + + [Authorize(AbpIdentityServerPermissions.ApiResources.Scope.Delete)] + public virtual async Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName) + { + var apiResource = await ApiResourceRepository.GetAsync(apiScopeGetByName.ApiResourceId); + apiResource.RemoveScope(apiScopeGetByName.Name); + } + } +} diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs index 678ce5006..f6d100596 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs @@ -1,15 +1,18 @@ -using System; +using IdentityServer4; +using IdentityServer4.Models; +using Microsoft.AspNetCore.Authorization; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.Security.Encryption; +using Client = Volo.Abp.IdentityServer.Clients.Client; namespace LINGYUN.Abp.IdentityServer.Clients { + [Authorize(AbpIdentityServerPermissions.Clients.Default)] public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService { private IStringEncryptionService _encryptionService; @@ -22,6 +25,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients ClientRepository = clientRepository; } + [Authorize(AbpIdentityServerPermissions.Clients.Claims.Create)] public virtual async Task AddClaimAsync(ClientClaimCreateDto clientClaimCreate) { var client = await ClientRepository.GetAsync(clientClaimCreate.ClientId); @@ -32,6 +36,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(clientClaim); } + [Authorize(AbpIdentityServerPermissions.Clients.Properties.Create)] public virtual async Task AddPropertyAsync(ClientPropertyCreateDto clientPropertyCreate) { var client = await ClientRepository.GetAsync(clientPropertyCreate.ClientId); @@ -42,12 +47,30 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(clientProperty); } + [Authorize(AbpIdentityServerPermissions.Clients.Secrets.Create)] public virtual async Task AddSecretAsync(ClientSecretCreateDto clientSecretCreate) { var client = await ClientRepository.GetAsync(clientSecretCreate.ClientId); - var clientSecretValue = EncryptionService.Encrypt(clientSecretCreate.Value); + var clientSecretValue = clientSecretCreate.Value; + // 如果是 SharedSecret 类型的密钥 + // 采用 IdentityServer4 服务器扩展方法加密 + if (IdentityServerConstants.SecretTypes.SharedSecret.Equals(clientSecretCreate.Type)) + { + if(clientSecretCreate.HashType == HashType.Sha256) + { + clientSecretValue = clientSecretCreate.Value.Sha256(); + } + else if (clientSecretCreate.HashType == HashType.Sha512) + { + clientSecretValue = clientSecretCreate.Value.Sha512(); + } + } + else + { + clientSecretValue = EncryptionService.Encrypt(clientSecretCreate.Value); + } client.AddSecret(clientSecretValue, clientSecretCreate.Expiration, clientSecretCreate.Type, clientSecretCreate.Description); @@ -56,6 +79,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(clientSecret); } + [Authorize(AbpIdentityServerPermissions.Clients.Create)] public virtual async Task CreateAsync(ClientCreateDto clientCreate) { var clientIdExists = await ClientRepository.CheckClientIdExistAsync(clientCreate.ClientId); @@ -76,11 +100,13 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(client); } + [Authorize(AbpIdentityServerPermissions.Clients.Delete)] public virtual async Task DeleteAsync(ClientGetByIdInputDto clientGetByIdInput) { await ClientRepository.DeleteAsync(clientGetByIdInput.Id); } + [Authorize(AbpIdentityServerPermissions.Clients.Claims.Delete)] public virtual async Task DeleteClaimAsync(ClientClaimGetByKeyInputDto clientClaimGetByKey) { var client = await ClientRepository.GetAsync(clientClaimGetByKey.ClientId); @@ -88,6 +114,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients await ClientRepository.UpdateAsync(client); } + [Authorize(AbpIdentityServerPermissions.Clients.Properties.Delete)] public virtual async Task DeletePropertyAsync(ClientPropertyGetByKeyDto clientPropertyGetByKey) { var client = await ClientRepository.GetAsync(clientPropertyGetByKey.ClientId); @@ -95,6 +122,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients await ClientRepository.UpdateAsync(client); } + [Authorize(AbpIdentityServerPermissions.Clients.Secrets.Delete)] public virtual async Task DeleteSecretAsync(ClientSecretGetByTypeDto clientSecretGetByType) { var client = await ClientRepository.GetAsync(clientSecretGetByType.ClientId); @@ -102,6 +130,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients await ClientRepository.UpdateAsync(client); } + public virtual async Task GetAsync(ClientGetByIdInputDto clientGetById) { var client = await ClientRepository.GetAsync(clientGetById.Id); @@ -121,6 +150,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients ObjectMapper.Map, List>(clients)); } + [Authorize(AbpIdentityServerPermissions.Clients.Update)] public virtual async Task UpdateAsync(ClientUpdateInputDto clientUpdateInput) { var client = await ClientRepository.GetAsync(clientUpdateInput.Id); @@ -183,78 +213,60 @@ namespace LINGYUN.Abp.IdentityServer.Clients #region AllowScope - foreach(var scope in clientUpdateInput.Client.AllowedScopes) + client.RemoveAllScopes(); + foreach (var scope in clientUpdateInput.Client.AllowedScopes) { - var clientScope = client.FindScope(scope.Scope); - if (clientScope == null) - { - client.AddScope(scope.Scope); - } + client.AddScope(scope.Scope); } #endregion #region RedirectUris - foreach(var redirect in clientUpdateInput.Client.RedirectUris) + client.RemoveAllRedirectUris(); + foreach (var redirect in clientUpdateInput.Client.RedirectUris) { - var clientRedirect = client.FindRedirectUri(redirect.RedirectUri); - if(clientRedirect == null) - { - client.AddRedirectUri(redirect.RedirectUri); - } + client.AddRedirectUri(redirect.RedirectUri); } #endregion #region AllowedGrantTypes + client.RemoveAllAllowedGrantTypes(); foreach (var grantType in clientUpdateInput.Client.AllowedGrantTypes) { - var clientGrantType = client.FindGrantType(grantType.GrantType); - if (clientGrantType == null) - { - client.AddGrantType(grantType.GrantType); - } + client.AddGrantType(grantType.GrantType); } #endregion #region AllowedCorsOrigins + client.RemoveAllCorsOrigins(); foreach (var corgOrigin in clientUpdateInput.Client.AllowedCorsOrigins) { - var clientCorsOrigin = client.FindCorsOrigin(corgOrigin.Origin); - if (clientCorsOrigin == null) - { - client.AddCorsOrigin(corgOrigin.Origin); - } + client.AddCorsOrigin(corgOrigin.Origin); } #endregion #region PostLogoutRedirectUris + client.RemoveAllPostLogoutRedirectUris(); foreach (var logoutRedirect in clientUpdateInput.Client.PostLogoutRedirectUris) { - var clientLogoutRedirect = client.FindPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri); - if (clientLogoutRedirect == null) - { - client.AddPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri); - } + client.AddPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri); } #endregion #region IdentityProviderRestrictions + client.RemoveAllIdentityProviderRestrictions(); foreach (var provider in clientUpdateInput.Client.IdentityProviderRestrictions) { - var clientIdentityProvider = client.FindIdentityProviderRestriction(provider.Provider); - if (clientIdentityProvider == null) - { - client.AddIdentityProviderRestriction(provider.Provider); - } + client.AddIdentityProviderRestriction(provider.Provider); } #endregion @@ -264,6 +276,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(client); } + [Authorize(AbpIdentityServerPermissions.Clients.Claims.Update)] public virtual async Task UpdateClaimAsync(ClientClaimUpdateDto clientClaimUpdate) { var client = await ClientRepository.GetAsync(clientClaimUpdate.ClientId); @@ -278,6 +291,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(clientClaim); } + [Authorize(AbpIdentityServerPermissions.Clients.Properties.Update)] public virtual async Task UpdatePropertyAsync(ClientPropertyUpdateDto clientPropertyUpdate) { var client = await ClientRepository.GetAsync(clientPropertyUpdate.ClientId); @@ -294,6 +308,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients return ObjectMapper.Map(clientProperty); } + [Authorize(AbpIdentityServerPermissions.Clients.Secrets.Update)] public virtual async Task UpdateSecretAsync(ClientSecretUpdateDto clientSecretUpdate) { var client = await ClientRepository.GetAsync(clientSecretUpdate.ClientId); @@ -305,7 +320,26 @@ namespace LINGYUN.Abp.IdentityServer.Clients throw new UserFriendlyException( L[AbpIdentityServerErrorConsts.ClientSecretNotFound, clientSecretUpdate.Type]); } - clientSecret.Value = EncryptionService.Encrypt(clientSecretUpdate.Value); + var clientSecretValue = clientSecret.Value; + + // 如果是 SharedSecret 类型的密钥 + // 采用 IdentityServer4 服务器扩展方法加密 + if (IdentityServerConstants.SecretTypes.SharedSecret.Equals(clientSecretUpdate.Type)) + { + if (clientSecretUpdate.HashType == HashType.Sha256) + { + clientSecretValue = clientSecretUpdate.Value.Sha256(); + } + else if (clientSecretUpdate.HashType == HashType.Sha512) + { + clientSecretValue = clientSecretUpdate.Value.Sha512(); + } + } + else + { + clientSecretValue = EncryptionService.Encrypt(clientSecretUpdate.Value); + } + clientSecret.Value = clientSecretValue; return ObjectMapper.Map(clientSecret); } diff --git a/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.HttpApi/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceController.cs b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.HttpApi/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceController.cs new file mode 100644 index 000000000..791d183f7 --- /dev/null +++ b/aspnet-core/modules/identityServer/LINGYUN.IdentityServer.HttpApi/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceController.cs @@ -0,0 +1,81 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.IdentityServer.ApiResources +{ + [RemoteService(Name = AbpIdentityServerConsts.RemoteServiceName)] + [Area("IdentityServer")] + [Route("api/IdentityServer/ApiResources")] + public class ApiResourceController : AbpController, IApiResourceAppService + { + protected IApiResourceAppService ApiResourceAppService { get; } + public ApiResourceController( + IApiResourceAppService apiResourceAppService) + { + ApiResourceAppService = apiResourceAppService; + } + + [HttpGet] + [Route("{Id}")] + public virtual async Task GetAsync(ApiResourceGetByIdInputDto apiResourceGetById) + { + return await ApiResourceAppService.GetAsync(apiResourceGetById); + } + + [HttpGet] + public virtual async Task> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged) + { + return await ApiResourceAppService.GetAsync(apiResourceGetByPaged); + } + + [HttpPost] + public virtual async Task CreateAsync(ApiResourceCreateDto apiResourceCreate) + { + return await ApiResourceAppService.CreateAsync(apiResourceCreate); + } + + [HttpPut] + public virtual async Task UpdateAsync(ApiResourceUpdateDto apiResourceUpdate) + { + return await ApiResourceAppService.UpdateAsync(apiResourceUpdate); + } + + [HttpDelete] + [Route("{Id}")] + public virtual async Task DeleteAsync(ApiResourceGetByIdInputDto apiResourceGetById) + { + await ApiResourceAppService.DeleteAsync(apiResourceGetById); + } + + [HttpPost] + [Route("Secrets")] + public virtual async Task AddSecretAsync(ApiSecretCreateDto apiSecretCreate) + { + return await ApiResourceAppService.AddSecretAsync(apiSecretCreate); + } + + [HttpDelete] + [Route("Secrets")] + public virtual async Task DeleteSecretAsync(ApiSecretGetByTypeInputDto apiSecretGetByType) + { + await ApiResourceAppService.DeleteSecretAsync(apiSecretGetByType); + } + + [HttpPost] + [Route("Scopes")] + public virtual async Task AddScopeAsync(ApiScopeCreateDto apiScopeCreate) + { + return await ApiResourceAppService.AddScopeAsync(apiScopeCreate); + } + + [HttpDelete] + [Route("Scopes")] + public virtual async Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName) + { + await ApiResourceAppService.DeleteScopeAsync(apiScopeGetByName); + } + } +} diff --git a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs index 654453936..0a589966c 100644 --- a/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs +++ b/aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs @@ -158,12 +158,12 @@ namespace AuthServer.Host app.UseCorrelationId(); app.UseVirtualFiles(); + app.UseAbpRequestLocalization(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); app.UseJwtTokenMiddleware(); app.UseMultiTenancy(); - app.UseAbpRequestLocalization(); app.UseIdentityServer(); app.UseSwagger(); app.UseSwaggerUI(options => diff --git a/vueJs/src/api/apigateway.ts b/vueJs/src/api/apigateway.ts index c3488fa7f..72efb3516 100644 --- a/vueJs/src/api/apigateway.ts +++ b/vueJs/src/api/apigateway.ts @@ -311,7 +311,7 @@ export class ReRouteBase { reRouteIsCaseSensitive? = true serviceName? = '' serviceNamespace? = '' - downstreamScheme? = '' + downstreamScheme? = 'HTTP' downstreamHostAndPorts!: HostAndPort[] upstreamHost = '' key? = '' diff --git a/vueJs/src/api/apiresources.ts b/vueJs/src/api/apiresources.ts new file mode 100644 index 000000000..d89b6c259 --- /dev/null +++ b/vueJs/src/api/apiresources.ts @@ -0,0 +1,280 @@ +import ApiService from './serviceBase' +import { pagerFormat } from '@/utils/index' +import { FullAuditedEntityDto, PagedAndSortedResultRequestDto, PagedResultDto } from './types' + +const serviceUrl = process.env.VUE_APP_BASE_API + +export default class ApiResourceService { + /** + * 获取Api资源 + * @param id Api资源标识 + */ + public static getApiResourceById(id: string) { + let _url = '/api/IdentityServer/ApiResources/' + _url += id + return ApiService.Get(_url, serviceUrl) + } + + /** + * 获取Api资源列表 + * @param payload 查询参数 + */ + public static getApiResources(payload: ApiResourceGetByPaged) { + let _url = '/api/IdentityServer/ApiResources' + _url += '?filter=' + payload.filter + _url += '&sorting=' + payload.sorting + _url += '&skipCount=' + pagerFormat(payload.skipCount) + _url += '&maxResultCount=' + payload.maxResultCount + return ApiService.Get>(_url, serviceUrl) + } + + /** + * 创建Api资源 + * @param payload api资源参数 + */ + public static createApiResource(payload: ApiResourceCreate) { + const _url = '/api/IdentityServer/ApiResources' + return ApiService.Post(_url, payload, serviceUrl) + } + + /** + * 变更Api资源 + * @param payload api资源参数 + */ + public static updateApiResource(payload: ApiResourceUpdate) { + const _url = '/api/IdentityServer/ApiResources' + return ApiService.Put(_url, payload, serviceUrl) + } + + /** + * 删除Api资源 + * @param id Api资源标识 + */ + public static deleteApiResource(id: string) { + let _url = '/api/IdentityServer/ApiResources/' + _url += id + return ApiService.Delete(_url, serviceUrl) + } + + /** + * 增加Api密钥 + * @param payload Api密钥参数 + */ + public static addApiSecret(payload: ApiSecretCreate) { + const _url = '/api/IdentityServer/ApiResources/Secrets' + return ApiService.Post(_url, payload, serviceUrl) + } + + /** + * 删除Api密钥 + * @param apiResourceId 资源标识 + * @param type 密钥类型 + * @param value 密钥值 + */ + public static deleteApiSecret(apiResourceId: string, type: string, value: string) { + let _url = '/api/IdentityServer/ApiResources/Secrets/' + _url += '?apiResourceId=' + apiResourceId + _url += '&type=' + type + _url += '&value=' + value + return ApiService.Delete(_url, serviceUrl) + } + + /** + * 增加Api授权范围 + * @param payload api授权范围参数 + */ + public static addApiScope(payload: ApiScopeCreate) { + const _url = '/api/IdentityServer/ApiResources/Scopes' + return ApiService.Post(_url, payload, serviceUrl) + } + + /** + * 删除Api授权范围 + * @param apiResourceId api资源标识 + * @param name 授权范围名称 + */ + public static deleteApiScope(apiResourceId: string, name: string) { + let _url = '/api/IdentityServer/ApiResources/Scopes' + _url += '?apiResourceId=' + apiResourceId + _url += '&name=' + name + return ApiService.Delete(_url, serviceUrl) + } +} + +export enum HashType { + Sha256, + Sha512 +} + +export class ApiSecret { + type!: string + value!: string + hashType?: HashType + description?: string + expiration?: Date +} + +export class ApiScopeClaim { + type!: string +} + +export class ApiResourceClaim { + type!: string +} + +export class ApiScope { + name!: string + displayName?: string + description?: string + required!: boolean + emphasize!: boolean + showInDiscoveryDocument!: boolean + userClaims : ApiScopeClaim[] + + constructor() { + this.userClaims = new Array() + } +} + +export class ApiScopeCreate { + apiResourceId!: string + name!: string + displayName?: string + description?: string + required!: boolean + emphasize!: boolean + showInDiscoveryDocument!: boolean + userClaims : ApiScopeClaim[] + + constructor() { + this.apiResourceId = '' + this.name = '' + this.displayName = '' + this.description = '' + this.required = false + this.emphasize = false + this.showInDiscoveryDocument = false + this.userClaims = new Array() + } + + public static empty() { + return new ApiScopeCreate() + } +} + +export class ApiSecretCreate { + apiResourceId!: string + type!: string + value!: string + hashType?: HashType + description?: string + expiration?: Date + + constructor() { + this.type = 'SharedSecret' + this.value = '' + this.hashType = HashType.Sha256 + this.description = '' + this.expiration = undefined + } + + public static empty() { + return new ApiSecretCreate() + } +} + +export class ApiResourceCreate { + name!: string + displayName?: string + description?: string + enabled!: boolean + userClaims!: ApiResourceClaim[] + + constructor() { + this.name = '' + this.displayName = '' + this.description = '' + this.enabled = true + this.userClaims = new Array() + } + + public static empty() { + return new ApiResourceCreate() + } + + public static create(apiResource: ApiResource) { + const resource = ApiResourceCreate.empty() + resource.name = apiResource.name + resource.displayName = apiResource.displayName + resource.description = apiResource.description + resource.enabled = apiResource.enabled + resource.userClaims = apiResource.userClaims + return resource + } +} + +export class ApiResourceUpdate { + id!: string + displayName?: string + description?: string + enabled!: boolean + userClaims!: ApiResourceClaim[] + + constructor() { + this.id = '' + this.displayName = '' + this.description = '' + this.enabled = true + this.userClaims = new Array() + } + + public static empty() { + return new ApiResourceUpdate() + } + + public static create(apiResource: ApiResource) { + const resource = ApiResourceUpdate.empty() + resource.id = apiResource.id + resource.displayName = apiResource.displayName + resource.description = apiResource.description + resource.enabled = apiResource.enabled + resource.userClaims = apiResource.userClaims + return resource + } +} + +export class ApiResource extends FullAuditedEntityDto { + id!: string + name!: string + displayName?: string + description?: string + enabled!: boolean + secrets!: ApiSecret[] + scopes!: ApiScope[] + userClaims!: ApiResourceClaim[] + + constructor() { + super() + this.id = '' + this.name = '' + this.displayName = '' + this.description = '' + this.enabled = true + this.scopes = new Array() + this.secrets = new Array() + this.userClaims = new Array() + } + + public static empty() { + return new ApiResource() + } +} + +export class ApiResourceGetByPaged extends PagedAndSortedResultRequestDto { + filter!: string + + constructor() { + super() + this.filter = '' + } +} \ No newline at end of file diff --git a/vueJs/src/api/clients.ts b/vueJs/src/api/clients.ts index 522cfb9fc..7a6e49655 100644 --- a/vueJs/src/api/clients.ts +++ b/vueJs/src/api/clients.ts @@ -79,9 +79,15 @@ export class ClientGetByPaged extends PagedAndSortedResultRequestDto { filter?: string } +export enum HashType { + Sha256, + Sha512 +} + export class ClientSecret { type = '' value = '' + hashType = HashType.Sha256 description? = '' expiration? = undefined } @@ -126,6 +132,7 @@ export class ClientSecretCreate extends ClientSecret { constructor() { super() this.type = 'SharedSecret' + this.hashType = HashType.Sha256 } } @@ -210,6 +217,10 @@ export class Client extends FullAuditedEntityDto { this.claims = new Array() this.properties = new Array() } + + public static empty() { + return new Client() + } } export class ClientUpdateData { diff --git a/vueJs/src/api/types.ts b/vueJs/src/api/types.ts index 0a3c72eca..8e637984b 100644 --- a/vueJs/src/api/types.ts +++ b/vueJs/src/api/types.ts @@ -70,7 +70,7 @@ export class PagedAndSortedResultRequestDto implements IPagedResultRequest, ISor /** 创建实体审计对象 */ export class CreationAuditedEntityDto implements IMayHaveCreator { creatorId: string | undefined - creatorTime!: Date + creationTime!: Date } /** 实体审计对象 */ @@ -78,7 +78,7 @@ export class AuditedEntityDto implements CreationAuditedEntityDto, IModification lastModifierId: string | undefined lastModificationTime: Date | undefined creatorId: string | undefined - creatorTime!: Date + creationTime!: Date } /** 所有实体审计对象 */ @@ -86,7 +86,7 @@ export class FullAuditedEntityDto implements AuditedEntityDto, IDeletionAuditedO lastModifierId: string | undefined lastModificationTime: Date | undefined creatorId: string | undefined - creatorTime!: Date + creationTime!: Date deleterId!: string deletionTime: Date | undefined isDeleted!: boolean @@ -155,7 +155,7 @@ export interface IMayHaveCreator extends IHasCreationTime { /** 创建时间接口 */ export interface IHasCreationTime { /** 创建时间 */ - creatorTime: Date + creationTime: Date } /** 修改人接口 */ diff --git a/vueJs/src/components/InputTag/index.vue b/vueJs/src/components/InputTag/index.vue index 8e2330cef..3d618f658 100644 --- a/vueJs/src/components/InputTag/index.vue +++ b/vueJs/src/components/InputTag/index.vue @@ -22,7 +22,6 @@ v-model="newTag" :size="size" :class="[size ? 'tag-input--' + size : 'tag-input']" - @keydown.delete.stop="removeLastTag" @keydown="addNew" @blur="addNew" > diff --git a/vueJs/src/components/InputTagEx/index.vue b/vueJs/src/components/InputTagEx/index.vue index 42b84afff..fddbe46e8 100644 --- a/vueJs/src/components/InputTagEx/index.vue +++ b/vueJs/src/components/InputTagEx/index.vue @@ -30,7 +30,7 @@ diff --git a/vueJs/src/components/PermissionTree/index.vue b/vueJs/src/components/PermissionTree/index.vue index 8f5e52a60..1cc397558 100644 --- a/vueJs/src/components/PermissionTree/index.vue +++ b/vueJs/src/components/PermissionTree/index.vue @@ -187,12 +187,16 @@ export default class extends Vue { /** 自定义权限树子节点渲染 */ private renderContent(h: any, context: { node: any, data: PermissionTree}) { if (this.horizontally) { - let className = '' - if (context.data && context.data.parent) { - className = 'horizontally' + if (context.data.children.length > 0) { + return h( + 'span', + { class: 'el-tree-node__label' }, + [context.node.label] + ) + } else { return h( 'div', - { class: className }, + { class: 'horizontally' }, [context.node.label]) } } diff --git a/vueJs/src/lang/zh.ts b/vueJs/src/lang/zh.ts index ff4819d25..6771186c8 100644 --- a/vueJs/src/lang/zh.ts +++ b/vueJs/src/lang/zh.ts @@ -73,7 +73,8 @@ export default { global: '全局配置', route: '路由配置', identityServer: '身份认证服务器', - clients: '客户端管理' + clients: '客户端管理', + apiresources: 'Api资源管理' }, navbar: { logOut: '退出登录', @@ -265,10 +266,14 @@ export default { pleaseInputBy: '请输入{key}', pleaseSelectBy: '请选择{key}', none: '未定义', + questingDeleteByMessage: '是否要删除{message}?', delNotRecoverData: '请注意,删除后不可恢复!', whetherDeleteData: '是否删除选择的记录 {name} ?', dataHasBeenDeleted: '选定的记录 {name} 已删除!', fieldLengthMustBeRange: '字段的长度必须在{min}到{max}之间!', + enabled: '启用', + disbled: '停用', + lastModificationTime: '修改时间', apiGateWay: { createGroup: '新建分组', updateGroup: '编辑分组', @@ -294,8 +299,11 @@ export default { active: '启用', dnActive: '禁用', basicOptions: '基础配置', + routingForward: '路由转发', + requestProcessing: '请求处理', httpOptions: 'Http选项', rateLimitOptions: '流量控制', + authorization: '安全认证', qoSOptions: '服务质量', loadBalancerOptions: '负载均衡', serviceDiscovery: '服务发现', @@ -366,6 +374,7 @@ export default { otherOpera: '更多操作', enabled: '启用客户端', disbled: '停用客户端', + clientStatus: '客户端状态', deleteClient: '删除客户端', updateClient: '编辑客户端', updateClientByName: '编辑客户端 {name}', @@ -392,7 +401,7 @@ export default { deletePropertySuccess: '客户端属性: {key} 已删除!', createPropertySuccess: '客户端属性: {key} 已添加!', createProperty: '添加客户端属性', - createClient: '创建客户端', + createClient: '添加客户端', clientId: '客户端标识', clientName: '客户端名称', description: '客户端说明', @@ -437,11 +446,45 @@ export default { userCodeType: '用户代码类型', secretType: '密钥类型', secretValue: '密钥值', + secretHashType: '哈希类型', + hashOnlySharedSecret: '哈希类型仅适用于 SharedSecret 类型', secretDescription: '密钥说明', expiration: '过期日期', claimType: '声明类型', claimValue: '声明值', propertyKey: '属性名称', - propertyValue: '属性值' + propertyValue: '属性值', + createApiResource: '添加Api资源', + updateApiResource: '编辑Api资源', + updateApiResourceByName: '编辑Api资源 {name}', + deleteApiResourceByName: '删除Api资源 {name}', + createApiResourceSuccess: 'Api资源 {name} 已添加!', + deleteApiResourceSuccess: 'Api资源 {name} 已删除!', + updateApiResourceSuccess: 'Api资源 {name} 已修改!', + createApiSecret: '添加Api密钥', + deleteApiSecret: '删除Api密钥', + deleteApiSecretByType: '删除Api密钥 {type}', + createApiSecretSuccess: 'Api密钥 {type} 已添加!', + deleteApiSecretSuccess: 'Api密钥 {type} 已删除!', + apiResourceSecret: 'Api 密钥', + createApiScope: '添加Api作用域', + deleteApiScope: '删除Api作用域', + deleteApiScopeByName: '删除Api作用域 {name}', + createApiScopeSuccess: 'Api作用域 {name} 已添加!', + deleteApiScopeSuccess: 'Api作用域 {name} 已删除!', + apiResourceScope: 'Api 作用域', + deleteApiResource: '删除资源', + apiResourceName: '资源名称', + apiResourceDisplayName: '显示名称', + enabledApiResource: '启用资源', + apiResourceStatus: '资源状态', + apiResourceDescription: '资源说明', + apiResourceUserClaims: '用户声明', + apiScopeName: '名称', + apiScopeDisplayName: '显示名称', + apiScopeDescription: '描述', + apiScopeRequired: '必须', + apiScopeEmphasize: '强调', + apiScopeShowInDiscoveryDocument: '在发现文档显示' } } diff --git a/vueJs/src/router/index.ts b/vueJs/src/router/index.ts index b5bad93f5..40e2a8b42 100644 --- a/vueJs/src/router/index.ts +++ b/vueJs/src/router/index.ts @@ -372,6 +372,16 @@ export const asyncRoutes: RouteConfig[] = [ icon: 'clients', roles: ['IdentityServer.Clients'] } + }, + { + path: 'apiresources', + component: () => import('@/views/admin/identityServer/api-resources/index.vue'), + name: 'apiresources', + meta: { + title: 'apiresources', + icon: 'apiresources', + roles: ['IdentityServer.ApiResources'] + } } ] }, diff --git a/vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue b/vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue index c99a12eb5..4a60ba420 100644 --- a/vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue +++ b/vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue @@ -62,7 +62,6 @@ export default class extends Vue { @Watch('value', { immediate: true }) private onValueChanged(val: any) { - console.log('onValueChanged') if (!val) { this.innerTags = new Array() } else { diff --git a/vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue b/vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue index 7832dce60..eea1d1484 100644 --- a/vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue +++ b/vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue @@ -64,7 +64,6 @@ export default class extends Vue { @Watch('value', { immediate: true }) private onHostAndPortsChanged(val: HostAndPort[]) { - console.log(val) if (Array.isArray(val)) { if (val.length === 0) { this.innerTags = new Array() diff --git a/vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue b/vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue index ff91b7143..c52e9bec0 100644 --- a/vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue +++ b/vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue @@ -4,8 +4,11 @@ label-width="100px" :model="apiGateWayRoute" > - - + + - + - + - + - + - + - + - + new Array() }) private appIdOptions!: RouteGroupAppIdDto[] + private activeTablePane: string private apiGateWayRoute: ReRouteDto private httpMethodsFilter: { [key: string]: string } = { GET: '', @@ -547,6 +572,7 @@ export default class extends Vue { constructor() { super() + this.activeTablePane = 'basicOptions' this.apiGateWayRoute = new ReRouteDto() } @@ -556,6 +582,8 @@ export default class extends Vue { ApiGateWayService.getReRouteByRouteId(routeId).then(route => { this.apiGateWayRoute = route }) + } else { + this.apiGateWayRoute = new ReRouteDto() } } @@ -575,8 +603,9 @@ export default class extends Vue { createRouteDto.appId = this.apiGateWayRoute.appId this.apiGateWayRoute = await ApiGateWayService.createReRoute(createRouteDto) } - this.$message('successful') + this.$message.success(this.$t('successful').toString()) routeEditForm.resetFields() + this.activeTablePane = 'basicOptions' this.$emit('closed', true) } }) @@ -585,6 +614,7 @@ export default class extends Vue { private onCancel() { const routeEditForm = this.$refs.formRoute as any routeEditForm.resetFields() + this.activeTablePane = 'basicOptions' this.$emit('closed') } } diff --git a/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue new file mode 100644 index 000000000..e6f69ae80 --- /dev/null +++ b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceScopeEditForm.vue b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceScopeEditForm.vue new file mode 100644 index 000000000..fe01859fe --- /dev/null +++ b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceScopeEditForm.vue @@ -0,0 +1,246 @@ + + + + + diff --git a/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceSecretEditForm.vue b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceSecretEditForm.vue new file mode 100644 index 000000000..c7094cdb8 --- /dev/null +++ b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceSecretEditForm.vue @@ -0,0 +1,289 @@ + + + + + diff --git a/vueJs/src/views/admin/identityServer/api-resources/index.vue b/vueJs/src/views/admin/identityServer/api-resources/index.vue new file mode 100644 index 000000000..366e5c013 --- /dev/null +++ b/vueJs/src/views/admin/identityServer/api-resources/index.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue b/vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue index cde01154d..3d6dd038a 100644 --- a/vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue +++ b/vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue @@ -33,6 +33,7 @@ {{ $t('identityServer.createClaim') }} @@ -81,7 +82,7 @@ >