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 (
getKafkaUserList()}>
{ setSearchKeywords(searchKeywordsInput); }} style={{ fontSize: '16px' }} /> } placeholder="请输入 Kafka User" value={searchKeywordsInput} onPressEnter={(_) => { setSearchKeywords(searchKeywordsInput); }} onChange={(e) => { setSearchKeywordsInput(e.target.value); }} />
); }; export default SecurityUsers;