mirror of
https://github.com/apache/rocketmq-dashboard.git
synced 2026-06-08 13:53:17 +08:00
@@ -77,7 +77,7 @@ const remoteApi = {
|
||||
listUsers: async (brokerAddress) => {
|
||||
const params = new URLSearchParams();
|
||||
if (brokerAddress) params.append('brokerAddress', brokerAddress);
|
||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/acl/acls.query?${params.toString()}`));
|
||||
const response = await remoteApi._fetch(remoteApi.buildUrl(`/acl/users.query?${params.toString()}`));
|
||||
return await response.json();
|
||||
},
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ export const translations = {
|
||||
"USER_NAME": "用户名",
|
||||
"PASSWORD": "密码",
|
||||
"SYSTEM": "系统",
|
||||
"WELCOME": "您好,欢迎使用RocketMQ仪表盘",
|
||||
"WELCOME": "欢迎使用RocketMQ仪表盘",
|
||||
"ENABLE_MESSAGE_TRACE": "开启消息轨迹",
|
||||
"MESSAGE_TRACE_DETAIL": "消息轨迹详情",
|
||||
"TRACE_TOPIC": "消息轨迹主题",
|
||||
@@ -284,6 +284,12 @@ export const translations = {
|
||||
"PROXY_ENABLED": "代理启用",
|
||||
"BROKER_OVERVIEW": "Broker概览",
|
||||
"TOTAL_MSG_RECEIVED_TODAY": "今天接收的总消息数",
|
||||
"LOGIN_SUCCESS": "登录成功",
|
||||
"LOGIN_FAILED": "登录失败",
|
||||
"USERNAME_REQUIRED": "用户名为必填项",
|
||||
"USERNAME_PLACEHOLDER": "用户名",
|
||||
"PASSWORD_REQUIRED": "密码为必填项",
|
||||
"PASSWORD_PLACEHOLDER": "密码",
|
||||
},
|
||||
en: {
|
||||
"DEFAULT": "Default",
|
||||
@@ -417,7 +423,7 @@ export const translations = {
|
||||
"USER_NAME": "Username",
|
||||
"PASSWORD": "Password",
|
||||
"SYSTEM": "SYSTEM",
|
||||
"WELCOME": "Hi, welcome using RocketMQ Dashboard",
|
||||
"WELCOME": "Welcome using RocketMQ Dashboard",
|
||||
"ENABLE_MESSAGE_TRACE": "Enable Message Trace",
|
||||
"MESSAGE_TRACE_DETAIL": "Message Trace Detail",
|
||||
"TRACE_TOPIC": "TraceTopic",
|
||||
@@ -546,6 +552,12 @@ export const translations = {
|
||||
"PROXY_ENABLED": "Proxy Enabled",
|
||||
"BROKER_OVERVIEW": "Broker Overview",
|
||||
"TOTAL_MSG_RECEIVED_TODAY": "Total messages received today",
|
||||
"LOGIN_SUCCESS": "Login successful",
|
||||
"LOGIN_FAILED": "Login failed",
|
||||
"USERNAME_REQUIRED": "Username is required",
|
||||
"USERNAME_PLACEHOLDER": "Username placeholder",
|
||||
"PASSWORD_REQUIRED": "Password is required",
|
||||
"PASSWORD_PLACEHOLDER": "Password placeholder",
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ const Acl = () => {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
const [isAclModalVisible, setIsAclModalVisible] = useState(false);
|
||||
const [writeOperationEnabled, setWriteOperationEnabled] = useState(true);
|
||||
const [currentAcl, setCurrentAcl] = useState(null);
|
||||
const [aclForm] = Form.useForm();
|
||||
const [messageApi, msgContextHolder] = message.useMessage();
|
||||
@@ -132,6 +133,16 @@ const Acl = () => {
|
||||
|
||||
}, [activeTab]); // Dependencies for useEffect
|
||||
|
||||
useEffect(() => {
|
||||
const userPermission = localStorage.getItem('userrole');
|
||||
console.log(userPermission);
|
||||
if (userPermission == 2) {
|
||||
setWriteOperationEnabled(false);
|
||||
} else {
|
||||
setWriteOperationEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// --- Helper function to update broker options based on selected cluster ---
|
||||
const updateBrokerOptions = (clusterName, info = clusterData) => {
|
||||
if (!info || !info.clusterAddrTable) {
|
||||
@@ -488,24 +499,26 @@ const Acl = () => {
|
||||
dataIndex: 'userStatus',
|
||||
key: 'userStatus',
|
||||
render: (status) => (
|
||||
<Tag color={status=== 'enable' ? 'green' : 'red'}>{status}</Tag>
|
||||
<Tag color={status === 'Enabled' ? 'green' : 'red'}>{status}</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t.OPERATION,
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Space size="middle">
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEditUser(record)}>{t.MODIFY}</Button>
|
||||
<Popconfirm
|
||||
title={t.CONFIRM_DELETE_USER}
|
||||
onConfirm={() => handleDeleteUser(record.username)}
|
||||
okText={t.YES}
|
||||
cancelText={t.NO}
|
||||
>
|
||||
<Button icon={<DeleteOutlined />} danger>{t.DELETE}</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
writeOperationEnabled ? (
|
||||
<Space size="middle">
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEditUser(record)}>{t.MODIFY}</Button>
|
||||
<Popconfirm
|
||||
title={t.CONFIRM_DELETE_USER}
|
||||
onConfirm={() => handleDeleteUser(record.username)}
|
||||
okText={t.YES}
|
||||
cancelText={t.NO}
|
||||
>
|
||||
<Button icon={<DeleteOutlined />} danger>{t.DELETE}</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
) : null
|
||||
),
|
||||
},
|
||||
];
|
||||
@@ -552,17 +565,19 @@ const Acl = () => {
|
||||
title: t.OPERATION,
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Space size="middle">
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEditAcl(record)}>{t.MODIFY}</Button>
|
||||
<Popconfirm
|
||||
title={t.CONFIRM_DELETE_ACL}
|
||||
onConfirm={() => handleDeleteAcl(record.subject, record.resource)}
|
||||
okText={t.YES}
|
||||
cancelText={t.NO}
|
||||
>
|
||||
<Button icon={<DeleteOutlined />} danger>{t.DELETE}</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
writeOperationEnabled ? (
|
||||
<Space size="middle">
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEditAcl(record)}>{t.MODIFY}</Button>
|
||||
<Popconfirm
|
||||
title={t.CONFIRM_DELETE_ACL}
|
||||
onConfirm={() => handleDeleteAcl(record.subject, record.resource)}
|
||||
okText={t.YES}
|
||||
cancelText={t.NO}
|
||||
>
|
||||
<Button icon={<DeleteOutlined />} danger>{t.DELETE}</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
) : null
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -232,6 +232,15 @@ const ConsumerGroupList = () => {
|
||||
return () => clearInterval(intervalId);
|
||||
}, [intervalProcessSwitch, loadConsumerGroups]);
|
||||
|
||||
useEffect(() => {
|
||||
const userPermission = localStorage.getItem('userrole');
|
||||
console.log(userPermission);
|
||||
if (userPermission == 2) {
|
||||
setWriteOperationEnabled(false);
|
||||
} else {
|
||||
setWriteOperationEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
filterList(paginationConf.current, allConsumerGroupList);
|
||||
|
||||
@@ -250,7 +250,6 @@ const DashboardPage = () => {
|
||||
const brokerAddrTable = resp.data.clusterInfo.brokerAddrTable; // Corrected to brokerAddrTable
|
||||
const brokerDetail = resp.data.brokerServer;
|
||||
const clusterMap = tools.generateBrokerMap(brokerDetail, clusterAddrTable, brokerAddrTable);
|
||||
console.log(brokerAddrTable)
|
||||
let brokerArray = [];
|
||||
Object.values(clusterMap).forEach(brokersInCluster => {
|
||||
brokerArray = brokerArray.concat(brokersInCluster);
|
||||
@@ -260,8 +259,7 @@ const DashboardPage = () => {
|
||||
...broker,
|
||||
key: broker.brokerName,
|
||||
}));
|
||||
console.log("即将设置的数据:", newData); // 先打印
|
||||
setBrokerTableData(newData); // 再设置状态
|
||||
setBrokerTableData(newData);
|
||||
|
||||
brokerArray.sort((firstBroker, lastBroker) => {
|
||||
const firstTotalMsg = parseFloat(firstBroker.msgGetTotalTodayNow || 0);
|
||||
|
||||
@@ -75,7 +75,7 @@ const DlqMessageQueryPage = () => {
|
||||
useEffect(() => {
|
||||
const fetchConsumerGroups = async () => {
|
||||
setLoading(true);
|
||||
const resp = await remoteApi.queryConsumerGroupList();
|
||||
const resp = await remoteApi.queryConsumerGroupList(false);
|
||||
if (resp.status === 0) {
|
||||
const filteredGroups = resp.data
|
||||
.filter(consumerGroup => !consumerGroup.group.startsWith(SYS_GROUP_TOPIC_PREFIX))
|
||||
|
||||
@@ -18,23 +18,24 @@
|
||||
import React from 'react';
|
||||
import {Button, Form, Input, message, Typography} from 'antd';
|
||||
import {remoteApi} from "../../api/remoteApi/remoteApi";
|
||||
import {useLanguage} from "../../i18n/LanguageContext";
|
||||
|
||||
const {Title} = Typography;
|
||||
|
||||
const Login = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [messageApi, msgContextHolder] = message.useMessage();
|
||||
|
||||
const {t} = useLanguage();
|
||||
const onFinish = async (values) => {
|
||||
const {username, password} = values;
|
||||
remoteApi.login(username, password).then((res) => {
|
||||
if (res.status === 0) {
|
||||
messageApi.success('登录成功');
|
||||
messageApi.success(t.LOGIN_SUCCESS);
|
||||
window.localStorage.setItem("username", res.data.loginUserName);
|
||||
window.localStorage.setItem("userrole", res.data.loginUserRole);
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
messageApi.error(res.message || '登录失败,请检查用户名和密码');
|
||||
messageApi.error(res.message || t.LOGIN_FAILED);
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -50,7 +51,7 @@ const Login = () => {
|
||||
borderRadius: 8
|
||||
}}>
|
||||
<Title level={3} style={{textAlign: 'center', marginBottom: 24}}>
|
||||
WELCOME
|
||||
{t.WELCOME}
|
||||
</Title>
|
||||
<Form
|
||||
form={form}
|
||||
@@ -60,30 +61,27 @@ const Login = () => {
|
||||
initialValues={{username: '', password: ''}}
|
||||
>
|
||||
<Form.Item
|
||||
label="用户名"
|
||||
label={t.USERNAME}
|
||||
name="username"
|
||||
rules={[{required: true, message: '请输入用户名'}]}
|
||||
>
|
||||
<Input placeholder="请输入用户名"/>
|
||||
rules={[{required: true, message: t.USERNAME_REQUIRED}]}>
|
||||
<Input placeholder={t.USERNAME_PLACEHOLDER}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="密码"
|
||||
label={t.PASSWORD}
|
||||
name="password"
|
||||
rules={[{required: true, message: '请输入密码'}]}
|
||||
>
|
||||
<Input.Password placeholder="请输入密码"/>
|
||||
rules={[{required: true, message: t.PASSWORD_REQUIRED}]}>
|
||||
<Input.Password placeholder={t.PASSWORD_PLACEHOLDER}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" block>
|
||||
登录
|
||||
{t.LOGIN}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,16 @@ const Ops = () => {
|
||||
fetchOpsData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const userPermission = localStorage.getItem('userrole');
|
||||
console.log(userPermission);
|
||||
if (userPermission == 2) {
|
||||
setWriteOperationEnabled(false);
|
||||
} else {
|
||||
setWriteOperationEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleUpdateNameSvrAddr = async () => {
|
||||
if (!selectedNamesrv) {
|
||||
messageApi.warning('请选择一个 NameServer 地址');
|
||||
|
||||
@@ -37,9 +37,13 @@ const ProxyManager = () => {
|
||||
const [notificationApi, notificationContextHolder] = notification.useNotification();
|
||||
|
||||
useEffect(() => {
|
||||
const userRole = sessionStorage.getItem("userrole");
|
||||
const isWriteEnabled = userRole === null || userRole === '1';
|
||||
setWriteOperationEnabled(isWriteEnabled);
|
||||
const userPermission = localStorage.getItem('userrole');
|
||||
console.log(userPermission);
|
||||
if (userPermission == 2) {
|
||||
setWriteOperationEnabled(false);
|
||||
} else {
|
||||
setWriteOperationEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -100,6 +100,16 @@ const DeployHistoryList = () => {
|
||||
}, [filterStr, filterNormal, filterDelay, filterFifo, filterTransaction,
|
||||
filterUnspecified, filterRetry, filterDLQ, filterSystem, allTopicList]);
|
||||
|
||||
useEffect(() => {
|
||||
const userPermission = localStorage.getItem('userrole');
|
||||
console.log(userPermission);
|
||||
if (userPermission == 2) {
|
||||
setWriteOperationEnabled(false);
|
||||
} else {
|
||||
setWriteOperationEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Close functions for Modals
|
||||
const closeAddUpdateDialog = () => {
|
||||
setIsAddUpdateTopicModalVisible(false);
|
||||
|
||||
Reference in New Issue
Block a user