Browse Source

增加Api资源管理

pull/1/head
cKey 6 years ago
parent
commit
c7830c58d8
  1. 27
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs
  2. 23
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs
  3. 7
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceClaimDto.cs
  4. 28
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceCreateDto.cs
  5. 30
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceDto.cs
  6. 9
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByIdInputDto.cs
  7. 9
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceGetByPagedInputDto.cs
  8. 29
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiResourceUpdateDto.cs
  9. 7
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeClaimDto.cs
  10. 36
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeCreateDto.cs
  11. 26
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeDto.cs
  12. 16
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiScopeGetByNameInputDto.cs
  13. 32
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretCreateDto.cs
  14. 6
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretDto.cs
  15. 20
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/Dto/ApiSecretGetByTypeInputDto.cs
  16. 27
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/ApiResources/IApiResourceAppService.cs
  17. 7
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretCreateDto.cs
  18. 2
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientSecretUpdateDto.cs
  19. 8
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/HashType.cs
  20. 3
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json
  21. 3
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json
  22. 8
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs
  23. 132
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceAppService.cs
  24. 106
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs
  25. 81
      aspnet-core/modules/identityServer/LINGYUN.IdentityServer.HttpApi/LINGYUN/Abp/IdentityServer/ApiResources/ApiResourceController.cs
  26. 2
      aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs
  27. 2
      vueJs/src/api/apigateway.ts
  28. 280
      vueJs/src/api/apiresources.ts
  29. 11
      vueJs/src/api/clients.ts
  30. 8
      vueJs/src/api/types.ts
  31. 1
      vueJs/src/components/InputTag/index.vue
  32. 19
      vueJs/src/components/InputTagEx/index.vue
  33. 12
      vueJs/src/components/PermissionTree/index.vue
  34. 49
      vueJs/src/lang/zh.ts
  35. 10
      vueJs/src/router/index.ts
  36. 1
      vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue
  37. 1
      vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue
  38. 50
      vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue
  39. 171
      vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue
  40. 246
      vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceScopeEditForm.vue
  41. 289
      vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceSecretEditForm.vue
  42. 402
      vueJs/src/views/admin/identityServer/api-resources/index.vue
  43. 3
      vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue
  44. 4
      vueJs/src/views/admin/identityServer/client/components/ClientCreateForm.vue
  45. 24
      vueJs/src/views/admin/identityServer/client/components/ClientEditForm.vue
  46. 15
      vueJs/src/views/admin/identityServer/client/components/ClientPermissionEditForm.vue
  47. 3
      vueJs/src/views/admin/identityServer/client/components/ClientPropertyEditForm.vue
  48. 32
      vueJs/src/views/admin/identityServer/client/components/ClientSecretEditForm.vue
  49. 44
      vueJs/src/views/admin/identityServer/client/index.vue

27
aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissionDefinitionProvider.cs

@ -1,7 +1,4 @@
using System; using Volo.Abp.Authorization.Permissions;
using System.Collections.Generic;
using System.Text;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Localization; using Volo.Abp.Localization;
@ -13,6 +10,7 @@ namespace LINGYUN.Abp.IdentityServer
{ {
var identityServerGroup = context.AddGroup(AbpIdentityServerPermissions.GroupName, L("Permissions:IdentityServer")); var identityServerGroup = context.AddGroup(AbpIdentityServerPermissions.GroupName, L("Permissions:IdentityServer"));
// 客户端权限
var clientPermissions = identityServerGroup.AddPermission(AbpIdentityServerPermissions.Clients.Default, L("Permissions:Clients")); var clientPermissions = identityServerGroup.AddPermission(AbpIdentityServerPermissions.Clients.Default, L("Permissions:Clients"));
clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Create, L("Permissions:Create")); clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Create, L("Permissions:Create"));
clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Update, L("Permissions:Update")); 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.Delete, L("Permissions:Delete"));
clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.ManagePermissions, L("Permissions:ManagePermissions")); clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.ManagePermissions, L("Permissions:ManagePermissions"));
// 客户端声明权限
var clientClaimPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Claims.Default, L("Permissions:Clients:Claims")); 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.Create, L("Permissions:Create"));
clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Update, L("Permissions:Update")); clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Update, L("Permissions:Update"));
clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Delete, L("Permissions:Delete")); clientClaimPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Claims.Delete, L("Permissions:Delete"));
// 客户端密钥权限
var clientSecretPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Default, L("Permissions:Clients:Secrets")); 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.Create, L("Permissions:Create"));
clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Update, L("Permissions:Update")); clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Update, L("Permissions:Update"));
clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Delete, L("Permissions:Delete")); clientSecretPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Secrets.Delete, L("Permissions:Delete"));
// 客户端属性权限
var clientPropertyPermissiosn = clientPermissions.AddChild(AbpIdentityServerPermissions.Clients.Properties.Default, L("Permissions:Clients:Properties")); 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.Create, L("Permissions:Create"));
clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Update, L("Permissions:Update")); clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Update, L("Permissions:Update"));
clientPropertyPermissiosn.AddChild(AbpIdentityServerPermissions.Clients.Properties.Delete, L("Permissions:Delete")); 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) protected virtual LocalizableString L(string name)

23
aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/AbpIdentityServerPermissions.cs

@ -38,5 +38,28 @@
public const string Delete = Default + ".Delete"; 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";
}
}
} }
} }

7
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; }
}
}

28
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<ApiResourceClaimDto> UserClaims { get; set; }
public ApiResourceCreateDto()
{
Enabled = true;
UserClaims = new List<ApiResourceClaimDto>();
}
}
}

30
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<Guid>
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool Enabled { get; set; }
public List<ApiSecretDto> Secrets { get; set; }
public List<ApiScopeDto> Scopes { get; set; }
public List<ApiResourceClaimDto> UserClaims { get; set; }
public ApiResourceDto()
{
Scopes = new List<ApiScopeDto>();
Secrets = new List<ApiSecretDto>();
UserClaims = new List<ApiResourceClaimDto>();
}
}
}

9
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<Guid>
{
}
}

9
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; }
}
}

29
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<ApiResourceClaimDto> UserClaims { get; set; }
public ApiResourceUpdateDto()
{
UserClaims = new List<ApiResourceClaimDto>();
}
}
}

7
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; }
}
}

36
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<ApiScopeClaimDto> UserClaims { get; set; }
public ApiScopeCreateDto()
{
UserClaims = new List<ApiScopeClaimDto>();
}
}
}

26
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<ApiScopeClaimDto> UserClaims { get; set; }
public ApiScopeDto()
{
UserClaims = new List<ApiScopeClaimDto>();
}
}
}

16
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; }
}
}

32
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;
}
}
}

6
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
{
}
}

20
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; }
}
}

27
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<ApiResourceDto> GetAsync(ApiResourceGetByIdInputDto apiResourceGetById);
Task<PagedResultDto<ApiResourceDto>> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged);
Task<ApiResourceDto> CreateAsync(ApiResourceCreateDto apiResourceCreate);
Task<ApiResourceDto> UpdateAsync(ApiResourceUpdateDto apiResourceUpdate);
Task DeleteAsync(ApiResourceGetByIdInputDto apiResourceGetById);
Task<ApiSecretDto> AddSecretAsync(ApiSecretCreateDto apiSecretCreate);
Task DeleteSecretAsync(ApiSecretGetByTypeInputDto apiSecretGetByType);
Task<ApiScopeDto> AddScopeAsync(ApiScopeCreateDto apiScopeCreate);
Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName);
}
}

7
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)] [StringLength(SecretConsts.TypeMaxLength)]
public string Type { get; set; } public string Type { get; set; }
public HashType HashType { get; set; }
[Required] [Required]
[StringLength(SecretConsts.ValueMaxLength)] [StringLength(SecretConsts.ValueMaxLength)]
public string Value { get; set; } public string Value { get; set; }
@ -21,5 +23,10 @@ namespace LINGYUN.Abp.IdentityServer.Clients
public string Description { get; set; } public string Description { get; set; }
public DateTime? Expiration { get; set; } public DateTime? Expiration { get; set; }
public ClientSecretCreateDto()
{
HashType = 0;
}
} }
} }

2
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)] [StringLength(SecretConsts.TypeMaxLength)]
public string Type { get; set; } public string Type { get; set; }
public HashType HashType { get; set; }
[Required] [Required]
[StringLength(SecretConsts.ValueMaxLength)] [StringLength(SecretConsts.ValueMaxLength)]
public string Value { get; set; } public string Value { get; set; }

8
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
}
}

3
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:Claims": "Client claim",
"Permissions:Clients:Secrets": "Client secret", "Permissions:Clients:Secrets": "Client secret",
"Permissions:Clients:Properties": "Client property", "Permissions:Clients:Properties": "Client property",
"Permissions:ApiResources": "ApiResources",
"Permissions:ApiResources:Scope": "Api scope",
"Permissions:ApiResources:Secrets": "Api secret",
"ClientIdExisted": "Client id: {0} already exists!", "ClientIdExisted": "Client id: {0} already exists!",
"ClientClaimNotFound": "Client claim: {0} not found!", "ClientClaimNotFound": "Client claim: {0} not found!",
"ClientSecretNotFound": "Client secret: {0} not found!", "ClientSecretNotFound": "Client secret: {0} not found!",

3
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:Secrets": "客户端密钥",
"Permissions:Clients:Properties": "客户端属性", "Permissions:Clients:Properties": "客户端属性",
"Permissions:Clients:Claims": "客户端声明", "Permissions:Clients:Claims": "客户端声明",
"Permissions:ApiResources": "Api资源管理",
"Permissions:ApiResources:Scope": "授权范围",
"Permissions:ApiResources:Secrets": "Api密钥",
"ClientIdExisted": "客户端标识: {0} 已经存在!", "ClientIdExisted": "客户端标识: {0} 已经存在!",
"ClientClaimNotFound": "客户端声明: {0} 不存在!", "ClientClaimNotFound": "客户端声明: {0} 不存在!",
"ClientSecretNotFound": "客户端密钥: {0} 不存在!", "ClientSecretNotFound": "客户端密钥: {0} 不存在!",

8
aspnet-core/modules/identityServer/LINGYUN.IdentityServer.Application/LINGYUN/Abp/IdentityServer/AbpIdentityServerAutoMapperProfile.cs

@ -1,5 +1,7 @@
using AutoMapper; using AutoMapper;
using LINGYUN.Abp.IdentityServer.ApiResources;
using LINGYUN.Abp.IdentityServer.Clients; using LINGYUN.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Clients;
namespace LINGYUN.Abp.IdentityServer namespace LINGYUN.Abp.IdentityServer
@ -18,6 +20,12 @@ namespace LINGYUN.Abp.IdentityServer
CreateMap<ClientRedirectUri, ClientRedirectUriDto>(); CreateMap<ClientRedirectUri, ClientRedirectUriDto>();
CreateMap<ClientScope, ClientScopeDto>(); CreateMap<ClientScope, ClientScopeDto>();
CreateMap<Client, ClientDto>(); CreateMap<Client, ClientDto>();
CreateMap<ApiSecret, ApiSecretDto>();
CreateMap<ApiScope, ApiScopeDto>();
CreateMap<ApiScopeClaim, ApiScopeClaimDto>();
CreateMap<ApiResourceClaim, ApiResourceClaimDto>();
CreateMap<ApiResource, ApiResourceDto>();
} }
} }
} }

132
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<ApiResourceDto> GetAsync(ApiResourceGetByIdInputDto apiResourceGetById)
{
var apiResource = await ApiResourceRepository.GetAsync(apiResourceGetById.Id);
return ObjectMapper.Map<ApiResource, ApiResourceDto>(apiResource);
}
public virtual async Task<PagedResultDto<ApiResourceDto>> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged)
{
var apiResources = await ApiResourceRepository.GetListAsync(apiResourceGetByPaged.Sorting,
apiResourceGetByPaged.SkipCount, apiResourceGetByPaged.MaxResultCount);
var apiResourceCount = await ApiResourceRepository.GetCountAsync();
return new PagedResultDto<ApiResourceDto>(apiResourceCount,
ObjectMapper.Map<List<ApiResource>, List<ApiResourceDto>>(apiResources));
}
[Authorize(AbpIdentityServerPermissions.ApiResources.Create)]
public virtual async Task<ApiResourceDto> 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, ApiResourceDto>(apiResource);
}
[Authorize(AbpIdentityServerPermissions.ApiResources.Update)]
public virtual async Task<ApiResourceDto> 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, ApiResourceDto>(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<ApiSecretDto> 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<ApiSecret, ApiSecretDto>(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<ApiScopeDto> 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<ApiScope, ApiScopeDto>(apiResourceScope);
}
[Authorize(AbpIdentityServerPermissions.ApiResources.Scope.Delete)]
public virtual async Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName)
{
var apiResource = await ApiResourceRepository.GetAsync(apiScopeGetByName.ApiResourceId);
apiResource.RemoveScope(apiScopeGetByName.Name);
}
}
}

106
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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.Security.Encryption; using Volo.Abp.Security.Encryption;
using Client = Volo.Abp.IdentityServer.Clients.Client;
namespace LINGYUN.Abp.IdentityServer.Clients namespace LINGYUN.Abp.IdentityServer.Clients
{ {
[Authorize(AbpIdentityServerPermissions.Clients.Default)]
public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService
{ {
private IStringEncryptionService _encryptionService; private IStringEncryptionService _encryptionService;
@ -22,6 +25,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
ClientRepository = clientRepository; ClientRepository = clientRepository;
} }
[Authorize(AbpIdentityServerPermissions.Clients.Claims.Create)]
public virtual async Task<ClientClaimDto> AddClaimAsync(ClientClaimCreateDto clientClaimCreate) public virtual async Task<ClientClaimDto> AddClaimAsync(ClientClaimCreateDto clientClaimCreate)
{ {
var client = await ClientRepository.GetAsync(clientClaimCreate.ClientId); var client = await ClientRepository.GetAsync(clientClaimCreate.ClientId);
@ -32,6 +36,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<ClientClaim, ClientClaimDto>(clientClaim); return ObjectMapper.Map<ClientClaim, ClientClaimDto>(clientClaim);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Properties.Create)]
public virtual async Task<ClientPropertyDto> AddPropertyAsync(ClientPropertyCreateDto clientPropertyCreate) public virtual async Task<ClientPropertyDto> AddPropertyAsync(ClientPropertyCreateDto clientPropertyCreate)
{ {
var client = await ClientRepository.GetAsync(clientPropertyCreate.ClientId); var client = await ClientRepository.GetAsync(clientPropertyCreate.ClientId);
@ -42,12 +47,30 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<ClientProperty, ClientPropertyDto>(clientProperty); return ObjectMapper.Map<ClientProperty, ClientPropertyDto>(clientProperty);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Secrets.Create)]
public virtual async Task<ClientSecretDto> AddSecretAsync(ClientSecretCreateDto clientSecretCreate) public virtual async Task<ClientSecretDto> AddSecretAsync(ClientSecretCreateDto clientSecretCreate)
{ {
var client = await ClientRepository.GetAsync(clientSecretCreate.ClientId); 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, client.AddSecret(clientSecretValue, clientSecretCreate.Expiration,
clientSecretCreate.Type, clientSecretCreate.Description); clientSecretCreate.Type, clientSecretCreate.Description);
@ -56,6 +79,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<ClientSecret, ClientSecretDto>(clientSecret); return ObjectMapper.Map<ClientSecret, ClientSecretDto>(clientSecret);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Create)]
public virtual async Task<ClientDto> CreateAsync(ClientCreateDto clientCreate) public virtual async Task<ClientDto> CreateAsync(ClientCreateDto clientCreate)
{ {
var clientIdExists = await ClientRepository.CheckClientIdExistAsync(clientCreate.ClientId); var clientIdExists = await ClientRepository.CheckClientIdExistAsync(clientCreate.ClientId);
@ -76,11 +100,13 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<Client, ClientDto>(client); return ObjectMapper.Map<Client, ClientDto>(client);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Delete)]
public virtual async Task DeleteAsync(ClientGetByIdInputDto clientGetByIdInput) public virtual async Task DeleteAsync(ClientGetByIdInputDto clientGetByIdInput)
{ {
await ClientRepository.DeleteAsync(clientGetByIdInput.Id); await ClientRepository.DeleteAsync(clientGetByIdInput.Id);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Claims.Delete)]
public virtual async Task DeleteClaimAsync(ClientClaimGetByKeyInputDto clientClaimGetByKey) public virtual async Task DeleteClaimAsync(ClientClaimGetByKeyInputDto clientClaimGetByKey)
{ {
var client = await ClientRepository.GetAsync(clientClaimGetByKey.ClientId); var client = await ClientRepository.GetAsync(clientClaimGetByKey.ClientId);
@ -88,6 +114,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
await ClientRepository.UpdateAsync(client); await ClientRepository.UpdateAsync(client);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Properties.Delete)]
public virtual async Task DeletePropertyAsync(ClientPropertyGetByKeyDto clientPropertyGetByKey) public virtual async Task DeletePropertyAsync(ClientPropertyGetByKeyDto clientPropertyGetByKey)
{ {
var client = await ClientRepository.GetAsync(clientPropertyGetByKey.ClientId); var client = await ClientRepository.GetAsync(clientPropertyGetByKey.ClientId);
@ -95,6 +122,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
await ClientRepository.UpdateAsync(client); await ClientRepository.UpdateAsync(client);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Secrets.Delete)]
public virtual async Task DeleteSecretAsync(ClientSecretGetByTypeDto clientSecretGetByType) public virtual async Task DeleteSecretAsync(ClientSecretGetByTypeDto clientSecretGetByType)
{ {
var client = await ClientRepository.GetAsync(clientSecretGetByType.ClientId); var client = await ClientRepository.GetAsync(clientSecretGetByType.ClientId);
@ -102,6 +130,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
await ClientRepository.UpdateAsync(client); await ClientRepository.UpdateAsync(client);
} }
public virtual async Task<ClientDto> GetAsync(ClientGetByIdInputDto clientGetById) public virtual async Task<ClientDto> GetAsync(ClientGetByIdInputDto clientGetById)
{ {
var client = await ClientRepository.GetAsync(clientGetById.Id); var client = await ClientRepository.GetAsync(clientGetById.Id);
@ -121,6 +150,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
ObjectMapper.Map<List<Client>, List<ClientDto>>(clients)); ObjectMapper.Map<List<Client>, List<ClientDto>>(clients));
} }
[Authorize(AbpIdentityServerPermissions.Clients.Update)]
public virtual async Task<ClientDto> UpdateAsync(ClientUpdateInputDto clientUpdateInput) public virtual async Task<ClientDto> UpdateAsync(ClientUpdateInputDto clientUpdateInput)
{ {
var client = await ClientRepository.GetAsync(clientUpdateInput.Id); var client = await ClientRepository.GetAsync(clientUpdateInput.Id);
@ -183,78 +213,60 @@ namespace LINGYUN.Abp.IdentityServer.Clients
#region AllowScope #region AllowScope
foreach(var scope in clientUpdateInput.Client.AllowedScopes) client.RemoveAllScopes();
foreach (var scope in clientUpdateInput.Client.AllowedScopes)
{ {
var clientScope = client.FindScope(scope.Scope); client.AddScope(scope.Scope);
if (clientScope == null)
{
client.AddScope(scope.Scope);
}
} }
#endregion #endregion
#region RedirectUris #region RedirectUris
foreach(var redirect in clientUpdateInput.Client.RedirectUris) client.RemoveAllRedirectUris();
foreach (var redirect in clientUpdateInput.Client.RedirectUris)
{ {
var clientRedirect = client.FindRedirectUri(redirect.RedirectUri); client.AddRedirectUri(redirect.RedirectUri);
if(clientRedirect == null)
{
client.AddRedirectUri(redirect.RedirectUri);
}
} }
#endregion #endregion
#region AllowedGrantTypes #region AllowedGrantTypes
client.RemoveAllAllowedGrantTypes();
foreach (var grantType in clientUpdateInput.Client.AllowedGrantTypes) foreach (var grantType in clientUpdateInput.Client.AllowedGrantTypes)
{ {
var clientGrantType = client.FindGrantType(grantType.GrantType); client.AddGrantType(grantType.GrantType);
if (clientGrantType == null)
{
client.AddGrantType(grantType.GrantType);
}
} }
#endregion #endregion
#region AllowedCorsOrigins #region AllowedCorsOrigins
client.RemoveAllCorsOrigins();
foreach (var corgOrigin in clientUpdateInput.Client.AllowedCorsOrigins) foreach (var corgOrigin in clientUpdateInput.Client.AllowedCorsOrigins)
{ {
var clientCorsOrigin = client.FindCorsOrigin(corgOrigin.Origin); client.AddCorsOrigin(corgOrigin.Origin);
if (clientCorsOrigin == null)
{
client.AddCorsOrigin(corgOrigin.Origin);
}
} }
#endregion #endregion
#region PostLogoutRedirectUris #region PostLogoutRedirectUris
client.RemoveAllPostLogoutRedirectUris();
foreach (var logoutRedirect in clientUpdateInput.Client.PostLogoutRedirectUris) foreach (var logoutRedirect in clientUpdateInput.Client.PostLogoutRedirectUris)
{ {
var clientLogoutRedirect = client.FindPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri); client.AddPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri);
if (clientLogoutRedirect == null)
{
client.AddPostLogoutRedirectUri(logoutRedirect.PostLogoutRedirectUri);
}
} }
#endregion #endregion
#region IdentityProviderRestrictions #region IdentityProviderRestrictions
client.RemoveAllIdentityProviderRestrictions();
foreach (var provider in clientUpdateInput.Client.IdentityProviderRestrictions) foreach (var provider in clientUpdateInput.Client.IdentityProviderRestrictions)
{ {
var clientIdentityProvider = client.FindIdentityProviderRestriction(provider.Provider); client.AddIdentityProviderRestriction(provider.Provider);
if (clientIdentityProvider == null)
{
client.AddIdentityProviderRestriction(provider.Provider);
}
} }
#endregion #endregion
@ -264,6 +276,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<Client, ClientDto>(client); return ObjectMapper.Map<Client, ClientDto>(client);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Claims.Update)]
public virtual async Task<ClientClaimDto> UpdateClaimAsync(ClientClaimUpdateDto clientClaimUpdate) public virtual async Task<ClientClaimDto> UpdateClaimAsync(ClientClaimUpdateDto clientClaimUpdate)
{ {
var client = await ClientRepository.GetAsync(clientClaimUpdate.ClientId); var client = await ClientRepository.GetAsync(clientClaimUpdate.ClientId);
@ -278,6 +291,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<ClientClaim, ClientClaimDto>(clientClaim); return ObjectMapper.Map<ClientClaim, ClientClaimDto>(clientClaim);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Properties.Update)]
public virtual async Task<ClientPropertyDto> UpdatePropertyAsync(ClientPropertyUpdateDto clientPropertyUpdate) public virtual async Task<ClientPropertyDto> UpdatePropertyAsync(ClientPropertyUpdateDto clientPropertyUpdate)
{ {
var client = await ClientRepository.GetAsync(clientPropertyUpdate.ClientId); var client = await ClientRepository.GetAsync(clientPropertyUpdate.ClientId);
@ -294,6 +308,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
return ObjectMapper.Map<ClientProperty, ClientPropertyDto>(clientProperty); return ObjectMapper.Map<ClientProperty, ClientPropertyDto>(clientProperty);
} }
[Authorize(AbpIdentityServerPermissions.Clients.Secrets.Update)]
public virtual async Task<ClientSecretDto> UpdateSecretAsync(ClientSecretUpdateDto clientSecretUpdate) public virtual async Task<ClientSecretDto> UpdateSecretAsync(ClientSecretUpdateDto clientSecretUpdate)
{ {
var client = await ClientRepository.GetAsync(clientSecretUpdate.ClientId); var client = await ClientRepository.GetAsync(clientSecretUpdate.ClientId);
@ -305,7 +320,26 @@ namespace LINGYUN.Abp.IdentityServer.Clients
throw new UserFriendlyException( throw new UserFriendlyException(
L[AbpIdentityServerErrorConsts.ClientSecretNotFound, clientSecretUpdate.Type]); 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, ClientSecretDto>(clientSecret); return ObjectMapper.Map<ClientSecret, ClientSecretDto>(clientSecret);
} }

81
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<ApiResourceDto> GetAsync(ApiResourceGetByIdInputDto apiResourceGetById)
{
return await ApiResourceAppService.GetAsync(apiResourceGetById);
}
[HttpGet]
public virtual async Task<PagedResultDto<ApiResourceDto>> GetAsync(ApiResourceGetByPagedInputDto apiResourceGetByPaged)
{
return await ApiResourceAppService.GetAsync(apiResourceGetByPaged);
}
[HttpPost]
public virtual async Task<ApiResourceDto> CreateAsync(ApiResourceCreateDto apiResourceCreate)
{
return await ApiResourceAppService.CreateAsync(apiResourceCreate);
}
[HttpPut]
public virtual async Task<ApiResourceDto> 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<ApiSecretDto> 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<ApiScopeDto> AddScopeAsync(ApiScopeCreateDto apiScopeCreate)
{
return await ApiResourceAppService.AddScopeAsync(apiScopeCreate);
}
[HttpDelete]
[Route("Scopes")]
public virtual async Task DeleteScopeAsync(ApiScopeGetByNameInputDto apiScopeGetByName)
{
await ApiResourceAppService.DeleteScopeAsync(apiScopeGetByName);
}
}
}

2
aspnet-core/services/account/AuthServer.Host/AuthIdentityServerModule.cs

@ -158,12 +158,12 @@ namespace AuthServer.Host
app.UseCorrelationId(); app.UseCorrelationId();
app.UseVirtualFiles(); app.UseVirtualFiles();
app.UseAbpRequestLocalization();
app.UseRouting(); app.UseRouting();
app.UseCors(DefaultCorsPolicyName); app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication(); app.UseAuthentication();
app.UseJwtTokenMiddleware(); app.UseJwtTokenMiddleware();
app.UseMultiTenancy(); app.UseMultiTenancy();
app.UseAbpRequestLocalization();
app.UseIdentityServer(); app.UseIdentityServer();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(options => app.UseSwaggerUI(options =>

2
vueJs/src/api/apigateway.ts

@ -311,7 +311,7 @@ export class ReRouteBase {
reRouteIsCaseSensitive? = true reRouteIsCaseSensitive? = true
serviceName? = '' serviceName? = ''
serviceNamespace? = '' serviceNamespace? = ''
downstreamScheme? = '' downstreamScheme? = 'HTTP'
downstreamHostAndPorts!: HostAndPort[] downstreamHostAndPorts!: HostAndPort[]
upstreamHost = '' upstreamHost = ''
key? = '' key? = ''

280
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<ApiResource>(_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<PagedResultDto<ApiResource>>(_url, serviceUrl)
}
/**
* Api资源
* @param payload api资源参数
*/
public static createApiResource(payload: ApiResourceCreate) {
const _url = '/api/IdentityServer/ApiResources'
return ApiService.Post<ApiResource>(_url, payload, serviceUrl)
}
/**
* Api资源
* @param payload api资源参数
*/
public static updateApiResource(payload: ApiResourceUpdate) {
const _url = '/api/IdentityServer/ApiResources'
return ApiService.Put<ApiResource>(_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<ApiSecret>(_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<ApiScope>(_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<ApiScopeClaim>()
}
}
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<ApiScopeClaim>()
}
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<ApiResourceClaim>()
}
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<ApiResourceClaim>()
}
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<ApiScope>()
this.secrets = new Array<ApiSecret>()
this.userClaims = new Array<ApiResourceClaim>()
}
public static empty() {
return new ApiResource()
}
}
export class ApiResourceGetByPaged extends PagedAndSortedResultRequestDto {
filter!: string
constructor() {
super()
this.filter = ''
}
}

11
vueJs/src/api/clients.ts

@ -79,9 +79,15 @@ export class ClientGetByPaged extends PagedAndSortedResultRequestDto {
filter?: string filter?: string
} }
export enum HashType {
Sha256,
Sha512
}
export class ClientSecret { export class ClientSecret {
type = '' type = ''
value = '' value = ''
hashType = HashType.Sha256
description? = '' description? = ''
expiration? = undefined expiration? = undefined
} }
@ -126,6 +132,7 @@ export class ClientSecretCreate extends ClientSecret {
constructor() { constructor() {
super() super()
this.type = 'SharedSecret' this.type = 'SharedSecret'
this.hashType = HashType.Sha256
} }
} }
@ -210,6 +217,10 @@ export class Client extends FullAuditedEntityDto {
this.claims = new Array<ClientClaim>() this.claims = new Array<ClientClaim>()
this.properties = new Array<ClientProperty>() this.properties = new Array<ClientProperty>()
} }
public static empty() {
return new Client()
}
} }
export class ClientUpdateData { export class ClientUpdateData {

8
vueJs/src/api/types.ts

@ -70,7 +70,7 @@ export class PagedAndSortedResultRequestDto implements IPagedResultRequest, ISor
/** 创建实体审计对象 */ /** 创建实体审计对象 */
export class CreationAuditedEntityDto implements IMayHaveCreator { export class CreationAuditedEntityDto implements IMayHaveCreator {
creatorId: string | undefined creatorId: string | undefined
creatorTime!: Date creationTime!: Date
} }
/** 实体审计对象 */ /** 实体审计对象 */
@ -78,7 +78,7 @@ export class AuditedEntityDto implements CreationAuditedEntityDto, IModification
lastModifierId: string | undefined lastModifierId: string | undefined
lastModificationTime: Date | undefined lastModificationTime: Date | undefined
creatorId: string | undefined creatorId: string | undefined
creatorTime!: Date creationTime!: Date
} }
/** 所有实体审计对象 */ /** 所有实体审计对象 */
@ -86,7 +86,7 @@ export class FullAuditedEntityDto implements AuditedEntityDto, IDeletionAuditedO
lastModifierId: string | undefined lastModifierId: string | undefined
lastModificationTime: Date | undefined lastModificationTime: Date | undefined
creatorId: string | undefined creatorId: string | undefined
creatorTime!: Date creationTime!: Date
deleterId!: string deleterId!: string
deletionTime: Date | undefined deletionTime: Date | undefined
isDeleted!: boolean isDeleted!: boolean
@ -155,7 +155,7 @@ export interface IMayHaveCreator extends IHasCreationTime {
/** 创建时间接口 */ /** 创建时间接口 */
export interface IHasCreationTime { export interface IHasCreationTime {
/** 创建时间 */ /** 创建时间 */
creatorTime: Date creationTime: Date
} }
/** 修改人接口 */ /** 修改人接口 */

1
vueJs/src/components/InputTag/index.vue

@ -22,7 +22,6 @@
v-model="newTag" v-model="newTag"
:size="size" :size="size"
:class="[size ? 'tag-input--' + size : 'tag-input']" :class="[size ? 'tag-input--' + size : 'tag-input']"
@keydown.delete.stop="removeLastTag"
@keydown="addNew" @keydown="addNew"
@blur="addNew" @blur="addNew"
> >

19
vueJs/src/components/InputTagEx/index.vue

@ -30,7 +30,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator' import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { AppModule } from '@/store/modules/app' import { AppModule } from '@/store/modules/app'
/* eslint-disable */ /* eslint-disable */
@ -40,11 +40,15 @@ const regExpValidate: { [key: string]: RegExp } = {
/* eslint-enable */ /* eslint-enable */
@Component({ @Component({
name: 'ElInputTagEx' name: 'ElInputTagEx',
model: {
prop: 'value',
event: 'change'
}
}) })
export default class extends Vue { export default class extends Vue {
@Prop({ default: () => new Array<any>() }) @Prop({ default: () => new Array<any>() })
private data!: any[] private value!: any[]
@Prop({ default: 'key' }) @Prop({ default: 'key' })
private label!: string private label!: string
@ -59,12 +63,19 @@ export default class extends Vue {
private validate!: string private validate!: string
// 'none' | 'email' | 'phone' | 'ipaddress' | 'ip:port' | 'key:value' | 'url' // 'none' | 'email' | 'phone' | 'ipaddress' | 'ip:port' | 'key:value' | 'url'
private data: any[]
private size = AppModule.size private size = AppModule.size
public newTag: string public newTag: string
constructor() { constructor() {
super() super()
this.newTag = '' this.newTag = ''
this.data = new Array<any>()
}
@Watch('value', { immediate: true })
private onValueChanged() {
this.data = this.value
} }
private foucusTagInput() { private foucusTagInput() {
@ -137,7 +148,7 @@ export default class extends Vue {
} }
private tagChange() { private tagChange() {
this.$emit('input', this.data) this.$emit('change', this.data)
} }
} }
</script> </script>

12
vueJs/src/components/PermissionTree/index.vue

@ -187,12 +187,16 @@ export default class extends Vue {
/** 自定义权限树子节点渲染 */ /** 自定义权限树子节点渲染 */
private renderContent(h: any, context: { node: any, data: PermissionTree}) { private renderContent(h: any, context: { node: any, data: PermissionTree}) {
if (this.horizontally) { if (this.horizontally) {
let className = '' if (context.data.children.length > 0) {
if (context.data && context.data.parent) { return h(
className = 'horizontally' 'span',
{ class: 'el-tree-node__label' },
[context.node.label]
)
} else {
return h( return h(
'div', 'div',
{ class: className }, { class: 'horizontally' },
[context.node.label]) [context.node.label])
} }
} }

49
vueJs/src/lang/zh.ts

@ -73,7 +73,8 @@ export default {
global: '全局配置', global: '全局配置',
route: '路由配置', route: '路由配置',
identityServer: '身份认证服务器', identityServer: '身份认证服务器',
clients: '客户端管理' clients: '客户端管理',
apiresources: 'Api资源管理'
}, },
navbar: { navbar: {
logOut: '退出登录', logOut: '退出登录',
@ -265,10 +266,14 @@ export default {
pleaseInputBy: '请输入{key}', pleaseInputBy: '请输入{key}',
pleaseSelectBy: '请选择{key}', pleaseSelectBy: '请选择{key}',
none: '未定义', none: '未定义',
questingDeleteByMessage: '是否要删除{message}?',
delNotRecoverData: '请注意,删除后不可恢复!', delNotRecoverData: '请注意,删除后不可恢复!',
whetherDeleteData: '是否删除选择的记录 {name} ?', whetherDeleteData: '是否删除选择的记录 {name} ?',
dataHasBeenDeleted: '选定的记录 {name} 已删除!', dataHasBeenDeleted: '选定的记录 {name} 已删除!',
fieldLengthMustBeRange: '字段的长度必须在{min}到{max}之间!', fieldLengthMustBeRange: '字段的长度必须在{min}到{max}之间!',
enabled: '启用',
disbled: '停用',
lastModificationTime: '修改时间',
apiGateWay: { apiGateWay: {
createGroup: '新建分组', createGroup: '新建分组',
updateGroup: '编辑分组', updateGroup: '编辑分组',
@ -294,8 +299,11 @@ export default {
active: '启用', active: '启用',
dnActive: '禁用', dnActive: '禁用',
basicOptions: '基础配置', basicOptions: '基础配置',
routingForward: '路由转发',
requestProcessing: '请求处理',
httpOptions: 'Http选项', httpOptions: 'Http选项',
rateLimitOptions: '流量控制', rateLimitOptions: '流量控制',
authorization: '安全认证',
qoSOptions: '服务质量', qoSOptions: '服务质量',
loadBalancerOptions: '负载均衡', loadBalancerOptions: '负载均衡',
serviceDiscovery: '服务发现', serviceDiscovery: '服务发现',
@ -366,6 +374,7 @@ export default {
otherOpera: '更多操作', otherOpera: '更多操作',
enabled: '启用客户端', enabled: '启用客户端',
disbled: '停用客户端', disbled: '停用客户端',
clientStatus: '客户端状态',
deleteClient: '删除客户端', deleteClient: '删除客户端',
updateClient: '编辑客户端', updateClient: '编辑客户端',
updateClientByName: '编辑客户端 {name}', updateClientByName: '编辑客户端 {name}',
@ -392,7 +401,7 @@ export default {
deletePropertySuccess: '客户端属性: {key} 已删除!', deletePropertySuccess: '客户端属性: {key} 已删除!',
createPropertySuccess: '客户端属性: {key} 已添加!', createPropertySuccess: '客户端属性: {key} 已添加!',
createProperty: '添加客户端属性', createProperty: '添加客户端属性',
createClient: '创建客户端', createClient: '添加客户端',
clientId: '客户端标识', clientId: '客户端标识',
clientName: '客户端名称', clientName: '客户端名称',
description: '客户端说明', description: '客户端说明',
@ -437,11 +446,45 @@ export default {
userCodeType: '用户代码类型', userCodeType: '用户代码类型',
secretType: '密钥类型', secretType: '密钥类型',
secretValue: '密钥值', secretValue: '密钥值',
secretHashType: '哈希类型',
hashOnlySharedSecret: '哈希类型仅适用于 SharedSecret 类型',
secretDescription: '密钥说明', secretDescription: '密钥说明',
expiration: '过期日期', expiration: '过期日期',
claimType: '声明类型', claimType: '声明类型',
claimValue: '声明值', claimValue: '声明值',
propertyKey: '属性名称', 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: '在发现文档显示'
} }
} }

10
vueJs/src/router/index.ts

@ -372,6 +372,16 @@ export const asyncRoutes: RouteConfig[] = [
icon: 'clients', icon: 'clients',
roles: ['IdentityServer.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']
}
} }
] ]
}, },

1
vueJs/src/views/admin/apigateway/components/DictionaryInputTag.vue

@ -62,7 +62,6 @@ export default class extends Vue {
@Watch('value', { immediate: true }) @Watch('value', { immediate: true })
private onValueChanged(val: any) { private onValueChanged(val: any) {
console.log('onValueChanged')
if (!val) { if (!val) {
this.innerTags = new Array<string>() this.innerTags = new Array<string>()
} else { } else {

1
vueJs/src/views/admin/apigateway/components/HostAndPortInputTag.vue

@ -64,7 +64,6 @@ export default class extends Vue {
@Watch('value', { immediate: true }) @Watch('value', { immediate: true })
private onHostAndPortsChanged(val: HostAndPort[]) { private onHostAndPortsChanged(val: HostAndPort[]) {
console.log(val)
if (Array.isArray(val)) { if (Array.isArray(val)) {
if (val.length === 0) { if (val.length === 0) {
this.innerTags = new Array<string>() this.innerTags = new Array<string>()

50
vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue

@ -4,8 +4,11 @@
label-width="100px" label-width="100px"
:model="apiGateWayRoute" :model="apiGateWayRoute"
> >
<el-tabs> <el-tabs v-model="activeTablePane">
<el-tab-pane :label="$t('apiGateWay.basicOptions')"> <el-tab-pane
:label="$t('apiGateWay.basicOptions')"
name="basicOptions"
>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item
@ -118,7 +121,10 @@
</el-col> </el-col>
</el-row> </el-row>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="路由转发"> <el-tab-pane
:label="$t('apiGateWay.routingForward')"
name="routingForward"
>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item <el-form-item
@ -205,7 +211,10 @@
/> />
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="请求处理"> <el-tab-pane
:label="$t('apiGateWay.requestProcessing')"
name="requestProcessing"
>
<el-form-item <el-form-item
prop="addClaimsToRequest" prop="addClaimsToRequest"
:label="$t('apiGateWay.addClaimsToRequest')" :label="$t('apiGateWay.addClaimsToRequest')"
@ -279,7 +288,10 @@
/> />
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('apiGateWay.httpOptions')"> <el-tab-pane
:label="$t('apiGateWay.httpOptions')"
name="httpOptions"
>
<el-form-item <el-form-item
prop="httpHandlerOptions.maxConnectionsPerServer" prop="httpHandlerOptions.maxConnectionsPerServer"
:label="$t('apiGateWay.maxConnectionsPerServer')" :label="$t('apiGateWay.maxConnectionsPerServer')"
@ -337,7 +349,10 @@
</el-col> </el-col>
</el-row> </el-row>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('apiGateWay.qoSOptions')"> <el-tab-pane
:label="$t('apiGateWay.qoSOptions')"
name="qoSOptions"
>
<el-form-item <el-form-item
prop="qoSOptions.timeoutValue" prop="qoSOptions.timeoutValue"
:label="$t('apiGateWay.timeoutValue')" :label="$t('apiGateWay.timeoutValue')"
@ -367,7 +382,10 @@
/> />
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('apiGateWay.loadBalancerOptions')"> <el-tab-pane
:label="$t('apiGateWay.loadBalancerOptions')"
name="loadBalancerOptions"
>
<el-form-item <el-form-item
prop="loadBalancerOptions.type" prop="loadBalancerOptions.type"
:label="$t('apiGateWay.loadBalancerType')" :label="$t('apiGateWay.loadBalancerType')"
@ -409,7 +427,10 @@
/> />
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="流量控制"> <el-tab-pane
:label="$t('apiGateWay.rateLimitOptions')"
name="rateLimitOptions"
>
<el-row> <el-row>
<el-col :span="6"> <el-col :span="6">
<el-form-item <el-form-item
@ -451,7 +472,10 @@
/> />
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="安全认证"> <el-tab-pane
:label="$t('apiGateWay.authorization')"
name="authorization"
>
<el-form-item <el-form-item
prop="authenticationOptions.authenticationProviderKey" prop="authenticationOptions.authenticationProviderKey"
:label="$t('apiGateWay.authenticationProviderKey')" :label="$t('apiGateWay.authenticationProviderKey')"
@ -529,6 +553,7 @@ export default class extends Vue {
@Prop({ default: () => new Array<RouteGroupAppIdDto>() }) @Prop({ default: () => new Array<RouteGroupAppIdDto>() })
private appIdOptions!: RouteGroupAppIdDto[] private appIdOptions!: RouteGroupAppIdDto[]
private activeTablePane: string
private apiGateWayRoute: ReRouteDto private apiGateWayRoute: ReRouteDto
private httpMethodsFilter: { [key: string]: string } = { private httpMethodsFilter: { [key: string]: string } = {
GET: '', GET: '',
@ -547,6 +572,7 @@ export default class extends Vue {
constructor() { constructor() {
super() super()
this.activeTablePane = 'basicOptions'
this.apiGateWayRoute = new ReRouteDto() this.apiGateWayRoute = new ReRouteDto()
} }
@ -556,6 +582,8 @@ export default class extends Vue {
ApiGateWayService.getReRouteByRouteId(routeId).then(route => { ApiGateWayService.getReRouteByRouteId(routeId).then(route => {
this.apiGateWayRoute = route this.apiGateWayRoute = route
}) })
} else {
this.apiGateWayRoute = new ReRouteDto()
} }
} }
@ -575,8 +603,9 @@ export default class extends Vue {
createRouteDto.appId = this.apiGateWayRoute.appId createRouteDto.appId = this.apiGateWayRoute.appId
this.apiGateWayRoute = await ApiGateWayService.createReRoute(createRouteDto) this.apiGateWayRoute = await ApiGateWayService.createReRoute(createRouteDto)
} }
this.$message('successful') this.$message.success(this.$t('successful').toString())
routeEditForm.resetFields() routeEditForm.resetFields()
this.activeTablePane = 'basicOptions'
this.$emit('closed', true) this.$emit('closed', true)
} }
}) })
@ -585,6 +614,7 @@ export default class extends Vue {
private onCancel() { private onCancel() {
const routeEditForm = this.$refs.formRoute as any const routeEditForm = this.$refs.formRoute as any
routeEditForm.resetFields() routeEditForm.resetFields()
this.activeTablePane = 'basicOptions'
this.$emit('closed') this.$emit('closed')
} }
} }

171
vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue

@ -0,0 +1,171 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-form
ref="formApiResource"
label-width="100px"
:model="apiResource"
:rules="apiResourceRules"
>
<el-form-item
prop="enabled"
:label="$t('identityServer.enabledApiResource')"
>
<el-switch
v-model="apiResource.enabled"
/>
</el-form-item>
<el-form-item
prop="name"
:label="$t('identityServer.apiResourceName')"
>
<el-input
v-model="apiResource.name"
:readonly="isEdit"
:placeholder="$t('pleaseInputBy', {key: $t('identityServer.apiResourceName')})"
/>
</el-form-item>
<el-form-item
prop="displayName"
:label="$t('identityServer.apiResourceDisplayName')"
>
<el-input
v-model="apiResource.displayName"
/>
</el-form-item>
<el-form-item
prop="description"
:label="$t('identityServer.apiResourceDescription')"
>
<el-input
v-model="apiResource.description"
/>
</el-form-item>
<el-form-item
prop="userClaims"
:label="$t('identityServer.apiResourceUserClaims')"
>
<el-input-tag-ex
v-model="apiResource.userClaims"
label="type"
/>
</el-form-item>
<el-form-item>
<el-button
class="cancel"
style="width:100px"
@click="onCancel"
>
{{ $t('table.cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px"
@click="onSaveApiResource"
>
{{ $t('table.confirm') }}
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script lang="ts">
import ApiResourceService, { ApiResourceCreate, ApiResourceUpdate, ApiResource } from '@/api/apiresources'
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import ElInputTagEx from '@/components/InputTagEx/index.vue'
@Component({
name: 'ApiResourceCreateOrEditForm',
components: {
ElInputTagEx
}
})
export default class extends Vue {
@Prop({ default: '' })
private apiResourceId!: string
private apiResource: ApiResource
private apiResourceRules = {
name: [
{ required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.apiResourceName') }), trigger: 'blur' }
]
}
get isEdit() {
if (this.apiResource.id) {
return true
}
return false
}
constructor() {
super()
this.apiResource = ApiResource.empty()
}
@Watch('apiResourceId', { immediate: true })
private onApiResourceIdChanged() {
if (this.apiResourceId) {
ApiResourceService.getApiResourceById(this.apiResourceId).then(resource => {
this.apiResource = resource
})
}
}
private onSaveApiResource() {
const frmApiResource = this.$refs.formApiResource as any
frmApiResource.validate((valid: boolean) => {
if (valid) {
if (this.isEdit) {
const updateApiResource = ApiResourceUpdate.create(this.apiResource)
ApiResourceService.updateApiResource(updateApiResource).then(resource => {
this.apiResource = resource
const successMessage = this.l('identityServer.updateApiResourceSuccess', { name: resource.name })
this.$message.success(successMessage)
frmApiResource.resetFields()
this.$emit('closed', true)
})
} else {
const createApiResource = ApiResourceCreate.create(this.apiResource)
ApiResourceService.createApiResource(createApiResource).then(resource => {
this.apiResource = resource
const successMessage = this.l('identityServer.createApiResourceSuccess', { name: resource.name })
this.$message.success(successMessage)
frmApiResource.resetFields()
this.$emit('closed', true)
})
}
}
})
}
private onCancel() {
this.resetFields()
this.$emit('closed', false)
}
public resetFields() {
const frmApiResource = this.$refs.formApiResource as any
frmApiResource.resetFields()
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
right: 10px;
}
.cancel {
position: absolute;
right: 120px;
}
</style>

246
vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceScopeEditForm.vue

@ -0,0 +1,246 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-form
ref="formApiScope"
label-width="120px"
:model="apiScope"
:rules="apiScopeRules"
>
<el-form-item
prop="name"
:label="$t('identityServer.apiScopeName')"
>
<el-input
v-model="apiScope.name"
:placeholder="$t('pleaseInputBy', {key: $t('identityServer.apiScopeName')})"
/>
</el-form-item>
<el-form-item
prop="displayName"
:label="$t('identityServer.apiScopeDisplayName')"
>
<el-input
v-model="apiScope.displayName"
/>
</el-form-item>
<el-form-item
prop="description"
:label="$t('identityServer.apiScopeDescription')"
>
<el-input
v-model="apiScope.description"
/>
</el-form-item>
<el-form-item
prop="required"
:label="$t('identityServer.apiScopeRequired')"
>
<el-switch
v-model="apiScope.required"
/>
</el-form-item>
<el-form-item
prop="emphasize"
:label="$t('identityServer.apiScopeEmphasize')"
>
<el-switch
v-model="apiScope.emphasize"
/>
</el-form-item>
<el-form-item
prop="showInDiscoveryDocument"
:label="$t('identityServer.apiScopeShowInDiscoveryDocument')"
>
<el-switch
v-model="apiScope.showInDiscoveryDocument"
/>
</el-form-item>
<el-form-item
prop="userClaims"
:label="$t('identityServer.apiResourceUserClaims')"
>
<el-input-tag-ex
v-model="apiScope.userClaims"
label="type"
/>
</el-form-item>
<el-form-item
style="text-align: center;"
label-width="0px"
>
<el-button
type="primary"
style="width:180px"
:disabled="!checkPermission(['IdentityServer.ApiResources.Secrets.Create'])"
@click="onSaveApiScope"
>
{{ $t('identityServer.createApiScope') }}
</el-button>
</el-form-item>
</el-form>
</div>
<el-divider />
<el-table
row-key="value"
:data="apiScopes"
border
fit
highlight-current-row
style="width: 100%;"
>
<el-table-column
:label="$t('identityServer.apiScopeName')"
prop="name"
sortable
width="150px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.apiScopeDisplayName')"
prop="displayName"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.apiScopeDescription')"
prop="description"
width="300px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
width="150px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['IdentityServer.ApiResources.Scope.Delete'])"
size="mini"
type="primary"
@click="handleDeleteApiScope(row.name)"
>
{{ $t('identityServer.deleteApiScope') }}
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts">
import ApiResourceService, { ApiScope, ApiScopeCreate } from '@/api/apiresources'
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { dateFormat } from '@/utils/index'
import { checkPermission } from '@/utils/permission'
import ElInputTagEx from '@/components/InputTagEx/index.vue'
@Component({
name: 'ApiScopeEditForm',
components: {
ElInputTagEx
},
filters: {
dateTimeFilter(datetime: string) {
if (datetime) {
const date = new Date(datetime)
return dateFormat(date, 'YYYY-mm-dd HH:MM')
}
return ''
}
},
methods: {
checkPermission
}
})
export default class extends Vue {
@Prop({ default: '' })
private apiResourceId!: string
@Prop({ default: () => new Array<ApiScope>() })
private apiScopes!: ApiScope[]
private apiScopeChanged: boolean
private apiScope: ApiScopeCreate
private apiScopeRules = {
name: [
{ required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.apiScopeName') }), trigger: 'blur' }
]
}
constructor() {
super()
this.apiScopeChanged = false
this.apiScope = ApiScopeCreate.empty()
}
@Watch('apiResourceId', { immediate: true })
private onApiResourceIdChanged() {
this.apiScope.apiResourceId = this.apiResourceId
}
private handleDeleteApiScope(name: string) {
this.$confirm(this.l('identityServer.deleteApiScopeByName', { name: name }),
this.l('identityServer.deleteApiScope'), {
callback: (action) => {
if (action === 'confirm') {
ApiResourceService.deleteApiScope(this.apiResourceId, name).then(() => {
const deleteScopeIndex = this.apiScopes.findIndex(scope => scope.name === name)
this.apiScopes.splice(deleteScopeIndex, 1)
this.$message.success(this.l('identityServer.deleteApiScopeSuccess', { name: name }))
this.$emit('apiScopeChanged')
})
}
}
})
}
private onSaveApiScope() {
const frmApiScope = this.$refs.formApiScope as any
frmApiScope.validate((valid: boolean) => {
if (valid) {
this.apiScope.apiResourceId = this.apiResourceId
ApiResourceService.addApiScope(this.apiScope).then(scope => {
this.apiScopes.push(scope)
const successMessage = this.l('identityServer.createApiScopeSuccess', { name: this.apiScope.name })
this.$message.success(successMessage)
frmApiScope.resetFields()
this.$emit('apiScopeChanged')
})
}
})
}
public resetFields() {
const frmApiScope = this.$refs.formApiScope as any
frmApiScope.resetFields()
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
}
</script>
<style lang="scss" scoped>
.full-select {
width: 100%;
}
</style>

289
vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceSecretEditForm.vue

@ -0,0 +1,289 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-form
ref="formApiSecret"
label-width="100px"
:model="apiSecret"
:rules="apiSecretRules"
>
<el-form-item
prop="type"
:label="$t('identityServer.secretType')"
>
<el-select
v-model="apiSecret.type"
class="full-select"
:placeholder="$t('pleaseSelectBy', {key: $t('identityServer.secretType')})"
>
<el-option
key="JWK"
label="JsonWebKey"
value="JWK"
/>
<el-option
key="SharedSecret"
label="SharedSecret"
value="SharedSecret"
/>
<el-option
key="X509Name"
label="X509CertificateName"
value="X509Name"
/>
<el-option
key="X509CertificateBase64"
label="X509CertificateBase64"
value="X509CertificateBase64"
/>
<el-option
key="X509Thumbprint"
label="X509CertificateThumbprint"
value="X509Thumbprint"
/>
</el-select>
</el-form-item>
<el-form-item
prop="hashType"
:label="$t('identityServer.secretHashType')"
>
<el-popover
ref="popHashType"
placement="top-start"
trigger="hover"
:content="$t('identityServer.hashOnlySharedSecret')"
/>
<el-select
v-model="apiSecret.hashType"
v-popover:popHashType
:disabled="apiSecret.type !== 'SharedSecret'"
class="full-select"
:placeholder="$t('pleaseSelectBy', {key: $t('identityServer.secretHashType')})"
>
<el-option
:key="0"
label="Sha256"
:value="0"
/>
<el-option
:key="1"
label="Sha512"
:value="1"
/>
</el-select>
</el-form-item>
<el-form-item
prop="value"
:label="$t('identityServer.secretValue')"
>
<el-input
v-model="apiSecret.value"
:placeholder="$t('pleaseInputBy', {key: $t('identityServer.secretValue')})"
/>
</el-form-item>
<el-form-item
prop="description"
:label="$t('identityServer.secretDescription')"
>
<el-input
v-model="apiSecret.description"
/>
</el-form-item>
<el-form-item
prop="expiration"
:label="$t('identityServer.expiration')"
>
<el-date-picker
v-model="apiSecret.expiration"
class="full-select"
type="datetime"
/>
</el-form-item>
<el-form-item
style="text-align: center;"
label-width="0px"
>
<el-button
type="primary"
style="width:180px"
:disabled="!checkPermission(['IdentityServer.ApiResources.Secrets.Create'])"
@click="onSaveApiSecret"
>
{{ $t('identityServer.createApiSecret') }}
</el-button>
</el-form-item>
</el-form>
</div>
<el-divider />
<el-table
row-key="value"
:data="apiSecrets"
border
fit
highlight-current-row
style="width: 100%;"
>
<el-table-column
:label="$t('identityServer.secretType')"
prop="type"
sortable
width="150px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.type }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.secretValue')"
prop="value"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.value }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.secretDescription')"
prop="description"
width="170px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.expiration')"
prop="expiration"
width="170px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.expiration | dateTimeFilter }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
width="150px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['IdentityServer.ApiResources.Secrets.Delete'])"
size="mini"
type="primary"
@click="handleDeleteApiSecret(row.type, row.value)"
>
{{ $t('identityServer.deleteApiSecret') }}
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts">
import ApiResourceService, { ApiSecret, ApiSecretCreate } from '@/api/apiresources'
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { dateFormat } from '@/utils/index'
import { checkPermission } from '@/utils/permission'
@Component({
name: 'ApiSecretEditForm',
filters: {
dateTimeFilter(datetime: string) {
if (datetime) {
const date = new Date(datetime)
return dateFormat(date, 'YYYY-mm-dd HH:MM')
}
return ''
}
},
methods: {
checkPermission
}
})
export default class extends Vue {
@Prop({ default: '' })
private apiResourceId!: string
@Prop({ default: () => new Array<ApiSecret>() })
private apiSecrets!: ApiSecret[]
private apiSecretChanged: boolean
private apiSecret: ApiSecretCreate
private apiSecretRules = {
type: [
{ required: true, message: this.l('pleaseSelectBy', { key: this.l('identityServer.secretType') }), trigger: 'change' }
],
value: [
{ required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.secretValue') }), trigger: 'blur' }
]
}
constructor() {
super()
this.apiSecretChanged = false
this.apiSecret = ApiSecretCreate.empty()
}
@Watch('apiResourceId', { immediate: true })
private onApiResourceIdChanged() {
this.apiSecret.apiResourceId = this.apiResourceId
}
private handleDeleteApiSecret(type: string, value: string) {
this.$confirm(this.l('identityServer.deleteApiSecretByType', { type: value }),
this.l('identityServer.deleteApiSecret'), {
callback: (action) => {
if (action === 'confirm') {
ApiResourceService.deleteApiSecret(this.apiResourceId, type, value).then(() => {
const deleteSecretIndex = this.apiSecrets.findIndex(secret => secret.type === type)
this.apiSecrets.splice(deleteSecretIndex, 1)
this.$message.success(this.l('identityServer.deleteApiSecretSuccess', { type: value }))
this.$emit('apiSecretChanged')
})
}
}
})
}
private onSaveApiSecret() {
const frmApiSecret = this.$refs.formApiSecret as any
frmApiSecret.validate((valid: boolean) => {
if (valid) {
this.apiSecret.apiResourceId = this.apiResourceId
ApiResourceService.addApiSecret(this.apiSecret).then(secret => {
this.apiSecrets.push(secret)
const successMessage = this.l('identityServer.createApiSecretSuccess', { type: this.apiSecret.type })
this.$message.success(successMessage)
frmApiSecret.resetFields()
this.$emit('apiSecretChanged')
})
}
})
}
public resetFields() {
const frmApiSecret = this.$refs.formApiSecret as any
frmApiSecret.resetFields()
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
}
</script>
<style lang="scss" scoped>
.full-select {
width: 100%;
}
</style>

402
vueJs/src/views/admin/identityServer/api-resources/index.vue

@ -0,0 +1,402 @@
<template>
<div class="app-container">
<div class="filter-container">
<label
class="radio-label"
style="padding-left:10px;"
>{{ $t('queryFilter') }}</label>
<el-input
v-model="apiResourceGetPagedFilter.filter"
:placeholder="$t('filterString')"
style="width: 250px;margin-left: 10px;"
class="filter-item"
/>
<el-button
class="filter-item"
style="margin-left: 10px; text-alignt"
type="primary"
@click="handleGetApiResources"
>
{{ $t('searchList') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['IdentityServer.ApiResources.Create'])"
@click="handleShowEditApiResourceForm()"
>
{{ $t('identityServer.createApiResource') }}
</el-button>
</div>
<el-table
v-loading="apiResourceListLoading"
row-key="id"
:data="apiResourceList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('identityServer.apiResourceName')"
prop="name"
sortable
width="150px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.apiResourceDisplayName')"
prop="displayName"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.displayName }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.apiResourceStatus')"
prop="enabled"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<el-tag :type="row.enabled | statusFilter">
{{ formatStatusText(row.enabled) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('identityServer.apiResourceDescription')"
prop="description"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('creationTime')"
prop="creationTime"
width="170px"
align="center"
>
<template slot-scope="{row}">
<span>
<el-tag>
{{ row.creationTime | datetimeFilter }}
</el-tag>
</span>
</template>
</el-table-column>
<el-table-column
:label="$t('lastModificationTime')"
prop="lastModificationTime"
width="170px"
align="center"
>
<template slot-scope="{row}">
<span>
<el-tag type="warning">
{{ row.lastModificationTime | datetimeFilter }}
</el-tag>
</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
width="250px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['IdentityServer.ApiResources.Update'])"
size="mini"
type="primary"
@click="handleShowEditApiResourceForm(row)"
>
{{ $t('identityServer.updateApiResource') }}
</el-button>
<el-dropdown
class="options"
@command="handleCommand"
>
<el-button
v-permission="['IdentityServer.ApiResources']"
size="mini"
type="info"
>
{{ $t('identityServer.otherOpera') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'secret', row}"
:disabled="!checkPermission(['IdentityServer.ApiResources.Secrets'])"
>
{{ $t('identityServer.apiResourceSecret') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'scope', row}"
:disabled="!checkPermission(['IdentityServer.ApiResources.Scope'])"
>
{{ $t('identityServer.apiResourceScope') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="!checkPermission(['IdentityServer.ApiResources.Delete'])"
>
{{ $t('identityServer.deleteApiResource') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<Pagination
v-show="apiResourceListCount>0"
:total="apiResourceListCount"
:page.sync="apiResourceGetPagedFilter.skipCount"
:limit.sync="apiResourceGetPagedFilter.maxResultCount"
@pagination="handleGetApiResources"
@sort-change="handleSortChange"
/>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible.sync="showEditApiResourceDialog"
:title="editApiResourceTitle"
custom-class="modal-form"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<ApiResourceCreateOrEditForm
:api-resource-id="editApiResource.id"
@closed="handleApiResourceEditFormClosed"
/>
</el-dialog>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible.sync="showEditApiSecretDialog"
:title="$t('identityServer.apiResourceSecret')"
custom-class="modal-form"
:show-close="false"
@closed="handleApiSecretEditFormClosed"
>
<ApiSecretEditForm
ref="formApiSecret"
:api-resource-id="editApiResource.id"
:api-secrets="editApiResource.secrets"
@apiSecretChanged="handleGetApiResources"
/>
</el-dialog>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible.sync="showEditApiScopeDialog"
:title="$t('identityServer.apiResourceScope')"
custom-class="modal-form"
:show-close="false"
@closed="handleApiScopeEditFormClosed"
>
<ApiScopeEditForm
ref="formApiScope"
:api-resource-id="editApiResource.id"
:api-scopes="editApiResource.scopes"
@apiSecretChanged="handleGetApiResources"
/>
</el-dialog>
</div>
</template>
<script lang="ts">
import { checkPermission } from '@/utils/permission'
import { Component, Vue } from 'vue-property-decorator'
import { dateFormat } from '@/utils/index'
import Pagination from '@/components/Pagination/index.vue'
import ApiScopeEditForm from './components/ApiResourceScopeEditForm.vue'
import ApiSecretEditForm from './components/ApiResourceSecretEditForm.vue'
import ApiResourceCreateOrEditForm from './components/ApiResourceCreateOrEditForm.vue'
import ApiResourceService, { ApiResource, ApiResourceGetByPaged } from '@/api/apiresources'
@Component({
name: 'IdentityServerApiResource',
components: {
Pagination,
ApiScopeEditForm,
ApiSecretEditForm,
ApiResourceCreateOrEditForm
},
methods: {
checkPermission,
local(name: string) {
return this.$t(name)
}
},
filters: {
statusFilter(status: boolean) {
if (status) {
return 'success'
}
return 'warning'
},
datetimeFilter(val: string) {
const date = new Date(val)
return dateFormat(date, 'YYYY-mm-dd HH:MM')
}
}
})
export default class extends Vue {
private editApiResource: ApiResource
private apiResourceListCount: number
private editApiResourceTitle: any
private apiResourceList: ApiResource[]
private apiResourceListLoading: boolean
private apiResourceGetPagedFilter: ApiResourceGetByPaged
private showEditApiScopeDialog: boolean
private showEditApiSecretDialog: boolean
private showEditApiResourceDialog: boolean
constructor() {
super()
this.apiResourceListCount = 0
this.editApiResourceTitle = ''
this.apiResourceListLoading = false
this.editApiResource = new ApiResource()
this.apiResourceList = new Array<ApiResource>()
this.apiResourceGetPagedFilter = new ApiResourceGetByPaged()
this.showEditApiScopeDialog = false
this.showEditApiSecretDialog = false
this.showEditApiResourceDialog = false
}
mounted() {
this.handleGetApiResources()
}
private handleGetApiResources() {
this.apiResourceListLoading = true
ApiResourceService.getApiResources(this.apiResourceGetPagedFilter).then(resources => {
this.apiResourceList = resources.items
this.apiResourceListCount = resources.totalCount
}).finally(() => {
this.apiResourceListLoading = false
})
}
private handleSortChange(column: any) {
this.apiResourceGetPagedFilter.sorting = column.prop
}
private handleShowEditApiResourceForm(resource: ApiResource) {
if (resource) {
this.editApiResource = resource
this.editApiResourceTitle = this.l('identityServer.updateApiResourceByName', { name: this.editApiResource.name })
} else {
this.editApiResource = ApiResource.empty()
this.editApiResourceTitle = this.l('identityServer.createApiResource')
}
this.showEditApiResourceDialog = true
}
private handleApiResourceEditFormClosed(changed: boolean) {
this.editApiResourceTitle = ''
this.editApiResource = ApiResource.empty()
this.showEditApiResourceDialog = false
if (changed) {
this.handleGetApiResources()
}
}
private handleApiSecretEditFormClosed() {
this.showEditApiSecretDialog = false
const frmApiSecret = this.$refs.formApiSecret as ApiSecretEditForm
frmApiSecret.resetFields()
}
private handleApiScopeEditFormClosed() {
this.showEditApiScopeDialog = false
const frmApiScope = this.$refs.formApiScope as ApiScopeEditForm
frmApiScope.resetFields()
}
private handleDeleteApiResource(id: string, name: string) {
this.$confirm(this.l('identityServer.deleteApiResourceByName', { name: name }),
this.l('identityServer.deleteApiResource'), {
callback: (action) => {
if (action === 'confirm') {
ApiResourceService.deleteApiResource(id).then(() => {
this.$message.success(this.l('identityServer.deleteApiResourceSuccess', { name: name }))
this.handleGetApiResources()
})
}
}
})
}
private handleCommand(command: {key: string, row: ApiResource}) {
this.editApiResource = command.row
switch (command.key) {
case 'secret' :
this.showEditApiSecretDialog = true
break
case 'scope' :
this.showEditApiScopeDialog = true
break
case 'delete' :
this.handleDeleteApiResource(command.row.id, command.row.name)
break
default: break
}
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
private formatStatusText(status: boolean) {
let statusText = ''
if (status) {
statusText = this.l('enabled')
} else {
statusText = this.l('disbled')
}
return statusText
}
}
</script>
<style lang="scss" scoped>
.roleItem {
width: 40px;
}
.options {
vertical-align: top;
margin-left: 20px;
}
.el-dropdown + .el-dropdown {
margin-left: 15px;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>

3
vueJs/src/views/admin/identityServer/client/components/ClientClaimEditForm.vue

@ -33,6 +33,7 @@
<el-button <el-button
type="primary" type="primary"
style="width:180px" style="width:180px"
:disabled="!checkPermission(['IdentityServer.Clients.Claims.Create'])"
@click="onSaveClientClaim" @click="onSaveClientClaim"
> >
{{ $t('identityServer.createClaim') }} {{ $t('identityServer.createClaim') }}
@ -81,7 +82,7 @@
> >
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button <el-button
:disabled="!checkPermission(['IdentityServer.Clients.Update'])" :disabled="!checkPermission(['IdentityServer.Clients.Claims.Delete'])"
size="mini" size="mini"
type="primary" type="primary"
@click="handleDeleteClientClaim(row.type, row.value)" @click="handleDeleteClientClaim(row.type, row.value)"

4
vueJs/src/views/admin/identityServer/client/components/ClientCreateForm.vue

@ -65,14 +65,10 @@
<script lang="ts"> <script lang="ts">
import ClientService, { ClientCreate } from '@/api/clients' import ClientService, { ClientCreate } from '@/api/clients'
import { Component, Vue } from 'vue-property-decorator' import { Component, Vue } from 'vue-property-decorator'
import { checkPermission } from '@/utils/permission'
import ElInputTagEx from '@/components/InputTagEx/index.vue' import ElInputTagEx from '@/components/InputTagEx/index.vue'
@Component({ @Component({
name: 'ClientCreateForm', name: 'ClientCreateForm',
methods: {
checkPermission
},
components: { components: {
ElInputTagEx ElInputTagEx
} }

24
vueJs/src/views/admin/identityServer/client/components/ClientEditForm.vue

@ -126,7 +126,6 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.allowedScopes" v-model="client.allowedScopes"
:data="client.allowedScopes"
label="scope" label="scope"
/> />
</el-form-item> </el-form-item>
@ -136,7 +135,6 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.redirectUris" v-model="client.redirectUris"
:data="client.redirectUris"
label="redirectUri" label="redirectUri"
validate="url" validate="url"
/> />
@ -148,7 +146,6 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.allowedGrantTypes" v-model="client.allowedGrantTypes"
:data="client.allowedGrantTypes"
label="grantType" label="grantType"
/> />
</el-form-item> </el-form-item>
@ -219,6 +216,8 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.postLogoutRedirectUris" v-model="client.postLogoutRedirectUris"
label="postLogoutRedirectUri"
validate="url"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
@ -228,6 +227,7 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.identityProviderRestrictions" v-model="client.identityProviderRestrictions"
label="provider"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
@ -365,6 +365,8 @@
> >
<el-input-tag-ex <el-input-tag-ex
v-model="client.allowedCorsOrigins" v-model="client.allowedCorsOrigins"
label="origin"
validate="url"
/> />
</el-form-item> </el-form-item>
<el-row> <el-row>
@ -593,13 +595,12 @@ export default class extends Vue {
const updateClient = new ClientUpdate() const updateClient = new ClientUpdate()
updateClient.id = this.clientId updateClient.id = this.clientId
updateClient.client.setClient(this.client) updateClient.client.setClient(this.client)
ClientService.updateClient(updateClient).then(client => { ClientService.updateClient(updateClient).then(clientDto => {
this.client = client this.client = clientDto
const successMessage = this.l('identityServer.updateClientSuccess', { id: client.clientId }) const successMessage = this.l('identityServer.updateClientSuccess', { id: this.client.clientId })
this.$message.success(successMessage) this.$message.success(successMessage)
clientEditForm.resetFields() clientEditForm.resetFields()
this.$emit('clientChanged') this.$emit('closed', true)
this.$emit('closed')
}) })
} }
}) })
@ -608,12 +609,17 @@ export default class extends Vue {
private onCancel() { private onCancel() {
const clientEditForm = this.$refs.formClient as any const clientEditForm = this.$refs.formClient as any
clientEditForm.resetFields() clientEditForm.resetFields()
this.$emit('closed') this.$emit('closed', false)
} }
private l(name: string, values?: any[] | { [key: string]: any }) { private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString() return this.$t(name, values).toString()
} }
private test(v: any) {
console.log(v)
console.log(this.client.redirectUris)
}
} }
</script> </script>

15
vueJs/src/views/admin/identityServer/client/components/ClientPermissionEditForm.vue

@ -9,6 +9,7 @@
<PermissionTree <PermissionTree
ref="PermissionTree" ref="PermissionTree"
:expanded="false" :expanded="false"
:horizontally="true"
:readonly="!checkPermission(['IdentityServer.Clients.ManagePermissions'])" :readonly="!checkPermission(['IdentityServer.Clients.ManagePermissions'])"
:permission="clientPermission" :permission="clientPermission"
@onPermissionChanged="onPermissionChanged" @onPermissionChanged="onPermissionChanged"
@ -52,14 +53,17 @@ import PermissionService, { PermissionDto, UpdatePermissionsDto } from '@/api/pe
} }
}) })
export default class extends Vue { export default class extends Vue {
/** 客户端标识 */
@Prop({ default: '' }) @Prop({ default: '' })
private clientId!: string private clientId!: string
/** 客户端权限 */
private clientPermission: PermissionDto private clientPermission: PermissionDto
/** 是否已加载权限 */
private hasLoadPermission: boolean private hasLoadPermission: boolean
/** 角色权限已变更 */ /** 客户端权限已变更 */
private clientPermissionChanged: boolean private clientPermissionChanged: boolean
/** 变更角色权限数据 */ /** 变更客户端权限数据 */
private editClientPermissions: IPermission[] private editClientPermissions: IPermission[]
constructor() { constructor() {
@ -70,6 +74,7 @@ export default class extends Vue {
this.editClientPermissions = new Array<IPermission>() this.editClientPermissions = new Array<IPermission>()
} }
/** 监听客户端标识变更事件,刷新客户端权限数据 */
@Watch('clientId', { immediate: true }) @Watch('clientId', { immediate: true })
private onClientIdChanged() { private onClientIdChanged() {
if (this.clientId) { if (this.clientId) {
@ -80,12 +85,15 @@ export default class extends Vue {
} }
} }
/** 角色权限树变更事件 */ /**
* @param permissions 变更权限数据
*/
private onPermissionChanged(permissions: IPermission[]) { private onPermissionChanged(permissions: IPermission[]) {
this.clientPermissionChanged = true this.clientPermissionChanged = true
this.editClientPermissions = permissions this.editClientPermissions = permissions
} }
/** 保存客户端权限 */
private onSaveClientPemissions() { private onSaveClientPemissions() {
if (this.clientPermissionChanged) { if (this.clientPermissionChanged) {
const setClientPermissions = new UpdatePermissionsDto() const setClientPermissions = new UpdatePermissionsDto()
@ -96,6 +104,7 @@ export default class extends Vue {
} }
} }
/** 取消操作 */
private onCancel() { private onCancel() {
const permissionTree = this.$refs.PermissionTree as PermissionTree const permissionTree = this.$refs.PermissionTree as PermissionTree
permissionTree.resetPermissions() permissionTree.resetPermissions()

3
vueJs/src/views/admin/identityServer/client/components/ClientPropertyEditForm.vue

@ -33,6 +33,7 @@
<el-button <el-button
type="primary" type="primary"
style="width:180px" style="width:180px"
:disabled="!checkPermission(['IdentityServer.Clients.Properties.Create'])"
@click="onSaveClientProperty" @click="onSaveClientProperty"
> >
{{ $t('identityServer.createProperty') }} {{ $t('identityServer.createProperty') }}
@ -81,7 +82,7 @@
> >
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button <el-button
:disabled="!checkPermission(['IdentityServer.Clients.Update'])" :disabled="!checkPermission(['IdentityServer.Clients.Properties.Delete'])"
size="mini" size="mini"
type="primary" type="primary"
@click="handleDeleteClientProperty(row.key, row.value)" @click="handleDeleteClientProperty(row.key, row.value)"

32
vueJs/src/views/admin/identityServer/client/components/ClientSecretEditForm.vue

@ -43,6 +43,35 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item
prop="hashType"
:label="$t('identityServer.secretHashType')"
>
<el-popover
ref="popHashType"
placement="top-start"
trigger="hover"
:content="$t('identityServer.hashOnlySharedSecret')"
/>
<el-select
v-model="clientSecret.hashType"
v-popover:popHashType
:disabled="clientSecret.type !== 'SharedSecret'"
class="full-select"
:placeholder="$t('pleaseSelectBy', {key: $t('identityServer.secretHashType')})"
>
<el-option
:key="0"
label="Sha256"
:value="0"
/>
<el-option
:key="1"
label="Sha512"
:value="1"
/>
</el-select>
</el-form-item>
<el-form-item <el-form-item
prop="value" prop="value"
:label="$t('identityServer.secretValue')" :label="$t('identityServer.secretValue')"
@ -78,6 +107,7 @@
<el-button <el-button
type="primary" type="primary"
style="width:180px" style="width:180px"
:disabled="!checkPermission(['IdentityServer.Clients.Secrets.Create'])"
@click="onSaveClientSecret" @click="onSaveClientSecret"
> >
{{ $t('identityServer.createSecret') }} {{ $t('identityServer.createSecret') }}
@ -146,7 +176,7 @@
> >
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button <el-button
:disabled="!checkPermission(['IdentityServer.Clients.Update'])" :disabled="!checkPermission(['IdentityServer.Clients.Secrets.Delete'])"
size="mini" size="mini"
type="primary" type="primary"
@click="handleDeleteClientSecret(row.type, row.value)" @click="handleDeleteClientSecret(row.type, row.value)"

44
vueJs/src/views/admin/identityServer/client/index.vue

@ -61,6 +61,19 @@
<span>{{ row.clientName }}</span> <span>{{ row.clientName }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
:label="$t('identityServer.clientStatus')"
prop="enabled"
sortable
width="140px"
align="center"
>
<template slot-scope="{row}">
<el-tag :type="row.enabled | statusFilter">
{{ formatStatusText(row.enabled) }}
</el-tag>
</template>
</el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.identityTokenLifetime')" :label="$t('identityServer.identityTokenLifetime')"
prop="identityTokenLifetime" prop="identityTokenLifetime"
@ -212,7 +225,6 @@
custom-class="modal-form" custom-class="modal-form"
:show-close="false" :show-close="false"
@closed="handleClientCreateFormClosed" @closed="handleClientCreateFormClosed"
@clientChanged="handleGetClients"
> >
<ClientCreateForm <ClientCreateForm
ref="formCreateClient" ref="formCreateClient"
@ -329,7 +341,18 @@ import ClientService, { Client, ClientGetByPaged } from '@/api/clients'
ClientPermissionEditForm ClientPermissionEditForm
}, },
methods: { methods: {
checkPermission checkPermission,
local(name: string) {
return this.$t(name)
}
},
filters: {
statusFilter(status: boolean) {
if (status) {
return 'success'
}
return 'warning'
}
} }
}) })
export default class extends Vue { export default class extends Vue {
@ -354,7 +377,7 @@ export default class extends Vue {
this.showEditClientDialog = false this.showEditClientDialog = false
this.showCreateClientDialog = false this.showCreateClientDialog = false
this.showEditClientPermissionDialog = false this.showEditClientPermissionDialog = false
this.editClient = new Client() this.editClient = Client.empty()
this.clientList = new Array<Client>() this.clientList = new Array<Client>()
this.showEditClientSecretDialog = false this.showEditClientSecretDialog = false
this.showEditClientClaimDialog = false this.showEditClientClaimDialog = false
@ -381,7 +404,7 @@ export default class extends Vue {
} }
private handleShowCreateClientForm() { private handleShowCreateClientForm() {
this.editClient = new Client() this.editClient = Client.empty()
this.editClientTitle = this.$t('identityServer.createClient') this.editClientTitle = this.$t('identityServer.createClient')
this.showCreateClientDialog = true this.showCreateClientDialog = true
} }
@ -394,6 +417,7 @@ export default class extends Vue {
private handleClientCreateFormClosed(changed: boolean) { private handleClientCreateFormClosed(changed: boolean) {
this.editClientTitle = '' this.editClientTitle = ''
this.editClient = Client.empty()
this.showCreateClientDialog = false this.showCreateClientDialog = false
const frmClient = this.$refs.formCreateClient as ClientCreateForm const frmClient = this.$refs.formCreateClient as ClientCreateForm
frmClient.resetFields() frmClient.resetFields()
@ -404,6 +428,7 @@ export default class extends Vue {
private handleClientEditFormClosed(changed: boolean) { private handleClientEditFormClosed(changed: boolean) {
this.editClientTitle = '' this.editClientTitle = ''
this.editClient = Client.empty()
this.showEditClientDialog = false this.showEditClientDialog = false
if (changed) { if (changed) {
this.handleGetClients() this.handleGetClients()
@ -429,6 +454,7 @@ export default class extends Vue {
} }
private handleClientPermissionEditFormClosed() { private handleClientPermissionEditFormClosed() {
this.editClient = Client.empty()
this.showEditClientPermissionDialog = false this.showEditClientPermissionDialog = false
} }
@ -471,6 +497,16 @@ export default class extends Vue {
private l(name: string, values?: any[] | { [key: string]: any }) { private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString() return this.$t(name, values).toString()
} }
private formatStatusText(status: boolean) {
let statusText = ''
if (status) {
statusText = this.l('enabled')
} else {
statusText = this.l('disbled')
}
return statusText
}
} }
</script> </script>

Loading…
Cancel
Save