From 48215226f047ff43921130e131698f969008ef5c Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Sat, 17 Oct 2020 19:22:17 +0800 Subject: [PATCH] Refactoring Api: identity-resource Add New New component :PermissionForm --- ...ientCloneInputDto.cs => ClientCloneDto.cs} | 0 .../Clients/Dto/ClientCorsOriginDto.cs | 9 - .../Clients/Dto/ClientUpdateDto.cs | 5 + .../Dto/IdentityResourceDto.cs | 2 - .../Localization/Resources/en.json | 68 ++- .../Localization/Resources/zh-Hans.json | 69 ++- .../Clients/ClientAppService.cs | 39 +- .../LINGYUN.ApiGateway.Host/event-bus-cap.db | Bin 32768 -> 32768 bytes vueJs/src/api/clients.ts | 268 ++-------- vueJs/src/api/identity-resources.ts | 166 +------ vueJs/src/api/permission.ts | 12 + vueJs/src/components/PermissionForm/index.vue | 466 ++++++++++++++++++ .../CreateOrUpdateCliamTypeForm.vue | 5 - .../ApiResourceCreateOrEditForm.vue | 5 - .../admin/identityServer/client/index.vue | 204 +++----- .../IdentityResourceCreateOrEditForm.vue | 238 +++++---- .../identity-resources/index.vue | 120 ++--- .../RoleClaimCreateOrUpdateForm.vue | 5 - .../admin/roles/components/RoleEditForm.vue | 5 - .../UserClaimCreateOrUpdateForm.vue | 5 - 20 files changed, 928 insertions(+), 763 deletions(-) rename aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/{ClientCloneInputDto.cs => ClientCloneDto.cs} (100%) delete mode 100644 aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs create mode 100644 vueJs/src/components/PermissionForm/index.vue diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneInputDto.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneDto.cs similarity index 100% rename from aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneInputDto.cs rename to aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCloneDto.cs diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs deleted file mode 100644 index 5fb829c5b..000000000 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientCorsOriginDto.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.IdentityServer.Clients -{ - public class ClientCorsOriginDto : EntityDto - { - public string Origin { get; set; } - } -} diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientUpdateDto.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientUpdateDto.cs index 6e536f198..c8d740c42 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Clients/Dto/ClientUpdateDto.cs +++ b/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 /// 密钥 /// public List Secrets { get; set; } + /// + /// 声明 + /// + public List Claims { get; set; } public ClientUpdateDto() { @@ -127,6 +131,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients IdentityProviderRestrictions = new List(); Properties = new Dictionary(); Secrets = new List(); + Claims = new List(); } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/IdentityResources/Dto/IdentityResourceDto.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/IdentityResources/Dto/IdentityResourceDto.cs index 6405f03ef..8e64e7298 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/IdentityResources/Dto/IdentityResourceDto.cs +++ b/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 ConcurrencyStamp { get; set; } - public bool Enabled { get; set; } public bool Required { get; set; } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json index 4c9081486..6bd155344 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json @@ -31,7 +31,11 @@ "Resource:Enabled": "Enabled", "Resource:New": "Add New", "Resource:Edit": "Edit", + "Resource:Delete": "Delete", + "Resource:WillDelete": "Resource :{0} will be deleted", "Resource:Name": "Resource - {0}", + "Resource:Api": "Api Resource", + "Resource:Identity": "Identity Resource", "UserClaim": "User claim", "NoClaim": "Owned claims", "ExistsClaim": "Not owned claims", @@ -49,6 +53,68 @@ "Secret:New": "Add New", "Secret:Type": "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" } } \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json index ef7a37930..5f948995a 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json @@ -32,7 +32,10 @@ "Resource:New": "添加新资源", "Resource:Edit": "编辑资源", "Resource:Delete": "删除资源", + "Resource:WillDelete": "资源:{0} 将被删除", "Resource:Name": "资源 - {0}", + "Resource:Api": "Api 资源", + "Resource:Identity": "身份资源", "UserClaim": "用户声明", "NoClaim": "未拥有声明", "ExistsClaim": "已拥有声明", @@ -43,13 +46,75 @@ "Description": "描述", "Required": "必要", "Emphasize": "强调", - "ShowInDiscoveryDocument": "强调", + "ShowInDiscoveryDocument": "在发现文档中显示", "Expiration": "过期", "Scope:New": "添加新作用域", "Scope:Delete": "删除作用域", "Secret:New": "添加新密钥", "Secret:Type": "密钥类型", "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": "权限" } } \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs index 58507bf51..057711c51 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs +++ b/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 = await ClientRepository.InsertAsync(client, true); + client = await ClientRepository.InsertAsync(client); await CurrentUnitOfWork.SaveChangesAsync(); @@ -50,7 +50,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients [Authorize(AbpIdentityServerPermissions.Clients.Delete)] public virtual async Task DeleteAsync(Guid id) { - await ClientRepository.DeleteAsync(id); + var client = await ClientRepository.GetAsync(id); + await ClientRepository.DeleteAsync(client); await CurrentUnitOfWork.SaveChangesAsync(); } @@ -64,10 +65,9 @@ namespace LINGYUN.Abp.IdentityServer.Clients public virtual async Task> GetListAsync(ClientGetByPagedDto input) { - // Abp官方IdentityServer项目不支持Filter过滤... var clients = await ClientRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, - input.Filter, true); + input.Filter); var clientCount = await ClientRepository.GetCountAsync(); @@ -245,6 +245,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients #region Secrets + // 移除已经不存在的客户端密钥 + client.ClientSecrets.RemoveAll(secret => !input.Secrets.Any(inputSecret => secret.Value == inputSecret.Value && secret.Type == inputSecret.Type)); var currentSecrets = new List(); foreach (var inputSecret in input.Secrets) { @@ -271,23 +273,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients if (clientSecret == null) { 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 @@ -305,6 +292,20 @@ namespace LINGYUN.Abp.IdentityServer.Clients #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); await CurrentUnitOfWork.SaveChangesAsync(); diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db index 6bb259759f87eabe4e894cd90d9c0c777933fd03..75f99141b6152b9646fa1b10597c9abfa7b65c46 100644 GIT binary patch delta 1299 zcmeH_OKTHR7=}+K(`jy#(+(A_4)M@MapUA%=FBBzS4dmjD6Lskgi0GwqX>~mDQGfS zf)p1m0|i}3{Rv?j|AQbd1Q-4RL2#??#BXXYZSxb9nX`E3{m#e3J8!$KwA;$wCB2Ri zO7%~2|B9Qach?W`j1HeB)DF_$W$&j8+9$Q6l)C{@BHLI|W|nbIn+}q!b1Sv5aM@Uz zJDTf-H;flp*o@j9<obRY zG`wASKBVJ*pKj!PBHVvm4aq}wNXUJQJFe~e-WXwQxjvV!Jw^x?+~GEpCkXX3gu6@4 zI6}yWdX5KsfRNJg&aHYzY} zHW3PDV)kI=+1wT4&cxE9^ ze-FPnzxZYug)shlpt3$8X;t^B+Z!0Tft*Gl$LXqh0|OTiGaI9jyMF%FuL=x2V2;~2 znKxS%pfYaXB>$NzFmOU;#2ZT$7&suDdFD|-4#>qkLarP5=N@igfEpI257f^M)xvmk zs{$JXJBYXWyFQl!KifqHRwf$;mNwokAP;U92q> diff --git a/vueJs/src/api/clients.ts b/vueJs/src/api/clients.ts index ec06284f6..c4929a346 100644 --- a/vueJs/src/api/clients.ts +++ b/vueJs/src/api/clients.ts @@ -1,18 +1,17 @@ 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 export default class ClientService { public static getClientById(id: string) { - let _url = '/api/IdentityServer/Clients/' - _url += id + const _url = sourceUrl + '/' + id return ApiService.Get(_url, serviceUrl) } public static getClients(payload: ClientGetByPaged) { - let _url = '/api/IdentityServer/Clients' - _url += '?filter=' + payload.filter + let _url = sourceUrl + '?filter=' + payload.filter _url += '&sorting=' + payload.sorting _url += '&skipCount=' + payload.skipCount _url += '&maxResultCount=' + payload.maxResultCount @@ -20,144 +19,39 @@ export default class ClientService { } public static createClient(payload: ClientCreate) { - const _url = '/api/IdentityServer/Clients' - return ApiService.Post(_url, payload, serviceUrl) + return ApiService.Post(sourceUrl, payload, serviceUrl) } - public static cloneClient(payload: ClientClone) { - const _url = '/api/IdentityServer/Clients/Clone' + public static cloneClient(id: string, payload: ClientClone) { + const _url = sourceUrl + '/' + id + '/clone' return ApiService.Post(_url, payload, serviceUrl) } - public static updateClient(payload: ClientUpdate) { - const _url = '/api/IdentityServer/Clients' + public static updateClient(id: string, payload: ClientUpdate) { + const _url = sourceUrl + '/' + id return ApiService.Put(_url, payload, serviceUrl) } public static deleteClient(id: string) { - const _url = '/api/IdentityServer/Clients/' + id - return ApiService.Delete(_url, serviceUrl) - } - - public static addClientSecret(payload: ClientSecretCreate) { - const _url = '/api/IdentityServer/Clients/Secrets' - return ApiService.Post(_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(_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(_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 + const _url = sourceUrl + '/' + id return ApiService.Delete(_url, serviceUrl) } } -export class ClientGetByPaged extends PagedAndSortedResultRequestDto { - filter = '' -} - export enum HashType { - Sha256, - Sha512 + Sha256 = 0, + Sha512 = 1 } -export class ClientSecret { - type = '' - value = '' +export class SecretCreateOrUpdate extends SecretBase { 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 { - clientId!: string - - 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 ClientGetByPaged extends PagedAndSortedResultRequestDto { + filter = '' } -export class ClientCreate { - clientId = '' - clientName = '' - description? = '' - allowedGrantTypes?: ClientGrantType[] - - constructor() { - this.allowedGrantTypes = new Array() - } -} +export class ClientClaim extends Claim {} export class ClientClone { sourceClientId = '' @@ -218,39 +112,27 @@ export class Client extends FullAuditedEntityDto { userSsoLifetime!: number userCodeType?: string deviceCodeLifetime!: number - allowedScopes!: ClientScope[] - clientSecrets!: ClientSecret[] - allowedGrantTypes!: ClientGrantType[] - allowedCorsOrigins!: ClientCorsOrigin[] - redirectUris!: ClientRedirectUri[] - postLogoutRedirectUris!: ClientPostLogoutRedirectUri[] - identityProviderRestrictions!: ClientIdPRestriction[] - claims!: ClientClaim[] - properties!: ClientProperty[] - - constructor() { - super() - this.allowedScopes = new Array() - this.clientSecrets = new Array() - this.allowedGrantTypes = new Array() - this.allowedCorsOrigins = new Array() - this.redirectUris = new Array() - this.postLogoutRedirectUris = new Array() - this.identityProviderRestrictions = new Array() - this.claims = new Array() - this.properties = new Array() - } - - public static empty() { - return new Client() - } -} - -export class ClientUpdateData { - concurrencyStamp!: string + allowedScopes = new Array() + clientSecrets = new Array() + allowedGrantTypes = new Array() + allowedCorsOrigins = new Array() + redirectUris = new Array() + postLogoutRedirectUris = new Array() + identityProviderRestrictions = new Array() + claims = new Array() + properties = new Array() +} + +export class ClientCreateOrUpdate { clientId = '' clientName = '' description? = '' + allowedGrantTypes = new Array() +} + +export class ClientCreate extends ClientCreateOrUpdate {} + +export class ClientUpdate extends ClientCreateOrUpdate { clientUri? = '' logoUri? = '' enabled = true @@ -266,7 +148,7 @@ export class ClientUpdateData { frontChannelLogoutSessionRequired = true backChannelLogoutUri? = '' backChannelLogoutSessionRequired = true - allowOfflineAccess = false + allowOfflineAccess = true identityTokenLifetime = 300 accessTokenLifetime = 3600 authorizationCodeLifetime = 300 @@ -285,75 +167,13 @@ export class ClientUpdateData { userSsoLifetime!: number userCodeType? = '' deviceCodeLifetime = 300 - allowedScopes!: ClientScope[] - allowedGrantTypes!: ClientGrantType[] - allowedCorsOrigins!: ClientCorsOrigin[] - redirectUris!: ClientRedirectUri[] - postLogoutRedirectUris!: ClientPostLogoutRedirectUri[] - identityProviderRestrictions!: ClientIdPRestriction[] - - constructor() { - this.allowedScopes = new Array() - this.allowedGrantTypes = new Array() - this.allowedCorsOrigins = new Array() - this.redirectUris = new Array() - this.postLogoutRedirectUris = new Array() - this.identityProviderRestrictions = new Array() - } - - 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() - } + apiResources = new Array() + identityResources = new Array() + allowedCorsOrigins = new Array() + redirectUris = new Array() + postLogoutRedirectUris = new Array() + identityProviderRestrictions = new Array() + properties: {[key: string]: string} = {} + secrets = new Array() + claims = new Array() } diff --git a/vueJs/src/api/identity-resources.ts b/vueJs/src/api/identity-resources.ts index b2a8f1477..3928d82c2 100644 --- a/vueJs/src/api/identity-resources.ts +++ b/vueJs/src/api/identity-resources.ts @@ -35,7 +35,7 @@ export default class IdentityResourceService { * @param payload 类型为 IdentityResourceCreate 的对象 * @returns 返回类型为 IdentityResource 的对象 */ - public static createIdentityResource(payload: IdentityResourceCreate) { + public static createIdentityResource(payload: IdentityResourceCreateOrUpdate) { return ApiService.Post(sourceUrl, payload, serviceUrl) } @@ -44,7 +44,7 @@ export default class IdentityResourceService { * @param payload 类型为 IdentityResourceUpdate 的对象 * @returns 返回类型为 IdentityResource 的对象 */ - public static updateIdentityResource(id: string, payload: IdentityResourceUpdate) { + public static updateIdentityResource(id: string, payload: IdentityResourceCreateOrUpdate) { const _url = sourceUrl + '/' + id return ApiService.Put(_url, payload, serviceUrl) } @@ -59,161 +59,31 @@ export default class IdentityResourceService { } } -/** 身份资源用户声明 */ -export class IdentityClaim { - /** 用户声明 */ - 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 { - /** 名称 */ +export class IdentityResource extends FullAuditedEntityDto { + id!: string name = '' - /** 显示名称 */ - displayName? = '' - /** 说明 */ - description? = '' - /** 启用 */ + displayName?: string = '' + description?: string = '' enabled = true - /** 必须 */ required = false - /** 强调 */ emphasize = false - /** 在发现文档显示 */ - showInDiscoveryDocument = false - /** 用户声明 */ - userClaims = new Array() - - /** 返回一个空对象 */ - public static empty() { - return new IdentityResourceCreate() - } + showInDiscoveryDocument = true + userClaims = new Array() + properties: {[key: string]: string} = {} +} - /** 创建身份资源 */ - public static create(identityResource: IdentityResource) { - 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 IdentityResourceGetByPaged extends PagedAndSortedResultRequestDto { + filter = '' } -/** 身份资源变更对象 */ -export class IdentityResourceUpdate { - /** 身份资源标识 */ - id = '' - /** 名称 */ +export class IdentityResourceCreateOrUpdate { name = '' - /** 显示名称 */ - displayName? = '' - /** 说明 */ - description? = '' - /** 启用 */ + displayName?: string = '' + description?: string = '' enabled = true - /** 必须 */ required = false - /** 强调 */ emphasize = false - /** 在发现文档显示 */ - showInDiscoveryDocument = false - /** 并发令牌 */ - concurrencyStamp = '' - /** 用户声明 */ - userClaims = new Array() - - /** 返回一个空对象 */ - 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 - } + showInDiscoveryDocument = true + userClaims = new Array() + properties: {[key: string]: string} = {} } diff --git a/vueJs/src/api/permission.ts b/vueJs/src/api/permission.ts index 549712c03..fa7c516a4 100644 --- a/vueJs/src/api/permission.ts +++ b/vueJs/src/api/permission.ts @@ -36,11 +36,23 @@ export class UpdatePermissionsDto { constructor() { this.permissions = new Array() } + + public addPermission(name: string, isGranted: boolean) { + this.permissions.push(new UpdatePermissionDto(name, isGranted)) + } } export class UpdatePermissionDto implements IPermission { name!: string isGranted!: boolean + + constructor( + name: string, + isGranted: boolean + ) { + this.name = name + this.isGranted = isGranted + } } export class PermissionProvider { diff --git a/vueJs/src/components/PermissionForm/index.vue b/vueJs/src/components/PermissionForm/index.vue new file mode 100644 index 000000000..06065499e --- /dev/null +++ b/vueJs/src/components/PermissionForm/index.vue @@ -0,0 +1,466 @@ + + + + + diff --git a/vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue b/vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue index 44bc4fb99..94a08c017 100644 --- a/vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue +++ b/vueJs/src/views/admin/claim-type/components/CreateOrUpdateCliamTypeForm.vue @@ -153,11 +153,6 @@ export default class CreateOrUpdateCliamTypeForm extends Vue { return false } - @Watch('claimTypeId') - private onClaimTypeIdChanged() { - this.handleGetClaimType() - } - @Watch('showDialog', { immediate: true }) private onShowDialogChanged() { this.handleGetClaimType() diff --git a/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue index e58985b7f..8db253243 100644 --- a/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue +++ b/vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue @@ -187,11 +187,6 @@ export default class extends Vue { return false } - @Watch('apiResourceId') - private onApiResourceIdChanged() { - this.handleGetApiResource() - } - @Watch('showDialog', { immediate: true }) private onShowDialogChanged() { this.handleGetApiResource() diff --git a/vueJs/src/views/admin/identityServer/client/index.vue b/vueJs/src/views/admin/identityServer/client/index.vue index a2e3f7708..3836010bf 100644 --- a/vueJs/src/views/admin/identityServer/client/index.vue +++ b/vueJs/src/views/admin/identityServer/client/index.vue @@ -25,7 +25,7 @@ :disabled="!checkPermission(['IdentityServer.Clients.Create'])" @click="handleShowCreateClientForm()" > - {{ $t('identityServer.createClient') }} + {{ $t('AbpIdentityServer.Client:New') }} @@ -40,7 +40,7 @@ @sort-change="handleSortChange" > + + + + + + - {{ $t('identityServer.updateClient') }} + {{ $t('AbpIdentityServer.Client:Edit') }} - {{ $t('identityServer.otherOpera') }} + {{ $t('global.operaActions') }} - {{ $t('identityServer.cloneClint') }} - - - {{ $t('identityServer.clientClaim') }} - - - {{ $t('identityServer.clientProperty') }} - - - {{ $t('identityServer.clientSecret') }} + {{ $t('AbpIdentityServer.Permissions') }} - {{ $t('identityServer.clientPermission') }} + {{ $t('AbpIdentityServer.Client:Clone') }} - {{ $t('identityServer.deleteClient') }} + {{ $t('AbpIdentityServer.Client:Delete') }} @@ -215,7 +219,7 @@ - - - - - - - - - - - - - - @@ -279,26 +244,15 @@ import { checkPermission } from '@/utils/permission' import DataListMiXin from '@/mixins/DataListMiXin' import Component, { mixins } from 'vue-class-component' 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 PermissionForm from '@/components/PermissionForm/index.vue' + @Component({ name: 'IdentityServerClient', components: { Pagination, - ClientEditForm, - ClientCloneForm, - ClientCreateForm, - ClientClaimEditForm, - ClientSecretEditForm, - ClientPropertyEditForm, - ClientPermissionEditForm + PermissionForm }, methods: { checkPermission, @@ -316,15 +270,12 @@ import ClientService, { Client, ClientGetByPaged } from '@/api/clients' } }) export default class extends mixins(DataListMiXin) { - private editClient = Client.empty() + private editClientId = '' private editClientTitle = '' private showEditClientDialog = false private showCloneClientDialog = false private showCreateClientDialog = false - private showEditClientSecretDialog = false - private showEditClientClaimDialog = false - private showEditClientPropertyDialog = false private showEditClientPermissionDialog = false public dataFilter = new ClientGetByPaged() @@ -342,14 +293,12 @@ export default class extends mixins(DataListMiXin) { } private handleShowCreateClientForm() { - this.editClient = Client.empty() - this.editClientTitle = this.l('identityServer.createClient') + this.editClientTitle = this.l('AbpIdentityServer.Client:New') this.showCreateClientDialog = true } private handleShowEditClientForm(client: Client) { - this.editClient = client - this.editClientTitle = this.l('identityServer.updateClientByName', { name: this.editClient.clientName }) + this.editClientId = client.clientId 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() { this.showEditClientPermissionDialog = false } private handleDeleteClient(id: string, clientId: string) { - this.$confirm(this.l('identityServer.deleteClientById', { id: clientId }), - this.l('identityServer.deleteClient'), { + this.$confirm(this.l('AbpIdentityServer.Client:WillDelete', { 0: clientId }), + this.l('AbpUi.AreYouSure'), { callback: (action) => { if (action === 'confirm') { ClientService.deleteClient(id).then(() => { - this.$message.success(this.l('identityServer.deleteClientSuccess', { id: clientId })) + this.$message.success(this.l('global.successful')) this.refreshPagedData() }) } @@ -405,20 +342,11 @@ export default class extends mixins(DataListMiXin) { } private handleCommand(command: {key: string, row: Client}) { - this.editClient = command.row + this.editClientId = command.row.clientId switch (command.key) { case 'clone' : this.showCloneClientDialog = true break - case 'secret' : - this.showEditClientSecretDialog = true - break - case 'claim' : - this.showEditClientClaimDialog = true - break - case 'property': - this.showEditClientPropertyDialog = true - break case 'permissions': this.showEditClientPermissionDialog = true break @@ -428,16 +356,6 @@ export default class extends mixins(DataListMiXin) { default: break } } - - private formatStatusText(status: boolean) { - let statusText = '' - if (status) { - statusText = this.l('enabled') - } else { - statusText = this.l('disbled') - } - return statusText - } } diff --git a/vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue b/vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue index f9d7e76a4..3562b9559 100644 --- a/vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue +++ b/vueJs/src/views/admin/identityServer/identity-resources/components/IdentityResourceCreateOrEditForm.vue @@ -13,92 +13,99 @@
- - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + {{ $t('global.cancel') }} @@ -106,7 +113,7 @@ class="confirm" type="primary" style="width:100px" - @click="onSaveIdentityResource" + @click="onSave" > {{ $t('global.confirm') }} @@ -117,10 +124,12 @@