import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import {
Button,
Form,
Input,
Modal,
message,
ProTable,
Drawer,
Space,
Divider,
AppContainer,
DKSBreadcrumb,
Utils,
Checkbox,
Tooltip,
IconFont,
Alert,
} from 'knowdesign';
import { CloseOutlined, EyeInvisibleOutlined, EyeOutlined, LoadingOutlined } from '@ant-design/icons';
import './index.less';
import api from '@src/api';
import { useParams } from 'react-router-dom';
import { regKafkaPassword } from '@src/constants/reg';
import { tableHeaderPrefix } from '@src/constants/common';
export const randomString = (len = 32, chars = 'abcdefghijklmnopqrstuvwxyz1234567890'): string => {
const maxPos = chars.length;
let str = '';
for (let i = 0; i < len; i++) {
str += chars.charAt(Math.floor(Math.random() * maxPos));
}
return str;
};
const { confirm } = Modal;
enum UsersOperate {
Add,
ChangePassword,
}
export type UsersProps = {
clusterId: number;
name: string;
authType: any;
authName: string;
createTime: string;
updateTime: string;
};
export const defaultPagination = {
current: 1,
pageSize: 10,
position: 'bottomRight',
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
};
const AES_KEY = 'KnowStreamingKM$';
const initialShowPassword = '********';
const AUTH_TYPES = [
{
label: 'SCRAM',
value: 1300,
},
{
label: 'GSSAPI',
value: 'gssapi',
disabled: true,
},
{
label: 'PLAIN',
value: 'plain',
disabled: true,
},
{
label: 'OAUTHBEARER',
value: 'oauthbearer',
disabled: true,
},
];
const PasswordContent = (props: { clusterId: string; name: string }) => {
const { clusterId, name } = props;
const [loading, setLoading] = useState(false);
const [pw, setPw] = useState(initialShowPassword);
const switchPwStatus = () => {
if (!loading) {
setLoading(true);
if (pw === initialShowPassword) {
Utils.request(api.getKafkaUserToken(clusterId, name)).then(
(res: any) => {
let token = res.token || '';
if (res?.decrypt) {
token = Utils.decryptAES(token, AES_KEY);
}
setPw(token);
setLoading(false);
},
() => setLoading(false)
);
} else {
setPw(initialShowPassword);
setLoading(false);
}
}
};
return (
{pw}
{loading ? : pw === initialShowPassword ? : }
);
};
// 新增 KafkaUser / 修改 KafkaUser 密码
// eslint-disable-next-line react/display-name
const EditKafkaUser = forwardRef((_, ref) => {
const { clusterId } = useParams<{
clusterId: string;
}>();
const [type, setType] = useState(UsersOperate.Add);
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const callback = useRef(() => {
return;
});
// 提交表单
const onSubmit = () => {
form.validateFields().then((formData) => {
// 对密码进行加密
formData.token = Utils.encryptAES(formData.token, AES_KEY);
// 注意:目前 authType 字段固定传 SCRAM 认证方式的值,之后如果开通了多认证方式,这里需要做更改
formData.authType = 1300;
setConfirmLoading(true);
Utils.request(type === UsersOperate.Add ? api.kafkaUser : api.updateKafkaUserToken, {
method: type === UsersOperate.Add ? 'POST' : 'PUT',
data: Object.assign(formData, { clusterId: Number(clusterId) }),
}).then(
() => {
// 执行回调,刷新列表数据
callback.current();
onClose();
message.success(type === UsersOperate.Add ? '成功新增 KafkaUser' : '成功修改密码');
},
() => setConfirmLoading(false)
);
});
};
// 展开抽屉
const onOpen = (status: boolean, type: UsersOperate, cbk: () => void, detail: UsersProps) => {
detail && form.setFieldsValue({ kafkaUser: detail.name });
setType(type);
setVisible(status);
callback.current = cbk;
};
// 关闭抽屉
const onClose = () => {
setVisible(false);
setConfirmLoading(false);
form.resetFields();
};
useImperativeHandle(ref, () => ({
onOpen,
}));
return (
}
>
{type === UsersOperate.Add && (
)}
{type === UsersOperate.Add && (
{AUTH_TYPES.map((type) => {
return type.disabled ? (
{type.label}
) : (
{type.label}
);
})}
)}
{type === UsersOperate.ChangePassword && 'New'} Password
{
const randomStr = randomString(
12,
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-!"#$%&\'()*+,./:;<=>?@[]^`{|}~'
);
form && form.setFieldsValue({ token: randomStr });
}}
/>
}
name="token"
rules={[
{ required: true, message: 'Password 不能为空' },
{
pattern: regKafkaPassword,
message: '密码支持中英文、数字、特殊字符 ! " # $ % & \' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~',
},
]}
>
);
});
const SecurityUsers = (): JSX.Element => {
const [global] = AppContainer.useGlobalValue();
const { clusterId } = useParams<{
clusterId: string;
}>();
const [loading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [pagination, setPagination] = useState(defaultPagination);
const [searchKeywords, setSearchKeywords] = useState('');
const [searchKeywordsInput, setSearchKeywordsInput] = useState('');
const editDrawerRef = useRef(null);
const getKafkaUserList = (query = {}) => {
const queryParams = {
pageNo: pagination.current,
pageSize: pagination.pageSize,
searchKeywords,
...query,
};
setLoading(true);
Utils.request(api.getKafkaUsers(clusterId), {
method: 'POST',
data: queryParams,
}).then(
(res: any) => {
const { pageNo, pageSize, total } = res.pagination;
const pages = Math.ceil(total / pageSize);
if (pageNo > pages && pages !== 0) {
getKafkaUserList({ pageNo: pages });
return false;
}
setPagination({
...pagination,
current: pageNo,
pageSize,
total,
});
setData(res.bizData);
setLoading(false);
return true;
},
() => setLoading(false)
);
};
const columns = () => {
const baseColumns = [
{
title: 'KafkaUser',
dataIndex: 'name',
width: 300,
render(name: string) {
return (
{name}
);
},
},
{
title: '认证方式',
dataIndex: 'authName',
},
{
title: 'Password',
dataIndex: 'token',
width: 300,
render(_: string, record: UsersProps) {
return ;
},
},
{
title: '操作',
dataIndex: '',
width: 240,
render(record: UsersProps) {
return (
<>
>
);
},
},
];
return baseColumns;
};
const onDelete = (record: UsersProps) => {
confirm({
title: '确定删除该 KafkaUser 吗?',
okText: '删除',
okType: 'primary',
centered: true,
okButtonProps: {
size: 'small',
danger: true,
},
cancelButtonProps: {
size: 'small',
},
maskClosable: false,
onOk() {
return Utils.request(api.kafkaUser, {
method: 'DELETE',
data: {
clusterId,
kafkaUser: record.name,
},
}).then((_) => {
message.success('删除成功');
getKafkaUserList();
});
},
});
};
const onTableChange = (curPagination: any) => {
getKafkaUserList({ pageNo: curPagination.current, pageSize: curPagination.pageSize });
};
useEffect(() => {
// 获取配置列表
getKafkaUserList();
}, []);
useEffect(() => {
(searchKeywords || searchKeywords === '') && getKafkaUserList({ pageNo: 1 });
}, [searchKeywords]);
return (
);
};
export default SecurityUsers;