mirror of https://gitee.com/topiam/eiam
⚡ 优化应用
parent
7f983484aa
commit
b1a0693eac
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* 应用信息
|
||||
*/
|
||||
export type GetApp = {
|
||||
id: string;
|
||||
type: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
template: string;
|
||||
protocol: string;
|
||||
protocolName: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
//sso发起方
|
||||
initLoginType: string;
|
||||
//sso登录链接
|
||||
initLoginUrl: string;
|
||||
nameIdValueType: string;
|
||||
//授权范围
|
||||
authorizationType: string;
|
||||
enabled: boolean;
|
||||
remark: string;
|
||||
groupIds: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 应用权限列表
|
||||
*/
|
||||
export type AppAccessPolicyList = {
|
||||
id: string;
|
||||
//主体ID
|
||||
subjectId: string;
|
||||
//主体名称
|
||||
subjectName: string;
|
||||
//主体类型
|
||||
subjectType: string;
|
||||
//应用类型
|
||||
appType: string;
|
||||
appProtocol: string;
|
||||
//Effect
|
||||
effect: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
type AppPermissionRoleList = {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
enabled: boolean;
|
||||
appId: string;
|
||||
remark: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
type GetAppPermissionRole = {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
enabled: boolean;
|
||||
appId: string;
|
||||
remark: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 资源列表
|
||||
*/
|
||||
type AppPermissionResourceList = {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
enabled: boolean;
|
||||
desc: string;
|
||||
appId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 权限资源点
|
||||
*/
|
||||
type AppPermissionResourceActionList = {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
desc: string;
|
||||
appId: string;
|
||||
menus: {
|
||||
access: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
datas: {
|
||||
access: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
buttons: {
|
||||
access: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
apis: {
|
||||
access: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
others: {
|
||||
access: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 权限授权列表
|
||||
*/
|
||||
type AppPermissionPolicyList = {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
enabled: boolean;
|
||||
desc: string;
|
||||
appId: string;
|
||||
};
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { request } from '@@/exports';
|
||||
import {
|
||||
AppPermissionPolicyList,
|
||||
AppPermissionResourceActionList,
|
||||
AppPermissionResourceList,
|
||||
AppPermissionRoleList,
|
||||
GetApp,
|
||||
GetAppPermissionRole,
|
||||
} from './data.d';
|
||||
import { RequestData } from '@ant-design/pro-components';
|
||||
|
||||
/**
|
||||
* Get Application
|
||||
*/
|
||||
export async function getApp(id: string): Promise<API.ApiResult<GetApp>> {
|
||||
return request<API.ApiResult<GetApp>>(`/api/v1/app/get/${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Role list
|
||||
*/
|
||||
export async function getPermissionRoleList(
|
||||
params: Record<string, any>,
|
||||
): Promise<RequestData<AppPermissionRoleList>> {
|
||||
return request<API.ApiResult<AppPermissionRoleList>>('/api/v1/app/permission/role/list', {
|
||||
params,
|
||||
}).then((result) => {
|
||||
const data: RequestData<AppPermissionRoleList> = {
|
||||
data: result?.result?.list,
|
||||
success: result?.success,
|
||||
total: result?.result?.pagination ? result?.result?.pagination.total : 0,
|
||||
};
|
||||
return Promise.resolve(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Role
|
||||
*/
|
||||
export async function createPermissionRole(
|
||||
params: Record<string, any>,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request('/api/v1/app/permission/role/create', {
|
||||
data: params,
|
||||
method: 'POST',
|
||||
requestType: 'form',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Role
|
||||
*/
|
||||
export async function updatePermissionRole(
|
||||
params: Record<string, string>,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/update`, {
|
||||
data: params,
|
||||
method: 'PUT',
|
||||
requestType: 'form',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Role
|
||||
*/
|
||||
export async function enablePermissionRole(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/enable/${id}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Role
|
||||
*/
|
||||
export async function disableRole(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/disable/${id}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove role
|
||||
*/
|
||||
export async function deletePermissionRole(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/delete/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove role
|
||||
*/
|
||||
export async function batchDeletePermissionRole(
|
||||
ids: (number | string)[],
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/delete`, {
|
||||
params: { ids },
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Role details
|
||||
*/
|
||||
export async function getPermissionRole(id: string): Promise<API.ApiResult<GetAppPermissionRole>> {
|
||||
return request(`/api/v1/app/permission/role/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证角色信息
|
||||
*
|
||||
* @param appId
|
||||
* @param type
|
||||
* @param value
|
||||
* @param id
|
||||
*/
|
||||
export async function permissionRoleParamCheck(
|
||||
appId: string,
|
||||
type: string,
|
||||
value: string,
|
||||
id?: string,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/role/param_check`, {
|
||||
params: { appId, id, type, value },
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Resource list
|
||||
*/
|
||||
export async function getPermissionResourceList(
|
||||
params: Record<string, any>,
|
||||
): Promise<RequestData<AppPermissionResourceList>> {
|
||||
return request<API.ApiResult<AppPermissionResourceList>>('/api/v1/app/permission/resource/list', {
|
||||
params,
|
||||
}).then((result) => {
|
||||
const data: RequestData<AppPermissionResourceList> = {
|
||||
data: result?.result?.list,
|
||||
success: result?.success,
|
||||
total: result?.result?.pagination ? result?.result?.pagination.total : 0,
|
||||
};
|
||||
return Promise.resolve(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Permission Policy list
|
||||
*/
|
||||
export async function getPermissionPolicyList(
|
||||
params: Record<string, any>,
|
||||
): Promise<RequestData<AppPermissionPolicyList>> {
|
||||
return request<API.ApiResult<AppPermissionPolicyList>>('/api/v1/app/permission/policy/list', {
|
||||
params,
|
||||
}).then((result) => {
|
||||
const data: RequestData<AppPermissionPolicyList> = {
|
||||
data: result?.result?.list,
|
||||
success: result?.success,
|
||||
total: result?.result?.pagination ? result?.result?.pagination.total : 0,
|
||||
};
|
||||
return Promise.resolve(data);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Resource
|
||||
*/
|
||||
export async function getPermissionResource(
|
||||
id: string,
|
||||
): Promise<API.ApiResult<Record<string, any>>> {
|
||||
return request(`/api/v1/app/permission/resource/get/${id}`, {
|
||||
method: 'GET',
|
||||
requestType: 'json',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Permission action list
|
||||
*/
|
||||
export async function getPermissionActionList(
|
||||
params: Record<string, any>,
|
||||
): Promise<API.ApiResult<AppPermissionResourceActionList>> {
|
||||
return request(`/api/v1/app/permission/action/list`, {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Resource
|
||||
*/
|
||||
export async function createPermissionResource(
|
||||
params: Record<string, any>,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request('/api/v1/app/permission/resource/create', {
|
||||
data: params,
|
||||
method: 'POST',
|
||||
requestType: 'json',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Resource
|
||||
*/
|
||||
export async function deletePermissionResource(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/resource/delete/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Resource
|
||||
*/
|
||||
export async function updatePermissionResource(
|
||||
params: Record<string, string>,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/resource/update`, {
|
||||
data: params,
|
||||
method: 'PUT',
|
||||
requestType: 'json',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证资源信息
|
||||
*
|
||||
* @param appId
|
||||
* @param type
|
||||
* @param value
|
||||
* @param id
|
||||
*/
|
||||
export async function permissionResourceParamCheck(
|
||||
appId: string,
|
||||
type: string,
|
||||
value: string,
|
||||
id?: string,
|
||||
): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/resource/param_check`, {
|
||||
params: { appId, id, type, value },
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Resource
|
||||
*/
|
||||
export async function enableResource(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/resource/enable/${id}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Resource
|
||||
*/
|
||||
export async function disableResource(id: string): Promise<API.ApiResult<boolean>> {
|
||||
return request(`/api/v1/app/permission/resource/disable/${id}`, {
|
||||
method: 'PUT',
|
||||
});
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { history } from '@@/core/history';
|
||||
import { PageContainer, ProDescriptions, RouteContext } from '@ant-design/pro-components';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { App, Button, Skeleton } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import AccessPolicy from './components/AccessPolicy';
|
||||
import AppAccount from './components/AppAccount';
|
||||
import AppConfig from './components/AppConfig';
|
||||
import { ConfigTabs } from './constant';
|
||||
import AppProtocol from './components/AppProtocol';
|
||||
import queryString from 'query-string';
|
||||
import { useIntl, useLocation } from '@umijs/max';
|
||||
import { GetApp } from './data.d';
|
||||
import { getApp } from './service';
|
||||
import { ExclamationCircleFilled } from '@ant-design/icons';
|
||||
import { removeApp } from '@/services/app';
|
||||
|
||||
export default () => {
|
||||
const [tabActiveKey, setTabActiveKey] = useState<string>(ConfigTabs.app_config);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const location = useLocation();
|
||||
const intl = useIntl();
|
||||
const { message, modal } = App.useApp();
|
||||
const [app, setApp] = useState<GetApp>();
|
||||
const query = queryString.parse(location.search) as {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
protocol: string;
|
||||
};
|
||||
const { type, id } = query as {
|
||||
id: string;
|
||||
type: ConfigTabs;
|
||||
};
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
if (!id) {
|
||||
message.error(intl.formatMessage({ id: 'pages.app.config.detail.error' }));
|
||||
history.push('/app');
|
||||
return;
|
||||
}
|
||||
if (!type || !ConfigTabs[type]) {
|
||||
setTabActiveKey(ConfigTabs.app_config);
|
||||
history.replace({
|
||||
pathname: location.pathname,
|
||||
search: queryString.stringify({
|
||||
type: ConfigTabs.app_config,
|
||||
id,
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
setLoading(true);
|
||||
const { result, success } = await getApp(id).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
if (success && result) {
|
||||
setApp(result);
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
const description = (
|
||||
<RouteContext.Consumer>
|
||||
{({ isMobile }) =>
|
||||
loading ? (
|
||||
<Skeleton active paragraph={{ rows: 1 }} />
|
||||
) : (
|
||||
<ProDescriptions
|
||||
size="small"
|
||||
column={isMobile ? 1 : 2}
|
||||
dataSource={{ ...app }}
|
||||
style={{ marginBlockEnd: -16 }}
|
||||
>
|
||||
<ProDescriptions.Item
|
||||
dataIndex="type"
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.type' })}
|
||||
editable={false}
|
||||
valueEnum={{
|
||||
custom_made: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.config.type.value_enum.custom_made',
|
||||
}),
|
||||
},
|
||||
standard: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.config.type.value_enum.standard',
|
||||
}),
|
||||
},
|
||||
self_developed: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.config.type.value_enum.self_developed',
|
||||
}),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<ProDescriptions.Item
|
||||
dataIndex="enabled"
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.enabled' })}
|
||||
editable={false}
|
||||
valueEnum={{
|
||||
true: { text: intl.formatMessage({ id: 'app.normal' }), status: 'Success' },
|
||||
false: { text: intl.formatMessage({ id: 'app.disable' }), status: 'Error' },
|
||||
}}
|
||||
/>
|
||||
<ProDescriptions.Item
|
||||
dataIndex="clientId"
|
||||
ellipsis
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.client_id' })}
|
||||
valueType={'text'}
|
||||
editable={false}
|
||||
copyable={true}
|
||||
/>
|
||||
<ProDescriptions.Item
|
||||
dataIndex="clientSecret"
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.client_secret' })}
|
||||
valueType={'password'}
|
||||
editable={false}
|
||||
copyable={true}
|
||||
/>
|
||||
<ProDescriptions.Item
|
||||
dataIndex="createTime"
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.create_time' })}
|
||||
valueType={'dateTime'}
|
||||
copyable={false}
|
||||
editable={false}
|
||||
/>
|
||||
</ProDescriptions>
|
||||
)
|
||||
}
|
||||
</RouteContext.Consumer>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
title={loading ? <Skeleton.Input style={{ width: 50 }} active size={'small'} /> : app?.name}
|
||||
style={{ overflow: 'hidden' }}
|
||||
onBack={() => {
|
||||
history.push('/app');
|
||||
}}
|
||||
loading={loading}
|
||||
extra={[
|
||||
<Button
|
||||
key="delete"
|
||||
type="primary"
|
||||
danger
|
||||
onClick={() => {
|
||||
const confirmed = modal.error({
|
||||
centered: true,
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.extra.delete.confirm_title',
|
||||
}),
|
||||
icon: <ExclamationCircleFilled />,
|
||||
content: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.extra.delete.confirm_content',
|
||||
}),
|
||||
okText: intl.formatMessage({ id: 'app.confirm' }),
|
||||
okType: 'danger',
|
||||
okCancel: true,
|
||||
cancelText: intl.formatMessage({ id: 'app.cancel' }),
|
||||
onOk: async () => {
|
||||
const { success } = await removeApp(id);
|
||||
if (success) {
|
||||
message.success(intl.formatMessage({ id: 'app.operation_success' }));
|
||||
confirmed.destroy();
|
||||
}
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{intl.formatMessage({ id: 'pages.app.config.detail.extra.delete' })}
|
||||
</Button>,
|
||||
]}
|
||||
tabActiveKey={tabActiveKey}
|
||||
onTabChange={setTabActiveKey}
|
||||
tabList={[
|
||||
{
|
||||
key: ConfigTabs.app_config,
|
||||
tab: intl.formatMessage({ id: 'pages.app.config.detail.config' }),
|
||||
},
|
||||
{
|
||||
key: ConfigTabs.login_access,
|
||||
tab: intl.formatMessage({ id: 'pages.app.config.detail.items.login_access' }),
|
||||
},
|
||||
{
|
||||
key: ConfigTabs.app_account,
|
||||
tab: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.app_account',
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: ConfigTabs.access_policy,
|
||||
tab: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
content={description}
|
||||
>
|
||||
{app && (
|
||||
<>
|
||||
{/*基本信息*/}
|
||||
{ConfigTabs.app_config === tabActiveKey && <AppConfig app={app} />}
|
||||
{/*协议配置*/}
|
||||
{ConfigTabs.login_access === tabActiveKey && <AppProtocol appId={app?.id} />}
|
||||
{/*应用账户*/}
|
||||
{ConfigTabs.app_account === tabActiveKey && (
|
||||
<AppAccount appId={app?.id} protocol={app.protocol} />
|
||||
)}
|
||||
{/*访问策略*/}
|
||||
{ConfigTabs.access_policy === tabActiveKey && <AccessPolicy appId={app?.id} />}
|
||||
</>
|
||||
)}
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
|
@ -57,7 +57,7 @@ const CreateAppAccessPolicy = (props: {
|
|||
<>
|
||||
<ModalForm
|
||||
title={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy',
|
||||
})}
|
||||
width={600}
|
||||
open={open}
|
||||
|
@ -81,7 +81,7 @@ const CreateAppAccessPolicy = (props: {
|
|||
<ProFormRadio.Group
|
||||
name="subjectType"
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type',
|
||||
})}
|
||||
initialValue={AccessPolicyType.USER}
|
||||
fieldProps={{
|
||||
|
@ -94,19 +94,19 @@ const CreateAppAccessPolicy = (props: {
|
|||
{
|
||||
value: AccessPolicyType.USER,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.user',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: AccessPolicyType.USER_GROUP,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.user_group',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user_group',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: AccessPolicyType.ORGANIZATION,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.organization',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.organization',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
|
@ -114,7 +114,7 @@ const CreateAppAccessPolicy = (props: {
|
|||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
|
@ -127,21 +127,21 @@ const CreateAppAccessPolicy = (props: {
|
|||
<>
|
||||
<Form.Item
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user',
|
||||
})}
|
||||
name={'subjectIds'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<UserSelect
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.placeholder',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.placeholder',
|
||||
})}
|
||||
mode={'multiple'}
|
||||
/>
|
||||
|
@ -153,21 +153,21 @@ const CreateAppAccessPolicy = (props: {
|
|||
return (
|
||||
<Form.Item
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group',
|
||||
})}
|
||||
name={'subjectIds'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<UserGroupSelect
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group.rule.0.message',
|
||||
})}
|
||||
mode={'multiple'}
|
||||
/>
|
||||
|
@ -179,21 +179,21 @@ const CreateAppAccessPolicy = (props: {
|
|||
<>
|
||||
<Form.Item
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization',
|
||||
})}
|
||||
name={'subjectIds'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<OrgCascader
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message',
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
@ -216,7 +216,7 @@ export default (props: { appId: string }) => {
|
|||
const columns: ProColumns<AppAPI.AppAccessPolicyList>[] = [
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_name',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_name',
|
||||
}),
|
||||
dataIndex: 'subjectName',
|
||||
ellipsis: true,
|
||||
|
@ -224,7 +224,7 @@ export default (props: { appId: string }) => {
|
|||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type',
|
||||
}),
|
||||
dataIndex: 'subjectType',
|
||||
valueType: 'select',
|
||||
|
@ -232,24 +232,24 @@ export default (props: { appId: string }) => {
|
|||
valueEnum: {
|
||||
USER: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.user',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user',
|
||||
}),
|
||||
},
|
||||
USER_GROUP: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.user_group',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user_group',
|
||||
}),
|
||||
},
|
||||
ORGANIZATION: {
|
||||
text: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.subject_type.value_enum.organization',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.organization',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.create_time',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.create_time',
|
||||
}),
|
||||
align: 'center',
|
||||
ellipsis: true,
|
||||
|
@ -259,7 +259,7 @@ export default (props: { appId: string }) => {
|
|||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.option',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.option',
|
||||
}),
|
||||
valueType: 'option',
|
||||
key: 'option',
|
||||
|
@ -269,7 +269,7 @@ export default (props: { appId: string }) => {
|
|||
render: (text, record) => [
|
||||
<Popconfirm
|
||||
title={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.columns.option.popconfirm.title',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.columns.option.popconfirm.title',
|
||||
})}
|
||||
placement="bottomRight"
|
||||
icon={
|
||||
|
@ -299,7 +299,7 @@ export default (props: { appId: string }) => {
|
|||
}}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.cancel_policy',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.cancel_policy',
|
||||
})}
|
||||
</a>
|
||||
</Popconfirm>,
|
||||
|
@ -326,11 +326,6 @@ export default (props: { appId: string }) => {
|
|||
pagination={{
|
||||
defaultPageSize: 5,
|
||||
}}
|
||||
style={{
|
||||
height: 'calc(100vh - 178px)',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
cardProps={{ style: { minHeight: '100%' } }}
|
||||
dateFormatter="string"
|
||||
toolBarRender={() => [
|
||||
<Button
|
||||
|
@ -342,7 +337,7 @@ export default (props: { appId: string }) => {
|
|||
}}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.access_policy.create_policy',
|
||||
id: 'pages.app.config.detail.items.login_access.access_policy.create_policy',
|
||||
})}
|
||||
</Button>,
|
||||
]}
|
|
@ -21,13 +21,13 @@ import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
|||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ModalForm, ProFormText, ProTable } from '@ant-design/pro-components';
|
||||
|
||||
import { Alert, App, Button, Form, Popconfirm, Table } from 'antd';
|
||||
import { App, Button, Form, Popconfirm, Table } from 'antd';
|
||||
import { useRef } from 'react';
|
||||
import { AppProtocolType } from '@/constant';
|
||||
import { Base64 } from 'js-base64';
|
||||
import { useIntl } from '@umijs/max';
|
||||
|
||||
export default (props: { appId: string; protocol: AppProtocolType }) => {
|
||||
export default (props: { appId: string; protocol: AppProtocolType | string }) => {
|
||||
const actionRef = useRef<ActionType>();
|
||||
const intl = useIntl();
|
||||
const { message } = App.useApp();
|
||||
|
@ -35,7 +35,7 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
const columns: ProColumns<AppAPI.AppAccountList>[] = [
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.username',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.username',
|
||||
}),
|
||||
dataIndex: 'username',
|
||||
ellipsis: true,
|
||||
|
@ -43,14 +43,14 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.account',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.account',
|
||||
}),
|
||||
dataIndex: 'account',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.create_time',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.create_time',
|
||||
}),
|
||||
dataIndex: 'createTime',
|
||||
valueType: 'dateTime',
|
||||
|
@ -59,7 +59,7 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.option',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.option',
|
||||
}),
|
||||
valueType: 'option',
|
||||
key: 'option',
|
||||
|
@ -69,7 +69,7 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
render: (text, record) => [
|
||||
<Popconfirm
|
||||
title={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.option.popconfirm.title',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.option.popconfirm.title',
|
||||
})}
|
||||
placement="bottomRight"
|
||||
icon={
|
||||
|
@ -117,7 +117,7 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
<>
|
||||
<ModalForm
|
||||
title={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account',
|
||||
})}
|
||||
width={500}
|
||||
form={form}
|
||||
|
@ -125,7 +125,7 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
trigger={
|
||||
<Button key="button" icon={<PlusOutlined />} type="primary">
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account',
|
||||
})}
|
||||
</Button>
|
||||
}
|
||||
|
@ -155,21 +155,21 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
>
|
||||
<Form.Item
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.columns.username',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.columns.username',
|
||||
})}
|
||||
name={'userId'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.user_id.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.user_id.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<UserSelect
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.user_id.placeholder',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.user_id.placeholder',
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
@ -178,34 +178,34 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
<>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.account',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.account',
|
||||
})}
|
||||
name={'account'}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.account.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.account.rule.0.message',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.account.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.account.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText.Password
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.password',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.password',
|
||||
})}
|
||||
name={'password'}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.password.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.password.rule.0.message',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.password.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.password.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
|
@ -215,17 +215,17 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
//非Form协议
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.app_identity',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.app_identity',
|
||||
})}
|
||||
name={'account'}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.app_identity.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.app_identity.rule.0.message',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.create_app_account.modal_form.app_identity.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.app_identity.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
|
@ -237,14 +237,6 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
};
|
||||
return (
|
||||
<>
|
||||
<Alert
|
||||
banner
|
||||
type={'info'}
|
||||
message={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.app_account.alert.message',
|
||||
})}
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<ProTable<AppAPI.AppAccountList>
|
||||
columns={columns}
|
||||
actionRef={actionRef}
|
||||
|
@ -258,11 +250,6 @@ export default (props: { appId: string; protocol: AppProtocolType }) => {
|
|||
params={{ appId: appId }}
|
||||
rowKey="id"
|
||||
search={{}}
|
||||
style={{
|
||||
height: 'calc(100vh - 244px)',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
cardProps={{ style: { minHeight: '100%' } }}
|
||||
options={false}
|
||||
pagination={{
|
||||
defaultPageSize: 5,
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { getAllAppGroupList, updateApp } from '@/services/app';
|
||||
|
||||
import {
|
||||
ProCard,
|
||||
ProForm,
|
||||
ProFormItem,
|
||||
ProFormSelect,
|
||||
ProFormText,
|
||||
ProFormTextArea,
|
||||
} from '@ant-design/pro-components';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { App, Col, FormInstance, Row, Space, Upload, UploadFile, UploadProps } from 'antd';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { history, useIntl, useLocation } from '@umijs/max';
|
||||
import queryString from 'query-string';
|
||||
|
||||
import { GetApp } from '../../data.d';
|
||||
import { uploadFile } from '@/services/upload';
|
||||
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { RcFile, UploadChangeParam } from 'antd/es/upload';
|
||||
import { Container } from '@/components/Container';
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 12 },
|
||||
};
|
||||
const AppBasic = (props: { app: GetApp }) => {
|
||||
const { app } = props;
|
||||
const intl = useIntl();
|
||||
const form = useRef<FormInstance>();
|
||||
const location = useLocation();
|
||||
const useApp = App.useApp();
|
||||
const [iconUploadLoading, setIconUploadLoading] = useState<boolean>(false);
|
||||
const [icon, setIcon] = useState<string>();
|
||||
|
||||
const query = queryString.parse(location.search) as {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
protocol: string;
|
||||
};
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
form?.current?.setFieldsValue({
|
||||
...app,
|
||||
});
|
||||
setIcon(app?.icon);
|
||||
}, []);
|
||||
|
||||
const getBase64 = (img: RcFile, callback: (url: string) => void) => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => callback(reader.result as string));
|
||||
reader.readAsDataURL(img);
|
||||
};
|
||||
|
||||
const handleChange: UploadProps['onChange'] = (info: UploadChangeParam<UploadFile>) => {
|
||||
if (info.file.status === 'uploading') {
|
||||
setIconUploadLoading(true);
|
||||
return;
|
||||
}
|
||||
if (info.file.status === 'error') {
|
||||
setIconUploadLoading(false);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
getBase64(info.file.originFileObj as RcFile, (url) => {
|
||||
setIconUploadLoading(false);
|
||||
setIcon(url);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const uploadButton = (
|
||||
<div>
|
||||
{iconUploadLoading ? <LoadingOutlined /> : <PlusOutlined />}
|
||||
<div style={{ marginTop: 8 }}>{intl.formatMessage({ id: 'custom.upload' })}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<ProCard>
|
||||
<Container maxWidth={1152}>
|
||||
<ProForm
|
||||
layout="horizontal"
|
||||
formRef={form}
|
||||
{...formItemLayout}
|
||||
submitter={{
|
||||
render: (props, doms) => {
|
||||
return (
|
||||
<Row>
|
||||
<Col span={12} offset={6}>
|
||||
<Space>{doms}</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
},
|
||||
}}
|
||||
onFinish={async (params) => {
|
||||
const { success } = await updateApp(params);
|
||||
if (success) {
|
||||
useApp.message.success(intl.formatMessage({ id: 'app.operation_success' }));
|
||||
history.replace(
|
||||
`/app/detail?id=${query.id}&name=${params.name}&protocol=${query.protocol}&type=${query.type}`,
|
||||
);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
}}
|
||||
>
|
||||
<ProFormText name={'id'} hidden />
|
||||
<ProFormText
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.name' })}
|
||||
name={'name'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.config.name.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormItem
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.icon' })}
|
||||
extra={
|
||||
<div style={{ color: 'rgba(0, 0, 0, 0.45)' }}>
|
||||
<span>{intl.formatMessage({ id: 'pages.app.config.detail.config.icon.desc.1' })}</span>
|
||||
<br />
|
||||
<span>{intl.formatMessage({ id: 'pages.app.config.detail.config.icon.desc.2' })}</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Upload
|
||||
listType="picture-card"
|
||||
multiple={false}
|
||||
accept="image/png, image/jpeg"
|
||||
onChange={handleChange}
|
||||
showUploadList={false}
|
||||
customRequest={async ({ file, onProgress, onSuccess, onError }) => {
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
const result = await uploadFile(file, undefined, (ev) => {
|
||||
const percent = (ev.loaded / ev.total) * 100;
|
||||
// 计算出上传进度,调用组件进度条方法
|
||||
onProgress?.({ percent });
|
||||
});
|
||||
if (result.success && result.result) {
|
||||
onSuccess?.(result.result);
|
||||
return;
|
||||
}
|
||||
onError?.(new Error(result.message), result);
|
||||
useApp.message.error(result.message);
|
||||
}}
|
||||
>
|
||||
{icon ? <img src={icon} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
|
||||
</Upload>
|
||||
</ProFormItem>
|
||||
<ProFormSelect
|
||||
name="groupIds"
|
||||
mode="multiple"
|
||||
fieldProps={{
|
||||
maxTagCount: 'responsive',
|
||||
}}
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.group' })}
|
||||
request={async () => {
|
||||
const { success, data } = await getAllAppGroupList({}, {}, {});
|
||||
if (success && data) {
|
||||
return data.map((i) => {
|
||||
return { label: i.name, value: i.id };
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}}
|
||||
/>
|
||||
<ProFormTextArea
|
||||
label={intl.formatMessage({ id: 'pages.app.config.detail.config.remark' })}
|
||||
name={'remark'}
|
||||
fieldProps={{ rows: 2, maxLength: 200, showCount: false }}
|
||||
/>
|
||||
</ProForm>
|
||||
</Container>
|
||||
</ProCard>
|
||||
);
|
||||
};
|
||||
export default AppBasic;
|
|
@ -26,11 +26,9 @@ import FromConfig from './FromProtocolConfig';
|
|||
import JwtConfig from './JwtProtocolConfig';
|
||||
import OidcConfig from './OidcProtocolConfig';
|
||||
import { GetApp } from '../../data.d';
|
||||
import { useIntl } from '@@/exports';
|
||||
|
||||
export default (props: { appId: string }) => {
|
||||
const { appId } = props;
|
||||
const intl = useIntl();
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [app, setApp] = useState<GetApp>();
|
||||
useAsyncEffect(async () => {
|
||||
|
@ -52,12 +50,7 @@ export default (props: { appId: string }) => {
|
|||
return <Component app={app} />;
|
||||
};
|
||||
return (
|
||||
<ProCard
|
||||
title={intl.formatMessage({ id: 'pages.app.config.items.login_access.protocol_config' })}
|
||||
style={{ height: 'calc(100vh - 178px)', overflow: 'auto' }}
|
||||
bodyStyle={{ height: '100%' }}
|
||||
headerBordered
|
||||
>
|
||||
<ProCard>
|
||||
<Skeleton loading={loading} active={true} paragraph={{ rows: 5 }}>
|
||||
{app && ComponentByKey({ key: app?.protocol, app: app })}
|
||||
</Skeleton>
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { SsoScope } from '@/pages/app/AppConfig/constant';
|
||||
import { SsoScope } from '@/pages/app/AppDetail/constant';
|
||||
import { ProFormSelect } from '@ant-design/pro-components';
|
||||
import { useIntl } from '@@/exports';
|
||||
|
||||
|
@ -31,18 +31,18 @@ export default () => {
|
|||
return (
|
||||
<ProFormSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.common.authorization_type',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type',
|
||||
})}
|
||||
name={'authorizationType'}
|
||||
allowClear={false}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.common.authorization_type.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.common.authorization_type.rule.0.message',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
|
@ -50,13 +50,13 @@ export default () => {
|
|||
{
|
||||
value: SsoScope.AUTHORIZATION,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.common.authorization_type.option.0',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.option.0',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: SsoScope.ALL_ACCESS,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.common.authorization_type.option.1',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.option.1',
|
||||
}),
|
||||
},
|
||||
]}
|
|
@ -20,6 +20,17 @@ import { useAsyncEffect } from 'ahooks';
|
|||
import { Collapse, Form, Typography } from 'antd';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import Alert from '@/components/Alert';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { ColProps } from 'antd/es/grid/col';
|
||||
|
||||
const useStyles = createStyles(({ prefixCls }) => ({
|
||||
alert: {
|
||||
[`.${prefixCls}-alert-content .${prefixCls}-alert-description .${prefixCls}-form-item:last-child`]:
|
||||
{
|
||||
marginBottom: '0 !important',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
/**
|
||||
* 配置信息
|
||||
|
@ -30,10 +41,23 @@ export default (props: {
|
|||
appId: string;
|
||||
protocolEndpoint: Record<string, string>;
|
||||
collapsed?: boolean;
|
||||
labelCol?: ColProps;
|
||||
wrapperCol?: ColProps;
|
||||
}) => {
|
||||
const [configForm] = Form.useForm();
|
||||
const { protocolEndpoint, appId, collapsed = true } = props;
|
||||
const {
|
||||
protocolEndpoint,
|
||||
appId,
|
||||
collapsed = true,
|
||||
labelCol = {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol = {
|
||||
span: 12,
|
||||
},
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const { styles } = useStyles();
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
configForm.setFieldsValue(protocolEndpoint);
|
||||
|
@ -42,8 +66,8 @@ export default (props: {
|
|||
return (
|
||||
<ProForm
|
||||
layout={'horizontal'}
|
||||
labelCol={{ xs: { span: 24 }, sm: { span: 6 } }}
|
||||
wrapperCol={{ xs: { span: 24 }, sm: { span: 12 } }}
|
||||
labelCol={labelCol}
|
||||
wrapperCol={wrapperCol}
|
||||
labelAlign={'right'}
|
||||
submitter={false}
|
||||
labelWrap
|
||||
|
@ -59,22 +83,23 @@ export default (props: {
|
|||
label: (
|
||||
<a>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.form.config_about',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.config_about',
|
||||
})}
|
||||
</a>
|
||||
),
|
||||
children: (
|
||||
<Alert
|
||||
type={'grey'}
|
||||
className={styles.alert}
|
||||
description={
|
||||
<>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.form.config_about.idp_sso_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.config_about.idp_sso_endpoint',
|
||||
})}
|
||||
name={'idpSsoEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.form.config_about.idp_sso_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.config_about.idp_sso_endpoint.extra',
|
||||
})}
|
||||
readonly
|
||||
proFieldProps={{
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { getAppConfig, saveAppConfig } from '@/services/app';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { Alert, App, Divider, Form, Spin } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
EditableProTable,
|
||||
FooterToolbar,
|
||||
ProColumns,
|
||||
ProForm,
|
||||
ProFormDependency,
|
||||
ProFormRadio,
|
||||
ProFormSelect,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components';
|
||||
import { FormEncryptType } from '../../../constant';
|
||||
import { omit } from 'lodash';
|
||||
import ConfigAbout from './ConfigAbout';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { AuthorizationType } from '../CommonConfig';
|
||||
import { GetApp } from '../../../data.d';
|
||||
import { generateUUID } from '@/utils/utils';
|
||||
import { Container } from '@/components/Container';
|
||||
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 12,
|
||||
},
|
||||
};
|
||||
export default (props: { app: GetApp | Record<string, any> }) => {
|
||||
const { app } = props;
|
||||
const intl = useIntl();
|
||||
const { message } = App.useApp();
|
||||
const { id, template } = app;
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [otherFieldTableForm] = Form.useForm();
|
||||
const [otherFieldEditableKeys, setOtherFieldEditableKeys] = useState<React.Key[]>(() => []);
|
||||
const [protocolEndpoint, setProtocolEndpoint] = useState<Record<string, string>>({});
|
||||
|
||||
const getConfig = async () => {
|
||||
setLoading(true);
|
||||
const { result, success } = await getAppConfig(id);
|
||||
if (success && result) {
|
||||
form.setFieldsValue({ ...omit(result, 'protocolEndpoint', 'otherField'), appId: id });
|
||||
//设置Endpoint相关
|
||||
setProtocolEndpoint(result.protocolEndpoint);
|
||||
//其他字段
|
||||
if (result?.otherField) {
|
||||
const otherField = result?.otherField.map((i: Record<string, string>) => {
|
||||
return { key: generateUUID(), fieldValue: i.fieldValue, fieldName: i.fieldName };
|
||||
});
|
||||
form.setFieldsValue({ otherField: otherField });
|
||||
setOtherFieldEditableKeys(
|
||||
otherField.map((i: Record<string, string>) => {
|
||||
return i.key;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
await getConfig();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<Alert
|
||||
banner
|
||||
type={'info'}
|
||||
showIcon={true}
|
||||
message={
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'app.issue' })}
|
||||
{intl.formatMessage({ id: 'app.disposition' })}{' '}
|
||||
<a
|
||||
target={'_blank'}
|
||||
href={'https://eiam.topiam.cn/docs/application/form/overview'}
|
||||
rel="noreferrer"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form',
|
||||
})}
|
||||
</a>{' '}
|
||||
。
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<Container maxWidth={1152}>
|
||||
<ProForm
|
||||
form={form}
|
||||
requiredMark={true}
|
||||
layout={'horizontal'}
|
||||
{...layout}
|
||||
scrollToFirstError
|
||||
onFinish={async (values) => {
|
||||
const validate = await otherFieldTableForm.validateFields();
|
||||
setLoading(true);
|
||||
if (validate) {
|
||||
const { success } = await saveAppConfig({
|
||||
id,
|
||||
template,
|
||||
config: omit(values, 'id', 'template'),
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
if (success) {
|
||||
message.success(intl.formatMessage({ id: 'app.save_success' }));
|
||||
await getConfig();
|
||||
return true;
|
||||
}
|
||||
message.error(intl.formatMessage({ id: 'app.save_fail' }));
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
submitter={{
|
||||
render: (_, dom) => {
|
||||
return <FooterToolbar>{dom}</FooterToolbar>;
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ProFormText name={'appId'} hidden />
|
||||
<ProFormText
|
||||
name={'loginUrl'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.login_url',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.login_url.placeholder',
|
||||
})}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.login_url.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.login_url.rule.0.message',
|
||||
}),
|
||||
},
|
||||
{
|
||||
type: 'url',
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.login_url.rule.1.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
name={'usernameField'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_field',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_field.placeholder',
|
||||
})}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_field.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_field.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
name={'passwordField'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_field',
|
||||
})}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_field.placeholder',
|
||||
})}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_field.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_field.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_type',
|
||||
})}
|
||||
name={'passwordEncryptType'}
|
||||
options={[
|
||||
{ value: FormEncryptType.aes, label: 'AES' },
|
||||
{ value: FormEncryptType.base64, label: 'BASE64' },
|
||||
{ value: FormEncryptType.md5, label: 'MD5' },
|
||||
]}
|
||||
fieldProps={{ allowClear: true }}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_type.extra',
|
||||
})}
|
||||
/>
|
||||
<ProFormDependency name={['passwordEncryptType']}>
|
||||
{({ passwordEncryptType }) => {
|
||||
return passwordEncryptType === FormEncryptType.aes ? (
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key',
|
||||
})}
|
||||
name={'passwordEncryptKey'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}}
|
||||
</ProFormDependency>
|
||||
<ProFormSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_type',
|
||||
})}
|
||||
name={'usernameEncryptType'}
|
||||
options={[
|
||||
{ value: FormEncryptType.aes, label: 'AES' },
|
||||
{ value: FormEncryptType.base64, label: 'BASE64' },
|
||||
]}
|
||||
fieldProps={{ allowClear: true }}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_type.extra',
|
||||
})}
|
||||
/>
|
||||
<ProFormDependency name={['usernameEncryptType']}>
|
||||
{({ usernameEncryptType }) => {
|
||||
return usernameEncryptType === FormEncryptType.aes ? (
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key',
|
||||
})}
|
||||
name={'usernameEncryptKey'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}}
|
||||
</ProFormDependency>
|
||||
<ProFormRadio.Group
|
||||
name={'submitType'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.submit_type',
|
||||
})}
|
||||
initialValue={['post']}
|
||||
options={[
|
||||
{ value: 'post', label: 'POST' },
|
||||
{ value: 'get', label: 'GET' },
|
||||
]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.submit_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Divider />
|
||||
{/*授权类型*/}
|
||||
<AuthorizationType />
|
||||
<Divider />
|
||||
<ProForm.Item
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field',
|
||||
})}
|
||||
name="otherField"
|
||||
trigger="onValuesChange"
|
||||
>
|
||||
<EditableProTable
|
||||
rowKey={'key'}
|
||||
toolBarRender={false}
|
||||
scroll={{
|
||||
x: 500,
|
||||
}}
|
||||
columns={
|
||||
[
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_name',
|
||||
}),
|
||||
dataIndex: 'fieldName',
|
||||
fieldProps: {
|
||||
allowClear: false,
|
||||
},
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_name.rule.0',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_value',
|
||||
}),
|
||||
key: 'fieldValue',
|
||||
dataIndex: 'fieldValue',
|
||||
ellipsis: true,
|
||||
formItemProps: {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_value.rule.0',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.option',
|
||||
}),
|
||||
valueType: 'option',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
width: 50,
|
||||
},
|
||||
] as ProColumns[]
|
||||
}
|
||||
recordCreatorProps={{
|
||||
creatorButtonText: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.record_creator_props',
|
||||
}),
|
||||
newRecordType: 'dataSource',
|
||||
position: 'bottom',
|
||||
record: () => ({
|
||||
key: Date.now(),
|
||||
}),
|
||||
}}
|
||||
editable={{
|
||||
form: otherFieldTableForm,
|
||||
type: 'multiple',
|
||||
editableKeys: otherFieldEditableKeys,
|
||||
onChange: setOtherFieldEditableKeys,
|
||||
deletePopconfirmMessage: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.form.other_field.editable',
|
||||
}),
|
||||
actionRender: (row, _, dom) => {
|
||||
return [dom.delete];
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</ProForm.Item>
|
||||
</ProForm>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<ConfigAbout appId={id} protocolEndpoint={protocolEndpoint} collapsed={false} {...layout} />
|
||||
</Container>
|
||||
</Spin>
|
||||
);
|
||||
};
|
|
@ -20,12 +20,22 @@ import { useAsyncEffect } from 'ahooks';
|
|||
import { Collapse, Form, Typography } from 'antd';
|
||||
import { VerticalAlignBottomOutlined } from '@ant-design/icons';
|
||||
import { getCertList } from '@/services/app';
|
||||
import { CertUsingType } from '@/pages/app/AppConfig/constant';
|
||||
import { CertUsingType } from '@/pages/app/AppDetail/constant';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import Alert from '@/components/Alert';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { ColProps } from 'antd/es/grid/col';
|
||||
|
||||
const IDP_ENCRYPT_CERT = 'idpEncryptCert';
|
||||
|
||||
const useStyles = createStyles(({ prefixCls }) => ({
|
||||
alert: {
|
||||
[`.${prefixCls}-alert-content .${prefixCls}-alert-description .${prefixCls}-form-item:last-child`]:
|
||||
{
|
||||
marginBottom: '0 !important',
|
||||
},
|
||||
},
|
||||
}));
|
||||
/**
|
||||
* 配置信息
|
||||
*
|
||||
|
@ -35,17 +45,30 @@ export default (props: {
|
|||
appId: string;
|
||||
protocolEndpoint: Record<string, string>;
|
||||
collapsed?: boolean;
|
||||
labelCol?: ColProps;
|
||||
wrapperCol?: ColProps;
|
||||
}) => {
|
||||
const [configForm] = Form.useForm();
|
||||
const { protocolEndpoint, appId, collapsed = true } = props;
|
||||
const {
|
||||
protocolEndpoint,
|
||||
appId,
|
||||
collapsed = true,
|
||||
labelCol = {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol = {
|
||||
span: 12,
|
||||
},
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const { styles } = useStyles();
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
configForm.setFieldsValue(protocolEndpoint);
|
||||
}, [appId, protocolEndpoint]);
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
//获取SAML2签名证书
|
||||
//获取JWT签名证书
|
||||
const certResult = await getCertList(appId, CertUsingType.JWT_ENCRYPT);
|
||||
if (certResult.success && certResult.result) {
|
||||
certResult.result.forEach((value) => {
|
||||
|
@ -75,8 +98,8 @@ export default (props: {
|
|||
return (
|
||||
<ProForm
|
||||
layout={'horizontal'}
|
||||
labelCol={{ xs: { span: 24 }, sm: { span: 6 } }}
|
||||
wrapperCol={{ xs: { span: 24 }, sm: { span: 12 } }}
|
||||
labelCol={labelCol}
|
||||
wrapperCol={wrapperCol}
|
||||
labelAlign={'right'}
|
||||
labelWrap
|
||||
submitter={false}
|
||||
|
@ -92,22 +115,23 @@ export default (props: {
|
|||
label: (
|
||||
<a>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about',
|
||||
})}
|
||||
</a>
|
||||
),
|
||||
children: (
|
||||
<Alert
|
||||
type={'grey'}
|
||||
className={styles.alert}
|
||||
description={
|
||||
<>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint',
|
||||
})}
|
||||
name={'idpSsoEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint.extra',
|
||||
})}
|
||||
readonly
|
||||
proFieldProps={{
|
||||
|
@ -119,7 +143,7 @@ export default (props: {
|
|||
/>
|
||||
<ProFormTextArea
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert',
|
||||
})}
|
||||
name={IDP_ENCRYPT_CERT}
|
||||
disabled
|
||||
|
@ -128,7 +152,7 @@ export default (props: {
|
|||
<div style={{ display: 'inline-block' }}>
|
||||
<div style={{ display: 'inline-block' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.0',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.0',
|
||||
})}
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
|
@ -138,13 +162,13 @@ export default (props: {
|
|||
>
|
||||
<a>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.1',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.1',
|
||||
})}
|
||||
</a>
|
||||
</Typography.Paragraph>
|
||||
<a onClick={downloadEncryptCert}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.2',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.2',
|
||||
})}
|
||||
<VerticalAlignBottomOutlined />
|
||||
</a>
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { getAppConfig, saveAppConfig } from '@/services/app';
|
||||
import { useAsyncEffect } from 'ahooks';
|
||||
import { Alert, App, Divider, Form, Spin } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
FooterToolbar,
|
||||
ProForm,
|
||||
ProFormDigit,
|
||||
ProFormRadio,
|
||||
ProFormSelect,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components';
|
||||
import ConfigAbout from './ConfigAbout';
|
||||
import { omit } from 'lodash';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { AuthorizationType } from '../CommonConfig';
|
||||
import { GetApp } from '../../../data.d';
|
||||
import { Container } from '@/components/Container';
|
||||
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 12,
|
||||
},
|
||||
};
|
||||
export default (props: { app: GetApp | Record<string, any> }) => {
|
||||
const { app } = props;
|
||||
const { id, template } = app;
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [protocolEndpoint, setProtocolEndpoint] = useState<Record<string, string>>({});
|
||||
const intl = useIntl();
|
||||
const { message } = App.useApp();
|
||||
|
||||
const getConfig = async () => {
|
||||
setLoading(true);
|
||||
const { result, success } = await getAppConfig(id);
|
||||
if (success && result) {
|
||||
form.setFieldsValue({ ...omit(result, 'protocolEndpoint'), appId: id });
|
||||
//设置Endpoint相关
|
||||
setProtocolEndpoint(result.protocolEndpoint);
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
await getConfig();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<Alert
|
||||
showIcon={true}
|
||||
banner
|
||||
type={'info'}
|
||||
message={
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'app.issue' })}
|
||||
{intl.formatMessage({ id: 'app.disposition' })}{' '}
|
||||
<a
|
||||
target={'_blank'}
|
||||
href={'https://eiam.topiam.cn/docs/application/jwt/overview'}
|
||||
rel="noreferrer"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt',
|
||||
})}
|
||||
</a>{' '}
|
||||
。
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<Container maxWidth={1152}>
|
||||
<ProForm
|
||||
layout={'horizontal'}
|
||||
{...layout}
|
||||
form={form}
|
||||
scrollToFirstError
|
||||
onFinish={async (values) => {
|
||||
setLoading(true);
|
||||
const { success } = await saveAppConfig({
|
||||
id,
|
||||
template,
|
||||
config: omit(values, 'id', 'template'),
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
if (success) {
|
||||
message.success(intl.formatMessage({ id: 'app.save_success' }));
|
||||
await getConfig();
|
||||
return true;
|
||||
}
|
||||
message.error(intl.formatMessage({ id: 'app.save_fail' }));
|
||||
return false;
|
||||
}}
|
||||
submitter={{
|
||||
render: (_, dom) => {
|
||||
return <FooterToolbar>{dom}</FooterToolbar>;
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url',
|
||||
})}
|
||||
name={'redirectUrl'}
|
||||
fieldProps={{ allowClear: false }}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.rule.0.message',
|
||||
}),
|
||||
},
|
||||
{
|
||||
type: 'url',
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.rule.1.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
label={'target link url'}
|
||||
name={'targetLinkUrl'}
|
||||
fieldProps={{ allowClear: false }}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.target_link_url.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
type: 'url',
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.target_link_url.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<ProFormRadio.Group
|
||||
name={'bindingType'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type',
|
||||
})}
|
||||
initialValue={['post']}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type.extra',
|
||||
})}
|
||||
options={[
|
||||
{ value: 'post', label: 'POST' },
|
||||
{ value: 'get', label: 'GET' },
|
||||
]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type',
|
||||
})}
|
||||
name={'idTokenSubjectType'}
|
||||
options={[
|
||||
{
|
||||
value: 'user_id',
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.option.0',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: 'app_user',
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.option.1',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
fieldProps={{ allowClear: false }}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormDigit
|
||||
name={'idTokenTimeToLive'}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live',
|
||||
})}
|
||||
addonAfter={'秒'}
|
||||
max={84600}
|
||||
min={1}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Divider />
|
||||
{/*授权类型*/}
|
||||
<AuthorizationType />
|
||||
</ProForm>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<ConfigAbout
|
||||
appId={app.id}
|
||||
protocolEndpoint={protocolEndpoint}
|
||||
collapsed={false}
|
||||
{...layout}
|
||||
/>
|
||||
</Container>
|
||||
</Spin>
|
||||
);
|
||||
};
|
|
@ -20,7 +20,17 @@ import { useAsyncEffect } from 'ahooks';
|
|||
import { Collapse, Form, Typography } from 'antd';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import Alert from '@/components/Alert';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { ColProps } from 'antd/es/grid/col';
|
||||
|
||||
const useStyles = createStyles(({ prefixCls }) => ({
|
||||
alert: {
|
||||
[`.${prefixCls}-alert-content .${prefixCls}-alert-description .${prefixCls}-form-item:last-child`]:
|
||||
{
|
||||
marginBottom: '0 !important',
|
||||
},
|
||||
},
|
||||
}));
|
||||
/**
|
||||
* 配置信息
|
||||
*
|
||||
|
@ -30,10 +40,24 @@ export default (props: {
|
|||
appId: string;
|
||||
protocolEndpoint: Record<string, string>;
|
||||
collapsed?: boolean;
|
||||
labelCol?: ColProps;
|
||||
wrapperCol?: ColProps;
|
||||
}) => {
|
||||
const [configForm] = Form.useForm();
|
||||
const { protocolEndpoint, appId, collapsed = true } = props;
|
||||
const {
|
||||
protocolEndpoint,
|
||||
appId,
|
||||
collapsed = true,
|
||||
labelCol = {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol = {
|
||||
span: 12,
|
||||
},
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const { styles } = useStyles();
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
configForm.setFieldsValue(protocolEndpoint);
|
||||
}, [appId, protocolEndpoint]);
|
||||
|
@ -41,8 +65,8 @@ export default (props: {
|
|||
return (
|
||||
<ProForm
|
||||
layout={'horizontal'}
|
||||
labelCol={{ xs: { span: 24 }, sm: { span: 6 } }}
|
||||
wrapperCol={{ xs: { span: 24 }, sm: { span: 12 } }}
|
||||
labelCol={labelCol}
|
||||
wrapperCol={wrapperCol}
|
||||
labelAlign={'right'}
|
||||
submitter={false}
|
||||
labelWrap
|
||||
|
@ -58,20 +82,21 @@ export default (props: {
|
|||
label: (
|
||||
<a>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.config_about',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.config_about',
|
||||
})}
|
||||
</a>
|
||||
),
|
||||
children: (
|
||||
<Alert
|
||||
type={'grey'}
|
||||
className={styles.alert}
|
||||
description={
|
||||
<>
|
||||
<ProFormText
|
||||
label="Issuer"
|
||||
name={'issuer'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.config_about.issuer.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.config_about.issuer.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -83,11 +108,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.discovery_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.discovery_endpoint',
|
||||
})}
|
||||
name={'discoveryEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.discovery_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.discovery_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -99,11 +124,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.authorization_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.authorization_endpoint',
|
||||
})}
|
||||
name={'authorizationEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.authorization_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.authorization_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -115,11 +140,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.token_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.token_endpoint',
|
||||
})}
|
||||
name={'tokenEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.token_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.token_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -131,7 +156,7 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.revoke_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.revoke_endpoint',
|
||||
})}
|
||||
name={'revokeEndpoint'}
|
||||
proFieldProps={{
|
||||
|
@ -144,11 +169,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.jwks_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.jwks_endpoint',
|
||||
})}
|
||||
name={'jwksEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.jwks_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.jwks_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -160,11 +185,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.userinfo_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.userinfo_endpoint',
|
||||
})}
|
||||
name={'userinfoEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.userinfo_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.userinfo_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -176,11 +201,11 @@ export default (props: {
|
|||
/>
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.end_session_endpoint',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.end_session_endpoint',
|
||||
})}
|
||||
name={'endSessionEndpoint'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.items.login_access.protocol_config.oidc.end_session_endpoint.extra',
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.end_session_endpoint.extra',
|
||||
})}
|
||||
proFieldProps={{
|
||||
render: (value: string) => {
|
||||
|
@ -188,7 +213,9 @@ export default (props: {
|
|||
},
|
||||
}}
|
||||
readonly
|
||||
fieldProps={{ autoComplete: 'off' }}
|
||||
fieldProps={{
|
||||
autoComplete: 'off',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { SsoInitiator } from '@/pages/app/AppDetail/constant';
|
||||
import { getAppConfig, saveAppConfig } from '@/services/app';
|
||||
import {
|
||||
FooterToolbar,
|
||||
ProForm,
|
||||
ProFormCheckbox,
|
||||
ProFormDependency,
|
||||
ProFormDigit,
|
||||
ProFormSelect,
|
||||
ProFormSwitch,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components';
|
||||
import { useMount } from 'ahooks';
|
||||
import { Alert, App, Button, Collapse, Divider, Form, Input, Spin } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import ConfigAbout from './ConfigAbout';
|
||||
import { omit } from 'lodash';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { AuthorizationType } from '../CommonConfig';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { GetApp } from '../../../data.d';
|
||||
import { Container } from '@/components/Container';
|
||||
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 12,
|
||||
},
|
||||
};
|
||||
const formItemLayoutWithOutLabel = {
|
||||
wrapperCol: {
|
||||
span: 12,
|
||||
offset: 6,
|
||||
},
|
||||
};
|
||||
|
||||
const useStyle = createStyles(({ prefixCls, css }) => {
|
||||
return css`
|
||||
.${prefixCls}-checkbox-group-item {
|
||||
align-items: flex-start;
|
||||
}
|
||||
.${prefixCls}-checkbox {
|
||||
align-self: flex-start;
|
||||
top: 2px;
|
||||
}
|
||||
`;
|
||||
});
|
||||
|
||||
export default (props: { app: GetApp | Record<string, any> }) => {
|
||||
const intl = useIntl();
|
||||
const { styles } = useStyle();
|
||||
const { message } = App.useApp();
|
||||
const { app } = props;
|
||||
const { id, template } = app;
|
||||
const [form] = Form.useForm();
|
||||
const [protocolEndpoint, setProtocolEndpoint] = useState<Record<string, string>>({});
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
useMount(async () => {
|
||||
setLoading(true);
|
||||
const { result, success } = await getAppConfig(id);
|
||||
if (success && result) {
|
||||
form.setFieldsValue({
|
||||
appId: id,
|
||||
...result,
|
||||
});
|
||||
//设置Endpoint相关
|
||||
setProtocolEndpoint(result.protocolEndpoint);
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<Alert
|
||||
showIcon={true}
|
||||
banner
|
||||
type={'info'}
|
||||
message={
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'app.issue' })}
|
||||
{intl.formatMessage({ id: 'app.disposition' })}{' '}
|
||||
<a
|
||||
target={'_blank'}
|
||||
href={'https://eiam.topiam.cn/docs/application/oidc/overview'}
|
||||
rel="noreferrer"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc',
|
||||
})}
|
||||
</a>{' '}
|
||||
。
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<Container maxWidth={1152}>
|
||||
<ProForm
|
||||
className={styles}
|
||||
requiredMark={true}
|
||||
layout={'horizontal'}
|
||||
{...layout}
|
||||
form={form}
|
||||
scrollToFirstError
|
||||
onFinish={async (values) => {
|
||||
const { success } = await saveAppConfig({
|
||||
id,
|
||||
template,
|
||||
config: omit(values, 'id', 'template'),
|
||||
});
|
||||
if (success) {
|
||||
message.success(intl.formatMessage({ id: 'app.operation_success' }));
|
||||
return true;
|
||||
}
|
||||
message.success(intl.formatMessage({ id: 'app.operation_fail' }));
|
||||
return false;
|
||||
}}
|
||||
submitter={{
|
||||
render: (_, dom) => {
|
||||
return <FooterToolbar>{dom}</FooterToolbar>;
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ProFormText name={'appId'} hidden />
|
||||
<ProFormCheckbox.Group
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types',
|
||||
})}
|
||||
layout={'vertical'}
|
||||
name={'authGrantTypes'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
options={[
|
||||
{
|
||||
value: 'authorization_code',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.authorization_code.label.0',
|
||||
})}
|
||||
</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.authorization_code.label.1',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'refresh_token',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.refresh_token.label.0',
|
||||
})}
|
||||
</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.refresh_token.label.1',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'implicit',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.implicit.label.0',
|
||||
})}
|
||||
</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.implicit.label.1',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'password',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.password.label.0',
|
||||
})}
|
||||
</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.password.label.1',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormDependency name={['authGrantTypes']}>
|
||||
{({ authGrantTypes }) => {
|
||||
return (
|
||||
authGrantTypes?.includes('authorization_code') && (
|
||||
<ProFormSwitch
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.require_proof_key',
|
||||
})}
|
||||
name={'requireProofKey'}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.require_proof_key.extra',
|
||||
})}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</ProFormDependency>
|
||||
<Form.List
|
||||
name="redirectUris"
|
||||
rules={[
|
||||
{
|
||||
validator: async (_, value) => {
|
||||
if (value && value.length > 0) {
|
||||
return null;
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.rule.0.message',
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
{(fields, { add, remove }, { errors }) => (
|
||||
<>
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item
|
||||
{...(index === 0 ? layout : formItemLayoutWithOutLabel)}
|
||||
required={true}
|
||||
key={field.key}
|
||||
label={
|
||||
index === 0
|
||||
? intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris',
|
||||
})
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
{...field}
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.rule.0.message',
|
||||
}),
|
||||
},
|
||||
{
|
||||
type: 'url',
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.rule.1.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Input
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.placeholder',
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<DeleteOutlined onClick={() => remove(field.name)} />
|
||||
</div>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item
|
||||
{...(fields.length === 0 ? layout : formItemLayoutWithOutLabel)}
|
||||
required={true}
|
||||
label={
|
||||
fields.length === 0
|
||||
? intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris',
|
||||
})
|
||||
: ''
|
||||
}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.extra',
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
icon={<PlusOutlined />}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{intl.formatMessage({ id: 'app.add' })}
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
<Form.List name="postLogoutRedirectUris">
|
||||
{(fields, { add, remove }, {}) => (
|
||||
<>
|
||||
{fields.map((field, index) => {
|
||||
return (
|
||||
<Form.Item
|
||||
{...(index === 0 ? layout : formItemLayoutWithOutLabel)}
|
||||
key={field.key}
|
||||
label={
|
||||
index === 0
|
||||
? intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris',
|
||||
})
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
{...field}
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris',
|
||||
}),
|
||||
},
|
||||
{
|
||||
type: 'url',
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.rule.1.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
noStyle
|
||||
>
|
||||
<Input
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.placeholder',
|
||||
})}
|
||||
/>
|
||||
</Form.Item>
|
||||
<DeleteOutlined onClick={() => remove(field.name)} />
|
||||
</div>
|
||||
</Form.Item>
|
||||
);
|
||||
})}
|
||||
<Form.Item
|
||||
{...(fields.length === 0 ? layout : formItemLayoutWithOutLabel)}
|
||||
label={
|
||||
fields.length === 0
|
||||
? intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris',
|
||||
})
|
||||
: ''
|
||||
}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.extra',
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add()}
|
||||
icon={<PlusOutlined />}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{intl.formatMessage({ id: 'app.add' })}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
{/*授权类型*/}
|
||||
<AuthorizationType />
|
||||
<ProFormSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type',
|
||||
})}
|
||||
name={'initLoginType'}
|
||||
allowClear={false}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
options={[
|
||||
{
|
||||
value: SsoInitiator.APP,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.option.0',
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: SsoInitiator.PORTAL_OR_APP,
|
||||
label: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.option.1',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
extra={
|
||||
<>
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.extra.0',
|
||||
})}
|
||||
</span>
|
||||
<br />
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.extra.1',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<ProFormDependency name={['initLoginType']}>
|
||||
{(values) => {
|
||||
return (
|
||||
values?.initLoginType === SsoInitiator.PORTAL_OR_APP && (
|
||||
<ProFormText
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url',
|
||||
})}
|
||||
name={'initLoginUrl'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
fieldProps={{
|
||||
placeholder: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.field_props',
|
||||
}),
|
||||
}}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.extra',
|
||||
})}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}}
|
||||
</ProFormDependency>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<Collapse
|
||||
ghost
|
||||
expandIconPosition={'start'}
|
||||
defaultActiveKey={'advanced'}
|
||||
items={[
|
||||
{
|
||||
key: 'advanced',
|
||||
label: (
|
||||
<a>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced',
|
||||
})}
|
||||
</a>
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
<ProFormCheckbox.Group
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes',
|
||||
})}
|
||||
layout={'vertical'}
|
||||
name={'grantScopes'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.extra',
|
||||
})}
|
||||
options={[
|
||||
{
|
||||
value: 'openid',
|
||||
label: 'openid',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
value: 'email',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>email</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.1.label',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'phone',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>phone</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.2.label',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'profile',
|
||||
label: (
|
||||
<>
|
||||
<span style={{ marginRight: '12px' }}>profile</span>
|
||||
<span style={{ color: '#999' }}>
|
||||
{intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.3.label',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormDigit
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.access_token_time_to_live',
|
||||
})}
|
||||
name={'accessTokenTimeToLive'}
|
||||
addonAfter={intl.formatMessage({ id: 'app.minute' })}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.access_token_time_to_live.extra',
|
||||
})}
|
||||
/>
|
||||
<ProFormDigit
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.refresh_token_time_to_live',
|
||||
})}
|
||||
name={'refreshTokenTimeToLive'}
|
||||
addonAfter={intl.formatMessage({ id: 'app.minute' })}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.refresh_token_time_to_live.extra',
|
||||
})}
|
||||
/>
|
||||
<ProFormDigit
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_time_to_live',
|
||||
})}
|
||||
readonly
|
||||
name={'idTokenTimeToLive'}
|
||||
addonAfter={intl.formatMessage({ id: 'app.minute.not_update' })}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_time_to_live.extra',
|
||||
})}
|
||||
/>
|
||||
<ProFormSelect
|
||||
options={[
|
||||
{ value: 'ES256', label: 'ES256' },
|
||||
{ value: 'RS256', label: 'RS256' },
|
||||
]}
|
||||
label={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm',
|
||||
})}
|
||||
name={'idTokenSignatureAlgorithm'}
|
||||
allowClear={false}
|
||||
extra={intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm.extra',
|
||||
})}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage({
|
||||
id: 'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm.rule.0.message',
|
||||
}),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</ProForm>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
<ConfigAbout appId={id} protocolEndpoint={protocolEndpoint} collapsed={false} {...layout} />
|
||||
</Container>
|
||||
</Spin>
|
||||
);
|
||||
};
|
|
@ -19,22 +19,14 @@
|
|||
* ConfigTabs
|
||||
*/
|
||||
export enum ConfigTabs {
|
||||
//基本信息
|
||||
basic = 'basic',
|
||||
//应用配置
|
||||
app_config = 'app_config',
|
||||
//协议
|
||||
protocol_config = 'protocol_config',
|
||||
//账户同步
|
||||
account_sync = 'account_sync',
|
||||
//访问授权
|
||||
access_policy = 'access_policy',
|
||||
//登录访问
|
||||
login_access = 'login_access',
|
||||
//应用权限
|
||||
app_permission = 'app_permission',
|
||||
//资源管理
|
||||
permission_resource = 'permission_resource',
|
||||
//角色管理
|
||||
permission_role = 'permission_role',
|
||||
//应用账户
|
||||
app_account = 'app_account',
|
||||
}
|
||||
|
@ -63,7 +55,6 @@ export enum SsoScope {
|
|||
* 证书使用类型
|
||||
*/
|
||||
export enum CertUsingType {
|
||||
SAML_SIGN = 'saml_sign',
|
||||
JWT_ENCRYPT = 'jwt_encrypt',
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* 应用信息
|
||||
*/
|
||||
export type GetApp = {
|
||||
id: string;
|
||||
type: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
template: string;
|
||||
protocol: string;
|
||||
protocolName: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
//sso发起方
|
||||
initLoginType: string;
|
||||
//sso登录链接
|
||||
initLoginUrl: string;
|
||||
nameIdValueType: string;
|
||||
//授权范围
|
||||
authorizationType: string;
|
||||
enabled: boolean;
|
||||
remark: string;
|
||||
groupIds: string[];
|
||||
};
|
||||
|
|
@ -15,6 +15,6 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import AppBasic from './AppBasic';
|
||||
import AppDetail from './AppDetail';
|
||||
|
||||
export default AppBasic;
|
||||
export default AppDetail;
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
export default {
|
||||
'pages.app.config.detail.error': '未选择应用',
|
||||
'pages.app.config.detail.extra.delete': '删除应用',
|
||||
'pages.app.config.detail.extra.delete.confirm_title': '您确定要删除此应用?',
|
||||
'pages.app.config.detail.extra.delete.confirm_content': '此操作不可恢复,请谨慎操作!',
|
||||
'pages.app.config.detail.config': '应用配置',
|
||||
'pages.app.config.detail.config.name': '应用名称',
|
||||
'pages.app.config.detail.config.name.rule.0.message': '应用名称为必填项',
|
||||
'pages.app.config.detail.config.icon': '应用图标',
|
||||
'pages.app.config.detail.config.icon.rule.0.message': '应用图标为必填项',
|
||||
'pages.app.config.detail.config.icon.rule.1.message': '应用图标上传失败',
|
||||
'pages.app.config.detail.config.icon.desc.1': '必须为 PNG/JPG 格式',
|
||||
'pages.app.config.detail.config.icon.desc.2': '建议使用 256 * 256 像素方形图标',
|
||||
'pages.app.config.detail.config.enabled': '应用状态',
|
||||
'pages.app.config.detail.config.type': '应用类型',
|
||||
'pages.app.config.detail.config.group': '应用分组',
|
||||
'pages.app.config.detail.config.type.value_enum.custom_made': '定制应用',
|
||||
'pages.app.config.detail.config.type.value_enum.standard': '标准应用',
|
||||
'pages.app.config.detail.config.type.value_enum.self_developed': '自研应用',
|
||||
'pages.app.config.detail.config.protocol_name': '应用协议',
|
||||
'pages.app.config.detail.config.client_id': '客户端 ID',
|
||||
'pages.app.config.detail.config.client_secret': '客户端秘钥',
|
||||
'pages.app.config.detail.config.create_time': '创建时间',
|
||||
'pages.app.config.detail.config.remark': '备注',
|
||||
'pages.app.config.detail.items.login_access': '协议配置',
|
||||
'pages.app.config.detail.items.login_access.protocol_config': '单点登录',
|
||||
|
||||
'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type':
|
||||
'授权范围',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.extra':
|
||||
'若选择手动授权,需要在 访问授权 中进行权限分配。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.rule.0.message':
|
||||
'请选择授权范围',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.option.0':
|
||||
'手动授权',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.common.authorization_type.option.1':
|
||||
'全员可访问',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form': '表单代填单点登录',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.login_url': '登录提交URL',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.login_url.placeholder':
|
||||
'请输入登录提交URL',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.login_url.extra':
|
||||
'登录表单提交完整URL,以http://或https://开头,如:https://oa.xxxx.com/login',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.login_url.rule.0.message':
|
||||
'应用登录URL为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.login_url.rule.1.message':
|
||||
'URL格式不正确',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_field':
|
||||
'登录名属性名称',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_field.placeholder':
|
||||
'请输入登录名属性名称',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_field.extra':
|
||||
'username标签的name属性',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_field.rule.0.message':
|
||||
'登录名属性名称为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_field':
|
||||
'登录密码属性名称',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_field.placeholder':
|
||||
'请输入登录密码属性名称',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_field.extra':
|
||||
'password标签的name属性',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_field.rule.0.message':
|
||||
'登录密码属性名称为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_type':
|
||||
'登录密码加密算法',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_type.extra':
|
||||
'登录密码加密算法类型。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key':
|
||||
'登录密码加密秘钥',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key.extra':
|
||||
'登录密码加密秘钥。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.password_encrypt_key.rule.0.message':
|
||||
'登录密码加密秘钥为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_type':
|
||||
'用户名加密算法',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_type.extra':
|
||||
'用户名加密算法类型。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key':
|
||||
'用户名加密秘钥',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key.extra':
|
||||
'用户名加密秘钥。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.username_encrypt_key.rule.0.message':
|
||||
'用户名加密秘钥为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.submit_type': '登录提交方式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.submit_type.rule.0.message':
|
||||
'登录提交方式为必选项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field': '登录其他字段',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_name':
|
||||
'属性名称',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_name.rule.0':
|
||||
'此项为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_value':
|
||||
'属性值',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.field_value.rule.0':
|
||||
'此项为必填项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.columns.option':
|
||||
'操作',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.record_creator_props':
|
||||
'添加其他字段',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.other_field.editable':
|
||||
'您确定要删除此属性吗?',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.config_about': '应用配置信息',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.config_about.idp_sso_endpoint':
|
||||
'IdP SSO 地址',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.form.config_about.idp_sso_endpoint.extra':
|
||||
'应用发起单点登录的地址。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt': 'JWT单点登录',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url': 'SSO 地址',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.extra':
|
||||
'业务系统中的JWT SSO地址,在单点登录时本系统将向该地址发送id_token信息,参数名为id_token,业务系统通过id_token与Public Key可获取业务系统中的用户信息,如果在业务系统(SP)发起登录,请求SP登录地址时如果携带redirect_uri参数,系统会检验合法性,成功后会将浏览器重定向到该地址,并携带id_token身份令牌。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.rule.0.message':
|
||||
'请输入JWT应用SSO地址',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.redirect_url.rule.1.message':
|
||||
'JWT应用SSO地址格式不正确',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.target_link_url.extra':
|
||||
'业务系统中在JWT SSO成功后重定向的URL,一般用于跳转到二级菜单等,若设置了该URL,在JWT SSO时会以参数target_link_url优先传递该值,若未设置该值,此时若SSO中有请求参数target_link_url,则会按照请求参数传递该值。此项可选。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.target_link_url.rule.0.message':
|
||||
'地址格式不正确',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type': 'SSO 绑定类型',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type.extra':
|
||||
'指定向JWT应用发送 id_token 的请求方式。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.binding_type.rule.0.message':
|
||||
'登录提交方式为必选项',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type':
|
||||
'id_token 主体类型',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.option.0':
|
||||
'用户ID',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.option.1':
|
||||
'应用账户',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.extra':
|
||||
'id_token 中 sub 主体(用户) 类型',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_subject_type.rule.0.message':
|
||||
'请选择 CAS 用户标识',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live':
|
||||
'id_token 过期时间',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live.extra':
|
||||
'id_token 的有效期,单位为:秒。可设置范围为1-84600。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.idtoken_time_to_live.rule.0.message':
|
||||
'请配置 id_token 的有效期',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about': '应用配置信息',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint':
|
||||
'IdP SSO 地址',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_sso_endpoint.extra':
|
||||
'应用发起单点登录的地址。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_slo_endpoint':
|
||||
'登出端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_slo_endpoint.extra':
|
||||
'应用发起单点登出的地址。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert':
|
||||
'JWT 验签公钥',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.0':
|
||||
'下载或复制证书,并导入或粘贴到应用中。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.1':
|
||||
'复制证书内容',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.jwt.config_about.idp_encrypt_cert.extra.2':
|
||||
'下载证书 .cer 文件',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc': 'OIDC 单点登录',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types': '授权模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.rule.0.message':
|
||||
'请勾选授权模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.authorization_code.label.0':
|
||||
'授权码模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.authorization_code.label.1':
|
||||
' authorization_code 模式,用于账户的登录认证、授权。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.refresh_token.label.0':
|
||||
'令牌刷新模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.refresh_token.label.1':
|
||||
'refresh_token 模式,用于既有 token 的延期。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.implicit.label.0':
|
||||
'隐式模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.implicit.label.1':
|
||||
' implicit\n' +
|
||||
' 模式,由于协议本身的安全性,通常不推荐使用。如果有特殊需求,可以使用变体的' +
|
||||
' PKCE 的授权码模式。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.password.label.0':
|
||||
'密码模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.password.label.1':
|
||||
'password 模式,由于协议本身的安全性,通常不推荐使用。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.device.label.0':
|
||||
'设备模式',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.auth_grant_types.option.device.label.1':
|
||||
'device 模式,兼容设备发起的登录流程。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.require_proof_key':
|
||||
'PKCE(用于授权码模式)',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.require_proof_key.extra':
|
||||
'PKCE (Proof Key for Code Exchange)是 OAuth 2.0 的安全性扩展模式,用于防护 CSRF、中间人进攻等恶意攻击。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris':
|
||||
'登录 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.extra':
|
||||
'Redirect URI 白名单,应用在请求登录时携带 redirect_uri 参数,该值需要在白名单中,IAM 才会在认证完成后发起跳转。若有多条,请点击添加进行扩展',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.rule.0.message':
|
||||
'请配置登录 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.rule.1.message':
|
||||
'Redirect URI 格式不正确',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.redirect_uris.placeholder':
|
||||
'请输入登录 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris':
|
||||
'登出 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.extra':
|
||||
'登出 Redirect URI 白名单,应用在请求登录时携带 post_logout_redirect_uri 参数,该值需要在白名单中,IAM 才会在认证完成后发起跳转。若有多条,请点击添加进行扩展',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.rule.0.message':
|
||||
'请配置登出 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.rule.1.message':
|
||||
'登出 Redirect URI 格式不正确',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.post_logout_redirect_uris.placeholder':
|
||||
'请输入登出 Redirect URI',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type': 'SSO 发起方',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.rule.0.message':
|
||||
'请配置 SSO 发起方',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.option.0':
|
||||
'只允许应用发起',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.option.1':
|
||||
'支持门户和应用发起',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.extra.0':
|
||||
'门户发起:由 IAM 门户页点击进行 SSO 。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_type.extra.1':
|
||||
'应用发起:由应用登录主动发起。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url': '登录发起地址',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.rule.0.message':
|
||||
'登录发起地址不能为空',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.field_props':
|
||||
'请输入登录链接',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.init_login_url.extra':
|
||||
'若您希望由 TopIAM 门户页访问应用,请填写 TopIAM 发起 SSO 请求访问的应用地址。该地址接收到请求,应即刻转向 TopIAM / authorize 授权端点。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced': '显示高级配置',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes':
|
||||
'用户信息范围',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.rule.0.message':
|
||||
'请勾选用户信息范围',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.extra':
|
||||
'用户登录后,使用用户信息端点或解析 id_token 可以获取到的已登录用户信息 。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.1.label':
|
||||
'应用可获取登录用户邮箱信息。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.2.label':
|
||||
'应用可获取登录用户手机信息。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.grant_scopes.option.3.label':
|
||||
'应用可获取登录用户详情信息。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.access_token_time_to_live':
|
||||
'access_token 有效期',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.access_token_time_to_live.extra':
|
||||
'access_token 用于请求 IAM 接口,过期后需要使用 refresh_token 刷新,或重新登录。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.refresh_token_time_to_live':
|
||||
'refresh_token 有效期',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.refresh_token_time_to_live.extra':
|
||||
'用于获取新的 access_token 和 id_token,refresh_token 过期后,用户需要重新登录。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_time_to_live':
|
||||
'id_token 有效期',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_time_to_live.extra':
|
||||
'id_token 用于鉴别用户身份,JWT格式,允许应用使用公钥自行验证用户身份。最小5分钟,最大24小时,过期后需要使用refresh_token 刷新,或重新登录。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm':
|
||||
'id_token 签名算法',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm.extra':
|
||||
'id_token 签名使用的非对称算法。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.advanced.idtoken_signature_algorithm.rule.0.message':
|
||||
'请配置 id_token 签名算法',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.config_about': '应用配置信息',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.config_about.issuer.extra':
|
||||
'用于标识 token 发放来源的字段。同时是下述接口的 baseUrl。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.discovery_endpoint': '发现端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.discovery_endpoint.extra':
|
||||
'用于获取当前 IAM 支持的各端点信息和支持的模式、参数信息,可公开访问。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.authorization_endpoint':
|
||||
'授权端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.authorization_endpoint.extra':
|
||||
'应用发起单点登录的地址。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.token_endpoint': '令牌端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.token_endpoint.extra':
|
||||
'应用在单点登录过程中,拿到 code 后,从后端发起换取 token 的接口地址。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.revoke_endpoint': '令牌吊销端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.jwks_endpoint': '验签公钥端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.jwks_endpoint.extra':
|
||||
'用于验证 id_token、完成 SSO 流程的公钥端点。公钥可能会轮转。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.userinfo_endpoint':
|
||||
'用户信息端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.userinfo_endpoint.extra':
|
||||
'在账户登录后,使用 access_token 调用用户信息端点,获取账户基本信息。',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.end_session_endpoint':
|
||||
'结束会话端点',
|
||||
'pages.app.config.detail.items.login_access.protocol_config.oidc.end_session_endpoint.extra':
|
||||
'结束会话端点可用于触发单点注销。',
|
||||
'pages.app.config.detail.items.login_access.app_account': '应用账户',
|
||||
'pages.app.config.detail.items.login_access.app_account.columns.username': '系统用户',
|
||||
'pages.app.config.detail.items.login_access.app_account.columns.account': '应用账户',
|
||||
'pages.app.config.detail.items.login_access.app_account.columns.create_time': '添加时间',
|
||||
'pages.app.config.detail.items.login_access.app_account.columns.option': '操作',
|
||||
'pages.app.config.detail.items.login_access.app_account.columns.option.popconfirm.title':
|
||||
'您确定要删除此应用账户?',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account': '添加应用账户',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.user_id.rule.0.message':
|
||||
'请选择系统用户',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.user_id.placeholder':
|
||||
'请输入用户名、手机或邮箱搜索用户',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.account':
|
||||
'应用用户名',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.account.rule.0.message':
|
||||
'请输入账户访问应用时所使用户名',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.password':
|
||||
'应用用户密码',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.password.rule.0.message':
|
||||
'请输入账户访问应用时所使密码',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.app_identity':
|
||||
'应用身份',
|
||||
'pages.app.config.detail.items.login_access.app_account.create_app_account.modal_form.app_identity.rule.0.message':
|
||||
'请输入账户访问应用时所使身份',
|
||||
'pages.app.config.detail.items.login_access.access_policy': '访问授权',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.subject_name': '授权主体',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.subject_type': '主体类型',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user':
|
||||
'用户',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.user_group':
|
||||
'用户组',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.subject_type.value_enum.organization':
|
||||
'组织机构',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.create_time': '授权时间',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.option': '操作',
|
||||
'pages.app.config.detail.items.login_access.access_policy.columns.option.popconfirm.title':
|
||||
'您确定要取消主体授权?取消授权后不可自动恢复。',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy': '添加授权',
|
||||
'pages.app.config.detail.items.login_access.access_policy.cancel_policy': '取消授权',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type':
|
||||
'授权类型',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.rule.0.message':
|
||||
'请选择授权类型',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user':
|
||||
'授权用户',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.rule.0.message':
|
||||
'请选择授权用户',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user.placeholder':
|
||||
'请输入用户名搜索用户',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group':
|
||||
'授权分组',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_user_group.rule.0.message':
|
||||
'请选择授权分组',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization':
|
||||
'授权组织',
|
||||
'pages.app.config.detail.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message':
|
||||
'请选择组织节点',
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* eiam-console - Employee Identity and Access Management
|
||||
* Copyright © 2022-Present Jinan Yuanchuang Network Technology Co., Ltd. (support@topiam.cn)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { request } from '@@/exports';
|
||||
import {
|
||||
GetApp,
|
||||
} from './data.d';
|
||||
|
||||
/**
|
||||
* Get Application
|
||||
*/
|
||||
export async function getApp(id: string): Promise<API.ApiResult<GetApp>> {
|
||||
return request<API.ApiResult<GetApp>>(`/api/v1/app/get/${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue