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;
+ }}
+ >
+
+
+ {
+ if (!value) {
+ return Promise.resolve();
+ }
+ setLoading(true);
+ const { success, result } = await permissionResourceParamCheck(
+ appId,
+ 'NAME',
+ value,
+ id,
+ );
+ setLoading(false);
+ if (!success) {
+ return Promise.reject();
+ }
+ if (!result) {
+ return Promise.reject(new Error('资源名称已存在'));
+ }
+ },
+ validateTrigger: ['onBlur'],
+ },
+ ]}
+ />
+ {
+ return (
+ value && (
+
+ ${value}`,
+ }}
+ />
+
+ )
+ );
+ },
+ }}
+ readonly
+ extra="资源编码在当前应用中的唯一标识,不能重复,仅支持英文、数字、下划线,创建后不可修改。"
+ />
+
+
+
+ );
+};
+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;
+ }}
+ >
+
+
+
+ {
+ if (!value) {
+ return Promise.resolve();
+ }
+ setLoading(true);
+ const { success, result } = await permissionRoleParamCheck(
+ formRef.current?.getFieldValue('appId'),
+ 'NAME',
+ value,
+ id,
+ );
+ setLoading(false);
+ if (!success) {
+ return Promise.reject();
+ }
+ if (!result) {
+ return Promise.reject(new Error('手机号已存在'));
+ }
+ },
+ validateTrigger: ['onBlur'],
+ },
+ ]}
+ placeholder="请输入角色名称"
+ />
+ {
+ return (
+ value && (
+
+ ${value}`,
+ }}
+ />
+
+ )
+ );
+ },
+ }}
+ extra="角色编码在当前应用中的唯一标识,不能重复,仅支持英文、数字、下划线,创建后不可修改。"
+ />
+
+
+
+ );
+};
+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={() => [
+ }
+ onClick={() => {
+ setCreateModalOpen(true);
+ }}
+ type="primary"
+ >
+ {intl.formatMessage({ id: 'pages.app_group.list.create' })}
+ ,
+ ]}
+ />
+ {
+ 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) => {