diff --git a/eiam-common/src/main/java/cn/topiam/employee/common/entity/app/query/AppGroupQuery.java b/eiam-common/src/main/java/cn/topiam/employee/common/entity/app/query/AppGroupQuery.java index 74435300..4b8ecb6b 100644 --- a/eiam-common/src/main/java/cn/topiam/employee/common/entity/app/query/AppGroupQuery.java +++ b/eiam-common/src/main/java/cn/topiam/employee/common/entity/app/query/AppGroupQuery.java @@ -21,6 +21,8 @@ import java.io.Serializable; import org.springdoc.core.annotations.ParameterObject; +import cn.topiam.employee.common.enums.app.AppGroupType; + import lombok.Data; import io.swagger.v3.oas.annotations.Parameter; @@ -41,12 +43,18 @@ public class AppGroupQuery implements Serializable { * 分组名称 */ @Parameter(description = "分组名称") - private String name; + private String name; /** * 分组编码 */ @Parameter(description = "分组编码") - private String code; + private String code; + + /** + * 分组类型 + */ + @Parameter(description = "分组类型") + private AppGroupType type; } diff --git a/eiam-common/src/main/java/cn/topiam/employee/common/repository/app/impl/AppGroupRepositoryCustomizedImpl.java b/eiam-common/src/main/java/cn/topiam/employee/common/repository/app/impl/AppGroupRepositoryCustomizedImpl.java index 8de124b1..15637d1a 100644 --- a/eiam-common/src/main/java/cn/topiam/employee/common/repository/app/impl/AppGroupRepositoryCustomizedImpl.java +++ b/eiam-common/src/main/java/cn/topiam/employee/common/repository/app/impl/AppGroupRepositoryCustomizedImpl.java @@ -19,6 +19,7 @@ package cn.topiam.employee.common.repository.app.impl; import java.util.List; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -77,6 +78,11 @@ public class AppGroupRepositoryCustomizedImpl implements AppGroupRepositoryCusto builder.append(" AND `group`.code_ like '%").append(query.getCode()).append("%'"); } + //分组类型 + if (ObjectUtils.isNotEmpty(query.getType())) { + builder.append(" AND `group`.type_ like '%").append(query.getType().getCode()).append("%'"); + } + builder.append(" ORDER BY `group`.create_time DESC"); //@formatter:on String sql = builder.toString(); diff --git a/eiam-console/src/main/console-fe/config/routes.ts b/eiam-console/src/main/console-fe/config/routes.ts index a7c038f5..c5094337 100644 --- a/eiam-console/src/main/console-fe/config/routes.ts +++ b/eiam-console/src/main/console-fe/config/routes.ts @@ -134,26 +134,44 @@ export default [ }, ], }, - //应用列表 + //应用管理 { name: 'app', icon: 'AppstoreOutlined', path: '/app', - component: './app/AppList', - }, - //创建应用 - { - name: 'app.create', - path: '/app/create', - hideInMenu: true, - component: './app/AppCreate', - }, - //应用配置 - { - name: 'app.config', - path: '/app/config', - hideInMenu: true, - component: './app/AppConfig', + routes: [ + // 应用列表 + { + path: '/app', + redirect: '/app/list', + }, + // 应用列表 + { + name: 'list', + path: '/app/list', + component: './app/AppList', + }, + //创建应用 + { + name: 'create', + path: '/app/list/create', + hideInMenu: true, + component: './app/AppCreate', + }, + //应用配置 + { + name: 'config', + path: '/app/list/config', + hideInMenu: true, + component: './app/AppConfig', + }, + // 应用分组 + { + name: 'group', + path: '/app/group', + component: './app/AppGroup', + }, + ], }, //行为审计 { diff --git a/eiam-console/src/main/console-fe/package.json b/eiam-console/src/main/console-fe/package.json index 5c3e62bc..4ef36b8c 100644 --- a/eiam-console/src/main/console-fe/package.json +++ b/eiam-console/src/main/console-fe/package.json @@ -49,7 +49,7 @@ "@ant-design/maps": "^1.0.7", "@ant-design/pro-components": "^2.6.18", "ahooks": "^3.7.8", - "antd": "^5.8.6", + "antd": "^5.9.0", "antd-img-crop": "^4.12.2", "antd-style": "^3.4.5", "classnames": "^2.3.2", @@ -99,7 +99,7 @@ "@umijs/max": "^4.0.80", "cross-env": "^7.0.3", "cross-port-killer": "^1.4.0", - "eslint": "^8.48.0", + "eslint": "^8.49.0", "husky": "^8.0.3", "lint-staged": "^14.0.1", "prettier": "^3.0.3", diff --git a/eiam-console/src/main/console-fe/src/components/RightContent/index.tsx b/eiam-console/src/main/console-fe/src/components/RightContent/index.tsx index d969ffe3..8a9f6cb7 100644 --- a/eiam-console/src/main/console-fe/src/components/RightContent/index.tsx +++ b/eiam-console/src/main/console-fe/src/components/RightContent/index.tsx @@ -57,7 +57,7 @@ const GlobalHeaderRight: React.FC = () => { return (
- + diff --git a/eiam-console/src/main/console-fe/src/components/UserGroupSelect/UserGroupSelect.tsx b/eiam-console/src/main/console-fe/src/components/UserGroupSelect/UserGroupSelect.tsx index 2c07fdc3..90a1a634 100644 --- a/eiam-console/src/main/console-fe/src/components/UserGroupSelect/UserGroupSelect.tsx +++ b/eiam-console/src/main/console-fe/src/components/UserGroupSelect/UserGroupSelect.tsx @@ -18,7 +18,7 @@ import { getUserGroupList } from '@/services/account'; import type { SelectProps } from 'antd'; import { Select, Spin } from 'antd'; -import { ReactText, useState } from 'react'; +import { useState } from 'react'; import { useAsyncEffect } from 'ahooks'; import { SortOrder } from 'antd/es/table/interface'; import { RequestData } from '@ant-design/pro-components'; @@ -35,9 +35,9 @@ export type UserGroupSelectProps = Omit< >; async function getAllUserGroupList( - params?: Record, - sort?: Record, - filter?: Record, + params: Record, + sort: Record, + filter: Record, ): Promise> { let pageSize = 100, current = 1; @@ -79,7 +79,7 @@ const UserGroupSelect = (props: UserGroupSelectProps) => { useAsyncEffect(async () => { setFetching(true); - const { success, data } = await getAllUserGroupList().finally(() => { + const { success, data } = await getAllUserGroupList({}, {}, {}).finally(() => { setFetching(false); }); if (success && data) { diff --git a/eiam-console/src/main/console-fe/src/locales/zh-CN/menu.ts b/eiam-console/src/main/console-fe/src/locales/zh-CN/menu.ts index fbb062ec..c5c2b2e4 100644 --- a/eiam-console/src/main/console-fe/src/locales/zh-CN/menu.ts +++ b/eiam-console/src/main/console-fe/src/locales/zh-CN/menu.ts @@ -39,6 +39,8 @@ export default { 'menu.account.logout': '退出登录', 'menu.social-bind': '用户绑定', 'menu.app': '应用管理', + 'menu.app.list': '应用列表', + 'menu.app.group': '应用分组', 'menu.app.create': '创建应用', 'menu.app.config': '应用配置', 'menu.account': '账户管理', diff --git a/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceDetail/IdentitySourceDetail.tsx b/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceDetail/IdentitySourceDetail.tsx index 3f455900..c16294d8 100644 --- a/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceDetail/IdentitySourceDetail.tsx +++ b/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceDetail/IdentitySourceDetail.tsx @@ -81,7 +81,7 @@ export default () => { history.push(`/account/identity-source`); return; } - if (!type) { + if (!type || !IdentitySourceDetailTabs[type]) { setTabActiveKey(IdentitySourceDetailTabs.config); history.push({ pathname: location.pathname, diff --git a/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceList/components/CreateModal/CreateModal.tsx b/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceList/components/CreateModal/CreateModal.tsx index e728d9e2..0bad5845 100644 --- a/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceList/components/CreateModal/CreateModal.tsx +++ b/eiam-console/src/main/console-fe/src/pages/account/IdentitySourceList/components/CreateModal/CreateModal.tsx @@ -42,9 +42,9 @@ export default (props: CreateModelProps) => { wrapperCol={{ span: 19 }} onFinish={async (values: Record) => { setLoading(true); - const result = await onFinish(values); - setLoading(false); - return !!result; + await onFinish(values).finally(() => { + setLoading(false); + }); }} modalProps={{ destroyOnClose: true, diff --git a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/CreateOrganization/CreateOrganization.tsx b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/CreateOrganization/CreateOrganization.tsx index 23fc564c..5d5381ce 100644 --- a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/CreateOrganization/CreateOrganization.tsx +++ b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/CreateOrganization/CreateOrganization.tsx @@ -78,7 +78,7 @@ export default (props: CreateOrganizationFormProps { if (onCancel) { - await onCancel(); + onCancel(); } form.resetFields(); }; diff --git a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/Organization/UpdateModel.tsx b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/Organization/UpdateModel.tsx index 4001c414..bec422d9 100644 --- a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/Organization/UpdateModel.tsx +++ b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/Organization/UpdateModel.tsx @@ -78,9 +78,9 @@ const UpdateModel = (props: UpdateFormProps) => { open={visible} onFinish={async (values: AccountAPI.UpdateOrganization) => { setUpdateLoading(true); - const result = await onFinish(values); - setUpdateLoading(false); - return !!result; + await onFinish(values).finally(() => { + setUpdateLoading(false); + }); }} > diff --git a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/UpdateOrganization/UpdateOrganization.tsx b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/UpdateOrganization/UpdateOrganization.tsx index e0ae6160..454f9858 100644 --- a/eiam-console/src/main/console-fe/src/pages/account/UserList/components/UpdateOrganization/UpdateOrganization.tsx +++ b/eiam-console/src/main/console-fe/src/pages/account/UserList/components/UpdateOrganization/UpdateOrganization.tsx @@ -61,7 +61,7 @@ export default (props: UpdateOrganizationFormProps { if (onCancel) { - await onCancel(); + onCancel(); } form.resetFields(); }; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/AppConfig.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/AppConfig.tsx index f8b2faff..d83b5f6d 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/AppConfig.tsx +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/AppConfig.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ import { history } from '@@/core/history'; -import { DesktopOutlined, ProfileOutlined } from '@ant-design/icons'; +import { DesktopOutlined, ProfileOutlined, SafetyOutlined } from '@ant-design/icons'; import { GridContent, PageContainer } from '@ant-design/pro-components'; import { useAsyncEffect } from 'ahooks'; import type { MenuProps } from 'antd'; @@ -32,6 +32,8 @@ import { useIntl, useLocation } from '@umijs/max'; import useStyle from './style'; import classNames from 'classnames'; import { AppProtocolType } from '@/constant'; +import PermissionResource from './components/PermissionResource'; +import PermissionRole from './components/PermissionRole'; const prefixCls = 'app-config'; @@ -118,6 +120,27 @@ export default () => { }, ], }, + { + key: ConfigTabs.app_permission, + label: intl.formatMessage({ id: 'pages.app.config.items.app_permission' }), + icon: React.createElement(() => { + return ; + }), + children: [ + { + key: ConfigTabs.permission_resource, + label: intl.formatMessage({ + id: 'pages.app.config.items.app_permission.permission_resource', + }), + }, + { + key: ConfigTabs.permission_role, + label: intl.formatMessage({ + id: 'pages.app.config.items.app_permission.permission_role', + }), + }, + ], + }, ]; useAsyncEffect(async () => { @@ -126,12 +149,12 @@ export default () => { history.push('/app'); return; } - if (!type) { - setKeys([ConfigTabs.protocol_config]); + if (!type || !ConfigTabs[type]) { + setKeys([ConfigTabs.basic]); history.replace({ pathname: location.pathname, search: queryString.stringify({ - type: ConfigTabs.protocol_config, + type: ConfigTabs.basic, id, protocol, name, @@ -152,6 +175,8 @@ export default () => { [ConfigTabs.protocol_config]: AppProtocol, [ConfigTabs.app_account]: AppAccount, [ConfigTabs.access_policy]: AccessPolicy, + [ConfigTabs.permission_resource]: PermissionResource, + [ConfigTabs.permission_role]: PermissionRole, }; const Component = components[key]; return ; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/AppBasic.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/AppBasic.tsx index 1b1eb1ac..8ec26ef5 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/AppBasic.tsx +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/AppBasic.tsx @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { getApp, updateApp } from '@/services/app'; +import { updateApp } from '@/services/app'; import { ProCard, ProDescriptions } from '@ant-design/pro-components'; import { useAsyncEffect } from 'ahooks'; @@ -30,6 +30,7 @@ import classNames from 'classnames'; import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'; import { uploadFile } from '@/services/upload'; import { GetApp } from '@/pages/app/AppConfig/data'; +import { getApp } from '../../service'; const prefixCls = 'app-basic-info'; const AppBasic = (props: { appId: string }) => { diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/style.ts b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/style.ts index 2d6dee30..13f92e91 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/style.ts +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppBasic/style.ts @@ -23,6 +23,9 @@ const useStyle = createStyles(({ prefixCls, token }, props) => { return { main: { height: 'calc(100vh - 178px)', + [`${antCls}-pro-card-body`]: { + overflow: 'auto !important', + }, [`.${prefix}-descriptions`]: { [`${antCls}-descriptions-item-container ${antCls}-space-item`]: { span: { diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppProtocol/AppProtocol.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppProtocol/AppProtocol.tsx index a797b37a..8fb7a4b1 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppProtocol/AppProtocol.tsx +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/AppProtocol/AppProtocol.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ import { AppProtocolType } from '@/constant'; -import { getApp } from '@/services/app'; +import { getApp } from '../../service'; import { ProCard } from '@ant-design/pro-components'; import { useAsyncEffect } from 'ahooks'; @@ -25,7 +25,7 @@ import { useState } from 'react'; import FromConfig from './FromProtocolConfig'; import JwtConfig from './JwtProtocolConfig'; import OidcConfig from './OidcProtocolConfig'; -import { GetApp } from '../../data'; +import { GetApp } from '../../data.d'; import { useIntl } from '@@/exports'; export default (props: { appId: string }) => { diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionResource/UpdateModal.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionResource/UpdateModal.tsx new file mode 100644 index 00000000..6c711332 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionResource/UpdateModal.tsx @@ -0,0 +1,152 @@ +/* + * 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 . + */ +import { getPermissionResource, permissionResourceParamCheck } from '../../service'; +import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { Form, Spin } from 'antd'; +import React, { useState } from 'react'; +import { useAsyncEffect } from 'ahooks'; +import Paragraph from 'antd/es/typography/Paragraph'; + +type UpdateFormProps = { + /** + * ID + */ + id?: string; + /** + * SYSTEM + */ + appId: string; + /** + * 是否显示 + */ + open: boolean; + /** + * 取消方法 + */ + onCancel: (e?: React.MouseEvent | React.KeyboardEvent) => void; + /** + * 提交 + */ + onFinish?: (formData: Record) => Promise; +}; +const UpdateResource: React.FC = (props) => { + const { open, onCancel, onFinish, id, appId } = props; + const [loading, setLoading] = useState(false); + const [form] = Form.useForm(); + + useAsyncEffect(async () => { + if (open && id) { + setLoading(true); + const { success, result } = await getPermissionResource(id); + if (success && result) { + setLoading(false); + return; + } + } + }, [id, onCancel, open]); + + return ( + { + setLoading(true); + const result = await onFinish?.(values); + setLoading(false); + return result; + }} + > + + + + ); +}; +export default UpdateResource; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionRole/UpdateModel.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionRole/UpdateModel.tsx new file mode 100644 index 00000000..faaef7e9 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/components/PermissionRole/UpdateModel.tsx @@ -0,0 +1,149 @@ +/* + * 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 . + */ +import { getPermissionRole, permissionRoleParamCheck } from '../../service'; +import type { ProFormInstance } from '@ant-design/pro-components'; +import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { Spin } from 'antd'; +import React, { useRef, useState } from 'react'; +import { useAsyncEffect } from 'ahooks'; +import Paragraph from 'antd/es/typography/Paragraph'; + +type UpdateFormProps = { + /** + * ID + */ + id: string | undefined; + /** + * 是否显示 + */ + open: boolean; + /** + * 取消方法 + */ + onCancel: () => void; + /** + * 提交 + */ + onFinish?: (formData: Record) => Promise; +}; +const UpdateRole: React.FC = (props) => { + const { open, onCancel, onFinish, id } = props; + const [loading, setLoading] = useState(false); + const formRef = useRef(); + + useAsyncEffect(async () => { + if (open && id) { + setLoading(true); + const { success, result } = await getPermissionRole(id); + if (success && result) { + setLoading(false); + return; + } + } + }, [id, open]); + + return ( + { + setLoading(true); + const result = await onFinish?.(values); + setLoading(false); + return result; + }} + > + + + + ); +}; +export default UpdateRole; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/locales/zh-CN.ts b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/locales/zh-CN.ts index 6dfce6e3..ea83818f 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppConfig/locales/zh-CN.ts +++ b/eiam-console/src/main/console-fe/src/pages/app/AppConfig/locales/zh-CN.ts @@ -24,6 +24,7 @@ export default { 'pages.app.config.basic.icon.desc.2': '建议使用 256 * 256 像素方形图标', 'pages.app.config.basic.enabled': '应用状态', 'pages.app.config.basic.type': '应用类型', + 'pages.app.config.basic.group': '应用分组', 'pages.app.config.basic.type.value_enum.custom_made': '定制应用', 'pages.app.config.basic.type.value_enum.standard': '标准应用', 'pages.app.config.basic.type.value_enum.self_developed': '自研应用', @@ -591,6 +592,10 @@ export default { '授权组织', 'pages.app.config.items.login_access.access_policy.create_policy.modal_form.subject_type.auth_organization.rule.0.message': '请选择组织节点', + 'pages.app.config.items.app_permission': '权限管理', + 'pages.app.config.items.app_permission.permission_resource': '资源管理', + 'pages.app.config.items.app_permission.permission_role': '角色管理', + 'pages.app.config.items.app_permission.permission_audit': '权限审计', 'pages.app.config.items.account_sync': '账户同步', 'pages.app.config.error': '未指定应用', }; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppCreate/AppCreate.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppCreate/AppCreate.tsx index d04ea3b7..a2e044fc 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppCreate/AppCreate.tsx +++ b/eiam-console/src/main/console-fe/src/pages/app/AppCreate/AppCreate.tsx @@ -21,6 +21,7 @@ import { ModalForm, PageContainer, ProCard, + ProFormSelect, ProFormText, ProFormTextArea, ProList, @@ -38,6 +39,7 @@ import classnames from 'classnames'; import { ListTemplate } from './data.d'; import { AppType } from '@/constant'; import { createApp, getAppTemplateList } from './service'; +import { getAllAppGroupList } from '@/services/app'; const { Paragraph } = Typography; const prefixCls = 'topiam-create-app'; @@ -106,7 +108,7 @@ const CreateApp = (props: { onOk: () => { successModal.destroy(); history.push( - `/app/config?id=${result.id}&name=${values.name}&protocol=${protocol}`, + `/app/list/config?id=${result.id}&name=${values.name}&protocol=${protocol}`, ); }, }); @@ -128,6 +130,23 @@ const CreateApp = (props: { }, ]} /> + { + setLoading(true); + const { success, data } = await getAllAppGroupList({}, {}, {}).finally(() => { + setLoading(false); + }); + if (success && data) { + return data.map((i) => { + return { label: i.name, value: i.id }; + }); + } + return []; + }} + /> { ); }} /> - {createAppTemplate && ( - { - setCreateAppOpen(false); - setCreateAppTemplate(undefined); - }} - /> - )} + {createAppTemplate && ( + { + setCreateAppOpen(false); + setCreateAppTemplate(undefined); + }} + /> + )}
); }; -export default () => { - return ; -}; +export default AppCreate; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/AppGroup.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/AppGroup.tsx new file mode 100644 index 00000000..5def7cd0 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/AppGroup.tsx @@ -0,0 +1,221 @@ +/* + * 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 . + */ +import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'; +import type { ActionType, ProColumns } from '@ant-design/pro-components'; +import { PageContainer, ProTable } from '@ant-design/pro-components'; +import { App, Button, Popconfirm, Tag } from 'antd'; +import { useRef, useState } from 'react'; +import CreateModal from './components/CreateModal'; +import UpdateModal from './components/UpdateModal'; +import { createAppGroup, removeAppGroup, updateAppGroup } from './service'; +import { useIntl } from '@@/exports'; +import { getAppGroupList } from '@/services/app'; + +export default () => { + const intl = useIntl(); + const actionRef = useRef(); + const [createModalOpen, setCreateModalOpen] = useState(false); + const [updateModalOpen, setUpdateModalOpen] = useState(false); + const [id, setId] = useState(); + const { message } = App.useApp(); + const columns: ProColumns[] = [ + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.name' }), + dataIndex: 'name', + fixed: 'left', + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.code' }), + dataIndex: 'code', + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.app_count' }), + dataIndex: 'appCount', + search: false, + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.type' }), + dataIndex: 'type', + valueEnum: { + default: { + text: intl.formatMessage({ + id: 'pages.app_group.list.column.type.default', + }), + }, + custom: { + text: intl.formatMessage({ + id: 'pages.app_group.list.column.type.custom', + }), + }, + }, + render: (_, record) => ( + <> + {record.type === 'custom' && ( + + {intl.formatMessage({ + id: 'pages.app_group.list.column.type.custom', + })} + + )} + {record.type === 'default' && ( + + {intl.formatMessage({ + id: 'pages.app_group.list.column.type.default', + })} + + )} + + ), + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.create_time' }), + dataIndex: 'createTime', + search: false, + align: 'center', + ellipsis: true, + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.remark' }), + dataIndex: 'remark', + search: false, + ellipsis: true, + }, + { + title: intl.formatMessage({ id: 'pages.app_group.list.column.option' }), + valueType: 'option', + key: 'option', + width: 100, + align: 'center', + render: (text, record) => [ + { + setId(record.id); + setUpdateModalOpen(true); + }} + > + {intl.formatMessage({ id: 'app.update' })} + , + + } + onConfirm={async () => { + const { success } = await removeAppGroup(record.id); + if (success) { + message.success(intl.formatMessage({ id: 'app.operation_success' })); + actionRef.current?.reload(); + return; + } + }} + okText={intl.formatMessage({ id: 'app.yes' })} + cancelText={intl.formatMessage({ id: 'app.no' })} + key="delete" + > + + {intl.formatMessage({ id: 'app.delete' })} + + , + ], + }, + ]; + + return ( + + + columns={columns} + actionRef={actionRef} + request={getAppGroupList} + rowKey="id" + search={{ + labelWidth: 'auto', + }} + scroll={{ x: 900 }} + form={{ + syncToUrl: (values, type) => { + if (type === 'get') { + return { + ...values, + }; + } + return values; + }, + }} + pagination={{ + pageSize: 5, + }} + dateFormatter="string" + toolBarRender={() => [ + , + ]} + /> + { + setCreateModalOpen(false); + }} + onFinish={async (values) => { + const { result, success } = await createAppGroup(values); + if (success && result) { + message.success(intl.formatMessage({ id: 'app.create_success' })); + actionRef.current?.reload(); + } + actionRef.current?.reload(); + setCreateModalOpen(false); + return true; + }} + /> + {id && ( + { + setUpdateModalOpen(false); + }} + onFinish={async (values) => { + const { result, success } = await updateAppGroup(values); + if (success && result) { + message.success(intl.formatMessage({ id: 'app.create_success' })); + actionRef.current?.reload(); + } + actionRef.current?.reload(); + setUpdateModalOpen(false); + return true; + }} + /> + )} + + ); +}; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/components/UpdateModal/UpdateModal.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/components/UpdateModal/UpdateModal.tsx new file mode 100644 index 00000000..2b441811 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/components/UpdateModal/UpdateModal.tsx @@ -0,0 +1,105 @@ +/* + * 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 . + */ +import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { Form, Spin } from 'antd'; +import React, { useState } from 'react'; +import { useIntl } from '@@/exports'; +import { getAppGroup } from '@/pages/app/AppGroup/service'; + +export default (props: { + id: string; + open: boolean; + onFinish: (formData: Record) => Promise; + onCancel: (e: React.MouseEvent) => void; +}) => { + const { id, open, onCancel, onFinish } = props; + const [form] = Form.useForm(); + const intl = useIntl(); + const [loading, setLoading] = useState(false); + + return ( + { + if (visible) { + setLoading(true); + const { result, success } = await getAppGroup(id).finally(() => { + setLoading(false); + }); + if (success) { + form.setFieldsValue(result); + } + } + }} + onFinish={async (values) => { + setLoading(true); + await onFinish(values).finally(() => { + setLoading(false); + }); + }} + > + + + + ); +}; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/data.d.ts b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/data.d.ts new file mode 100644 index 00000000..90b20117 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/data.d.ts @@ -0,0 +1,17 @@ +/* + * 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 . + */ diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/index.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/index.tsx new file mode 100644 index 00000000..60e5a3df --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/index.tsx @@ -0,0 +1,19 @@ +/* + * 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 . + */ +import AppGroup from './AppGroup'; +export default AppGroup; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/locales/zh-CN.ts b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/locales/zh-CN.ts new file mode 100644 index 00000000..e0e8145e --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/locales/zh-CN.ts @@ -0,0 +1,40 @@ +/* + * 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 . + */ +export default { + 'pages.app_group.list.create': '创建分组', + 'pages.app_group.list.column.name': '分组名称', + 'pages.app_group.list.column.code': '分组编码', + 'pages.app_group.list.column.create_time': '创建时间', + 'pages.app_group.list.column.remark': '备注', + 'pages.app_group.list.column.app_count': '应用数量', + 'pages.app_group.list.column.type': '分组类型', + 'pages.app_group.list.column.type.default': '系统默认', + 'pages.app_group.list.column.type.custom': '自定义', + 'pages.app_group.list.column.option': '操作', + 'pages.app_group.list.actions.popconfirm.delete': '您确定要删除此应用分组?', + 'pages.app_group.create.modal_form.title': '添加分组', + 'pages.app_group.modal_form.name': '分组名称', + 'pages.app_group.modal_form.name.placeholder': '请输入分组名称', + 'pages.app_group.modal_form.name.rule.0.message': '分组名称为必填项', + 'pages.app_group.modal_form.code': '分组编码', + 'pages.app_group.modal_form.code.placeholder': '请输入分组编码', + 'pages.app_group.modal_form.code.rule.0.message': '分组编码为必填项', + 'pages.app_group.modal_form.remark': '备注', + 'pages.app_group.modal_form.remark.placeholder': '请输入备注', + 'pages.app_group.update.modal_form.title': '修改分组', +}; diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppGroup/service.ts b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/service.ts new file mode 100644 index 00000000..f17337f9 --- /dev/null +++ b/eiam-console/src/main/console-fe/src/pages/app/AppGroup/service.ts @@ -0,0 +1,62 @@ +/* + * 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 . + */ +import { request } from '@umijs/max'; + +/** + * 创建应用分组 + */ +export async function createAppGroup( + params: Record, +): Promise>> { + return request>>(`/api/v1/app/group/create`, { + method: 'POST', + data: params, + requestType: 'json', + }); +} + +/** + * 获取应用分组 + */ +export async function getAppGroup(id: string): Promise>> { + return request>>(`/api/v1/app/group/get/${id}`, { + method: 'GET', + }); +} + +/** + * 修改应用分组 + */ +export async function updateAppGroup( + params: Record, +): Promise>> { + return request>>(`/api/v1/app/group/update`, { + method: 'PUT', + data: params, + requestType: 'json', + }); +} + +/** + * Remove App Group + */ +export async function removeAppGroup(id: string): Promise> { + return request>(`/api/v1/app/group/delete/${id}`, { + method: 'DELETE', + }); +} diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppList/AppList.tsx b/eiam-console/src/main/console-fe/src/pages/app/AppList/AppList.tsx index 7ff32e36..e6f29f57 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppList/AppList.tsx +++ b/eiam-console/src/main/console-fe/src/pages/app/AppList/AppList.tsx @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { getAppList } from '@/services/app'; +import { getAllAppGroupList, getAppList } from '@/services/app'; import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'; import type { ActionType } from '@ant-design/pro-components'; import { PageContainer, ProList } from '@ant-design/pro-components'; @@ -86,7 +86,7 @@ export default () => { key={'create'} type="primary" onClick={() => { - history.push('/app/create'); + history.push('/app/list/create'); }} > @@ -102,7 +102,7 @@ export default () => { { history.push( - `/app/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`, + `/app/list/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`, ); }} > @@ -177,7 +177,7 @@ export default () => { key="config" onClick={() => { history.push( - `/app/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`, + `/app/list/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`, ); }} > @@ -213,6 +213,25 @@ export default () => { , ], }, + status: { + // 自己扩展的字段,主要用于筛选,不在列表中显示 + title: intl.formatMessage({ + id: 'pages.app.list.metas.group', + }), + valueType: 'select', + fieldProps: { + mode: 'multiple', + }, + request: async () => { + const { success, data } = await getAllAppGroupList({}, {}, {}); + if (success && data) { + return data.map((i) => { + return { label: i.name, value: i.id }; + }); + } + return []; + }, + }, }} /> diff --git a/eiam-console/src/main/console-fe/src/pages/app/AppList/locales/zh-CN.ts b/eiam-console/src/main/console-fe/src/pages/app/AppList/locales/zh-CN.ts index 2a35503b..716881dd 100644 --- a/eiam-console/src/main/console-fe/src/pages/app/AppList/locales/zh-CN.ts +++ b/eiam-console/src/main/console-fe/src/pages/app/AppList/locales/zh-CN.ts @@ -21,6 +21,7 @@ export default { 'pages.app.list.title': '应用列表', 'pages.app.list.tool_bar_render.add_app': '添加应用', 'pages.app.list.metas.title': '应用名称', + 'pages.app.list.metas.group': '应用分组', 'pages.app.list.actions.popconfirm.disable_app': '确定禁用该应用吗?', 'pages.app.list.actions.popconfirm.enable_app': '确定启用该应用吗?', 'pages.app.list.actions.popconfirm.delete_app': '您确定要删除此应用?', diff --git a/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/CreateModal/CreateModal.tsx b/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/CreateModal/CreateModal.tsx index 172f9344..7f628adf 100644 --- a/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/CreateModal/CreateModal.tsx +++ b/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/CreateModal/CreateModal.tsx @@ -83,9 +83,9 @@ export default (props: CreateDrawerProps) => { {...DRAWER_FORM_ITEM_LAYOUT} onFinish={async (values: Record) => { setLoading(true); - const result = await onFinish(values); - setLoading(false); - return !!result; + await onFinish(values).finally(() => { + setLoading(false); + }); }} > diff --git a/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/UpdateModal/UpdateModal.tsx b/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/UpdateModal/UpdateModal.tsx index edca24eb..ed211dac 100644 --- a/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/UpdateModal/UpdateModal.tsx +++ b/eiam-console/src/main/console-fe/src/pages/authn/IdentityProvider/components/UpdateModal/UpdateModal.tsx @@ -74,9 +74,9 @@ export default (props: CreateDrawerProps) => { scrollToFirstError onFinish={async (values: Record) => { setUpdateLoading(true); - const result = await onFinish(values); - setUpdateLoading(false); - return !!result; + await onFinish(values).finally(() => { + setUpdateLoading(false); + }); }} open={visible} > diff --git a/eiam-console/src/main/console-fe/src/pages/security/Setting/service.ts b/eiam-console/src/main/console-fe/src/pages/security/Setting/service.ts index c90331fc..d51aaccc 100644 --- a/eiam-console/src/main/console-fe/src/pages/security/Setting/service.ts +++ b/eiam-console/src/main/console-fe/src/pages/security/Setting/service.ts @@ -16,13 +16,12 @@ * along with this program. If not, see . */ import { request } from '@umijs/max'; +import { BasicSettingConfig, SecurityDefensePolicyConfig } from './data.d'; /** * 获取基础配置 */ -export async function getBasicSettingConfig(): Promise< - API.ApiResult -> { +export async function getBasicSettingConfig(): Promise> { return request('/api/v1/setting/security/basic/config'); } @@ -30,7 +29,7 @@ export async function getBasicSettingConfig(): Promise< * 保存基础配置 */ export async function saveBasicSettingConfig( - params: Record, + params: BasicSettingConfig, ): Promise> { return request('/api/v1/setting/security/basic/save', { method: 'POST', @@ -43,7 +42,7 @@ export async function saveBasicSettingConfig( * 获取内容安全策略配置 */ export async function getSecurityDefensePolicyConfig(): Promise< - API.ApiResult + API.ApiResult > { return request('/api/v1/setting/security/defense_policy/config'); } @@ -52,7 +51,7 @@ export async function getSecurityDefensePolicyConfig(): Promise< * 保存内容安全策略配置 */ export async function saveSecurityDefensePolicyConfig( - params: Record, + params: SecurityDefensePolicyConfig, ): Promise> { return request('/api/v1/setting/security/defense_policy/save', { method: 'POST', diff --git a/eiam-console/src/main/console-fe/src/pages/setting/Message/service.ts b/eiam-console/src/main/console-fe/src/pages/setting/Message/service.ts index b1f0aa08..937aa37b 100644 --- a/eiam-console/src/main/console-fe/src/pages/setting/Message/service.ts +++ b/eiam-console/src/main/console-fe/src/pages/setting/Message/service.ts @@ -24,7 +24,7 @@ import { EmailTemplateList, GetEmailTemplate, SmsTemplateList } from './data.d'; * @param params */ export async function getMailTemplateList( - params?: Record, + params: Record, ): Promise> { return request('/api/v1/setting/mail_template/list', { params }); } diff --git a/eiam-console/src/main/console-fe/src/pages/setting/Storage/components/AliCloud/index.tsx b/eiam-console/src/main/console-fe/src/pages/setting/Storage/components/AliCloud/index.tsx index 52e27fa4..8ab270e2 100644 --- a/eiam-console/src/main/console-fe/src/pages/setting/Storage/components/AliCloud/index.tsx +++ b/eiam-console/src/main/console-fe/src/pages/setting/Storage/components/AliCloud/index.tsx @@ -26,16 +26,16 @@ export default () => { , - sort?: Record, - filter?: Record, + sort: Record, + filter: Record, ): Promise> { return request>('/api/v1/user/list', { params: { ...params, ...sortParamConverter(sort), ...filterParamConverter(filter) }, @@ -170,8 +170,8 @@ export async function batchGetUser(ids: string[]): Promise, - sort?: Record, - filter?: Record, + sort: Record, + filter: Record, ): Promise> { return request>('/api/v1/user/login_audit/list', { method: 'GET', @@ -353,8 +353,8 @@ export async function getUserListNotInGroup( */ export async function getUserGroupList( params: Record, - sort?: Record, - filter?: Record, + sort: Record, + filter: Record, ): Promise> { return request>('/api/v1/user_group/list', { params: { ...params, ...sortParamConverter(sort), ...filterParamConverter(filter) }, @@ -433,8 +433,8 @@ export async function removeUserGroupMember( */ export async function getUserGroupMemberList( params: Record, - sort?: Record, - filter?: Record, + sort: Record, + filter: Record, ): Promise> { return request>( `/api/v1/user_group/${params.id}/member_list`, diff --git a/eiam-console/src/main/console-fe/src/services/app.ts b/eiam-console/src/main/console-fe/src/services/app.ts index f96d967b..5c36ded2 100644 --- a/eiam-console/src/main/console-fe/src/services/app.ts +++ b/eiam-console/src/main/console-fe/src/services/app.ts @@ -19,15 +19,14 @@ import { download, filterParamConverter, sortParamConverter } from '@/utils/util import type { RequestData } from '@ant-design/pro-components'; import type { SortOrder } from 'antd/es/table/interface'; import { request } from '@umijs/max'; -import type { UploadFile } from 'antd/es/upload/interface'; /** * 获取应用列表 */ export async function getAppList( - params?: Record, - sort?: Record, - filter?: Record, + params: Record, + sort: Record, + filter: Record, ): Promise> { return request>('/api/v1/app/list', { params: { ...params, ...sortParamConverter(sort), ...filterParamConverter(filter) }, @@ -192,32 +191,61 @@ export async function removeAppAccessPolicy(id: string): Promise>> { - return request(`/api/v1/app/saml2/parse/metadata_url`, { - method: 'POST', - params: { metadataUrl }, - }).catch(({ response: { data } }) => { - return data; +export async function getAppGroupList( + params: Record, + sort: Record, + filter: Record, +): Promise> { + return request>('/api/v1/app/group/list', { + params: { ...params, ...sortParamConverter(sort), ...filterParamConverter(filter) }, + }).then((result: API.ApiResult) => { + const data: RequestData = { + data: result?.result?.list ? result?.result?.list : [], + success: result?.success, + total: result?.result?.pagination ? result?.result?.pagination.total : 0, + totalPages: result?.result?.pagination?.totalPages, + }; + return Promise.resolve(data); }); } -/** - * parse Saml2 MetadataFile - */ -export async function parseSaml2MetadataFile( - file: UploadFile, -): Promise>> { - return request(`/api/v1/app/saml2/parse/metadata_file`, { - method: 'POST', - data: { file: file.originFileObj }, - headers: { - 'content-type': 'multipart/form-data', - }, - }).catch(({ response: { data } }) => { - return data; - }); +export async function getAllAppGroupList( + params: Record, + sort: Record, + filter: Record, +): Promise> { + let pageSize = 100, + current = 1; + // 存储所有数据的数组 + let result: RequestData = { + data: [], + success: false, + total: undefined, + }; + + while (true) { + // 调用分页接口 + const { success, data, total } = await getAppGroupList( + { current, pageSize, ...params }, + sort, + filter, + ); + if (success && data) { + // 如果当前页没有数据,表示已经加载完全部数据,退出循环 + if (data?.length === 0) { + break; + } + result = { data: result.data?.concat(data), success: success, total: total }; + // 增加当前页码 + if (total && total <= pageSize * current) { + break; + } else { + current = current + 1; + } + } + } + + return result; } diff --git a/eiam-console/src/main/console-fe/src/services/typings.d.ts b/eiam-console/src/main/console-fe/src/services/typings.d.ts index 7e4300f5..6f10be60 100644 --- a/eiam-console/src/main/console-fe/src/services/typings.d.ts +++ b/eiam-console/src/main/console-fe/src/services/typings.d.ts @@ -422,4 +422,13 @@ declare namespace AppAPI { template: string; remark: string; }; + + export type AppGroupList = { + id: string; + name: string; + code: string; + type: string; + appCount: string; + remark: string; + }; } diff --git a/eiam-console/src/main/console-fe/src/utils/utils.ts b/eiam-console/src/main/console-fe/src/utils/utils.ts index 3d15540b..520356c1 100644 --- a/eiam-console/src/main/console-fe/src/utils/utils.ts +++ b/eiam-console/src/main/console-fe/src/utils/utils.ts @@ -18,7 +18,6 @@ import type { SortOrder } from 'antd/es/table/interface'; import yaml from 'js-yaml'; import { parse } from 'querystring'; -import type { ReactText } from 'react'; import { history, matchPath } from '@umijs/max'; import YAML from 'yaml'; import { PhoneNumber } from 'google-libphonenumber'; @@ -106,7 +105,7 @@ export const sortParamConverter = (value: Record | undefined) * * @param value */ -export const filterParamConverter = (value: Record | undefined) => { +export const filterParamConverter = (value: Record) => { const param: Record = {}; if (value) Object.entries(value).forEach(([key], index) => { diff --git a/eiam-console/src/main/java/cn/topiam/employee/console/listener/ConsoleAuthenticationFailureEventListener.java b/eiam-console/src/main/java/cn/topiam/employee/console/listener/ConsoleAuthenticationFailureEventListener.java index 9711aaaa..e1604783 100644 --- a/eiam-console/src/main/java/cn/topiam/employee/console/listener/ConsoleAuthenticationFailureEventListener.java +++ b/eiam-console/src/main/java/cn/topiam/employee/console/listener/ConsoleAuthenticationFailureEventListener.java @@ -33,9 +33,9 @@ import cn.topiam.employee.audit.event.type.EventType; import cn.topiam.employee.common.entity.setting.AdministratorEntity; import cn.topiam.employee.common.repository.setting.AdministratorRepository; import cn.topiam.employee.support.context.ApplicationContextHelp; -import cn.topiam.employee.support.security.userdetails.UserDetails; import cn.topiam.employee.support.security.userdetails.UserType; import static cn.topiam.employee.core.security.util.SecurityUtils.getFailureMessage; +import static cn.topiam.employee.support.security.util.SecurityUtils.getPrincipal; /** * 认证失败 @@ -59,13 +59,7 @@ public class ConsoleAuthenticationFailureEventListener implements AuditEventPublish publish = ApplicationContextHelp.getBean(AuditEventPublish.class); String content = getFailureMessage(event); logger.error("认证失败 [{}]",content); - String principal = (String) event.getAuthentication().getPrincipal(); - if (event.getAuthentication().getPrincipal() instanceof String){ - principal = (String) event.getAuthentication().getPrincipal(); - } - if (event.getAuthentication().getPrincipal() instanceof UserDetails || event.getAuthentication().getPrincipal() instanceof org.springframework.security.core.userdetails.UserDetails){ - principal = ((UserDetails) event.getAuthentication().getPrincipal()).getUsername(); - } + String principal = getPrincipal(event); if (StringUtils.isNotBlank(principal)){ Optional optional = getAdministratorRepository().findByUsername(principal); if (optional.isEmpty()) { diff --git a/eiam-console/src/main/java/cn/topiam/employee/console/pojo/result/app/AppGroupListResult.java b/eiam-console/src/main/java/cn/topiam/employee/console/pojo/result/app/AppGroupListResult.java index 3471caef..e60310c5 100644 --- a/eiam-console/src/main/java/cn/topiam/employee/console/pojo/result/app/AppGroupListResult.java +++ b/eiam-console/src/main/java/cn/topiam/employee/console/pojo/result/app/AppGroupListResult.java @@ -55,6 +55,12 @@ public class AppGroupListResult implements Serializable { @Parameter(description = "分组编码") private String code; + /** + * 应用数量 + */ + @Parameter(description = "应用数量") + private Integer appCount; + /** * 分组类型 */ diff --git a/eiam-portal/src/main/java/cn/topiam/employee/portal/listener/PortalAuthenticationFailureEventListener.java b/eiam-portal/src/main/java/cn/topiam/employee/portal/listener/PortalAuthenticationFailureEventListener.java index c8a053e9..d6e13615 100644 --- a/eiam-portal/src/main/java/cn/topiam/employee/portal/listener/PortalAuthenticationFailureEventListener.java +++ b/eiam-portal/src/main/java/cn/topiam/employee/portal/listener/PortalAuthenticationFailureEventListener.java @@ -38,11 +38,11 @@ import cn.topiam.employee.common.enums.UserStatus; import cn.topiam.employee.common.repository.account.UserRepository; import cn.topiam.employee.core.help.SettingHelp; import cn.topiam.employee.support.context.ApplicationContextHelp; -import cn.topiam.employee.support.security.userdetails.UserDetails; import cn.topiam.employee.support.util.PhoneNumberUtils; import static cn.topiam.employee.core.help.SettingHelp.getLoginFailureDuration; import static cn.topiam.employee.core.security.util.SecurityUtils.getFailureMessage; import static cn.topiam.employee.support.security.userdetails.UserType.USER; +import static cn.topiam.employee.support.security.util.SecurityUtils.getPrincipal; /** * 认证失败 @@ -67,13 +67,7 @@ public class PortalAuthenticationFailureEventListener implements AuditEventPublish publish = ApplicationContextHelp.getBean(AuditEventPublish.class); String content = getFailureMessage(event); logger.error("认证失败", event.getException()); - String principal = null; - if (event.getAuthentication().getPrincipal() instanceof String) { - principal = (String) event.getAuthentication().getPrincipal(); - } - if (event.getAuthentication().getPrincipal() instanceof UserDetails || event.getAuthentication().getPrincipal() instanceof org.springframework.security.core.userdetails.UserDetails) { - principal = ((UserDetails) event.getAuthentication().getPrincipal()).getUsername(); - } + String principal = getPrincipal(event); if (StringUtils.isNotBlank(principal)) { UserEntity user = getUserRepository().findByUsername(principal); if (ObjectUtils.isEmpty(user)) { diff --git a/eiam-portal/src/main/portal-fe/package.json b/eiam-portal/src/main/portal-fe/package.json index a05715f9..ffdc177c 100644 --- a/eiam-portal/src/main/portal-fe/package.json +++ b/eiam-portal/src/main/portal-fe/package.json @@ -50,7 +50,7 @@ "@ant-design/maps": "^1.0.7", "@ant-design/pro-components": "^2.6.18", "ahooks": "^3.7.8", - "antd": "^5.8.6", + "antd": "^5.9.0", "antd-img-crop": "^4.12.2", "antd-style": "^3.4.5", "classnames": "^2.3.2", @@ -94,7 +94,7 @@ "@umijs/max": "^4.0.80", "cross-env": "^7.0.3", "cross-port-killer": "^1.4.0", - "eslint": "^8.48.0", + "eslint": "^8.49.0", "husky": "^8.0.3", "lint-staged": "^14.0.1", "prettier": "^3.0.3", diff --git a/eiam-portal/src/main/portal-fe/src/pages/Application/service.ts b/eiam-portal/src/main/portal-fe/src/pages/Application/service.ts index 8e39b417..0f311201 100644 --- a/eiam-portal/src/main/portal-fe/src/pages/Application/service.ts +++ b/eiam-portal/src/main/portal-fe/src/pages/Application/service.ts @@ -19,15 +19,15 @@ import { filterParamConverter, sortParamConverter } from '@/utils/utils'; import type { RequestData } from '@ant-design/pro-components'; import type { SortOrder } from 'antd/es/table/interface'; import { request } from '@umijs/max'; -import type { AppList } from './data.d'; +import { AppGroupList, AppList } from './data.d'; /** * 获取应用列表 */ export async function queryAppList( - params?: Record, - sort?: Record, - filter?: Record, + params: Record, + sort: Record, + filter: Record, ): Promise> { const { result, success } = await request>('/api/v1/app/list', { params: { ...params, ...sortParamConverter(sort), ...filterParamConverter(filter) }, @@ -38,3 +38,10 @@ export async function queryAppList( total: result?.pagination ? result?.pagination.total : 0, }; } + +/** + * 获取应用分组 + */ +export async function getAppGroupList(): Promise> { + return request>('/api/v1/app/group_list', {}); +} diff --git a/eiam-portal/src/main/portal-fe/src/utils/utils.ts b/eiam-portal/src/main/portal-fe/src/utils/utils.ts index 878bb15b..4dae8cee 100644 --- a/eiam-portal/src/main/portal-fe/src/utils/utils.ts +++ b/eiam-portal/src/main/portal-fe/src/utils/utils.ts @@ -18,7 +18,6 @@ import { getEncryptSecret } from '@/services'; import type { SortOrder } from 'antd/es/table/interface'; import { parse } from 'querystring'; -import type { ReactText } from 'react'; import { history, matchPath } from '@umijs/max'; import { PhoneNumber } from 'google-libphonenumber'; @@ -94,7 +93,7 @@ export const sortParamConverter = (value: Record | undefined) * * @param value */ -export const filterParamConverter = (value: Record | undefined) => { +export const filterParamConverter = (value: Record) => { const param: Record = {}; if (value) Object.entries(value).forEach(([key], index) => {