Browse Source

Refactoring Api: identity-resource

Add New New component :PermissionForm
pull/109/head
cKey 5 years ago
parent
commit
48215226f0
  1. 0
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneDto.cs
  2. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs
  3. 5
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientUpdateDto.cs
  4. 2
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/IdentityResources/Dto/IdentityResourceDto.cs
  5. 68
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json
  6. 69
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json
  7. 39
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs
  8. BIN
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db
  9. 268
      vueJs/src/api/clients.ts
  10. 166
      vueJs/src/api/identity-resources.ts
  11. 12
      vueJs/src/api/permission.ts
  12. 466
      vueJs/src/components/PermissionForm/index.vue
  13. 5
      vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue
  14. 5
      vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue
  15. 204
      vueJs/src/views/admin/identityServer/client/index.vue
  16. 238
      vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue
  17. 120
      vueJs/src/views/admin/identityServer/identity-resources/index.vue
  18. 5
      vueJs/src/views/admin/roles/components/RoleClaimCreateOrUpdateForm.vue
  19. 5
      vueJs/src/views/admin/roles/components/RoleEditForm.vue
  20. 5
      vueJs/src/views/admin/users/components/UserClaimCreateOrUpdateForm.vue

0
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneInputDto.cs → aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneDto.cs

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs

@ -1,9 +0,0 @@
using Volo.Abp.Application.Dtos;
namespace LINGYUN.Abp.IdentityServer.Clients
{
public class ClientCorsOriginDto : EntityDto
{
public string Origin { get; set; }
}
}

5
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientUpdateDto.cs

@ -114,6 +114,10 @@ namespace LINGYUN.Abp.IdentityServer.Clients
/// 密钥 /// 密钥
/// </summary> /// </summary>
public List<SecretCreateOrUpdateDto> Secrets { get; set; } public List<SecretCreateOrUpdateDto> Secrets { get; set; }
/// <summary>
/// 声明
/// </summary>
public List<ClientClaimDto> Claims { get; set; }
public ClientUpdateDto() public ClientUpdateDto()
{ {
@ -127,6 +131,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
IdentityProviderRestrictions = new List<string>(); IdentityProviderRestrictions = new List<string>();
Properties = new Dictionary<string, string>(); Properties = new Dictionary<string, string>();
Secrets = new List<SecretCreateOrUpdateDto>(); Secrets = new List<SecretCreateOrUpdateDto>();
Claims = new List<ClientClaimDto>();
} }
} }
} }

2
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/IdentityResources/Dto/IdentityResourceDto.cs

@ -12,8 +12,6 @@ namespace LINGYUN.Abp.IdentityServer.IdentityResources
public string Description { get; set; } public string Description { get; set; }
public string ConcurrencyStamp { get; set; }
public bool Enabled { get; set; } public bool Enabled { get; set; }
public bool Required { get; set; } public bool Required { get; set; }

68
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json

@ -31,7 +31,11 @@
"Resource:Enabled": "Enabled", "Resource:Enabled": "Enabled",
"Resource:New": "Add New", "Resource:New": "Add New",
"Resource:Edit": "Edit", "Resource:Edit": "Edit",
"Resource:Delete": "Delete",
"Resource:WillDelete": "Resource :{0} will be deleted",
"Resource:Name": "Resource - {0}", "Resource:Name": "Resource - {0}",
"Resource:Api": "Api Resource",
"Resource:Identity": "Identity Resource",
"UserClaim": "User claim", "UserClaim": "User claim",
"NoClaim": "Owned claims", "NoClaim": "Owned claims",
"ExistsClaim": "Not owned claims", "ExistsClaim": "Not owned claims",
@ -49,6 +53,68 @@
"Secret:New": "Add New", "Secret:New": "Add New",
"Secret:Type": "Type", "Secret:Type": "Type",
"Secret:HashType": "Hash Type", "Secret:HashType": "Hash Type",
"Secret:Value": "Value" "Secret:Value": "Value",
"Client:Enabled": "Enabled",
"Client:New": "Add New",
"Client:Edit": "Edit",
"Client:Delete": "Delete",
"Client:WillDelete": "Client :{0} will be deleted",
"Client:Name": "Client - {0}",
"Client:Id": "Client Id",
"Client:Clone": "Clone",
"Clone:CopyAllowedGrantType": "Copy the Client allowed GrantType",
"Clone:CopyRedirectUri": "Copy the Client redirect Uri",
"Clone:CopyAllowedScope": "Copy the Client scopes",
"Clone:CopyClaim": "Copy the Client claims",
"Clone:CopyAllowedCorsOrigin": "Copy the Client Cors-Origin Uri",
"Clone:CopyPostLogoutRedirectUri": "Copy the Client Redirect Uri",
"Clone:CopyProperties": "Copy the Client Properties",
"Clone:CopyIdentityProviderRestriction": "Copy the Client Identity Provider Restriction",
"Client:ProtocolType": "Protocol Type",
"Client:RequiredClientSecret": "Require Client Secret",
"Client:RequiredPkce": "Required Pkce",
"Client:AllowedPlainTextPkce": "Allowed Plain Text Pkce",
"Client:AllowedOfflineAccess": "Allowed Offline Access",
"Client:AllowedScopes": "Allowed Scopes",
"Client:RedirectUris": "Redirect Uris",
"Client:AllowedGrantTypes": "Allowed Grant Types",
"Client:AllowedAccessTokensViaBrowser": "Allowed Access Tokens Via Browser",
"Client:IdentityTokenLifetime": "Identity Token Lifetime(s)",
"Client:AccessTokenLifetime": "Access Token Lifetime(s)",
"Client:AuthorizationCodeLifetime": "Authorization Code Lifetime(s)",
"Client:AbsoluteRefreshTokenLifetime": "Absolute Refresh Token Lifetime(s)",
"Client:SlidingRefreshTokenLifetime": "Sliding Refresh Token Lifetime(s)",
"Client:DeviceCodeLifetime": "Device Code Lifetime(s)",
"Client:ClientClaimsPrefix": "Client Claims Prefix",
"Client:FrontChannelLogoutUri": "Front Channel Logout Uri",
"Client:FrontChannelLogoutSessionRequired": "Front Channel Logout Session Required",
"Client:BackChannelLogoutUri": "Back Channel Logout Uri",
"Client:BackChannelLogoutSessionRequired": "Back Channel Logout Session Required",
"Client:EnableLocalLogin": "Enable Local Login",
"Client:PostLogoutRedirectUris": "Post Logout Redirect Uris",
"Client:IdentityProviderRestrictions": "Identity Provider Restrictions",
"Client:UserSsoLifetime": "User Sso Lifetime",
"Client:AccessTokenType": "AccessToken Type",
"Client:RefreshTokenUsage": "Refresh Token Usage",
"Client:RefreshTokenExpiration": "RefreshToken Expiration",
"Client:AllowedCorsOrigins": "Allowed Cors Origins",
"Client:UpdateAccessTokenClaimsOnRefresh": "Update AccessToken Claims On Refresh",
"Client:IncludeJwtId": "Include Jwt Id",
"Client:AlwaysSendClientClaims": "Always Send Client Claims",
"Client:AlwaysIncludeUserClaimsInIdToken": "Always Include User Claims In Id Token",
"Client:PairWiseSubjectSalt": "Pair Wise Subject Salt",
"Client:RequireConsent": "Require Consent",
"Client:AllowRememberConsent": "Allow Remember Consent",
"Client:ClientUri": "Client Uri",
"Client:LogoUri": "Logo Uri",
"Client:UserCodeType": "User Code Type",
"Claims": "Claims",
"Claims:New": "Add New",
"Claims:Type": "Type",
"Claims:Value": "Value",
"Propertites": "Propertites",
"Propertites:New": "Add New",
"Propertites:Value": "Value",
"Permissions": "Permissions"
} }
} }

69
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json

@ -32,7 +32,10 @@
"Resource:New": "添加新资源", "Resource:New": "添加新资源",
"Resource:Edit": "编辑资源", "Resource:Edit": "编辑资源",
"Resource:Delete": "删除资源", "Resource:Delete": "删除资源",
"Resource:WillDelete": "资源:{0} 将被删除",
"Resource:Name": "资源 - {0}", "Resource:Name": "资源 - {0}",
"Resource:Api": "Api 资源",
"Resource:Identity": "身份资源",
"UserClaim": "用户声明", "UserClaim": "用户声明",
"NoClaim": "未拥有声明", "NoClaim": "未拥有声明",
"ExistsClaim": "已拥有声明", "ExistsClaim": "已拥有声明",
@ -43,13 +46,75 @@
"Description": "描述", "Description": "描述",
"Required": "必要", "Required": "必要",
"Emphasize": "强调", "Emphasize": "强调",
"ShowInDiscoveryDocument": "强调", "ShowInDiscoveryDocument": "在发现文档中显示",
"Expiration": "过期", "Expiration": "过期",
"Scope:New": "添加新作用域", "Scope:New": "添加新作用域",
"Scope:Delete": "删除作用域", "Scope:Delete": "删除作用域",
"Secret:New": "添加新密钥", "Secret:New": "添加新密钥",
"Secret:Type": "密钥类型", "Secret:Type": "密钥类型",
"Secret:HashType": "哈希类型", "Secret:HashType": "哈希类型",
"Secret:Value": "值" "Secret:Value": "值",
"Client:Enabled": "启用客户端",
"Client:New": "添加新客户端",
"Client:Edit": "编辑客户端",
"Client:Delete": "删除客户端",
"Client:WillDelete": "客户端:{0} 将被删除",
"Client:Name": "客户端 - {0}",
"Client:Id": "客户端标识",
"Client:Clone": "克隆客户端",
"Clone:CopyAllowedGrantType": "复制客户端授权类型",
"Clone:CopyRedirectUri": "复制客户端重定向 Uri",
"Clone:CopyAllowedScope": "复制客户端作用域",
"Clone:CopyClaim": "复制客户端声明",
"Clone:CopyAllowedCorsOrigin": "复制客户端跨域来源",
"Clone:CopyPostLogoutRedirectUri": "复制客户端注销重定向 Uri",
"Clone:CopyProperties": "复制客户端属性",
"Clone:CopyIdentityProviderRestriction": "复制身份提供程序限制",
"Client:ProtocolType": "协议类型",
"Client:RequireClientSecret": "需要客户端密钥",
"Client:RequirePkce": "需要 Pkce",
"Client:AllowedPlainTextPkce": "允许纯文本 Pkce",
"Client:AllowedOfflineAccess": "允许离线访问",
"Client:AllowedScopes": "允许的作用域",
"Client:RedirectUris": "重定向 Uri",
"Client:AllowedGrantTypes": "允许的授权类型",
"Client:AllowedAccessTokensViaBrowser": "允许通过浏览器访问令牌",
"Client:IdentityTokenLifetime": "身份令牌有效期(s)",
"Client:AccessTokenLifetime": "访问令牌有效期(s)",
"Client:AuthorizationCodeLifetime": "授权码有效期(s)",
"Client:AbsoluteRefreshTokenLifetime": "绝对刷新令牌有效期(s)",
"Client:SlidingRefreshTokenLifetime": "滚动刷新令牌有效期(s)",
"Client:DeviceCodeLifetime": "设备授权码有效期(s)",
"Client:ClientClaimsPrefix": "客户端声明前缀",
"Client:FrontChannelLogoutUri": "前端通道注销 Uri",
"Client:FrontChannelLogoutSessionRequired": "需要前端通道注销会话",
"Client:BackChannelLogoutUri": "后端通道退出 Uri",
"Client:BackChannelLogoutSessionRequired": "需要后端通道注销会话",
"Client:EnableLocalLogin": "启用本地登录",
"Client:PostLogoutRedirectUris": "注销重定向 Uri",
"Client:IdentityProviderRestrictions": "身份提供程序限制",
"Client:UserSsoLifetime": "用户 SSO 生命周期",
"Client:AccessTokenType": "访问令牌类型",
"Client:RefreshTokenUsage": "刷新令牌使用情况",
"Client:RefreshTokenExpiration": "刷新令牌过期方式",
"Client:AllowedCorsOrigins": "允许跨域来源",
"Client:UpdateAccessTokenClaimsOnRefresh": "刷新时更新访问令牌声明",
"Client:IncludeJwtId": "包括 Jwt 标识",
"Client:AlwaysSendClientClaims": "始终发送客户端声明",
"Client:AlwaysIncludeUserClaimsInIdToken": "始终在标识令牌中包含用户声明",
"Client:PairWiseSubjectSalt": "配对主体盐",
"Client:RequireConsent": "需要同意",
"Client:AllowRememberConsent": "允许记住同意",
"Client:ClientUri": "客户端 Uri",
"Client:LogoUri": "徽标 Uri",
"Client:UserCodeType": "用户代码类型",
"Claims": "声明",
"Claims:New": "添加新声明",
"Claims:Type": "声明类型",
"Claims:Value": "值",
"Propertites": "属性",
"Propertites:New": "添加新属性",
"Propertites:Value": "值",
"Permissions": "权限"
} }
} }

39
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs

@ -40,7 +40,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients
client.AddGrantType(grantType); client.AddGrantType(grantType);
} }
client = await ClientRepository.InsertAsync(client, true); client = await ClientRepository.InsertAsync(client);
await CurrentUnitOfWork.SaveChangesAsync(); await CurrentUnitOfWork.SaveChangesAsync();
@ -50,7 +50,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients
[Authorize(AbpIdentityServerPermissions.Clients.Delete)] [Authorize(AbpIdentityServerPermissions.Clients.Delete)]
public virtual async Task DeleteAsync(Guid id) public virtual async Task DeleteAsync(Guid id)
{ {
await ClientRepository.DeleteAsync(id); var client = await ClientRepository.GetAsync(id);
await ClientRepository.DeleteAsync(client);
await CurrentUnitOfWork.SaveChangesAsync(); await CurrentUnitOfWork.SaveChangesAsync();
} }
@ -64,10 +65,9 @@ namespace LINGYUN.Abp.IdentityServer.Clients
public virtual async Task<PagedResultDto<ClientDto>> GetListAsync(ClientGetByPagedDto input) public virtual async Task<PagedResultDto<ClientDto>> GetListAsync(ClientGetByPagedDto input)
{ {
// Abp官方IdentityServer项目不支持Filter过滤...
var clients = await ClientRepository.GetListAsync(input.Sorting, var clients = await ClientRepository.GetListAsync(input.Sorting,
input.SkipCount, input.MaxResultCount, input.SkipCount, input.MaxResultCount,
input.Filter, true); input.Filter);
var clientCount = await ClientRepository.GetCountAsync(); var clientCount = await ClientRepository.GetCountAsync();
@ -245,6 +245,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients
#region Secrets #region Secrets
// 移除已经不存在的客户端密钥
client.ClientSecrets.RemoveAll(secret => !input.Secrets.Any(inputSecret => secret.Value == inputSecret.Value && secret.Type == inputSecret.Type));
var currentSecrets = new List<ClientSecretDto>(); var currentSecrets = new List<ClientSecretDto>();
foreach (var inputSecret in input.Secrets) foreach (var inputSecret in input.Secrets)
{ {
@ -271,23 +273,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients
if (clientSecret == null) if (clientSecret == null)
{ {
client.AddSecret(inputSecretValue, inputSecret.Expiration, inputSecret.Type, inputSecret.Description); client.AddSecret(inputSecretValue, inputSecret.Expiration, inputSecret.Type, inputSecret.Description);
currentSecrets.Add(new ClientSecretDto
{
Value = inputSecretValue,
Type = inputSecret.Type
});
}
else
{
currentSecrets.Add(new ClientSecretDto
{
Value = clientSecret.Value,
Type = clientSecret.Type
});
} }
} }
// 移除已经不存在的客户端密钥
client.ClientSecrets.RemoveAll(secret => !currentSecrets.Any(allowSecret => secret.Value == allowSecret.Value && secret.Type == allowSecret.Type));
#endregion #endregion
@ -305,6 +292,20 @@ namespace LINGYUN.Abp.IdentityServer.Clients
#endregion #endregion
#region Claims
// 移除已经不存在的客户端声明
client.ClientSecrets.RemoveAll(secret => !input.Claims.Any(inputClaim => secret.Value == inputClaim.Value && secret.Type == inputClaim.Type));
foreach (var inputClaim in input.Claims)
{
if (client.FindClaim(inputClaim.Value, inputClaim.Type) == null)
{
client.AddClaim(inputClaim.Value, inputClaim.Type);
}
}
#endregion
client = await ClientRepository.UpdateAsync(client); client = await ClientRepository.UpdateAsync(client);
await CurrentUnitOfWork.SaveChangesAsync(); await CurrentUnitOfWork.SaveChangesAsync();

BIN
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db

Binary file not shown.

268
vueJs/src/api/clients.ts

@ -1,18 +1,17 @@
import ApiService from './serviceBase' import ApiService from './serviceBase'
import { FullAuditedEntityDto, PagedAndSortedResultRequestDto, PagedResultDto } from './types' import { FullAuditedEntityDto, PagedAndSortedResultRequestDto, PagedResultDto, SecretBase, Claim } from './types'
const sourceUrl = '/api/identity-server/clients'
const serviceUrl = process.env.VUE_APP_BASE_API const serviceUrl = process.env.VUE_APP_BASE_API
export default class ClientService { export default class ClientService {
public static getClientById(id: string) { public static getClientById(id: string) {
let _url = '/api/IdentityServer/Clients/' const _url = sourceUrl + '/' + id
_url += id
return ApiService.Get<Client>(_url, serviceUrl) return ApiService.Get<Client>(_url, serviceUrl)
} }
public static getClients(payload: ClientGetByPaged) { public static getClients(payload: ClientGetByPaged) {
let _url = '/api/IdentityServer/Clients' let _url = sourceUrl + '?filter=' + payload.filter
_url += '?filter=' + payload.filter
_url += '&sorting=' + payload.sorting _url += '&sorting=' + payload.sorting
_url += '&skipCount=' + payload.skipCount _url += '&skipCount=' + payload.skipCount
_url += '&maxResultCount=' + payload.maxResultCount _url += '&maxResultCount=' + payload.maxResultCount
@ -20,144 +19,39 @@ export default class ClientService {
} }
public static createClient(payload: ClientCreate) { public static createClient(payload: ClientCreate) {
const _url = '/api/IdentityServer/Clients' return ApiService.Post<Client>(sourceUrl, payload, serviceUrl)
return ApiService.Post<Client>(_url, payload, serviceUrl)
} }
public static cloneClient(payload: ClientClone) { public static cloneClient(id: string, payload: ClientClone) {
const _url = '/api/IdentityServer/Clients/Clone' const _url = sourceUrl + '/' + id + '/clone'
return ApiService.Post<Client>(_url, payload, serviceUrl) return ApiService.Post<Client>(_url, payload, serviceUrl)
} }
public static updateClient(payload: ClientUpdate) { public static updateClient(id: string, payload: ClientUpdate) {
const _url = '/api/IdentityServer/Clients' const _url = sourceUrl + '/' + id
return ApiService.Put<Client>(_url, payload, serviceUrl) return ApiService.Put<Client>(_url, payload, serviceUrl)
} }
public static deleteClient(id: string) { public static deleteClient(id: string) {
const _url = '/api/IdentityServer/Clients/' + id const _url = sourceUrl + '/' + id
return ApiService.Delete(_url, serviceUrl)
}
public static addClientSecret(payload: ClientSecretCreate) {
const _url = '/api/IdentityServer/Clients/Secrets'
return ApiService.Post<ClientSecret>(_url, payload, serviceUrl)
}
public static deleteClientSecret(clientId: string, type: string, value: string) {
let _url = '/api/IdentityServer/Clients/Secrets'
_url += '?clientId=' + clientId
_url += '&type=' + type
_url += '&value=' + value
return ApiService.Delete(_url, serviceUrl)
}
public static addClientProperty(payload: ClientPropertyCreate) {
const _url = '/api/IdentityServer/Clients/Properties'
return ApiService.Post<ClientProperty>(_url, payload, serviceUrl)
}
public static deleteClientProperty(clientId: string, key: string, value: string) {
let _url = '/api/IdentityServer/Clients/Properties'
_url += '?clientId=' + clientId
_url += '&key=' + key
_url += '&value=' + value
return ApiService.Delete(_url, serviceUrl)
}
public static addClientClaim(payload: ClientClaimCreate) {
const _url = '/api/IdentityServer/Clients/Claims'
return ApiService.Post<ClientClaim>(_url, payload, serviceUrl)
}
public static deleteClientClaim(clientId: string, type: string, value: string) {
let _url = '/api/IdentityServer/Clients/Claims'
_url += '?clientId=' + clientId
_url += '&type=' + type
_url += '&value=' + value
return ApiService.Delete(_url, serviceUrl) return ApiService.Delete(_url, serviceUrl)
} }
} }
export class ClientGetByPaged extends PagedAndSortedResultRequestDto {
filter = ''
}
export enum HashType { export enum HashType {
Sha256, Sha256 = 0,
Sha512 Sha512 = 1
} }
export class ClientSecret { export class SecretCreateOrUpdate extends SecretBase {
type = ''
value = ''
hashType = HashType.Sha256 hashType = HashType.Sha256
description? = ''
expiration? = undefined
}
export class ClientRedirectUri {
redirectUri = ''
}
export class ClientClaim {
type = ''
value = ''
}
export class ClientCorsOrigin {
origin = ''
}
export class ClientGrantType {
grantType = ''
}
export class ClientIdPRestriction {
provider = ''
}
export class ClientPostLogoutRedirectUri {
postLogoutRedirectUri = ''
}
export class ClientProperty {
key = ''
value = ''
}
export class ClientScope {
scope = ''
} }
export class ClientSecretCreate extends ClientSecret { export class ClientGetByPaged extends PagedAndSortedResultRequestDto {
clientId!: string filter = ''
constructor() {
super()
this.type = 'SharedSecret'
this.hashType = HashType.Sha256
}
}
export class ClientClaimCreate extends ClientClaim {
clientId!: string
}
export class ClientPropertyCreate extends ClientProperty {
clientId!: string
} }
export class ClientCreate { export class ClientClaim extends Claim {}
clientId = ''
clientName = ''
description? = ''
allowedGrantTypes?: ClientGrantType[]
constructor() {
this.allowedGrantTypes = new Array<ClientGrantType>()
}
}
export class ClientClone { export class ClientClone {
sourceClientId = '' sourceClientId = ''
@ -218,39 +112,27 @@ export class Client extends FullAuditedEntityDto {
userSsoLifetime!: number userSsoLifetime!: number
userCodeType?: string userCodeType?: string
deviceCodeLifetime!: number deviceCodeLifetime!: number
allowedScopes!: ClientScope[] allowedScopes = new Array<string>()
clientSecrets!: ClientSecret[] clientSecrets = new Array<string>()
allowedGrantTypes!: ClientGrantType[] allowedGrantTypes = new Array<string>()
allowedCorsOrigins!: ClientCorsOrigin[] allowedCorsOrigins = new Array<string>()
redirectUris!: ClientRedirectUri[] redirectUris = new Array<string>()
postLogoutRedirectUris!: ClientPostLogoutRedirectUri[] postLogoutRedirectUris = new Array<string>()
identityProviderRestrictions!: ClientIdPRestriction[] identityProviderRestrictions = new Array<string>()
claims!: ClientClaim[] claims = new Array<string>()
properties!: ClientProperty[] properties = new Array<string>()
}
constructor() {
super() export class ClientCreateOrUpdate {
this.allowedScopes = new Array<ClientScope>()
this.clientSecrets = new Array<ClientSecret>()
this.allowedGrantTypes = new Array<ClientGrantType>()
this.allowedCorsOrigins = new Array<ClientCorsOrigin>()
this.redirectUris = new Array<ClientRedirectUri>()
this.postLogoutRedirectUris = new Array<ClientPostLogoutRedirectUri>()
this.identityProviderRestrictions = new Array<ClientIdPRestriction>()
this.claims = new Array<ClientClaim>()
this.properties = new Array<ClientProperty>()
}
public static empty() {
return new Client()
}
}
export class ClientUpdateData {
concurrencyStamp!: string
clientId = '' clientId = ''
clientName = '' clientName = ''
description? = '' description? = ''
allowedGrantTypes = new Array<string>()
}
export class ClientCreate extends ClientCreateOrUpdate {}
export class ClientUpdate extends ClientCreateOrUpdate {
clientUri? = '' clientUri? = ''
logoUri? = '' logoUri? = ''
enabled = true enabled = true
@ -266,7 +148,7 @@ export class ClientUpdateData {
frontChannelLogoutSessionRequired = true frontChannelLogoutSessionRequired = true
backChannelLogoutUri? = '' backChannelLogoutUri? = ''
backChannelLogoutSessionRequired = true backChannelLogoutSessionRequired = true
allowOfflineAccess = false allowOfflineAccess = true
identityTokenLifetime = 300 identityTokenLifetime = 300
accessTokenLifetime = 3600 accessTokenLifetime = 3600
authorizationCodeLifetime = 300 authorizationCodeLifetime = 300
@ -285,75 +167,13 @@ export class ClientUpdateData {
userSsoLifetime!: number userSsoLifetime!: number
userCodeType? = '' userCodeType? = ''
deviceCodeLifetime = 300 deviceCodeLifetime = 300
allowedScopes!: ClientScope[] apiResources = new Array<string>()
allowedGrantTypes!: ClientGrantType[] identityResources = new Array<string>()
allowedCorsOrigins!: ClientCorsOrigin[] allowedCorsOrigins = new Array<string>()
redirectUris!: ClientRedirectUri[] redirectUris = new Array<string>()
postLogoutRedirectUris!: ClientPostLogoutRedirectUri[] postLogoutRedirectUris = new Array<string>()
identityProviderRestrictions!: ClientIdPRestriction[] identityProviderRestrictions = new Array<string>()
properties: {[key: string]: string} = {}
constructor() { secrets = new Array<SecretCreateOrUpdate>()
this.allowedScopes = new Array<ClientScope>() claims = new Array<ClientClaim>()
this.allowedGrantTypes = new Array<ClientGrantType>()
this.allowedCorsOrigins = new Array<ClientCorsOrigin>()
this.redirectUris = new Array<ClientRedirectUri>()
this.postLogoutRedirectUris = new Array<ClientPostLogoutRedirectUri>()
this.identityProviderRestrictions = new Array<ClientIdPRestriction>()
}
public setClient(client: Client) {
this.absoluteRefreshTokenLifetime = client.absoluteRefreshTokenLifetime
this.accessTokenLifetime = client.accessTokenLifetime
this.accessTokenType = client.accessTokenType
this.allowAccessTokensViaBrowser = client.allowAccessTokensViaBrowser
this.allowOfflineAccess = client.allowOfflineAccess
this.allowPlainTextPkce = client.allowPlainTextPkce
this.allowRememberConsent = client.allowRememberConsent
this.allowedCorsOrigins = client.allowedCorsOrigins
this.allowedGrantTypes = client.allowedGrantTypes
this.allowedScopes = client.allowedScopes
this.alwaysIncludeUserClaimsInIdToken = client.alwaysIncludeUserClaimsInIdToken
this.alwaysSendClientClaims = client.alwaysSendClientClaims
this.authorizationCodeLifetime = client.authorizationCodeLifetime
this.backChannelLogoutSessionRequired = client.backChannelLogoutSessionRequired
this.backChannelLogoutUri = client.backChannelLogoutUri
this.clientClaimsPrefix = client.clientClaimsPrefix
this.clientId = client.clientId
this.clientName = client.clientName
this.clientUri = client.clientUri
this.concurrencyStamp = client.concurrencyStamp
this.consentLifetime = client.consentLifetime
this.description = client.description
this.deviceCodeLifetime = client.deviceCodeLifetime
this.enableLocalLogin = client.enableLocalLogin
this.enabled = client.enabled
this.frontChannelLogoutSessionRequired = client.frontChannelLogoutSessionRequired
this.frontChannelLogoutUri = client.frontChannelLogoutUri
this.identityProviderRestrictions = client.identityProviderRestrictions
this.identityTokenLifetime = client.identityTokenLifetime
this.includeJwtId = client.includeJwtId
this.logoUri = client.logoUri
this.pairWiseSubjectSalt = client.pairWiseSubjectSalt
this.postLogoutRedirectUris = client.postLogoutRedirectUris
this.protocolType = client.protocolType
this.redirectUris = client.redirectUris
this.refreshTokenExpiration = client.refreshTokenExpiration
this.refreshTokenUsage = client.refreshTokenUsage
this.requireClientSecret = client.requireClientSecret
this.requireConsent = client.requireConsent
this.requirePkce = client.requirePkce
this.slidingRefreshTokenLifetime = client.slidingRefreshTokenLifetime
this.updateAccessTokenClaimsOnRefresh = client.updateAccessTokenClaimsOnRefresh
this.userCodeType = client.userCodeType
this.userSsoLifetime = client.userSsoLifetime
}
}
export class ClientUpdate {
id!: string
client!: ClientUpdateData
constructor() {
this.client = new ClientUpdateData()
}
} }

166
vueJs/src/api/identity-resources.ts

@ -35,7 +35,7 @@ export default class IdentityResourceService {
* @param payload IdentityResourceCreate * @param payload IdentityResourceCreate
* @returns IdentityResource * @returns IdentityResource
*/ */
public static createIdentityResource(payload: IdentityResourceCreate) { public static createIdentityResource(payload: IdentityResourceCreateOrUpdate) {
return ApiService.Post<IdentityResource>(sourceUrl, payload, serviceUrl) return ApiService.Post<IdentityResource>(sourceUrl, payload, serviceUrl)
} }
@ -44,7 +44,7 @@ export default class IdentityResourceService {
* @param payload IdentityResourceUpdate * @param payload IdentityResourceUpdate
* @returns IdentityResource * @returns IdentityResource
*/ */
public static updateIdentityResource(id: string, payload: IdentityResourceUpdate) { public static updateIdentityResource(id: string, payload: IdentityResourceCreateOrUpdate) {
const _url = sourceUrl + '/' + id const _url = sourceUrl + '/' + id
return ApiService.Put<IdentityResource>(_url, payload, serviceUrl) return ApiService.Put<IdentityResource>(_url, payload, serviceUrl)
} }
@ -59,161 +59,31 @@ export default class IdentityResourceService {
} }
} }
/** 身份资源用户声明 */ export class IdentityResource extends FullAuditedEntityDto {
export class IdentityClaim { id!: string
/** 用户声明 */
type = ''
}
/** 身份资源属性 */
export class IdentityProperty {
/** 键 */
key = ''
/** 值 */
value = ''
}
/** 身份资源属性创建对象 */
export class IdentityPropertyCreate {
/** 身份资源标识 */
identityResourceId = ''
/** 键 */
key = ''
/** 值 */
value = ''
/** 并发令牌 */
concurrencyStamp = ''
/** 返回一个空对象 */
public static empty() {
return new IdentityPropertyCreate()
}
}
/** 身份资源分页查询对象 */
export class IdentityResourceGetByPaged extends PagedAndSortedResultRequestDto {
/** 过滤参数 */
filter = ''
/** 返回一个空对象 */
public static empty() {
return new IdentityResourceGetByPaged()
}
}
/** 身份资源创建对象 */
export class IdentityResourceCreate {
/** 名称 */
name = '' name = ''
/** 显示名称 */ displayName?: string = ''
displayName? = '' description?: string = ''
/** 说明 */
description? = ''
/** 启用 */
enabled = true enabled = true
/** 必须 */
required = false required = false
/** 强调 */
emphasize = false emphasize = false
/** 在发现文档显示 */ showInDiscoveryDocument = true
showInDiscoveryDocument = false userClaims = new Array<string>()
/** 用户声明 */ properties: {[key: string]: string} = {}
userClaims = new Array<IdentityClaim>() }
/** 返回一个空对象 */
public static empty() {
return new IdentityResourceCreate()
}
/** 创建身份资源 */ export class IdentityResourceGetByPaged extends PagedAndSortedResultRequestDto {
public static create(identityResource: IdentityResource) { filter = ''
const resource = new IdentityResourceCreate()
resource.description = identityResource.description
resource.displayName = identityResource.displayName
resource.emphasize = identityResource.emphasize
resource.enabled = identityResource.enabled
resource.name = identityResource.name
resource.required = identityResource.required
resource.showInDiscoveryDocument = identityResource.showInDiscoveryDocument
resource.userClaims = identityResource.userClaims
return resource
}
} }
/** 身份资源变更对象 */ export class IdentityResourceCreateOrUpdate {
export class IdentityResourceUpdate {
/** 身份资源标识 */
id = ''
/** 名称 */
name = '' name = ''
/** 显示名称 */ displayName?: string = ''
displayName? = '' description?: string = ''
/** 说明 */
description? = ''
/** 启用 */
enabled = true enabled = true
/** 必须 */
required = false required = false
/** 强调 */
emphasize = false emphasize = false
/** 在发现文档显示 */ showInDiscoveryDocument = true
showInDiscoveryDocument = false userClaims = new Array<string>()
/** 并发令牌 */ properties: {[key: string]: string} = {}
concurrencyStamp = ''
/** 用户声明 */
userClaims = new Array<IdentityClaim>()
/** 返回一个空对象 */
public static empty() {
return new IdentityResourceUpdate()
}
/** 创建身份资源 */
public static create(identityResource: IdentityResource) {
const resource = new IdentityResourceUpdate()
resource.concurrencyStamp = identityResource.concurrencyStamp
resource.description = identityResource.description
resource.displayName = identityResource.displayName
resource.emphasize = identityResource.emphasize
resource.enabled = identityResource.enabled
resource.id = identityResource.id
resource.name = identityResource.name
resource.required = identityResource.required
resource.showInDiscoveryDocument = identityResource.showInDiscoveryDocument
resource.userClaims = identityResource.userClaims
return resource
}
}
/** 身份资源对象 */
export class IdentityResource extends FullAuditedEntityDto {
/** 身份资源标识 */
id!: string
/** 名称 */
name!: string
/** 显示名称 */
displayName?: string
/** 说明 */
description?: string
/** 并发令牌 */
concurrencyStamp!: string
/** 启用 */
enabled!: boolean
/** 必须 */
required!: boolean
/** 强调 */
emphasize!: boolean
/** 在发现文档显示 */
showInDiscoveryDocument!: boolean
/** 用户声明 */
userClaims!: IdentityClaim[]
/** 属性 */
properties!: IdentityProperty[]
/** 返回一个空对象 */
public static empty() {
const resource = new IdentityResource()
resource.enabled = true
return resource
}
} }

12
vueJs/src/api/permission.ts

@ -36,11 +36,23 @@ export class UpdatePermissionsDto {
constructor() { constructor() {
this.permissions = new Array<UpdatePermissionDto>() this.permissions = new Array<UpdatePermissionDto>()
} }
public addPermission(name: string, isGranted: boolean) {
this.permissions.push(new UpdatePermissionDto(name, isGranted))
}
} }
export class UpdatePermissionDto implements IPermission { export class UpdatePermissionDto implements IPermission {
name!: string name!: string
isGranted!: boolean isGranted!: boolean
constructor(
name: string,
isGranted: boolean
) {
this.name = name
this.isGranted = isGranted
}
} }
export class PermissionProvider { export class PermissionProvider {

466
vueJs/src/components/PermissionForm/index.vue

@ -0,0 +1,466 @@
<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible="showDialog"
:title="$t('AbpPermissionManagement.Permissions') + '-' + entityDisplayName"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-checkbox
:disabled="readonly"
:value="grantAllCheckBoxCheckAll"
:indeterminate="grantAllCheckBoxForward"
@change="onGrantAllClicked"
>
{{ $t('AbpPermissionManagement.SelectAllInAllTabs') }}
</el-checkbox>
<el-divider />
<el-tabs
tab-position="left"
type="card"
>
<el-tab-pane
v-for="group in permissionGroups"
:key="group.name"
:label="group.displayName + ' (' + grantedCount(group) + ')'"
:name="group.name"
>
<el-card shadow="never">
<div
slot="header"
class="clearfix"
>
<h3>{{ group.displayName }}</h3>
</div>
<el-checkbox
:disabled="readonly"
:value="scopeCheckBoxCheckAll(group)"
:indeterminate="scopeCheckBoxForward(group)"
@change="(checked) => onCheckScopeAllClicked(checked, group, 'permissionTree-' + group.name)"
>
{{ $t('AbpPermissionManagement.SelectAllInThisTab') }}
</el-checkbox>
<el-divider />
<el-tree
:ref="'permissionTree-' + group.name"
show-checkbox
:check-strictly="true"
node-key="id"
:data="group.permissions"
:default-checked-keys="grantedPermissionKeys(group)"
@check-change="(permission, checked) => onPermissionTreeNodeCheckChanged(permission, checked, group, 'permissionTree-' + group.name)"
/>
</el-card>
</el-tab-pane>
</el-tabs>
<el-divider />
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpPermissionManagement.Cancel') }}
</el-button>
<el-button
:disabled="readonly"
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import PermissionApiService, { Permission, UpdatePermissionsDto } from '@/api/permission'
import { Tree } from 'element-ui'
/** element权限树 */
export class PermissionItem {
/** 权限标识 */
id = ''
/** 显示名称 */
label = ''
/** 是否授权 */
isGrant = false
/** 是否禁用 */
disabled = false
/** 子节点 */
children = new Array<PermissionItem>()
/** 父节点 */
parent?: PermissionItem
constructor(
id: string,
label: string,
isGrant: boolean
) {
this.id = id
this.label = label
this.isGrant = isGrant
}
public createChildren(permission: PermissionItem) {
permission.parent = this
this.children.push(permission)
}
public setGrant(grant: boolean) {
this.isGrant = grant
if (this.parent) {
this.parent.setGrant(grant)
}
}
public static setPermissionGrant(grant: boolean, permission: PermissionItem) {
permission.setGrant(grant)
if (!grant) {
permission.children.map(p => {
PermissionItem.setPermissionGrant(false, p)
})
}
}
public static setAllPermissionGrant(grant: boolean, permission: PermissionItem) {
permission.setGrant(grant)
permission.children.map(p => {
PermissionItem.setAllPermissionGrant(grant, p)
})
}
}
export class PermissionGroup {
name = ''
displayName = ''
permissions = new Array<PermissionItem>()
constructor(
name: string,
displayName: string
) {
this.name = name
this.displayName = displayName
}
public permissionCount() {
let count = 0
count += this.deepPermissionCount(this.permissions)
return count
}
public addPermission(permission: PermissionItem) {
this.permissions.push(permission)
}
public setAllGrant(grant: boolean) {
this.permissions.map(p => {
PermissionItem.setAllPermissionGrant(grant, p)
})
}
public grantedPermissionKeys() {
const keys = new Array<string>()
this.deepGrantedPermissionKeys(keys, this.permissions)
return keys
}
public grantedCount() {
let count = 0
count += this.deepGrantedCount(this.permissions)
return count
}
private deepGrantedCount(permissions: PermissionItem[]) {
let count = 0
count += permissions.filter(p => p.isGrant).length
permissions.forEach(p => {
count += this.deepGrantedCount(p.children)
})
return count
}
private deepGrantedPermissionKeys(keys: string[], permissions: PermissionItem[]) {
permissions.forEach(p => {
if (p.isGrant) {
keys.push(p.id)
}
this.deepGrantedPermissionKeys(keys, p.children)
})
}
private deepPermissionCount(permissions: PermissionItem[]) {
let count = 0
count += permissions.length
permissions.forEach(p => {
count += this.deepPermissionCount(p.children)
})
return count
}
}
/**
* 权限编辑组件
* 大量的计算属性与事件响应,还能再优化
*/
@Component({
name: 'PermissionForm'
})
export default class PermissionForm extends Vue {
/** 权限提供者名称 */
@Prop({ default: '' })
private providerName!: string
/** 权限提供者标识 */
@Prop({ default: '' })
private providerKey!: string
/** 是否展示权限编辑组件 */
@Prop({ default: false })
private showDialog!: boolean
/** 权限节点是否只读 */
@Prop({ default: false })
private readonly!: boolean
/** 确认按钮忙碌状态 */
private confirmButtonBusy = false
/** 当前编辑权限实体名称 */
private entityDisplayName = ''
/** 得到的权限组集合 */
private permissionGroups = new Array<PermissionGroup>()
/**
* 用于显示已授权数量
*/
get grantedCount() {
return (group: PermissionGroup) => {
return group.grantedCount()
}
}
/**
* 所有已授权数量
*/
get grantAllCount() {
let count = 0
this.permissionGroups.forEach(group => {
count += group.grantedCount()
})
return count
}
/**
* 用于勾选TreeNode
*/
get grantedPermissionKeys() {
return (group: PermissionGroup) => {
return group.grantedPermissionKeys()
}
}
/**
* 某个权限组权限数量
* 用于设定单个Tree的全选CheckBox状态
*/
get permissionCount() {
return (group: PermissionGroup) => {
return group.permissionCount()
}
}
/**
* 所有权限数量
*/
get permissionAllCount() {
let count = 0
this.permissionGroups.forEach(group => {
count += group.permissionCount()
})
return count
}
/**
* 单个Tree的全选CheckBox是否为选中状态
*/
get scopeCheckBoxCheckAll() {
return (group: PermissionGroup) => {
const grantCount = group.grantedCount()
return grantCount === group.permissionCount()
}
}
/**
* 单个Tree的全选CheckBox状态是否为预选状态
*/
get scopeCheckBoxForward() {
return (group: PermissionGroup) => {
const grantCount = group.grantedCount()
return grantCount > 0 && grantCount < group.permissionCount()
}
}
/**
* 授权所有CheckBox是否为选中状态
*/
get grantAllCheckBoxCheckAll() {
return this.grantAllCount === this.permissionAllCount
}
/**
* 授权所有CheckBox状态是否为预选状态
*/
get grantAllCheckBoxForward() {
const grantCount = this.grantAllCount
return grantCount > 0 && grantCount < this.permissionAllCount
}
/**
* 确认按钮标题
*/
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.$t('AbpPermissionManagement.SavingWithThreeDot')
}
return this.$t('AbpPermissionManagement.Save')
}
/**
* 响应组件可视事件
*/
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetPermissions()
}
/**
* 获取权限集合
*/
private handleGetPermissions() {
this.permissionGroups.length = 0
if (this.showDialog && this.providerName) {
PermissionApiService.getPermissionsByKey(this.providerName, this.providerKey).then(res => {
this.entityDisplayName = res.entityDisplayName
res.groups.map(g => {
const group = new PermissionGroup(g.name, g.displayName)
const parents = g.permissions.filter(p => p.parentName === null)
parents.forEach(parent => {
const permission = new PermissionItem(parent.name, parent.displayName, parent.isGranted)
permission.disabled = this.readonly
const subPermissions = g.permissions.filter(p => p.parentName?.startsWith(parent.name))
this.generatePermission(permission, subPermissions)
group.addPermission(permission)
})
this.permissionGroups.push(group)
})
})
}
}
/**
* @param permissionTree 二级权限树
* @param permissions 权限列表
*/
private generatePermission(permission: PermissionItem, permissions: Permission[]) {
const subPermissions = permissions.filter(p => p.parentName !== permission.id)
permissions = permissions.filter(p => p.parentName === permission.id)
permissions.forEach(p => {
const children = new PermissionItem(p.name, p.displayName, p.isGranted)
children.disabled = this.readonly
const itemSubPermissions = subPermissions.filter(sp => sp.parentName === p.name)
if (itemSubPermissions.length > 0) {
this.generatePermission(children, itemSubPermissions)
}
permission.createChildren(children)
})
}
/**
* 保存权限
*/
private onSave() {
const updatePermission = new UpdatePermissionsDto()
this.permissionGroups.forEach(group => {
this.updatePermissionByInput(updatePermission, group.permissions)
})
this.confirmButtonBusy = true
PermissionApiService
.setPermissionsByKey(this.providerName, this.providerKey, updatePermission)
.then(() => {
this.$message.success(this.$t('global.successful').toString())
})
.finally(() => {
this.confirmButtonBusy = false
})
}
private updatePermissionByInput(permissions: UpdatePermissionsDto, items: PermissionItem[]) {
items.forEach(p => {
permissions.addPermission(p.id, p.isGrant)
this.updatePermissionByInput(permissions, p.children)
})
}
/**
* 窗口关闭事件
*/
private onFormClosed() {
this.$emit('closed')
}
/**
* 授予所有权限 按钮事件
*/
private onGrantAllClicked(checked: boolean) {
this.permissionGroups.forEach(group => {
group.setAllGrant(checked)
const trees = this.$refs['permissionTree-' + group.name] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
})
}
/**
* Permission Tree 全选按钮事件
*/
private onCheckScopeAllClicked(checked: boolean, group: PermissionGroup, treeRef: any) {
group.setAllGrant(checked)
const trees = this.$refs[treeRef] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
}
/**
* Permission TreeNode 变更事件
*/
private onPermissionTreeNodeCheckChanged(permission: PermissionItem, checked: boolean, group: PermissionGroup, treeRef: any) {
PermissionItem.setPermissionGrant(checked, permission)
if (permission.children.length > 0) {
const trees = this.$refs[treeRef] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
}
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
right: 10px;
}
.cancel {
position: absolute;
right: 120px;
}
</style>

5
vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue

@ -153,11 +153,6 @@ export default class CreateOrUpdateCliamTypeForm extends Vue {
return false return false
} }
@Watch('claimTypeId')
private onClaimTypeIdChanged() {
this.handleGetClaimType()
}
@Watch('showDialog', { immediate: true }) @Watch('showDialog', { immediate: true })
private onShowDialogChanged() { private onShowDialogChanged() {
this.handleGetClaimType() this.handleGetClaimType()

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

@ -187,11 +187,6 @@ export default class extends Vue {
return false return false
} }
@Watch('apiResourceId')
private onApiResourceIdChanged() {
this.handleGetApiResource()
}
@Watch('showDialog', { immediate: true }) @Watch('showDialog', { immediate: true })
private onShowDialogChanged() { private onShowDialogChanged() {
this.handleGetApiResource() this.handleGetApiResource()

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

@ -25,7 +25,7 @@
:disabled="!checkPermission(['IdentityServer.Clients.Create'])" :disabled="!checkPermission(['IdentityServer.Clients.Create'])"
@click="handleShowCreateClientForm()" @click="handleShowCreateClientForm()"
> >
{{ $t('identityServer.createClient') }} {{ $t('AbpIdentityServer.Client:New') }}
</el-button> </el-button>
</div> </div>
@ -40,7 +40,7 @@
@sort-change="handleSortChange" @sort-change="handleSortChange"
> >
<el-table-column <el-table-column
:label="$t('identityServer.clientId')" :label="$t('AbpIdentityServer.Client:Id')"
prop="clientId" prop="clientId"
sortable sortable
width="150px" width="150px"
@ -51,7 +51,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.clientName')" :label="$t('AbpIdentityServer.Name')"
prop="clientName" prop="clientName"
sortable sortable
width="200px" width="200px"
@ -62,20 +62,43 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.clientStatus')" :label="$t('AbpIdentityServer.Description')"
prop="description"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentityServer.Client:Enabled')"
prop="enabled" prop="enabled"
sortable sortable
width="140px" width="140px"
align="center" align="center"
> >
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-tag :type="row.enabled | statusFilter"> <el-switch
{{ formatStatusText(row.enabled) }} v-model="row.enabled"
</el-tag> disabled
/>
</template>
</el-table-column>
<el-table-column
:label="$t('AbpIdentityServer.Client:ProtocolType')"
prop="protocolType"
sortable
width="120px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.protocolType }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.identityTokenLifetime')" :label="$t('AbpIdentityServer.Client:IdentityTokenLifetime')"
prop="identityTokenLifetime" prop="identityTokenLifetime"
width="170px" width="170px"
align="center" align="center"
@ -85,7 +108,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.accessTokenLifetime')" :label="$t('AbpIdentityServer.Client:AccessTokenLifetime')"
prop="accessTokenLifetime" prop="accessTokenLifetime"
width="170px" width="170px"
align="center" align="center"
@ -95,7 +118,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.authorizationCodeLifetime')" :label="$t('AbpIdentityServer.Client:AuthorizationCodeLifetime')"
prop="authorizationCodeLifetime" prop="authorizationCodeLifetime"
width="170px" width="170px"
align="center" align="center"
@ -105,7 +128,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.deviceCodeLifetime')" :label="$t('AbpIdentityServer.Client:DeviceCodeLifetime')"
prop="deviceCodeLifetime" prop="deviceCodeLifetime"
width="170px" width="170px"
align="center" align="center"
@ -115,7 +138,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.absoluteRefreshTokenLifetime')" :label="$t('AbpIdentityServer.Client:AbsoluteRefreshTokenLifetime')"
prop="absoluteRefreshTokenLifetime" prop="absoluteRefreshTokenLifetime"
width="180px" width="180px"
align="center" align="center"
@ -125,7 +148,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.slidingRefreshTokenLifetime')" :label="$t('AbpIdentityServer.Client:SlidingRefreshTokenLifetime')"
prop="slidingRefreshTokenLifetime" prop="slidingRefreshTokenLifetime"
width="180px" width="180px"
align="center" align="center"
@ -135,7 +158,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('identityServer.clientClaimsPrefix')" :label="$t('AbpIdentityServer.Client:ClientClaimsPrefix')"
prop="clientClaimsPrefix" prop="clientClaimsPrefix"
width="120px" width="120px"
align="center" align="center"
@ -157,7 +180,7 @@
type="primary" type="primary"
@click="handleShowEditClientForm(row)" @click="handleShowEditClientForm(row)"
> >
{{ $t('identityServer.updateClient') }} {{ $t('AbpIdentityServer.Client:Edit') }}
</el-button> </el-button>
<el-dropdown <el-dropdown
class="options" class="options"
@ -168,46 +191,27 @@
size="mini" size="mini"
type="info" type="info"
> >
{{ $t('identityServer.otherOpera') }}<i class="el-icon-arrow-down el-icon--right" /> {{ $t('global.operaActions') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button> </el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item <el-dropdown-item
:command="{key: 'clone', row}" :command="{key: 'permissions', row}"
:disabled="!checkPermission(['IdentityServer.Clients.Clone'])" :disabled="!checkPermission(['IdentityServer.Clients.ManagePermissions'])"
>
{{ $t('identityServer.cloneClint') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'claim', row}"
:disabled="!checkPermission(['IdentityServer.Clients.Claims'])"
>
{{ $t('identityServer.clientClaim') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'property', row}"
:disabled="!checkPermission(['IdentityServer.Clients.Properties'])"
>
{{ $t('identityServer.clientProperty') }}
</el-dropdown-item>
<el-dropdown-item
:command="{key: 'secret', row}"
:disabled="!checkPermission(['IdentityServer.Clients.Secrets'])"
> >
{{ $t('identityServer.clientSecret') }} {{ $t('AbpIdentityServer.Permissions') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item <el-dropdown-item
:command="{key: 'permissions', row}" :command="{key: 'clone', row}"
:disabled="!checkPermission(['IdentityServer.Clients.ManagePermissions'])" :disabled="!checkPermission(['IdentityServer.Clients.Clone'])"
> >
{{ $t('identityServer.clientPermission') }} {{ $t('AbpIdentityServer.Client:Clone') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item <el-dropdown-item
divided divided
:command="{key: 'delete', row}" :command="{key: 'delete', row}"
:disabled="!checkPermission(['IdentityServer.Clients.Delete'])" :disabled="!checkPermission(['IdentityServer.Clients.Delete'])"
> >
{{ $t('identityServer.deleteClient') }} {{ $t('AbpIdentityServer.Client:Delete') }}
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
@ -215,7 +219,7 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<Pagination <pagination
v-show="dataTotal>0" v-show="dataTotal>0"
:total="dataTotal" :total="dataTotal"
:page.sync="currentPage" :page.sync="currentPage"
@ -224,50 +228,11 @@
@sort-change="handleSortChange" @sort-change="handleSortChange"
/> />
<client-create-form <permission-form
:show-dialog="showCreateClientDialog" provider-name="C"
@closed="handleClientCreateFormClosed" :provider-key="editClientId"
/>
<client-clone-form
:show-dialog="showCloneClientDialog"
:client-id="editClient.id"
@closed="handleClientCloneFormClosed"
/>
<client-edit-form
:show-dialog="showEditClientDialog"
:client-id="editClient.id"
@closed="handleClientEditFormClosed"
/>
<client-secret-edit-form
:show-dialog="showEditClientSecretDialog"
:client-id="editClient.id"
:client-secrets="editClient.clientSecrets"
@closed="handleClientSecretEditFormClosed"
@clientClaimChanged="refreshPagedData"
/>
<client-claim-edit-form
:show-dialog="showEditClientClaimDialog"
:client-id="editClient.id"
:client-claims="editClient.claims"
@closed="handleClientClaimEditFormClosed"
@clientClaimChanged="refreshPagedData"
/>
<client-property-edit-form
:show-dialog="showEditClientPropertyDialog"
:client-id="editClient.id"
:client-properties="editClient.properties"
@clientPropertyChanged="refreshPagedData"
@closed="handleClientPropertyEditFormClosed"
/>
<client-permission-edit-form
:show-dialog="showEditClientPermissionDialog" :show-dialog="showEditClientPermissionDialog"
:client-id="editClient.clientId" :readonly="!checkPermission(['IdentityServer.Clients.ManagePermissions'])"
@closed="handleClientPermissionEditFormClosed" @closed="handleClientPermissionEditFormClosed"
/> />
</div> </div>
@ -279,26 +244,15 @@ import { checkPermission } from '@/utils/permission'
import DataListMiXin from '@/mixins/DataListMiXin' import DataListMiXin from '@/mixins/DataListMiXin'
import Component, { mixins } from 'vue-class-component' import Component, { mixins } from 'vue-class-component'
import Pagination from '@/components/Pagination/index.vue' import Pagination from '@/components/Pagination/index.vue'
import ClientEditForm from './components/ClientEditForm.vue'
import ClientCloneForm from './components/ClientCloneForm.vue'
import ClientCreateForm from './components/ClientCreateForm.vue'
import ClientSecretEditForm from './components/ClientSecretEditForm.vue'
import ClientClaimEditForm from './components/ClientClaimEditForm.vue'
import ClientPropertyEditForm from './components/ClientPropertyEditForm.vue'
import ClientPermissionEditForm from './components/ClientPermissionEditForm.vue'
import ClientService, { Client, ClientGetByPaged } from '@/api/clients' import ClientService, { Client, ClientGetByPaged } from '@/api/clients'
import PermissionForm from '@/components/PermissionForm/index.vue'
@Component({ @Component({
name: 'IdentityServerClient', name: 'IdentityServerClient',
components: { components: {
Pagination, Pagination,
ClientEditForm, PermissionForm
ClientCloneForm,
ClientCreateForm,
ClientClaimEditForm,
ClientSecretEditForm,
ClientPropertyEditForm,
ClientPermissionEditForm
}, },
methods: { methods: {
checkPermission, checkPermission,
@ -316,15 +270,12 @@ import ClientService, { Client, ClientGetByPaged } from '@/api/clients'
} }
}) })
export default class extends mixins(DataListMiXin) { export default class extends mixins(DataListMiXin) {
private editClient = Client.empty() private editClientId = ''
private editClientTitle = '' private editClientTitle = ''
private showEditClientDialog = false private showEditClientDialog = false
private showCloneClientDialog = false private showCloneClientDialog = false
private showCreateClientDialog = false private showCreateClientDialog = false
private showEditClientSecretDialog = false
private showEditClientClaimDialog = false
private showEditClientPropertyDialog = false
private showEditClientPermissionDialog = false private showEditClientPermissionDialog = false
public dataFilter = new ClientGetByPaged() public dataFilter = new ClientGetByPaged()
@ -342,14 +293,12 @@ export default class extends mixins(DataListMiXin) {
} }
private handleShowCreateClientForm() { private handleShowCreateClientForm() {
this.editClient = Client.empty() this.editClientTitle = this.l('AbpIdentityServer.Client:New')
this.editClientTitle = this.l('identityServer.createClient')
this.showCreateClientDialog = true this.showCreateClientDialog = true
} }
private handleShowEditClientForm(client: Client) { private handleShowEditClientForm(client: Client) {
this.editClient = client this.editClientId = client.clientId
this.editClientTitle = this.l('identityServer.updateClientByName', { name: this.editClient.clientName })
this.showEditClientDialog = true this.showEditClientDialog = true
} }
@ -374,29 +323,17 @@ export default class extends mixins(DataListMiXin) {
} }
} }
private handleClientSecretEditFormClosed() {
this.showEditClientSecretDialog = false
}
private handleClientClaimEditFormClosed() {
this.showEditClientClaimDialog = false
}
private handleClientPropertyEditFormClosed() {
this.showEditClientPropertyDialog = false
}
private handleClientPermissionEditFormClosed() { private handleClientPermissionEditFormClosed() {
this.showEditClientPermissionDialog = false this.showEditClientPermissionDialog = false
} }
private handleDeleteClient(id: string, clientId: string) { private handleDeleteClient(id: string, clientId: string) {
this.$confirm(this.l('identityServer.deleteClientById', { id: clientId }), this.$confirm(this.l('AbpIdentityServer.Client:WillDelete', { 0: clientId }),
this.l('identityServer.deleteClient'), { this.l('AbpUi.AreYouSure'), {
callback: (action) => { callback: (action) => {
if (action === 'confirm') { if (action === 'confirm') {
ClientService.deleteClient(id).then(() => { ClientService.deleteClient(id).then(() => {
this.$message.success(this.l('identityServer.deleteClientSuccess', { id: clientId })) this.$message.success(this.l('global.successful'))
this.refreshPagedData() this.refreshPagedData()
}) })
} }
@ -405,20 +342,11 @@ export default class extends mixins(DataListMiXin) {
} }
private handleCommand(command: {key: string, row: Client}) { private handleCommand(command: {key: string, row: Client}) {
this.editClient = command.row this.editClientId = command.row.clientId
switch (command.key) { switch (command.key) {
case 'clone' : case 'clone' :
this.showCloneClientDialog = true this.showCloneClientDialog = true
break break
case 'secret' :
this.showEditClientSecretDialog = true
break
case 'claim' :
this.showEditClientClaimDialog = true
break
case 'property':
this.showEditClientPropertyDialog = true
break
case 'permissions': case 'permissions':
this.showEditClientPermissionDialog = true this.showEditClientPermissionDialog = true
break break
@ -428,16 +356,6 @@ export default class extends mixins(DataListMiXin) {
default: break default: break
} }
} }
private formatStatusText(status: boolean) {
let statusText = ''
if (status) {
statusText = this.l('enabled')
} else {
statusText = this.l('disbled')
}
return statusText
}
} }
</script> </script>

238
vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue

@ -13,92 +13,99 @@
<div class="app-container"> <div class="app-container">
<el-form <el-form
ref="formIdentityResource" ref="formIdentityResource"
label-width="120px" label-width="130px"
:model="identityResource" :model="identityResource"
:rules="identityResourceRules" :rules="identityResourceRules"
> >
<el-form-item <el-tabs
prop="enabled" v-model="activeTable"
:label="$t('identityServer.enabledResource')" type="border-card"
> >
<el-switch <el-tab-pane
v-model="identityResource.enabled" name="information"
/> :label="$t('AbpIdentityServer.Information')"
</el-form-item> >
<el-form-item <el-form-item
prop="name" prop="enabled"
:label="$t('identityServer.resourceName')" :label="$t('AbpIdentityServer.Resource:Enabled')"
> >
<el-input <el-switch
v-model="identityResource.name" v-model="identityResource.enabled"
:disabled="isEdit" />
:placeholder="$t('pleaseInputBy', {key: $t('identityServer.resourceName')})" </el-form-item>
/> <el-form-item
</el-form-item> prop="name"
<el-form-item :label="$t('AbpIdentityServer.Name')"
prop="displayName" >
:label="$t('identityServer.resourceDisplayName')" <el-input
> v-model="identityResource.name"
<el-input :disabled="isEdit"
v-model="identityResource.displayName" :placeholder="$t('pleaseInputBy', {key: $t('AbpIdentityServer.Name')})"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="description" prop="displayName"
:label="$t('identityServer.resourceDescription')" :label="$t('AbpIdentityServer.DisplayName')"
> >
<el-input <el-input
v-model="identityResource.description" v-model="identityResource.displayName"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="required" prop="description"
:label="$t('identityServer.identityResourceRequired')" :label="$t('AbpIdentityServer.Description')"
> >
<el-switch <el-input
v-model="identityResource.required" v-model="identityResource.description"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="emphasize" prop="required"
:label="$t('identityServer.identityResourceEmphasize')" :label="$t('AbpIdentityServer.Required')"
> >
<el-switch <el-switch
v-model="identityResource.emphasize" v-model="identityResource.required"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="showInDiscoveryDocument" prop="emphasize"
:label="$t('identityServer.identityResourceShowInDiscoveryDocument')" :label="$t('AbpIdentityServer.Emphasize')"
> >
<el-switch <el-switch
v-model="identityResource.showInDiscoveryDocument" v-model="identityResource.emphasize"
/> />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="userClaims" prop="showInDiscoveryDocument"
:label="$t('identityServer.resourceUserClaims')" :label="$t('AbpIdentityServer.ShowInDiscoveryDocument')"
> >
<el-select <el-switch
v-model="identityResource.userClaims" v-model="identityResource.showInDiscoveryDocument"
multiple />
style="width: 100%;" </el-form-item>
value-key="type" </el-tab-pane>
<el-tab-pane
name="claims"
:label="$t('AbpIdentityServer.UserClaim')"
> >
<el-option <el-transfer
v-for="claim in identityClaims" v-model="identityResource.userClaims"
:key="claim.type" class="transfer-scope"
:label="claim.type" :data="identityClaims"
:value="claim" :props="{
key: 'type',
label: 'value'
}"
:titles="[$t('AbpIdentityServer.NoClaim'), $t('AbpIdentityServer.ExistsClaim')]"
/> />
</el-select> </el-tab-pane>
</el-form-item> </el-tabs>
<el-form-item> <el-form-item>
<el-button <el-button
class="cancel" class="cancel"
style="width:100px" style="width:100px"
@click="onCancel" @click="onFormClosed(false)"
> >
{{ $t('global.cancel') }} {{ $t('global.cancel') }}
</el-button> </el-button>
@ -106,7 +113,7 @@
class="confirm" class="confirm"
type="primary" type="primary"
style="width:100px" style="width:100px"
@click="onSaveIdentityResource" @click="onSave"
> >
{{ $t('global.confirm') }} {{ $t('global.confirm') }}
</el-button> </el-button>
@ -117,10 +124,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import IdentityResourceService, { IdentityResourceCreate, IdentityResourceUpdate, IdentityResource, IdentityClaim } from '@/api/identityresources'
import ClaimTypeApiService from '@/api/cliam-type'
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import { Form } from 'element-ui' import { Form } from 'element-ui'
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import { Claim } from '@/api/types'
import ClaimTypeApiService from '@/api/cliam-type'
import IdentityResourceService, { IdentityResource, IdentityResourceCreateOrUpdate } from '@/api/identity-resources'
@Component({ @Component({
name: 'IdentityResourceCreateOrEditForm' name: 'IdentityResourceCreateOrEditForm'
@ -135,8 +144,9 @@ export default class extends Vue {
@Prop({ default: '' }) @Prop({ default: '' })
private identityResourceId!: string private identityResourceId!: string
private identityClaims = new Array<IdentityClaim>() private activeTable = 'information'
private identityResource: IdentityResource private identityClaims = new Array<Claim>()
private identityResource = new IdentityResource()
private identityResourceRules = { private identityResourceRules = {
name: [ name: [
{ required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.resourceName') }), trigger: 'blur' } { required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.resourceName') }), trigger: 'blur' }
@ -150,20 +160,9 @@ export default class extends Vue {
return false return false
} }
constructor() { @Watch('showDialog', { immediate: true })
super() private onShowDialogChanged() {
this.identityResource = IdentityResource.empty() this.handleGetIdentityResource()
}
@Watch('identityResourceId', { immediate: true })
private onIdentityResourceIdChanged() {
if (this.identityResourceId) {
IdentityResourceService.getIdentityResourceById(this.identityResourceId).then(resource => {
this.identityResource = resource
})
} else {
this.identityResource = IdentityResource.empty()
}
} }
mounted() { mounted() {
@ -173,30 +172,40 @@ export default class extends Vue {
private handleGetClaimTypes() { private handleGetClaimTypes() {
ClaimTypeApiService.getActivedClaimTypes().then(res => { ClaimTypeApiService.getActivedClaimTypes().then(res => {
res.items.map(claim => { res.items.map(claim => {
const identityClaim = new IdentityClaim() const identityClaim = new Claim(claim.name, claim.name)
identityClaim.type = claim.name
this.identityClaims.push(identityClaim) this.identityClaims.push(identityClaim)
}) })
}) })
} }
private onSaveIdentityResource() { private handleGetIdentityResource() {
this.activeTable = 'information'
if (this.showDialog && this.identityResourceId) {
IdentityResourceService.getIdentityResourceById(this.identityResourceId).then(resource => {
this.identityResource = resource
})
} else {
this.identityResource = new IdentityResource()
}
}
private onSave() {
const frmIdentityResource = this.$refs.formIdentityResource as any const frmIdentityResource = this.$refs.formIdentityResource as any
frmIdentityResource.validate((valid: boolean) => { frmIdentityResource.validate((valid: boolean) => {
if (valid) { if (valid) {
const editIdentityResource = new IdentityResourceCreateOrUpdate()
this.updateIdentityResourceByInput(editIdentityResource)
if (this.isEdit) { if (this.isEdit) {
const updateIdentityResource = IdentityResourceUpdate.create(this.identityResource) IdentityResourceService.updateIdentityResource(this.identityResourceId, editIdentityResource).then(resource => {
IdentityResourceService.updateIdentityResource(updateIdentityResource).then(resource => {
this.identityResource = resource this.identityResource = resource
const successMessage = this.l('identityServer.updateIdentityResourceSuccess', { name: resource.name }) const successMessage = this.l('global.successful')
this.$message.success(successMessage) this.$message.success(successMessage)
this.onFormClosed(true) this.onFormClosed(true)
}) })
} else { } else {
const createIdentityResource = IdentityResourceCreate.create(this.identityResource) IdentityResourceService.createIdentityResource(editIdentityResource).then(resource => {
IdentityResourceService.createIdentityResource(createIdentityResource).then(resource => {
this.identityResource = resource this.identityResource = resource
const successMessage = this.l('identityServer.createIdentityResourceSuccess', { name: resource.name }) const successMessage = this.l('global.successful')
this.$message.success(successMessage) this.$message.success(successMessage)
this.onFormClosed(true) this.onFormClosed(true)
}) })
@ -205,15 +214,23 @@ export default class extends Vue {
}) })
} }
private updateIdentityResourceByInput(identityResource: IdentityResourceCreateOrUpdate) {
identityResource.name = this.identityResource.name
identityResource.displayName = this.identityResource.displayName
identityResource.description = this.identityResource.description
identityResource.enabled = this.identityResource.enabled
identityResource.required = this.identityResource.required
identityResource.emphasize = this.identityResource.emphasize
identityResource.showInDiscoveryDocument = this.identityResource.showInDiscoveryDocument
identityResource.userClaims = this.identityResource.userClaims
identityResource.properties = this.identityResource.properties
}
private onFormClosed(changed: boolean) { private onFormClosed(changed: boolean) {
this.resetFields() this.resetFields()
this.$emit('closed', changed) this.$emit('closed', changed)
} }
private onCancel() {
this.onFormClosed(false)
}
private resetFields() { private resetFields() {
const frmIdentityResource = this.$refs.formIdentityResource as Form const frmIdentityResource = this.$refs.formIdentityResource as Form
frmIdentityResource.resetFields() frmIdentityResource.resetFields()
@ -229,9 +246,14 @@ export default class extends Vue {
.confirm { .confirm {
position: absolute; position: absolute;
right: 10px; right: 10px;
top: 20px;
} }
.cancel { .cancel {
position: absolute; position: absolute;
right: 120px; right: 120px;
top: 20px;
}
.transfer-scope ::v-deep .el-transfer-panel{
width: 250px;
} }
</style> </style>

120
vueJs/src/views/admin/identityServer/identity-resources/index.vue

@ -25,7 +25,7 @@
:disabled="!checkPermission(['IdentityServer.IdentityResources.Create'])" :disabled="!checkPermission(['IdentityServer.IdentityResources.Create'])"
@click="handleShowEditIdentityResourceForm" @click="handleShowEditIdentityResourceForm"
> >
{{ $t('identityServer.createIdentityResource') }} {{ $t('AbpIdentityServer.Resource:New') }}
</el-button> </el-button>
</div> </div>
@ -40,7 +40,7 @@
@sort-change="handleSortChange" @sort-change="handleSortChange"
> >
<el-table-column <el-table-column
:label="$t('global.name')" :label="$t('AbpIdentityServer.Name')"
prop="name" prop="name"
sortable sortable
width="150px" width="150px"
@ -51,7 +51,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('global.displayName')" :label="$t('AbpIdentityServer.DisplayName')"
prop="displayName" prop="displayName"
sortable sortable
width="200px" width="200px"
@ -62,20 +62,21 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('global.status')" :label="$t('AbpIdentityServer.Resource:Enabled')"
prop="enabled" prop="enabled"
sortable sortable
width="140px" width="140px"
align="center" align="center"
> >
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-tag :type="row.enabled | statusFilter"> <el-switch
{{ formatStatusText(row.enabled) }} v-model="row.enabled"
</el-tag> disabled
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('global.description')" :label="$t('AbpIdentityServer.Description')"
prop="description" prop="description"
sortable sortable
width="200px" width="200px"
@ -125,35 +126,16 @@
type="primary" type="primary"
@click="handleShowEditIdentityResourceForm(row)" @click="handleShowEditIdentityResourceForm(row)"
> >
{{ $t('identityServer.updateIdentityResource') }} {{ $t('AbpIdentityServer.Resource:Edit') }}
</el-button> </el-button>
<el-dropdown <el-button
class="options" :disabled="!checkPermission(['IdentityServer.IdentityResources.Delete'])"
@command="handleCommand" size="mini"
type="danger"
@click="handleDeleteIdentityResource(row)"
> >
<el-button {{ $t('AbpIdentityServer.Resource:Delete') }}
v-permission="['IdentityServer.IdentityResources']" </el-button>
size="mini"
type="info"
>
{{ $t('global.otherOpera') }}<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:command="{key: 'property', row}"
:disabled="!checkPermission(['IdentityServer.IdentityResources.Properties'])"
>
{{ $t('identityServer.identityResourceProperties') }}
</el-dropdown-item>
<el-dropdown-item
divided
:command="{key: 'delete', row}"
:disabled="!checkPermission(['IdentityServer.IdentityResources.Delete'])"
>
{{ $t('identityServer.deleteIdentityResource') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -166,6 +148,13 @@
@pagination="refreshPagedData" @pagination="refreshPagedData"
@sort-change="handleSortChange" @sort-change="handleSortChange"
/> />
<identity-resource-create-or-edit-form
:identity-resource-id="editIdentityResourceId"
:title="editIdentityResourceTitle"
:show-dialog="showEditIdentityResourceDialog"
@closed="onIdentityResourceEditFormClosed"
/>
</div> </div>
</template> </template>
@ -177,10 +166,13 @@ import Component, { mixins } from 'vue-class-component'
import Pagination from '@/components/Pagination/index.vue' import Pagination from '@/components/Pagination/index.vue'
import IdentityResourceService, { IdentityResource, IdentityResourceGetByPaged } from '@/api/identity-resources' import IdentityResourceService, { IdentityResource, IdentityResourceGetByPaged } from '@/api/identity-resources'
import IdentityResourceCreateOrEditForm from './components/IdentityResourceCreateOrEditForm.vue'
@Component({ @Component({
name: 'IdentityServerIdentityResource', name: 'IdentityServerIdentityResource',
components: { components: {
Pagination Pagination,
IdentityResourceCreateOrEditForm
}, },
methods: { methods: {
checkPermission checkPermission
@ -199,10 +191,9 @@ import IdentityResourceService, { IdentityResource, IdentityResourceGetByPaged }
} }
}) })
export default class extends mixins(DataListMiXin) { export default class extends mixins(DataListMiXin) {
private editIdentityResource = IdentityResource.empty() private editIdentityResourceId = ''
private editIdentityResourceTitle = '' private editIdentityResourceTitle = ''
private showEditIdentityPropertyDialog = false
private showEditIdentityResourceDialog = false private showEditIdentityResourceDialog = false
public dataFilter = new IdentityResourceGetByPaged() public dataFilter = new IdentityResourceGetByPaged()
@ -220,31 +211,22 @@ export default class extends mixins(DataListMiXin) {
} }
private handleShowEditIdentityResourceForm(resource: IdentityResource) { private handleShowEditIdentityResourceForm(resource: IdentityResource) {
this.editIdentityResource = IdentityResource.empty()
if (resource) { if (resource) {
this.editIdentityResource = resource this.editIdentityResourceId = resource.id
this.editIdentityResourceTitle = this.l('identityServer.updateIdentityResourceByName', { name: this.editIdentityResource.name }) this.editIdentityResourceTitle = this.l('AbpIdentityServer.Resource:Name', { 0: resource.name })
} else { } else {
this.editIdentityResourceTitle = this.l('identityServer.createIdentityResource') this.editIdentityResourceTitle = this.l('AbpIdentityServer.Resource:New')
} }
this.showEditIdentityResourceDialog = true this.showEditIdentityResourceDialog = true
} }
private handleIdentityResourceEditFormClosed(changed: boolean) { private handleDeleteIdentityResource(resource: IdentityResource) {
this.reset(changed) this.$confirm(this.l('AbpIdentityServer.Resource:WillDelete', { 0: resource.name }),
} this.l('AbpUi.AreYouSure'), {
private handleIdentityPropertyEditFormClosed(changed: boolean) {
this.reset(changed)
}
private handleDeleteIdentityResource(id: string, name: string) {
this.$confirm(this.l('identityServer.deleteIdentityResourceByName', { name: name }),
this.l('identityServer.deleteIdentityResource'), {
callback: (action) => { callback: (action) => {
if (action === 'confirm') { if (action === 'confirm') {
IdentityResourceService.deleteIdentityResource(id).then(() => { IdentityResourceService.deleteIdentityResource(resource.id).then(() => {
this.$message.success(this.l('identityServer.deleteIdentityResourceSuccess', { name: name })) this.$message.success(this.l('global.successful'))
this.refreshPagedData() this.refreshPagedData()
}) })
} }
@ -252,34 +234,8 @@ export default class extends mixins(DataListMiXin) {
}) })
} }
private handleCommand(command: {key: string, row: IdentityResource}) { private onIdentityResourceEditFormClosed(changed: boolean) {
switch (command.key) {
case 'property' :
this.editIdentityResource = command.row
this.showEditIdentityPropertyDialog = true
break
case 'delete' :
this.handleDeleteIdentityResource(command.row.id, command.row.name)
break
default: break
}
}
private formatStatusText(status: boolean) {
let statusText = ''
if (status) {
statusText = this.l('enabled')
} else {
statusText = this.l('disbled')
}
return statusText
}
private reset(changed: boolean) {
this.editIdentityResourceTitle = ''
this.editIdentityResource = IdentityResource.empty()
this.showEditIdentityResourceDialog = false this.showEditIdentityResourceDialog = false
this.showEditIdentityPropertyDialog = false
if (changed) { if (changed) {
this.refreshPagedData() this.refreshPagedData()
} }

5
vueJs/src/views/admin/roles/components/RoleClaimCreateOrUpdateForm.vue

@ -197,11 +197,6 @@ export default class UserClaimCreateOrUpdateForm extends Vue {
} }
} }
@Watch('roleId')
private onUserIdChanged() {
this.handleGetRoleClaims()
}
@Watch('showDialog', { immediate: true }) @Watch('showDialog', { immediate: true })
private onShowDialogChanged() { private onShowDialogChanged() {
this.handleGetRoleClaims() this.handleGetRoleClaims()

5
vueJs/src/views/admin/roles/components/RoleEditForm.vue

@ -125,11 +125,6 @@ export default class extends Vue {
] ]
} }
@Watch('roleId')
private onRoleIdChanged() {
this.handleGetRole()
}
@Watch('showDialog', { immediate: true }) @Watch('showDialog', { immediate: true })
private onShowDialogChanged() { private onShowDialogChanged() {
this.handleGetRole() this.handleGetRole()

5
vueJs/src/views/admin/users/components/UserClaimCreateOrUpdateForm.vue

@ -197,11 +197,6 @@ export default class UserClaimCreateOrUpdateForm extends Vue {
} }
} }
@Watch('userId')
private onUserIdChanged() {
this.handleGetUserClaims()
}
@Watch('showDialog', { immediate: true }) @Watch('showDialog', { immediate: true })
private onShowDialogChanged() { private onShowDialogChanged() {
this.handleGetUserClaims() this.handleGetUserClaims()

Loading…
Cancel
Save