Browse Source

添加id4 ui

pull/6/head
WangJunZzz 5 years ago
parent
commit
7d2b0c03fe
  1. 7
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/ApiScopes/Dtos/PagingApiScopeListOutput.cs
  2. 12
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/Dtos/EnabledInput.cs
  3. 3
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/Dtos/UpdataBasicDataInput.cs
  4. 7
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/IIdentityServerClientAppService.cs
  5. 7
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/IdentityResources/Dtos/PagingIdentityResourceListOutput.cs
  6. 4
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs
  7. 14
      aspnet-core/services/src/CompanyName.ProjectName.Application/IdentityServers/Clients/IdentityServerClientAppService.cs
  8. 1
      aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs
  9. 12
      aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs
  10. 20
      aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs
  11. 2
      aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs
  12. 17152
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Logs/logs.txt
  13. 7
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/IdentityServers/ClientController.cs
  14. 2
      vue3/src/layouts/default/header/components/user-dropdown/index.vue
  15. 1
      vue3/src/router/menus/modules/identityServer.ts
  16. 5
      vue3/src/router/routes/modules/identityServer.ts
  17. 142
      vue3/src/services/ServiceProxies.ts
  18. 100
      vue3/src/views/identityServers/apiResources/ApiResources.ts
  19. 48
      vue3/src/views/identityServers/apiResources/ApiResources.vue
  20. 61
      vue3/src/views/identityServers/apiResources/CreateApiResource.vue
  21. 179
      vue3/src/views/identityServers/apiScopes/ApiScopes.ts
  22. 71
      vue3/src/views/identityServers/apiScopes/ApiScopes.vue
  23. 60
      vue3/src/views/identityServers/apiScopes/CreateApiScope.vue
  24. 72
      vue3/src/views/identityServers/apiScopes/EditApiScope.vue
  25. 326
      vue3/src/views/identityServers/clients/Clients.ts
  26. 116
      vue3/src/views/identityServers/clients/Clients.vue
  27. 61
      vue3/src/views/identityServers/clients/CreateClient.vue
  28. 156
      vue3/src/views/identityServers/clients/EditClientBasic.vue
  29. 60
      vue3/src/views/identityServers/identityResources/CreateIdentityResource.vue
  30. 13
      vue3/src/views/identityServers/identityResources/EditIdentityResources.vue
  31. 163
      vue3/src/views/identityServers/identityResources/IdentityResources.ts
  32. 71
      vue3/src/views/identityServers/identityResources/IdentityResources.vue

7
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/ApiScopes/Dtos/PagingApiScopeListOutput.cs

@ -1,6 +1,9 @@
namespace CompanyName.ProjectName.IdentityServers.ApiScopes.Dtos
using System;
using Volo.Abp.Application.Dtos;
namespace CompanyName.ProjectName.IdentityServers.ApiScopes.Dtos
{
public class PagingApiScopeListOutput
public class PagingApiScopeListOutput : EntityDto<Guid>
{
public bool Enabled { get; set; }

12
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/Dtos/EnabledInput.cs

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace CompanyName.ProjectName.IdentityServers.Clients
{
public class EnabledInput
{
[Required]
public string ClientId { get; set; }
public bool Enabled { get; set; }
}
}

3
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/Dtos/UpdataBasicDataInput.cs

@ -79,5 +79,8 @@
public string UserCodeType { get; set; }
public int DeviceCodeLifetime { get; set; } = 300;
public string Secret { get; set; }
public string SecretType { get; set; }
}
}

7
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/Clients/IIdentityServerClientAppService.cs

@ -67,5 +67,12 @@ namespace CompanyName.ProjectName.IdentityServers.Clients
/// 删除cors
/// </summary>
Task RemoveCorsAsync(RemoveCorsInput input);
/// <summary>
/// 禁用client
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
Task EnabledAsync(EnabledInput input);
}
}

7
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/IdentityServers/IdentityResources/Dtos/PagingIdentityResourceListOutput.cs

@ -1,6 +1,9 @@
namespace CompanyName.ProjectName.IdentityServers.IdentityResources.Dtos
using System;
using Volo.Abp.Application.Dtos;
namespace CompanyName.ProjectName.IdentityServers.IdentityResources.Dtos
{
public class PagingIdentityResourceListOutput
public class PagingIdentityResourceListOutput:EntityDto<Guid>
{
public string Name { get; set; }

4
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Permissions/ProjectNamePermissionDefinitionProvider.cs

@ -17,9 +17,7 @@ namespace CompanyName.ProjectName.Permissions
var roleManagement = abpIdentityGroup.GetPermissionOrNull(ProjectNamePermissions.AbpIdentityExtend.Roles);
roleManagement.AddChild(ProjectNamePermissions.AbpIdentityExtend.RoleQuery, L("Permissions:Query"));
var auditManagement = abpIdentityGroup.AddPermission(ProjectNamePermissions.AbpIdentityExtend.AuditLogs, L("Permissions:AuditLogManagement"));
auditManagement.AddChild(ProjectNamePermissions.AbpIdentityExtend.AuditLogQuery, L("Permissions:Query"));
}

14
aspnet-core/services/src/CompanyName.ProjectName.Application/IdentityServers/Clients/IdentityServerClientAppService.cs

@ -93,7 +93,9 @@ namespace CompanyName.ProjectName.IdentityServers.Clients
input.UserSsoLifetime,
input.UserCodeType,
input.DeviceCodeLifetime,
input.SlidingRefreshTokenLifetime
input.SlidingRefreshTokenLifetime,
input.Secret,
input.SecretType
);
}
@ -153,5 +155,15 @@ namespace CompanyName.ProjectName.IdentityServers.Clients
{
return _idenityServerClientManager.RemoveCorsAsync(input.ClientId, input.Origin);
}
/// <summary>
/// 禁用client
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public Task EnabledAsync(EnabledInput input)
{
return _idenityServerClientManager.EnabledAsync(input.ClientId, input.Enabled);
}
}
}

1
aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs

@ -89,7 +89,6 @@ namespace CompanyName.ProjectName.Roles
/// <summary>
/// 获取所有权限
/// </summary>
/// <param name="GetPermissionInput"></param>
/// <returns></returns>
public async Task<PermissionOutput> GetPermissionAsync(GetPermissionInput input)
{

12
aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs

@ -119,7 +119,17 @@ namespace CompanyName.ProjectName.IdentityServer
apiResource.ShowInDiscoveryDocument = showInDiscoveryDocument;
secrets?.Distinct().ToList().ForEach(item =>
{
apiResource.AddSecret(item.Value.ToSha256(), item.Expiration, item.Type, item.Description);
var secret = apiResource.Secrets.FirstOrDefault(e => e.Value == item.Value.ToSha256() && e.Type==item.Type);
if (secret != null)
{
secret.Expiration = item.Expiration;
secret.Description = item.Description;
}
else
{
apiResource.AddSecret(item.Value.ToSha256(), item.Expiration, item.Type, item.Description);
}
});
scopes?.Distinct().ToList().ForEach(item => { apiResource.AddScope(item.Scope); });

20
aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using IdentityModel;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.IdentityServer.Clients;
@ -44,7 +45,9 @@ namespace CompanyName.ProjectName.IdentityServer
public async Task<Client> CreateAsync(string clientId, string clientName, string description)
{
var entity = new Client(GuidGenerator.Create(), clientId)
var entity = await _clientRepository.FindByClientIdAsync(clientId);
if (null != entity) throw new UserFriendlyException(message: "当前ClientId已存在");
entity = new Client(GuidGenerator.Create(), clientId)
{
ClientName = clientName, Description = description
};
@ -90,7 +93,10 @@ namespace CompanyName.ProjectName.IdentityServer
int? userSsoLifetime,
string userCodeType,
int deviceCodeLifetime,
int slidingRefreshTokenLifetime
int slidingRefreshTokenLifetime,
string secret,
string secretType
)
{
var client = await _clientRepository.FindByClientIdAsync(clientId);
@ -138,6 +144,8 @@ namespace CompanyName.ProjectName.IdentityServer
client.UserSsoLifetime = userSsoLifetime;
client.UserCodeType = userCodeType;
client.EnableLocalLogin = enableLocalLogin;
client.ClientSecrets.Clear();
client.AddSecret(secret.ToSha256(), null, secretType, String.Empty);
return await _clientRepository.UpdateAsync(client);
}
@ -256,5 +264,13 @@ namespace CompanyName.ProjectName.IdentityServer
return client;
}
public async Task<Client> EnabledAsync(string clientId, bool enabled)
{
var client = await _clientRepository.FindByClientIdAsync(clientId);
if (client == null) throw new UserFriendlyException(message: "Client不存在");
client.Enabled = enabled;
return await _clientRepository.UpdateAsync(client);
}
}
}

2
aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs

@ -57,7 +57,7 @@ namespace CompanyName.ProjectName.IdentityServer
bool showInDiscoveryDocument)
{
var identityResource = await _identityResourceRepository.FindByNameAsync(name, false);
if (null == identityResource) throw new UserFriendlyException(message: $"{name}存在");
if (null != identityResource) throw new UserFriendlyException(message: $"{name}存在");
identityResource = new IdentityResource(GuidGenerator.Create(), name, displayName, description, required,
emphasize,
showInDiscoveryDocument, enabled);

17152
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Logs/logs.txt

File diff suppressed because it is too large

7
aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/IdentityServers/ClientController.cs

@ -94,5 +94,12 @@ namespace CompanyName.ProjectName.Controllers.IdentityServers
{
return _identityServerClientAppService.RemoveCorsAsync(input);
}
[HttpPost("enabled")]
[SwaggerOperation(summary: "禁用client", Tags = new[] {"Client"})]
public Task EnabledAsync(EnabledInput input)
{
return _identityServerClientAppService.EnabledAsync(input);
}
}
}

2
vue3/src/layouts/default/header/components/user-dropdown/index.vue

@ -18,7 +18,7 @@
</template>
</Dropdown>
<LockAction @register="register" />
<WarehouseAction @register="registerWarehouseModal" />
<PasswordAction @register="registerChangePasswordModal" />
</template>
<script lang="ts">

1
vue3/src/router/menus/modules/identityServer.ts

@ -1,5 +1,4 @@
import type { MenuModule } from '/@/router/types';
import { t } from '/@/hooks/web/useI18n';
const identityServer: MenuModule = {
orderNo: 20,

5
vue3/src/router/routes/modules/identityServer.ts

@ -1,6 +1,5 @@
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
import { t } from '/@/hooks/web/useI18n';
const identityServer: AppRouteModule = {
path: '/identityServer',
@ -35,7 +34,7 @@ const identityServer: AppRouteModule = {
name: 'ApiScopes',
component: () => import('/@/views/identityServers/apiScopes/ApiScopes.vue'),
meta: {
title: 'ApiResources',
title: 'ApiScopes',
icon: 'ant-design:skin-outlined',
},
},
@ -44,7 +43,7 @@ const identityServer: AppRouteModule = {
name: 'IdentityResources',
component: () => import('/@/views/identityServers/identityResources/IdentityResources.vue'),
meta: {
title: 'ApiResources',
title: 'IdentityResources',
icon: 'ant-design:skin-outlined',
},
},

142
vue3/src/services/ServiceProxies.ts

@ -2281,6 +2281,96 @@ export class ClientServiceProxy extends ServiceProxyBase {
}
return Promise.resolve<void>(<any>null);
}
/**
* client
* @param body (optional)
* @return Success
*/
enabled(body: EnabledInput | undefined , cancelToken?: CancelToken | undefined): Promise<void> {
let url_ = this.baseUrl + "/IdentityServer/Client/enabled";
url_ = url_.replace(/[?&]$/, "");
const content_ = JSON.stringify(body);
let options_ = <AxiosRequestConfig>{
data: content_,
method: "POST",
url: url_,
headers: {
"Content-Type": "application/json",
},
cancelToken
};
return this.transformOptions(options_).then(transformedOptions_ => {
return this.instance.request(transformedOptions_);
}).catch((_error: any) => {
if (isAxiosError(_error) && _error.response) {
return _error.response;
} else {
throw _error;
}
}).then((_response: AxiosResponse) => {
return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processEnabled(_response));
});
}
protected processEnabled(response: AxiosResponse): Promise<void> {
const status = response.status;
let _headers: any = {};
if (response.headers && typeof response.headers === "object") {
for (let k in response.headers) {
if (response.headers.hasOwnProperty(k)) {
_headers[k] = response.headers[k];
}
}
}
if (status === 200) {
const _responseText = response.data;
return Promise.resolve<void>(<any>null);
} else if (status === 403) {
const _responseText = response.data;
let result403: any = null;
let resultData403 = _responseText;
result403 = RemoteServiceErrorResponse.fromJS(resultData403);
return throwException("Forbidden", status, _responseText, _headers, result403);
} else if (status === 401) {
const _responseText = response.data;
let result401: any = null;
let resultData401 = _responseText;
result401 = RemoteServiceErrorResponse.fromJS(resultData401);
return throwException("Unauthorized", status, _responseText, _headers, result401);
} else if (status === 400) {
const _responseText = response.data;
let result400: any = null;
let resultData400 = _responseText;
result400 = RemoteServiceErrorResponse.fromJS(resultData400);
return throwException("Bad Request", status, _responseText, _headers, result400);
} else if (status === 404) {
const _responseText = response.data;
let result404: any = null;
let resultData404 = _responseText;
result404 = RemoteServiceErrorResponse.fromJS(resultData404);
return throwException("Not Found", status, _responseText, _headers, result404);
} else if (status === 501) {
const _responseText = response.data;
let result501: any = null;
let resultData501 = _responseText;
result501 = RemoteServiceErrorResponse.fromJS(resultData501);
return throwException("Server Error", status, _responseText, _headers, result501);
} else if (status === 500) {
const _responseText = response.data;
let result500: any = null;
let resultData500 = _responseText;
result500 = RemoteServiceErrorResponse.fromJS(resultData500);
return throwException("Server Error", status, _responseText, _headers, result500);
} else if (status !== 200 && status !== 204) {
const _responseText = response.data;
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
}
return Promise.resolve<void>(<any>null);
}
}
export class DataDictionaryServiceProxy extends ServiceProxyBase {
@ -6824,6 +6914,46 @@ export interface IEmailSettingsDto {
defaultFromDisplayName: string | undefined;
}
export class EnabledInput implements IEnabledInput {
clientId!: string;
enabled!: boolean;
constructor(data?: IEnabledInput) {
if (data) {
for (var property in data) {
if (data.hasOwnProperty(property))
(<any>this)[property] = (<any>data)[property];
}
}
}
init(_data?: any) {
if (_data) {
this.clientId = _data["clientId"];
this.enabled = _data["enabled"];
}
}
static fromJS(data: any): EnabledInput {
data = typeof data === 'object' ? data : {};
let result = new EnabledInput();
result.init(data);
return result;
}
toJSON(data?: any) {
data = typeof data === 'object' ? data : {};
data["clientId"] = this.clientId;
data["enabled"] = this.enabled;
return data;
}
}
export interface IEnabledInput {
clientId: string;
enabled: boolean;
}
export class EntityExtensionDto implements IEntityExtensionDto {
properties!: { [key: string]: ExtensionPropertyDto; } | undefined;
configuration!: { [key: string]: any; } | undefined;
@ -9504,6 +9634,7 @@ export interface IPagingApiScopeListInput {
}
export class PagingApiScopeListOutput implements IPagingApiScopeListOutput {
id!: string;
enabled!: boolean;
name!: string | undefined;
displayName!: string | undefined;
@ -9523,6 +9654,7 @@ export class PagingApiScopeListOutput implements IPagingApiScopeListOutput {
init(_data?: any) {
if (_data) {
this.id = _data["id"];
this.enabled = _data["enabled"];
this.name = _data["name"];
this.displayName = _data["displayName"];
@ -9542,6 +9674,7 @@ export class PagingApiScopeListOutput implements IPagingApiScopeListOutput {
toJSON(data?: any) {
data = typeof data === 'object' ? data : {};
data["id"] = this.id;
data["enabled"] = this.enabled;
data["name"] = this.name;
data["displayName"] = this.displayName;
@ -9554,6 +9687,7 @@ export class PagingApiScopeListOutput implements IPagingApiScopeListOutput {
}
export interface IPagingApiScopeListOutput {
id: string;
enabled: boolean;
name: string | undefined;
displayName: string | undefined;
@ -12079,6 +12213,8 @@ export class UpdataBasicDataInput implements IUpdataBasicDataInput {
userSsoLifetime!: number | undefined;
userCodeType!: string | undefined;
deviceCodeLifetime!: number;
secret!: string | undefined;
secretType!: string | undefined;
constructor(data?: IUpdataBasicDataInput) {
if (data) {
@ -12130,6 +12266,8 @@ export class UpdataBasicDataInput implements IUpdataBasicDataInput {
this.userSsoLifetime = _data["userSsoLifetime"];
this.userCodeType = _data["userCodeType"];
this.deviceCodeLifetime = _data["deviceCodeLifetime"];
this.secret = _data["secret"];
this.secretType = _data["secretType"];
}
}
@ -12181,6 +12319,8 @@ export class UpdataBasicDataInput implements IUpdataBasicDataInput {
data["userSsoLifetime"] = this.userSsoLifetime;
data["userCodeType"] = this.userCodeType;
data["deviceCodeLifetime"] = this.deviceCodeLifetime;
data["secret"] = this.secret;
data["secretType"] = this.secretType;
return data;
}
}
@ -12225,6 +12365,8 @@ export interface IUpdataBasicDataInput {
userSsoLifetime: number | undefined;
userCodeType: string | undefined;
deviceCodeLifetime: number;
secret: string | undefined;
secretType: string | undefined;
}
export class UpdateApiResourceInput implements IUpdateApiResourceInput {

100
vue3/src/views/identityServers/apiResources/ApiResources.ts

@ -1,6 +1,6 @@
import { FormSchema } from '/@/components/Table';
import { BasicColumn } from '/@/components/Table';
import { ClientServiceProxy, PagingClientListInput } from '/@/services/ServiceProxies';
import { ApiResourceServiceProxy, PagingApiRseourceListInput, IdInput } from '/@/services/ServiceProxies';
export const searchFormSchema: FormSchema[] = [
{
@ -13,12 +13,12 @@ export const searchFormSchema: FormSchema[] = [
export const tableColumns: BasicColumn[] = [
{
title: 'ClientId',
dataIndex: 'clientId',
title: 'name',
dataIndex: 'name',
},
{
title: 'ClientName',
dataIndex: 'clientName',
title: 'displayName',
dataIndex: 'displayName',
},
{
title: '是否启用',
@ -26,16 +26,67 @@ export const tableColumns: BasicColumn[] = [
slots: { customRender: 'enabled' },
},
{
title: 'AccessTokenLifetime',
dataIndex: 'accessTokenLifetime',
title: 'description',
dataIndex: 'description',
},
{
title: 'AbsoluteRefreshTokenLifetime',
dataIndex: 'absoluteRefreshTokenLifetime',
title: 'showInDiscoveryDocument',
dataIndex: 'showInDiscoveryDocument',
slots: { customRender: 'showInDiscoveryDocument' },
},
];
export const createFormSchema: FormSchema[] = [
{
title: 'Description',
dataIndex: 'description',
field: 'name',
label: 'name',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'displayName',
label: 'displayName',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'secret',
label: 'secret',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'description',
label: 'description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'enabled',
label: 'enabled',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'showInDiscoveryDocument',
label: 'showInDiscoveryDocument',
labelWidth: 200,
component: 'Switch',
colProps: { span: 20 },
},
{
field: 'allowedAccessTokenSigningAlgorithms',
label: 'allowedAccessTokenSigningAlgorithms',
component: 'Input',
colProps: { span: 20 },
},
];
/**
@ -43,7 +94,28 @@ export const tableColumns: BasicColumn[] = [
* @param params
* @returns
*/
export async function getTableListAsync(params: PagingClientListInput) {
const _clientServiceProxy = new ClientServiceProxy();
return _clientServiceProxy.page(params);
export async function getTableListAsync(params: PagingApiRseourceListInput) {
const _apiResourceServiceProxy = new ApiResourceServiceProxy();
return _apiResourceServiceProxy.page(params);
}
export async function deleteApiResourceAsync({ id, reload }) {
const _apiResourceServiceProxy = new ApiResourceServiceProxy();
const request = new IdInput();
request.id = id;
await _apiResourceServiceProxy.delete(request);
reload();
}
/**
* ApiResource
* @param params
* @returns
*/
export async function createApiResourceAsync({ request, changeOkLoading, validate, closeModal }) {
changeOkLoading(true);
await validate();
const _apiResourceServiceProxy = new ApiResourceServiceProxy();
await _apiResourceServiceProxy.create(request);
changeOkLoading(false);
closeModal();
}

48
vue3/src/views/identityServers/apiResources/ApiResources.vue

@ -1,32 +1,57 @@
<template>
<div>
<BasicTable @register="registerTable" size="small">
<template #toolbar>
<a-button type="primary" @click="openCreateApiResourceModal">
{{ t('common.createText') }}
</a-button>
</template>
<template #enabled="{ record }">
<Tag :color="record.enabled ? 'green' : 'red'">
{{ record.enabled ? '是' : '否' }}
</Tag>
</template>
</BasicTable></div
>
<template #showInDiscoveryDocument="{ record }">
<Tag :color="record.showInDiscoveryDocument ? 'green' : 'red'">
{{ record.showInDiscoveryDocument ? '是' : '否' }}
</Tag>
</template>
<template #action="{ record }">
<!-- <a-button type="link" size="small" @click="handleEdit(record)">
{{ t('common.editText') }}
</a-button> -->
<a-button type="link" size="small" @click="handleDelete(record)">
{{ t('common.delText') }}
</a-button>
</template>
</BasicTable>
<CreateApiResource @register="registerCreateApiResourceModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }"
/></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { tableColumns, searchFormSchema, getTableListAsync } from './ApiResources';
import { tableColumns, searchFormSchema, getTableListAsync, deleteApiResourceAsync } from './ApiResources';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tag } from 'ant-design-vue';
import CreateApiResource from './CreateApiResource.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useModal } from '/@/components/Modal';
export default defineComponent({
name: 'ApiResources',
components: {
BasicTable,
TableAction,
Tag,
CreateApiResource,
},
setup() {
const { t } = useI18n();
const { createConfirm } = useMessage();
// table
const [registerTable] = useTable({
const [registerTable, { reload }] = useTable({
columns: tableColumns,
formConfig: {
labelWidth: 70,
@ -48,10 +73,19 @@
fixed: 'right',
},
});
return {
registerTable,
const [registerCreateApiResourceModal, { openModal: openCreateApiResourceModal }] = useModal();
const handleDelete = async (record: Recordable) => {
let msg = '是否确认删除';
createConfirm({
iconType: 'warning',
title: '提示',
content: msg,
onOk: async () => {
await deleteApiResourceAsync({ id: record.id, reload });
},
});
};
return { reload, t, registerTable, handleDelete, registerCreateApiResourceModal, openCreateApiResourceModal };
},
});
</script>

61
vue3/src/views/identityServers/apiResources/CreateApiResource.vue

@ -0,0 +1,61 @@
<template>
<BasicModal title="创建ApiResource" :canFullscreen="false" @ok="submit" @cancel="cancel" @register="registerModal">
<BasicForm @register="registerApiResourceForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, useContext, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { createFormSchema, createApiResourceAsync } from './ApiResources';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'CreateApiResource',
components: {
BasicModal,
BasicForm,
},
setup() {
//
defineEmit(['reload']);
const ctx = useContext();
const { t } = useI18n();
const [registerApiResourceForm, { getFieldsValue, validate, resetFields }] = useForm({
labelWidth: 120,
schemas: createFormSchema,
showActionButtonGroup: false,
});
const [registerModal, { changeOkLoading, closeModal }] = useModalInner();
//
const submit = async () => {
try {
const request = getFieldsValue();
await createApiResourceAsync({ request, changeOkLoading, validate, closeModal });
resetFields();
ctx.emit('reload');
} catch (error) {
changeOkLoading(false);
}
};
const cancel = () => {
resetFields();
closeModal();
};
return {
t,
registerModal,
registerApiResourceForm,
submit,
cancel,
};
},
});
</script>
<style lang="less" scoped></style>

179
vue3/src/views/identityServers/apiScopes/ApiScopes.ts

@ -1,6 +1,6 @@
import { FormSchema } from '/@/components/Table';
import { BasicColumn } from '/@/components/Table';
import { ClientServiceProxy, PagingClientListInput } from '/@/services/ServiceProxies';
import { ApiScopeServiceProxy, PagingApiScopeListInput, IdInput } from '/@/services/ServiceProxies';
export const searchFormSchema: FormSchema[] = [
{
@ -13,12 +13,12 @@ export const searchFormSchema: FormSchema[] = [
export const tableColumns: BasicColumn[] = [
{
title: 'ClientId',
dataIndex: 'clientId',
title: 'name',
dataIndex: 'name',
},
{
title: 'ClientName',
dataIndex: 'clientName',
title: 'displayName',
dataIndex: 'displayName',
},
{
title: '是否启用',
@ -26,16 +26,135 @@ export const tableColumns: BasicColumn[] = [
slots: { customRender: 'enabled' },
},
{
title: 'AccessTokenLifetime',
dataIndex: 'accessTokenLifetime',
title: 'description',
dataIndex: 'description',
},
{
title: 'AbsoluteRefreshTokenLifetime',
dataIndex: 'absoluteRefreshTokenLifetime',
title: 'required',
dataIndex: 'required',
slots: { customRender: 'required' },
},
{
title: 'Description',
dataIndex: 'description',
title: 'emphasize',
dataIndex: 'emphasize',
slots: { customRender: 'emphasize' },
},
{
title: 'showInDiscoveryDocument',
dataIndex: 'showInDiscoveryDocument',
slots: { customRender: 'showInDiscoveryDocument' },
},
];
export const createFormSchema: FormSchema[] = [
{
field: 'name',
label: 'name',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'displayName',
label: 'displayName',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'enabled',
label: 'enabled',
component: 'Switch',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'description',
label: 'description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'required',
label: 'required',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'emphasize',
label: 'emphasize',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'showInDiscoveryDocument',
label: 'showInDiscoveryDocument',
labelWidth: 200,
component: 'Switch',
colProps: { span: 20 },
},
];
export const editFormSchema: FormSchema[] = [
{
field: 'name',
label: 'name',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
componentProps: {
disabled: true,
},
},
{
field: 'displayName',
label: 'displayName',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'enabled',
label: 'enabled',
component: 'Switch',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'description',
label: 'description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'required',
label: 'required',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'emphasize',
label: 'emphasize',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'showInDiscoveryDocument',
label: 'showInDiscoveryDocument',
labelWidth: 200,
component: 'Switch',
colProps: { span: 20 },
},
];
/**
@ -43,7 +162,39 @@ export const tableColumns: BasicColumn[] = [
* @param params
* @returns
*/
export async function getTableListAsync(params: PagingClientListInput) {
const _clientServiceProxy = new ClientServiceProxy();
return _clientServiceProxy.page(params);
export async function getTableListAsync(params: PagingApiScopeListInput) {
const _apiScopeServiceProxy = new ApiScopeServiceProxy();
return _apiScopeServiceProxy.page(params);
}
export async function createApiScopeAsync({ request, changeOkLoading, validate, closeModal }) {
changeOkLoading(true);
await validate();
const _apiScopeServiceProxy = new ApiScopeServiceProxy();
await _apiScopeServiceProxy.create(request);
changeOkLoading(false);
closeModal();
}
/**
*
* @param param0
*/
export async function deleteApiScopeAsync({ id, reload }) {
const _apiScopeServiceProxy = new ApiScopeServiceProxy();
const request = new IdInput();
request.id = id;
await _apiScopeServiceProxy.delete(request);
reload();
}
/**
*
* @param param0
*/
export async function editApiScopeAsync({ request, changeOkLoading, validate, closeModal }) {
await validate();
changeOkLoading(true);
const _apiScopeServiceProxy = new ApiScopeServiceProxy();
await _apiScopeServiceProxy.update(request);
changeOkLoading(false);
closeModal();
}

71
vue3/src/views/identityServers/apiScopes/ApiScopes.vue

@ -1,32 +1,70 @@
<template>
<div>
<BasicTable @register="registerTable" size="small">
<template #toolbar>
<a-button type="primary" @click="openCreateApiScopeModal">
{{ t('common.createText') }}
</a-button>
</template>
<template #enabled="{ record }">
<Tag :color="record.enabled ? 'green' : 'red'">
{{ record.enabled ? '是' : '否' }}
</Tag>
</template>
</BasicTable></div
>
<template #required="{ record }">
<Tag :color="record.required ? 'green' : 'red'">
{{ record.required ? '是' : '否' }}
</Tag>
</template>
<template #emphasize="{ record }">
<Tag :color="record.emphasize ? 'green' : 'red'">
{{ record.emphasize ? '是' : '否' }}
</Tag>
</template>
<template #showInDiscoveryDocument="{ record }">
<Tag :color="record.showInDiscoveryDocument ? 'green' : 'red'">
{{ record.showInDiscoveryDocument ? '是' : '否' }}
</Tag>
</template>
<template #action="{ record }">
<a-button type="link" size="small" @click="handleEdit(record)">
{{ t('common.editText') }}
</a-button>
<a-button type="link" size="small" @click="handleDelete(record)">
{{ t('common.delText') }}
</a-button>
</template>
</BasicTable>
<CreateApiScope @register="registerCreateApiScopeModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }" />
<EditApiScope @register="registerEditApiScopeModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }"
/></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { tableColumns, searchFormSchema, getTableListAsync } from './ApiScopes';
import { tableColumns, searchFormSchema, getTableListAsync, deleteApiScopeAsync } from './ApiScopes';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tag } from 'ant-design-vue';
import CreateApiScope from './CreateApiScope.vue';
import EditApiScope from './EditApiScope.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
export default defineComponent({
name: 'ApiScopes',
components: {
BasicTable,
TableAction,
Tag,
CreateApiScope,
EditApiScope,
},
setup() {
const { t } = useI18n();
const { createConfirm } = useMessage();
// table
const [registerTable] = useTable({
const [registerTable, { reload }] = useTable({
columns: tableColumns,
formConfig: {
labelWidth: 70,
@ -48,9 +86,32 @@
fixed: 'right',
},
});
const [registerCreateApiScopeModal, { openModal: openCreateApiScopeModal }] = useModal();
const [registerEditApiScopeModal, { openModal: openEditApiScopeModal }] = useModal();
const handleEdit = (record: Recordable) => {
openEditApiScopeModal(true, { record: record });
};
const handleDelete = (record: Recordable) => {
let msg = '是否确认删除';
createConfirm({
iconType: 'warning',
title: '提示',
content: msg,
onOk: async () => {
await deleteApiScopeAsync({ id: record.id, reload });
},
});
};
return {
t,
registerTable,
openCreateApiScopeModal,
registerCreateApiScopeModal,
registerEditApiScopeModal,
openEditApiScopeModal,
reload,
handleDelete,
handleEdit,
};
},
});

60
vue3/src/views/identityServers/apiScopes/CreateApiScope.vue

@ -0,0 +1,60 @@
<template>
<BasicModal title="创建ApiScope" :canFullscreen="false" @ok="submit" @cancel="cancel" @register="registerModal">
<BasicForm @register="registerApiScopeForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, useContext, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { createFormSchema, createApiScopeAsync } from './ApiScopes';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'CreateApiScope',
components: {
BasicModal,
BasicForm,
},
setup() {
//
defineEmit(['reload']);
const ctx = useContext();
const { t } = useI18n();
const [registerApiScopeForm, { getFieldsValue, validate, resetFields }] = useForm({
labelWidth: 120,
schemas: createFormSchema,
showActionButtonGroup: false,
});
const [registerModal, { changeOkLoading, closeModal }] = useModalInner();
const submit = async () => {
try {
const request = getFieldsValue();
await createApiScopeAsync({ request, changeOkLoading, validate, closeModal });
resetFields();
ctx.emit('reload');
} catch (error) {
changeOkLoading(false);
}
};
const cancel = () => {
resetFields();
closeModal();
};
return {
t,
registerModal,
registerApiScopeForm,
submit,
cancel,
};
},
});
</script>
<style lang="less" scoped></style>

72
vue3/src/views/identityServers/apiScopes/EditApiScope.vue

@ -0,0 +1,72 @@
<template>
<BasicModal title="创建ApiScope" :canFullscreen="false" @ok="submit" @cancel="cancel" @register="registerModal">
<BasicForm @register="registerApiScopeForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, useContext, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { editFormSchema, editApiScopeAsync } from './ApiScopes';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'EditApiScope',
components: {
BasicModal,
BasicForm,
},
setup() {
//
defineEmit(['reload']);
const ctx = useContext();
const { t } = useI18n();
const [registerApiScopeForm, { getFieldsValue, validate, resetFields, setFieldsValue }] = useForm({
labelWidth: 120,
schemas: editFormSchema,
showActionButtonGroup: false,
});
const [registerModal, { changeOkLoading, closeModal }] = useModalInner((data) => {
console.log(data.record);
setFieldsValue({
name: data.record.name,
enabled: data.record.enabled,
displayName: data.record.displayName,
description: data.record.description,
required: data.record.required,
emphasize: data.record.emphasize,
showInDiscoveryDocument: data.record.showInDiscoveryDocument,
});
});
//
const submit = async () => {
try {
const request = getFieldsValue();
await editApiScopeAsync({ request, changeOkLoading, validate, closeModal });
resetFields();
ctx.emit('reload');
} catch (error) {
changeOkLoading(false);
}
};
const cancel = () => {
resetFields();
closeModal();
};
return {
t,
registerModal,
registerApiScopeForm,
submit,
cancel,
};
},
});
</script>
<style lang="less" scoped></style>

326
vue3/src/views/identityServers/clients/Clients.ts

@ -0,0 +1,326 @@
import { FormSchema } from '/@/components/Table';
import { BasicColumn } from '/@/components/Table';
import { ClientServiceProxy, EnabledInput, IdInput, PagingClientListInput } from '/@/services/ServiceProxies';
export const searchFormSchema: FormSchema[] = [
{
field: 'filter',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
];
export const tableColumns: BasicColumn[] = [
{
title: 'ClientId',
dataIndex: 'clientId',
},
{
title: 'ClientName',
dataIndex: 'clientName',
},
{
title: '是否启用',
dataIndex: 'enabled',
slots: { customRender: 'enabled' },
},
{
title: 'AccessTokenLifetime',
dataIndex: 'accessTokenLifetime',
},
{
title: 'AbsoluteRefreshTokenLifetime',
dataIndex: 'absoluteRefreshTokenLifetime',
},
{
title: 'Description',
dataIndex: 'description',
},
];
export const createFormSchema: FormSchema[] = [
{
field: 'clientId',
label: 'ClientId',
component: 'Input',
required: true,
colProps: { span: 20 },
},
{
field: 'clientName',
label: 'ClientName',
component: 'Input',
required: true,
colProps: { span: 20 },
},
{
field: 'description',
label: 'Description',
component: 'Input',
colProps: { span: 20 },
},
];
export const editBasicDetailSchema: FormSchema[] = [
{
field: 'clientId',
label: 'ClientId',
component: 'Input',
required: true,
labelWidth: 200,
componentProps: {
disabled: true,
},
colProps: { span: 20 },
},
{
field: 'clientName',
label: 'ClientName',
component: 'Input',
labelWidth: 200,
required: true,
colProps: { span: 20 },
},
{
field: 'description',
label: 'Description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'clientUri',
label: 'ClientUri',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'logoUri',
label: 'LogoUri',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'frontChannelLogoutUri',
label: 'FrontChannelLogoutUri',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'backChannelLogoutUri',
label: 'BackChannelLogoutUri',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
];
export const editBasicOptionSchema: FormSchema[] = [
{
field: 'enabled',
label: 'enabled',
labelWidth: 250,
component: 'Switch',
colProps: { span: 10 },
},
{
field: 'requireClientSecret',
label: 'requireClientSecret',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'requireConsent',
label: 'requireConsent',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'allowRememberConsent',
label: 'allowRememberConsent',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'requirePkce',
label: 'requirePkce',
labelWidth: 250,
component: 'Switch',
colProps: { span: 10 },
},
{
field: 'allowOfflineAccess',
label: 'allowOfflineAccess',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'enableLocalLogin',
label: 'enableLocalLogin',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'includeJwtId',
label: 'includeJwtId',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'allowAccessTokensViaBrowser',
label: 'allowAccessTokensViaBrowser',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'alwaysIncludeUserClaimsInIdToken',
label: 'alwaysIncludeUserClaimsInIdToken',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'frontChannelLogoutSessionRequired',
label: 'frontChannelLogoutSessionRequired',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
{
field: 'backChannelLogoutSessionRequired',
label: 'backChannelLogoutSessionRequired',
component: 'Switch',
labelWidth: 250,
colProps: { span: 10 },
},
];
export const editBasicTokenSchema: FormSchema[] = [
{
field: 'accessTokenLifetime',
label: 'accessTokenLifetime',
labelWidth: 200,
component: 'Input',
},
{
field: 'authorizationCodeLifetime',
label: 'authorizationCodeLifetime',
labelWidth: 200,
component: 'Input',
},
{
field: 'absoluteRefreshTokenLifetime',
label: 'absoluteRefreshTokenLifetime',
labelWidth: 200,
component: 'Input',
},
{
field: 'slidingRefreshTokenLifetime',
label: 'slidingRefreshTokenLifetime',
labelWidth: 200,
component: 'Input',
},
{
field: 'refreshTokenExpiration',
label: 'refreshTokenExpiration',
labelWidth: 200,
component: 'Input',
},
{
field: 'deviceCodeLifetime',
label: 'deviceCodeLifetime',
labelWidth: 200,
component: 'Input',
},
];
export const editBasicSecretSchema: FormSchema[] = [
{
field: 'secretType',
component: 'Select',
label: 'Secret',
labelWidth: 100,
colProps: {
span: 15,
},
componentProps: {
options: [
{
label: 'SharedSecret',
value: 'SharedSecret',
key: '1',
},
{
label: 'X509Thumbprint',
value: 'X509Thumbprint',
key: '2',
},
],
},
},
{
field: 'secret',
label: 'secret',
labelWidth: 100,
component: 'InputPassword',
},
];
/**
*
* @param params
* @returns
*/
export async function getTableListAsync(params: PagingClientListInput) {
const _clientServiceProxy = new ClientServiceProxy();
return _clientServiceProxy.page(params);
}
/**
* client
* @param params
* @returns
*/
export async function createClientAsync({ request, changeOkLoading, validate, closeModal }) {
changeOkLoading(true);
await validate();
const _clientServiceProxy = new ClientServiceProxy();
await _clientServiceProxy.create(request);
changeOkLoading(false);
closeModal();
}
/**
*
* @param param0
*/
export async function deleteClientAsync({ id, reload }) {
const _clientServiceProxy = new ClientServiceProxy();
const request = new IdInput();
request.id = id;
await _clientServiceProxy.delete(request);
reload();
}
/**
*
* @param param0
*/
export async function enabledClientAsync({ clientId, enabled, reload }) {
const _clientServiceProxy = new ClientServiceProxy();
const request = new EnabledInput();
request.clientId = clientId;
request.enabled = enabled;
await _clientServiceProxy.enabled(request);
reload();
}

116
vue3/src/views/identityServers/clients/Clients.vue

@ -0,0 +1,116 @@
<template>
<div>
<BasicTable @register="registerTable" size="small">
<template #toolbar>
<a-button type="primary" @click="openCreateClientModal">
{{ t('common.createText') }}
</a-button>
</template>
<template #enabled="{ record }">
<Tag :color="record.enabled ? 'green' : 'red'">
{{ record.enabled ? '是' : '否' }}
</Tag>
</template>
<template #action="{ record }">
<a-button type="link" size="small" @click="handleEdit(record)">
{{ t('common.editText') }}
</a-button>
<a-button type="link" size="small" @click="handleEnabled(record)">
{{ record.enabled ? '禁用' : '启用' }}
</a-button>
<a-button type="link" size="small" @click="handleDelete(record)">
{{ t('common.delText') }}
</a-button>
</template>
</BasicTable>
<CreateClient @register="registerCreateClientModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }" />
<EditClientBasic @register="registerEditClientModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { tableColumns, searchFormSchema, getTableListAsync, deleteClientAsync, enabledClientAsync } from './Clients';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tag } from 'ant-design-vue';
import CreateClient from './CreateClient.vue';
import EditClientBasic from './EditClientBasic.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
export default defineComponent({
name: 'Clients',
components: {
BasicTable,
TableAction,
Tag,
CreateClient,
EditClientBasic,
},
setup() {
const { t } = useI18n();
const { createConfirm } = useMessage();
// table
const [registerTable, { reload }] = useTable({
columns: tableColumns,
formConfig: {
labelWidth: 70,
schemas: searchFormSchema,
},
api: getTableListAsync,
showTableSetting: true,
useSearchForm: true,
bordered: true,
canResize: true,
showIndexColumn: true,
actionColumn: {
width: 150,
title: t('common.action'),
dataIndex: 'action',
slots: {
customRender: 'action',
},
fixed: 'right',
},
});
const [registerCreateClientModal, { openModal: openCreateClientModal }] = useModal();
const [registerEditClientModal, { openModal: openEditClientModal }] = useModal();
const handleEdit = (record: Recordable) => {
openEditClientModal(true, {
record: record,
});
};
const handleDelete = (record: Recordable) => {
let msg = '是否确认删除';
createConfirm({
iconType: 'warning',
title: '提示',
content: msg,
onOk: async () => {
await deleteClientAsync({ id: record.id, reload });
},
});
};
const handleEnabled = async (record: Recordable) => {
await enabledClientAsync({ clientId: record.clientId, enabled: !record.enabled, reload });
};
return {
registerTable,
registerCreateClientModal,
openCreateClientModal,
registerEditClientModal,
openEditClientModal,
t,
reload,
handleEdit,
handleDelete,
handleEnabled,
};
},
});
</script>
<style lang="less" scoped></style>

61
vue3/src/views/identityServers/clients/CreateClient.vue

@ -0,0 +1,61 @@
<template>
<BasicModal title="创建Client" :canFullscreen="false" @ok="submit" @cancel="cancel" @register="registerModal">
<BasicForm @register="registerClientForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, useContext, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { createFormSchema, createClientAsync } from './Clients';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'CreateAbpRole',
components: {
BasicModal,
BasicForm,
},
setup() {
//
defineEmit(['reload']);
const ctx = useContext();
const { t } = useI18n();
const [registerClientForm, { getFieldsValue, validate, resetFields }] = useForm({
labelWidth: 120,
schemas: createFormSchema,
showActionButtonGroup: false,
});
const [registerModal, { changeOkLoading, closeModal }] = useModalInner();
//
const submit = async () => {
try {
const request = getFieldsValue();
await createClientAsync({ request, changeOkLoading, validate, closeModal });
resetFields();
ctx.emit('reload');
} catch (error) {
changeOkLoading(false);
}
};
const cancel = () => {
resetFields();
closeModal();
};
return {
t,
registerModal,
registerClientForm,
submit,
cancel,
};
},
});
</script>
<style lang="less" scoped></style>

156
vue3/src/views/identityServers/clients/EditClientBasic.vue

@ -0,0 +1,156 @@
<template>
<BasicModal
title="编辑Client"
:width="700"
:canFullscreen="false"
@ok="submit"
@cancel="cancel"
@register="registerModal"
@visible-change="visibleChange"
:bodyStyle="{ 'padding-top': '0' }"
:destroyOnClose="true"
:maskClosable="false"
>
<div>
<Tabs>
<TabPane tab="基本信息" key="1">
<BasicForm @register="registerDetailForm" />
</TabPane>
<TabPane tab="Options" key="2">
<BasicForm @register="registerOptionForm" />
</TabPane>
<TabPane tab="Tokens" key="3">
<BasicForm @register="registerTokenForm" />
</TabPane>
<TabPane tab="Secret" key="4">
<BasicForm @register="registerSecretForm" />
</TabPane>
</Tabs>
</div>
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { Tabs } from 'ant-design-vue';
import { editBasicDetailSchema, editBasicOptionSchema, editBasicTokenSchema, editBasicSecretSchema } from './Clients';
export default defineComponent({
name: 'EditAbpUser',
components: {
BasicModal,
BasicForm,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
//
defineEmit(['reload']);
const [registerDetailForm, { getFieldsValue: getFieldsDetailValue, validate: detailValidate, setFieldsValue: setDetailFieldsValue }] = useForm({
labelWidth: 120,
schemas: editBasicDetailSchema,
showActionButtonGroup: false,
});
const [registerOptionForm, { getFieldsValue: getFieldsOptionValue, validate: optionValidate, setFieldsValue: setOptionFieldsValue }] = useForm({
labelWidth: 120,
schemas: editBasicOptionSchema,
showActionButtonGroup: false,
});
const [registerTokenForm, { getFieldsValue: getFieldsTokenValue, validate: tokenValidate, setFieldsValue: setTokenFieldsValue }] = useForm({
labelWidth: 120,
schemas: editBasicTokenSchema,
showActionButtonGroup: false,
});
const [registerSecretForm, { getFieldsValue: getFieldsSecretnValue, validate: secretValidate, setFieldsValue: setSecretFieldsValue }] = useForm(
{
labelWidth: 120,
schemas: editBasicSecretSchema,
showActionButtonGroup: false,
}
);
let currentClient: any;
const [registerModal, { changeOkLoading, closeModal }] = useModalInner((data) => {
currentClient = data.record;
console.log(currentClient);
setDetailFieldsValue({
clientId: data.record.clientId,
clientName: data.record.clientName,
description: data.record.description,
clientUri: data.record.clientUri,
logoUri: data.record.logoUri,
frontChannelLogoutUri: data.record.frontChannelLogoutUri,
backChannelLogoutUri: data.record.backChannelLogoutUri,
});
setOptionFieldsValue({
enabled: data.record.enabled,
requireClientSecret: data.record.requireClientSecret,
requireConsent: data.record.requireConsent,
allowRememberConsent: data.record.allowRememberConsent,
requirePkce: data.record.requirePkce,
allowOfflineAccess: data.record.allowOfflineAccess,
enableLocalLogin: data.record.enableLocalLogin,
includeJwtId: data.record.includeJwtId,
allowAccessTokensViaBrowser: data.record.allowAccessTokensViaBrowser,
alwaysIncludeUserClaimsInIdToken: data.record.alwaysIncludeUserClaimsInIdToken,
frontChannelLogoutSessionRequired: data.record.frontChannelLogoutSessionRequired,
backChannelLogoutSessionRequired: data.record.backChannelLogoutSessionRequired,
});
setTokenFieldsValue({
accessTokenLifetime: data.record.accessTokenLifetime,
authorizationCodeLifetime: data.record.authorizationCodeLifetime,
absoluteRefreshTokenLifetime: data.record.absoluteRefreshTokenLifetime,
slidingRefreshTokenLifetime: data.record.slidingRefreshTokenLifetime,
refreshTokenExpiration: data.record.refreshTokenExpiration,
deviceCodeLifetime: data.record.deviceCodeLifetime,
});
if (data.record.clientSecrets.length > 0) {
setSecretFieldsValue({
secretType: data.record.clientSecrets[0].type,
secret: data.record.clientSecrets[0].value,
});
}
});
const visibleChange = async (visible: boolean) => {
if (visible) {
detailValidate();
optionValidate();
tokenValidate();
secretValidate();
getFieldsTokenValue();
getFieldsSecretnValue();
getFieldsOptionValue();
getFieldsDetailValue();
changeOkLoading(true);
} else {
}
};
const submit = async () => {};
const cancel = () => {
closeModal();
};
return {
registerModal,
registerDetailForm,
registerOptionForm,
registerTokenForm,
registerSecretForm,
submit,
visibleChange,
cancel,
};
},
});
</script>
<style lang="less" scoped>
.ant-checkbox-wrapper + .ant-checkbox-wrapper {
margin-left: 0px;
}
</style>

60
vue3/src/views/identityServers/identityResources/CreateIdentityResource.vue

@ -0,0 +1,60 @@
<template>
<BasicModal title="创建IdentityResource" :canFullscreen="false" @ok="submit" @cancel="cancel" @register="registerModal">
<BasicForm @register="registerApiScopeForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, useContext, defineEmit } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { createFormSchema, createIdentityResourcesAsync } from './IdentityResources';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'CreateIdentityResource',
components: {
BasicModal,
BasicForm,
},
setup() {
//
defineEmit(['reload']);
const ctx = useContext();
const { t } = useI18n();
const [registerApiScopeForm, { getFieldsValue, validate, resetFields }] = useForm({
labelWidth: 120,
schemas: createFormSchema,
showActionButtonGroup: false,
});
const [registerModal, { changeOkLoading, closeModal }] = useModalInner();
const submit = async () => {
try {
const request = getFieldsValue();
await createIdentityResourcesAsync({ request, changeOkLoading, validate, closeModal });
resetFields();
ctx.emit('reload');
} catch (error) {
changeOkLoading(false);
}
};
const cancel = () => {
resetFields();
closeModal();
};
return {
t,
registerModal,
registerApiScopeForm,
submit,
cancel,
};
},
});
</script>
<style lang="less" scoped></style>

13
vue3/src/views/identityServers/identityResources/EditIdentityResources.vue

@ -0,0 +1,13 @@
<template> </template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'EditIdentityResources',
setup() {
return {};
},
});
</script>
<style lang="less" scoped></style>

163
vue3/src/views/identityServers/identityResources/IdentityResources.ts

@ -1,6 +1,6 @@
import { FormSchema } from '/@/components/Table';
import { BasicColumn } from '/@/components/Table';
import { ClientServiceProxy, PagingClientListInput } from '/@/services/ServiceProxies';
import { IdentityResourceServiceProxy, PagingIdentityResourceListInput, IdInput } from '/@/services/ServiceProxies';
export const searchFormSchema: FormSchema[] = [
{
@ -13,12 +13,12 @@ export const searchFormSchema: FormSchema[] = [
export const tableColumns: BasicColumn[] = [
{
title: 'ClientId',
dataIndex: 'clientId',
title: 'name',
dataIndex: 'name',
},
{
title: 'ClientName',
dataIndex: 'clientName',
title: 'displayName',
dataIndex: 'displayName',
},
{
title: '是否启用',
@ -26,16 +26,132 @@ export const tableColumns: BasicColumn[] = [
slots: { customRender: 'enabled' },
},
{
title: 'AccessTokenLifetime',
dataIndex: 'accessTokenLifetime',
title: 'description',
dataIndex: 'description',
},
{
title: 'AbsoluteRefreshTokenLifetime',
dataIndex: 'absoluteRefreshTokenLifetime',
title: 'required',
dataIndex: 'required',
slots: { customRender: 'required' },
},
{
title: 'Description',
dataIndex: 'description',
title: 'emphasize',
dataIndex: 'emphasize',
slots: { customRender: 'emphasize' },
},
{
title: 'showInDiscoveryDocument',
dataIndex: 'showInDiscoveryDocument',
slots: { customRender: 'showInDiscoveryDocument' },
},
];
export const createFormSchema: FormSchema[] = [
{
field: 'name',
label: 'name',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'displayName',
label: 'displayName',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'enabled',
label: 'enabled',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'description',
label: 'description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'required',
label: 'required',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'emphasize',
label: 'emphasize',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'showInDiscoveryDocument',
label: 'showInDiscoveryDocument',
labelWidth: 200,
component: 'Switch',
colProps: { span: 20 },
},
];
export const editFormSchema: FormSchema[] = [
{
field: 'name',
label: 'name',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
componentProps: {
disabled: true,
},
},
{
field: 'displayName',
label: 'displayName',
component: 'Input',
required: true,
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'enabled',
label: 'enabled',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'description',
label: 'description',
component: 'Input',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'required',
label: 'required',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'emphasize',
label: 'emphasize',
component: 'Switch',
labelWidth: 200,
colProps: { span: 20 },
},
{
field: 'showInDiscoveryDocument',
label: 'showInDiscoveryDocument',
labelWidth: 200,
component: 'Switch',
colProps: { span: 20 },
},
];
/**
@ -43,7 +159,26 @@ export const tableColumns: BasicColumn[] = [
* @param params
* @returns
*/
export async function getTableListAsync(params: PagingClientListInput) {
const _clientServiceProxy = new ClientServiceProxy();
return _clientServiceProxy.page(params);
export async function getTableListAsync(params: PagingIdentityResourceListInput) {
const _identityResourceServiceProxy = new IdentityResourceServiceProxy();
return _identityResourceServiceProxy.page(params);
}
export async function createIdentityResourcesAsync({ request, changeOkLoading, validate, closeModal }) {
changeOkLoading(true);
await validate();
const _identityResourceServiceProxy = new IdentityResourceServiceProxy();
await _identityResourceServiceProxy.create(request);
changeOkLoading(false);
closeModal();
}
/**
*
* @param param0
*/
export async function deleteIdentityResourcesAsync({ id, reload }) {
const _identityResourceServiceProxy = new IdentityResourceServiceProxy();
const request = new IdInput();
request.id = id;
await _identityResourceServiceProxy.delete(request);
reload();
}

71
vue3/src/views/identityServers/identityResources/IdentityResources.vue

@ -1,32 +1,70 @@
<template>
<div>
<BasicTable @register="registerTable" size="small">
<template #toolbar>
<a-button type="primary" @click="openCreateIdentityResourcesModal">
{{ t('common.createText') }}
</a-button>
</template>
<template #enabled="{ record }">
<Tag :color="record.enabled ? 'green' : 'red'">
{{ record.enabled ? '是' : '否' }}
</Tag>
</template>
</BasicTable></div
>
<template #required="{ record }">
<Tag :color="record.required ? 'green' : 'red'">
{{ record.required ? '是' : '否' }}
</Tag>
</template>
<template #emphasize="{ record }">
<Tag :color="record.emphasize ? 'green' : 'red'">
{{ record.emphasize ? '是' : '否' }}
</Tag>
</template>
<template #showInDiscoveryDocument="{ record }">
<Tag :color="record.showInDiscoveryDocument ? 'green' : 'red'">
{{ record.showInDiscoveryDocument ? '是' : '否' }}
</Tag>
</template>
<template #action="{ record }">
<a-button type="link" size="small" @click="handleEdit(record)">
{{ t('common.editText') }}
</a-button>
<a-button type="link" size="small" @click="handleDelete(record)">
{{ t('common.delText') }}
</a-button>
</template>
</BasicTable>
<CreateIdentityResource @register="registerCreatIdentityResourcesModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }" />
<EditIdentityResources @register="registerEditIdentityResourcesModal" @reload="reload" :bodyStyle="{ 'padding-top': '0' }"
/></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { tableColumns, searchFormSchema, getTableListAsync } from './IdentityResources';
import { tableColumns, searchFormSchema, getTableListAsync, deleteIdentityResourcesAsync } from './IdentityResources';
import { useI18n } from '/@/hooks/web/useI18n';
import { Tag } from 'ant-design-vue';
import CreateIdentityResource from './CreateIdentityResource.vue';
import EditIdentityResources from './EditIdentityResources.vue';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
export default defineComponent({
name: 'IdentityResources',
components: {
BasicTable,
TableAction,
Tag,
CreateIdentityResource,
EditIdentityResources,
},
setup() {
const { t } = useI18n();
const { createConfirm } = useMessage();
// table
const [registerTable] = useTable({
const [registerTable, { reload }] = useTable({
columns: tableColumns,
formConfig: {
labelWidth: 70,
@ -48,9 +86,32 @@
fixed: 'right',
},
});
const [registerCreatIdentityResourcesModal, { openModal: openCreateIdentityResourcesModal }] = useModal();
const [registerEditIdentityResourcesModal, { openModal: openEditIdentityResourcesModal }] = useModal();
const handleEdit = (record: Recordable) => {
openEditIdentityResourcesModal(true, { record: record });
};
const handleDelete = (record: Recordable) => {
let msg = '是否确认删除';
createConfirm({
iconType: 'warning',
title: '提示',
content: msg,
onOk: async () => {
await deleteIdentityResourcesAsync({ id: record.id, reload });
},
});
};
return {
t,
registerTable,
registerCreatIdentityResourcesModal,
registerEditIdentityResourcesModal,
openCreateIdentityResourcesModal,
openEditIdentityResourcesModal,
handleDelete,
handleEdit,
reload,
};
},
});

Loading…
Cancel
Save