[GSOC][RIP-78][ISSUES#308] Add part of refactored backend files (#313)

This commit is contained in:
Crazylychee
2025-06-16 14:04:53 +08:00
committed by GitHub
parent 3cbff604e6
commit bc1a05d16c
86 changed files with 1624 additions and 1002 deletions

50
pom.xml
View File

@@ -82,29 +82,28 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<guava.version>29.0-jre</guava.version> <guava.version>29.0-jre</guava.version>
<commons-digester.version>2.1</commons-digester.version> <commons-digester.version>2.1</commons-digester.version>
<commons-lang.version>2.6</commons-lang.version> <commons-lang.version>2.6</commons-lang.version>
<commons-io.version>2.4</commons-io.version> <commons-io.version>2.4</commons-io.version>
<commons-cli.version>1.2</commons-cli.version> <commons-cli.version>1.2</commons-cli.version>
<commons-collections.version>3.2.2</commons-collections.version> <commons-collections.version>3.2.2</commons-collections.version>
<rocketmq.version>5.1.0</rocketmq.version> <rocketmq.version>5.3.3</rocketmq.version>
<surefire.version>2.19.1</surefire.version> <surefire.version>2.19.1</surefire.version>
<aspectj.version>1.9.6</aspectj.version> <aspectj.version>1.9.6</aspectj.version>
<lombok.version>1.18.22</lombok.version> <lombok.version>1.18.22</lombok.version>
<main.basedir>${basedir}/../..</main.basedir> <main.basedir>${basedir}/../..</main.basedir>
<docker.image.prefix>apacherocketmq</docker.image.prefix> <docker.image.prefix>apacherocketmq</docker.image.prefix>
<spring.boot.version>2.6.0</spring.boot.version> <spring.boot.version>3.4.5</spring.boot.version>
<mockito-inline.version>3.3.3</mockito-inline.version> <mockito-inline.version>3.3.3</mockito-inline.version>
<jaxb-api.version>2.3.1</jaxb-api.version> <jakarta.xml.bind-api.version>4.0.0</jakarta.xml.bind-api.version>
<commons-pool2.version>2.4.3</commons-pool2.version> <commons-pool2.version>2.4.3</commons-pool2.version>
<easyexcel.version>2.2.10</easyexcel.version> <easyexcel.version>2.2.10</easyexcel.version>
<asm.version>4.2</asm.version> <asm.version>4.2</asm.version>
<junit.version>4.12</junit.version> <junit.version>4.12</junit.version>
<snakeyaml.version>1.32</snakeyaml.version> <snakeyaml.version>2.0</snakeyaml.version>
<cglib.version>2.2.2</cglib.version> <cglib.version>2.2.2</cglib.version>
<joor.version>0.9.6</joor.version> <joor.version>0.9.6</joor.version>
<bcpkix-jdk15on.version>1.68</bcpkix-jdk15on.version> <bcpkix-jdk15on.version>1.68</bcpkix-jdk15on.version>
@@ -115,6 +114,12 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version> <version>${spring.boot.version}</version>
<exclusions>
<exclusion>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@@ -235,9 +240,9 @@
<version>${bcpkix-jdk15on.version}</version> <version>${bcpkix-jdk15on.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>jakarta.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jakarta.xml.bind-api</artifactId>
<version>${jaxb-api.version}</version> <version>${jakarta.xml.bind-api.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
@@ -282,7 +287,7 @@
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version> <version>3.11.0</version>
<configuration> <configuration>
<source>${maven.compiler.source}</source> <source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target> <target>${maven.compiler.target}</target>
@@ -296,19 +301,22 @@
<version>${lombok.version}</version> <version>${lombok.version}</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version> <version>${spring.boot.version}</version>
<executions> <!-- <executions>-->
<execution> <!-- <execution>-->
<goals> <!-- <goals>-->
<goal>repackage</goal> <!-- <goal>repackage</goal>-->
</goals> <!-- </goals>-->
</execution> <!-- </execution>-->
</executions> <!-- </executions>-->
</plugin> </plugin>
<!-- Use dockerfile-maven instead, https://github.com/spotify/dockerfile-maven --> <!-- Use dockerfile-maven instead, https://github.com/spotify/dockerfile-maven -->
<plugin> <plugin>
@@ -384,9 +392,9 @@
<version>4.3.0</version> <version>4.3.0</version>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>javax.xml.bind</groupId> <groupId>jakarta.xml.bind</groupId>
<artifactId>jaxb-api</artifactId> <artifactId>jakarta.xml.bind-api</artifactId>
<version>${jaxb-api.version}</version> <version>${jakarta.xml.bind-api.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>

View File

@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import org.apache.rocketmq.tools.admin.MQAdminExt;
@FunctionalInterface
public interface MQAdminExtCallback<T> {
T doInMQAdminExt(MQAdminExt mqAdminExt) throws Exception;
}

View File

@@ -16,7 +16,6 @@
*/ */
package org.apache.rocketmq.dashboard.admin; package org.apache.rocketmq.dashboard.admin;
import java.util.concurrent.atomic.AtomicLong;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.AclClientRPCHook;
@@ -26,6 +25,8 @@ import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import java.util.concurrent.atomic.AtomicLong;
@Slf4j @Slf4j
public class MQAdminFactory { public class MQAdminFactory {
private RMQConfigure rmqConfigure; private RMQConfigure rmqConfigure;

View File

@@ -0,0 +1,132 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@Component
@Slf4j
public class UserMQAdminPoolManager {
private final ConcurrentMap<String/* userAk */, GenericObjectPool<MQAdminExt>> userPools = new ConcurrentHashMap<>();
private final ClientConfig baseClientConfig;
@Autowired
public UserMQAdminPoolManager(RMQConfigure rmqConfigure) {
this.baseClientConfig = new ClientConfig();
this.baseClientConfig.setNamesrvAddr(rmqConfigure.getNamesrvAddr());
this.baseClientConfig.setClientCallbackExecutorThreads(rmqConfigure.getClientCallbackExecutorThreads());
this.baseClientConfig.setVipChannelEnabled(Boolean.parseBoolean(rmqConfigure.getIsVIPChannel()));
this.baseClientConfig.setUseTLS(rmqConfigure.isUseTLS());
log.info("UserMQAdminPoolManager initialized with baseClientConfig for NameServer: {}", rmqConfigure.getNamesrvAddr());
}
public MQAdminExt borrowMQAdminExt(String userAk, String userSk) throws Exception {
GenericObjectPool<MQAdminExt> userPool = userPools.get(userAk);
if (userPool == null) {
log.info("Creating new MQAdminExt pool for user: {}", userAk);
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(1);
poolConfig.setMaxIdle(1);
poolConfig.setMinIdle(0);
poolConfig.setTestWhileIdle(true);
poolConfig.setTimeBetweenEvictionRunsMillis(20000);
poolConfig.setMaxWaitMillis(10000);
UserSpecificMQAdminPooledObjectFactory factory =
new UserSpecificMQAdminPooledObjectFactory(baseClientConfig, userAk, userSk);
GenericObjectPool<MQAdminExt> newUserPool = new GenericObjectPool<>(factory, poolConfig);
GenericObjectPool<MQAdminExt> existingPool = userPools.putIfAbsent(userAk, newUserPool);
if (existingPool != null) {
log.warn("Another thread concurrently created MQAdminExt pool for user {}. Shutting down redundant pool.", userAk);
newUserPool.close();
userPool = existingPool;
} else {
userPool = newUserPool;
log.info("Successfully created and registered MQAdminExt pool for user: {}", userAk);
}
}
return userPool.borrowObject();
}
public void returnMQAdminExt(String userAk, MQAdminExt mqAdminExt) {
GenericObjectPool<MQAdminExt> userPool = userPools.get(userAk);
if (userPool != null) {
try {
userPool.returnObject(mqAdminExt);
log.debug("Returned MQAdminExt object ({}) to pool for user: {}", mqAdminExt, userAk);
} catch (Exception e) {
log.error("Failed to return MQAdminExt object ({}) for user {}: {}", mqAdminExt, userAk, e.getMessage(), e);
if (mqAdminExt != null) {
try {
mqAdminExt.shutdown();
} catch (Exception se) {
log.warn("Error shutting down MQAdminExt after failed return: {}", se.getMessage());
}
}
}
} else {
log.warn("Attempted to return MQAdminExt for non-existent user pool: {}. Shutting down the object directly.", userAk);
if (mqAdminExt != null) {
try {
mqAdminExt.shutdown();
} catch (Exception se) {
log.warn("Error shutting down MQAdminExt for non-existent pool: {}", se.getMessage());
}
}
}
}
public void shutdownUserPool(String userAk) {
GenericObjectPool<MQAdminExt> userPool = userPools.remove(userAk);
if (userPool != null) {
userPool.close();
log.info("Shutdown and removed MQAdminExt pool for user: {}", userAk);
} else {
log.warn("Attempted to shut down non-existent user pool: {}", userAk);
}
}
@PreDestroy
public void shutdownAllPools() {
log.info("Shutting down all MQAdminExt user pools...");
userPools.forEach((userAk, pool) -> {
pool.close();
log.info("Shutdown MQAdminExt pool for user: {}", userAk);
});
userPools.clear();
log.info("All MQAdminExt user pools have been shut down.");
}
}

View File

@@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.admin;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
@Slf4j
public class UserSpecificMQAdminPooledObjectFactory implements PooledObjectFactory<MQAdminExt> {
private final ClientConfig userSpecificClientConfig;
private final RPCHook rpcHook;
private final String userAk;
private final AtomicLong instanceCreationCounter = new AtomicLong(0);
public UserSpecificMQAdminPooledObjectFactory(ClientConfig baseClientConfig, String userAk, String userSk) {
this.userSpecificClientConfig = baseClientConfig.cloneClientConfig();
this.userSpecificClientConfig.setInstanceName("MQ_ADMIN_INSTANCE_" + userAk + "_" + UUID.randomUUID());
if (StringUtils.isNotEmpty(userAk) && StringUtils.isNotEmpty(userSk)) {
this.rpcHook = new AclClientRPCHook(new SessionCredentials(userAk, userSk));
} else {
this.rpcHook = null;
}
this.userAk = userAk;
log.info("UserSpecificMQAdminPooledObjectFactory initialized for user: {}", userAk);
log.debug("Factory ClientConfig for user {}: {}", userAk, userSpecificClientConfig);
}
@Override
public PooledObject<MQAdminExt> makeObject() throws Exception {
DefaultMQAdminExt mqAdminExt = new DefaultMQAdminExt(rpcHook);
mqAdminExt.setAdminExtGroup("MQ_ADMIN_GROUP_FOR_" + userAk + "_" + instanceCreationCounter.getAndIncrement());
mqAdminExt.start();
log.info("Created new MQAdminExt instance ({}) for user {}", mqAdminExt, userAk);
return new DefaultPooledObject<>(mqAdminExt);
}
@Override
public void destroyObject(PooledObject<MQAdminExt> p) {
MQAdminExt mqAdmin = p.getObject();
if (mqAdmin != null) {
try {
mqAdmin.shutdown();
} catch (Exception e) {
log.warn("Failed to shut down MQAdminExt object ({}) for user {}: {}", p.getObject(), userAk, e.getMessage(), e);
}
}
log.info("Destroyed MQAdminExt object ({}) for user {}", p.getObject(), userAk);
}
@Override
public boolean validateObject(PooledObject<MQAdminExt> p) {
MQAdminExt mqAdmin = p.getObject();
if (mqAdmin == null) {
log.warn("MQAdminExt object is null or not started for user {}: {}", userAk, mqAdmin);
return false;
}
try {
ClusterInfo clusterInfo = mqAdmin.examineBrokerClusterInfo();
boolean isValid = clusterInfo != null && !clusterInfo.getBrokerAddrTable().isEmpty();
if (!isValid) {
log.warn("Validation failed for MQAdminExt object for user {}: ClusterInfo is invalid or empty. ClusterInfo = {}", userAk, clusterInfo);
}
return isValid;
} catch (Exception e) {
log.warn("Validation error for MQAdminExt object for user {}: {}", userAk, e.getMessage(), e);
return false;
}
}
@Override
public void activateObject(PooledObject<MQAdminExt> p) {
log.debug("Activating MQAdminExt object ({}) for user {}", p.getObject(), userAk);
}
@Override
public void passivateObject(PooledObject<MQAdminExt> p) {
log.debug("Passivating MQAdminExt object ({}) for user {}", p.getObject(), userAk);
}
}

View File

@@ -18,42 +18,114 @@ package org.apache.rocketmq.dashboard.aspect.admin;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.dashboard.admin.UserMQAdminPoolManager;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.client.MQAdminInstance; import org.apache.rocketmq.dashboard.service.client.MQAdminInstance;
import org.apache.rocketmq.dashboard.util.UserInfoContext;
import org.apache.rocketmq.dashboard.util.WebUtil;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
@Aspect @Aspect
@Service @Component
@Slf4j @Slf4j
public class MQAdminAspect { public class MQAdminAspect {
@Autowired
private UserMQAdminPoolManager userMQAdminPoolManager;
@Autowired @Autowired
private GenericObjectPool<MQAdminExt> mqAdminExtPool; private GenericObjectPool<MQAdminExt> mqAdminExtPool;
public MQAdminAspect() { @Autowired
private RMQConfigure rmqConfigure;
private static final Set<String> METHODS_TO_CHECK = new HashSet<>();
static {
METHODS_TO_CHECK.add("getUser");
METHODS_TO_CHECK.add("examineBrokerClusterInfo");
METHODS_TO_CHECK.add("examineConsumerConnectionInfo");
METHODS_TO_CHECK.add("examineConsumeStats");
METHODS_TO_CHECK.add("examineProducerConnectionInfo");
} }
// Pointcut remains the same, targeting methods in MQAdminExtImpl
@Pointcut("execution(* org.apache.rocketmq.dashboard.service.client.MQAdminExtImpl..*(..))") @Pointcut("execution(* org.apache.rocketmq.dashboard.service.client.MQAdminExtImpl..*(..))")
public void mQAdminMethodPointCut() { public void mQAdminMethodPointCut() {
} }
@Around(value = "mQAdminMethodPointCut()") @Pointcut("execution(* org.apache.rocketmq.dashboard.service.client.ProxyAdminImpl..*(..))")
public void proxyAdminMethodPointCut() {
}
@Around(value = "mQAdminMethodPointCut()||proxyAdminMethodPointCut()")
public Object aroundMQAdminMethod(ProceedingJoinPoint joinPoint) throws Throwable { public Object aroundMQAdminMethod(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Object obj = null; MQAdminExt mqAdminExt = null; // The MQAdminExt instance borrowed from the pool
UserInfo currentUserInfo = null; // The user initiating the operation
String methodName = joinPoint.getSignature().getName();
try { try {
MQAdminInstance.createMQAdmin(mqAdminExtPool); if (isPoolConfigIsolatedByUser(rmqConfigure.isLoginRequired(), methodName)) {
obj = joinPoint.proceed(); currentUserInfo = (UserInfo) UserInfoContext.get(WebUtil.USER_NAME);
// 2. Borrow the user-specific MQAdminExt instance.
// currentUser.getName() is assumed to be the AccessKey, and currentUser.getPassword() is SecretKey.
mqAdminExt = userMQAdminPoolManager.borrowMQAdminExt(currentUserInfo.getUsername(), currentUserInfo.getPassword());
// 3. Set the borrowed MQAdminExt instance into the ThreadLocal for MQAdminInstance.
// This makes it available to MQAdminExtImpl methods.
MQAdminInstance.setCurrentMQAdminExt(mqAdminExt);
log.debug("MQAdminExt borrowed for user {} and set in ThreadLocal.", currentUserInfo.getUsername());
} else {
mqAdminExt = mqAdminExtPool.borrowObject(); // Fallback to a default MQAdminExt if no user is provided
MQAdminInstance.setCurrentMQAdminExt(mqAdminExt);
}
// 4. Proceed with the original method execution.
return joinPoint.proceed();
} finally { } finally {
MQAdminInstance.returnMQAdmin(mqAdminExtPool);
log.debug("op=look method={} cost={}", joinPoint.getSignature().getName(), System.currentTimeMillis() - start); if (currentUserInfo != null) {
if (mqAdminExt != null) {
userMQAdminPoolManager.returnMQAdminExt(currentUserInfo.getUsername(), mqAdminExt);
MQAdminInstance.clearCurrentMQAdminExt();
log.debug("MQAdminExt returned for user {} and cleared from ThreadLocal.", currentUserInfo.getUsername());
}
log.debug("Operation {} for user {} cost {}ms",
methodName,
currentUserInfo.getUsername(),
System.currentTimeMillis() - start);
} else {
if (mqAdminExt != null) {
mqAdminExtPool.returnObject(mqAdminExt);
MQAdminInstance.clearCurrentMQAdminExt();
log.debug("MQAdminExt returned to default pool and cleared from ThreadLocal.");
}
log.debug("Operation {} cost {}ms",
methodName,
System.currentTimeMillis() - start);
}
} }
return obj;
} }
private boolean isPoolConfigIsolatedByUser(boolean loginRequired, String methodName) {
if (!loginRequired) {
return false;
} else {
return !METHODS_TO_CHECK.contains(methodName);
}
}
} }

View File

@@ -17,6 +17,8 @@
package org.apache.rocketmq.dashboard.config; package org.apache.rocketmq.dashboard.config;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.rocketmq.dashboard.interceptor.AuthInterceptor; import org.apache.rocketmq.dashboard.interceptor.AuthInterceptor;
import org.apache.rocketmq.dashboard.model.UserInfo; import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.util.WebUtil; import org.apache.rocketmq.dashboard.util.WebUtil;
@@ -29,16 +31,16 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
@Configuration @Configuration
public class AuthWebMVCConfigurerAdapter extends WebMvcConfigurerAdapter { public class AuthWebMVCConfigurerAdapter implements WebMvcConfigurer {
@Autowired @Autowired
@Qualifier("authInterceptor") @Qualifier("authInterceptor")
private AuthInterceptor authInterceptor; private AuthInterceptor authInterceptor;
@@ -50,19 +52,19 @@ public class AuthWebMVCConfigurerAdapter extends WebMvcConfigurerAdapter {
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
if (configure.isLoginRequired()) { if (configure.isLoginRequired()) {
registry.addInterceptor(authInterceptor).addPathPatterns( registry.addInterceptor(authInterceptor).addPathPatterns(
"/cluster/**", "/cluster/**",
"/consumer/**", "/consumer/**",
"/dashboard/**", "/dashboard/**",
"/dlqMessage/**", "/dlqMessage/**",
"/message/**", "/message/**",
"/messageTrace/**", "/messageTrace/**",
"/monitor/**", "/monitor/**",
"/rocketmq/**", "/rocketmq/**",
"/ops/**", "/ops/**",
"/producer/**", "/producer/**",
"/test/**", "/test/**",
"/topic/**", "/topic/**",
"/acl/**"); "/acl/**");
} }
} }
@@ -77,19 +79,30 @@ public class AuthWebMVCConfigurerAdapter extends WebMvcConfigurerAdapter {
@Override @Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
UserInfo userInfo = (UserInfo) WebUtil.getValueFromSession((HttpServletRequest) nativeWebRequest.getNativeRequest(), UserInfo userInfo = (UserInfo) WebUtil.getValueFromSession((HttpServletRequest) nativeWebRequest.getNativeRequest(),
UserInfo.USER_INFO); UserInfo.USER_INFO);
if (userInfo != null) { if (userInfo != null) {
return userInfo; return userInfo;
} }
throw new MissingServletRequestPartException(UserInfo.USER_INFO); throw new MissingServletRequestPartException(UserInfo.USER_INFO);
} }
}); });
super.addArgumentResolvers(argumentResolvers); //REVIEW ME
} }
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("http://localhost:3003")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600)
.allowCredentials(true)
.allowedHeaders("content-type", "Authorization", "X-Requested-With", "Origin", "Accept")
.exposedHeaders("authorization");
}
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("*.htm").setViewName("forward:/app.html"); registry.addViewController("*.htm").setViewName("forward:/app.html");

View File

@@ -17,16 +17,17 @@
package org.apache.rocketmq.dashboard.config; package org.apache.rocketmq.dashboard.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@ConfigurationProperties(prefix = "threadpool.config") @ConfigurationProperties(prefix = "threadpool.config")

View File

@@ -16,7 +16,8 @@
*/ */
package org.apache.rocketmq.dashboard.config; package org.apache.rocketmq.dashboard.config;
import java.util.ArrayList; import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
@@ -31,68 +32,64 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY; import static org.apache.rocketmq.client.ClientConfig.SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY;
@Setter
@Getter
@Configuration @Configuration
@ConfigurationProperties(prefix = "rocketmq.config") @ConfigurationProperties(prefix = "rocketmq.config")
public class RMQConfigure { public class RMQConfigure {
private Logger logger = LoggerFactory.getLogger(RMQConfigure.class); private Logger logger = LoggerFactory.getLogger(RMQConfigure.class);
//use rocketmq.namesrv.addr first,if it is empty,than use system proerty or system env //use rocketmq.namesrv.addr first,if it is empty,than use system proerty or system env
@Getter
private volatile String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV)); private volatile String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV));
@Setter
@Getter
private volatile String proxyAddr; private volatile String proxyAddr;
@Getter
private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true"); private volatile String isVIPChannel = System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "true");
@Setter
private String dataPath = "/tmp/rocketmq-console/data"; private String dataPath = "/tmp/rocketmq-console/data";
@Getter
private boolean enableDashBoardCollect; private boolean enableDashBoardCollect;
@Setter
@Getter
private boolean loginRequired = false; private boolean loginRequired = false;
private String accessKey; private String accessKey;
@Setter
@Getter
private String secretKey; private String secretKey;
@Setter
@Getter
private boolean useTLS = false; private boolean useTLS = false;
@Setter
@Getter
private Long timeoutMillis; private Long timeoutMillis;
@Getter
private List<String> namesrvAddrs = new ArrayList<>(); private List<String> namesrvAddrs = new ArrayList<>();
@Getter
private List<String> proxyAddrs = new ArrayList<>(); private List<String> proxyAddrs = new ArrayList<>();
public String getAccessKey() { @Setter
return accessKey; @Getter
} private Integer clientCallbackExecutorThreads = 4;
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getNamesrvAddr() {
return namesrvAddr;
}
public List<String> getNamesrvAddrs() {
return namesrvAddrs;
}
public List<String> getProxyAddrs() {
return this.proxyAddrs;
}
public void setProxyAddrs(List<String> proxyAddrs) { public void setProxyAddrs(List<String> proxyAddrs) {
this.proxyAddrs = proxyAddrs; this.proxyAddrs = proxyAddrs;
@@ -101,14 +98,6 @@ public class RMQConfigure {
} }
} }
public String getProxyAddr() {
return proxyAddr;
}
public void setProxyAddr(String proxyAddr) {
this.proxyAddr = proxyAddr;
}
public void setNamesrvAddrs(List<String> namesrvAddrs) { public void setNamesrvAddrs(List<String> namesrvAddrs) {
this.namesrvAddrs = namesrvAddrs; this.namesrvAddrs = namesrvAddrs;
if (CollectionUtils.isNotEmpty(namesrvAddrs)) { if (CollectionUtils.isNotEmpty(namesrvAddrs)) {
@@ -135,14 +124,6 @@ public class RMQConfigure {
return dataPath + File.separator + "dashboard"; return dataPath + File.separator + "dashboard";
} }
public void setDataPath(String dataPath) {
this.dataPath = dataPath;
}
public String getIsVIPChannel() {
return isVIPChannel;
}
public void setIsVIPChannel(String isVIPChannel) { public void setIsVIPChannel(String isVIPChannel) {
if (StringUtils.isNotBlank(isVIPChannel)) { if (StringUtils.isNotBlank(isVIPChannel)) {
this.isVIPChannel = isVIPChannel; this.isVIPChannel = isVIPChannel;
@@ -151,38 +132,10 @@ public class RMQConfigure {
} }
} }
public boolean isEnableDashBoardCollect() {
return enableDashBoardCollect;
}
public void setEnableDashBoardCollect(String enableDashBoardCollect) { public void setEnableDashBoardCollect(String enableDashBoardCollect) {
this.enableDashBoardCollect = Boolean.valueOf(enableDashBoardCollect); this.enableDashBoardCollect = Boolean.valueOf(enableDashBoardCollect);
} }
public boolean isLoginRequired() {
return loginRequired;
}
public void setLoginRequired(boolean loginRequired) {
this.loginRequired = loginRequired;
}
public boolean isUseTLS() {
return useTLS;
}
public void setUseTLS(boolean useTLS) {
this.useTLS = useTLS;
}
public Long getTimeoutMillis() {
return timeoutMillis;
}
public void setTimeoutMillis(Long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}
// Error Page process logic, move to a central configure later // Error Page process logic, move to a central configure later
@Bean @Bean
public ErrorPageRegistrar errorPageRegistrar() { public ErrorPageRegistrar errorPageRegistrar() {

View File

@@ -14,133 +14,90 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.base.Preconditions; import org.apache.rocketmq.dashboard.model.PolicyRequest;
import java.util.List; import org.apache.rocketmq.dashboard.model.request.UserCreateRequest;
import javax.annotation.Resource; import org.apache.rocketmq.dashboard.model.request.UserUpdateRequest;
import javax.servlet.http.HttpServletRequest; import org.apache.rocketmq.dashboard.service.impl.AclServiceImpl;
import org.apache.commons.collections.CollectionUtils; import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.User;
import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.model.request.AclRequest;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.AclService;
import org.apache.rocketmq.dashboard.support.JsonResult;
import org.apache.rocketmq.dashboard.util.WebUtil;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController @RestController
@RequestMapping("/acl") @RequestMapping("/acl")
@Permission
public class AclController { public class AclController {
@Resource @Autowired
private AclService aclService; private AclServiceImpl aclService;
@Resource @GetMapping("/listUsers")
private RMQConfigure configure; @ResponseBody
public List<UserInfo> listUsers(@RequestParam(required = false) String brokerAddress) {
@GetMapping("/enable.query") return aclService.listUsers(brokerAddress);
public Object isEnableAcl() {
return new JsonResult<>(configure.isACLEnabled());
} }
@GetMapping("/config.query") @GetMapping("/listAcls")
public AclConfig getAclConfig(HttpServletRequest request) { @ResponseBody
if (!configure.isLoginRequired()) { public Object listAcls(
return aclService.getAclConfig(false); @RequestParam(required = false) String brokerAddress,
} @RequestParam(required = false) String searchParam) {
UserInfo userInfo = (UserInfo) WebUtil.getValueFromSession(request, WebUtil.USER_INFO); return aclService.listAcls(brokerAddress, searchParam);
// if user info is null but reach here, must exclude secret key for safety.
return aclService.getAclConfig(userInfo == null || userInfo.getUser().getType() != User.ADMIN);
} }
@PostMapping("/add.do") @PostMapping("/createAcl")
public Object addAclConfig(@RequestBody PlainAccessConfig config) { @ResponseBody
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getAccessKey()), "accessKey is null"); public Object createAcl(@RequestBody PolicyRequest request) {
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getSecretKey()), "secretKey is null"); aclService.createAcl(request);
aclService.addAclConfig(config);
return true; return true;
} }
@PostMapping("/delete.do") @DeleteMapping("/deleteUser")
public Object deleteAclConfig(@RequestBody PlainAccessConfig config) { @ResponseBody
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getAccessKey()), "accessKey is null"); public Object deleteUser(@RequestParam(required = false) String brokerAddress, @RequestParam String username) {
aclService.deleteAclConfig(config); aclService.deleteUser(brokerAddress, username);
return true; return true;
} }
@PostMapping("/update.do") @RequestMapping(value = "/updateUser", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Object updateAclConfig(@RequestBody PlainAccessConfig config) { @ResponseBody
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getSecretKey()), "secretKey is null"); public Object updateUser(@RequestBody UserUpdateRequest request) {
aclService.updateAclConfig(config); aclService.updateUser(request.getBrokerAddress(), request.getUserInfo());
return true; return true;
} }
@PostMapping("/topic/add.do") @PostMapping("/createUser")
public Object addAclTopicConfig(@RequestBody AclRequest request) { public Object createUser(@RequestBody UserCreateRequest request) {
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getAccessKey()), "accessKey is null"); aclService.createUser(request.getBrokerAddress(), request.getUserInfo());
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getSecretKey()), "secretKey is null");
Preconditions.checkArgument(CollectionUtils.isNotEmpty(request.getConfig().getTopicPerms()), "topic perms is null");
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getTopicPerm()), "topic perm is null");
aclService.addOrUpdateAclTopicConfig(request);
return true; return true;
} }
@PostMapping("/group/add.do") @DeleteMapping("/deleteAcl")
public Object addAclGroupConfig(@RequestBody AclRequest request) { public Object deleteAcl(
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getAccessKey()), "accessKey is null"); @RequestParam(required = false) String brokerAddress,
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getSecretKey()), "secretKey is null"); @RequestParam String subject,
Preconditions.checkArgument(CollectionUtils.isNotEmpty(request.getConfig().getGroupPerms()), "group perms is null"); @RequestParam(required = false) String resource) {
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getGroupPerm()), "group perm is null"); aclService.deleteAcl(brokerAddress, subject, resource);
aclService.addOrUpdateAclGroupConfig(request);
return true; return true;
} }
@PostMapping("/perm/delete.do") @RequestMapping(value = "/updateAcl", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Object deletePermConfig(@RequestBody AclRequest request) { @ResponseBody
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getAccessKey()), "accessKey is null"); public Object updateAcl(@RequestBody PolicyRequest request) {
Preconditions.checkArgument(StringUtils.isNotEmpty(request.getConfig().getSecretKey()), "secretKey is null"); aclService.updateAcl(request);
aclService.deletePermConfig(request);
return true; return true;
} }
@PostMapping("/sync.do")
public Object syncConfig(@RequestBody PlainAccessConfig config) {
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getAccessKey()), "accessKey is null");
Preconditions.checkArgument(StringUtils.isNotEmpty(config.getSecretKey()), "secretKey is null");
aclService.syncData(config);
return true;
}
@PostMapping("/white/list/add.do")
public Object addWhiteList(@RequestBody List<String> whiteList) {
Preconditions.checkArgument(CollectionUtils.isNotEmpty(whiteList), "white list is null");
aclService.addWhiteList(whiteList);
return true;
}
@DeleteMapping("/white/list/delete.do")
public Object deleteWhiteAddr(@RequestParam String request) {
aclService.deleteWhiteAddr(request);
return true;
}
@PostMapping("/white/list/sync.do")
public Object synchronizeWhiteList(@RequestBody List<String> whiteList) {
Preconditions.checkArgument(CollectionUtils.isNotEmpty(whiteList), "white list is null");
aclService.synchronizeWhiteList(whiteList);
return true;
}
} }

View File

@@ -16,14 +16,13 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ClusterService; import org.apache.rocketmq.dashboard.service.ClusterService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @Controller

View File

@@ -17,9 +17,8 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.dashboard.model.ConnectionInfo; import org.apache.rocketmq.dashboard.model.ConnectionInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo; import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest; import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
@@ -27,6 +26,7 @@ import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ConsumerService; import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.util.JsonUtil; import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;

View File

@@ -17,9 +17,8 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.DashboardService; import org.apache.rocketmq.dashboard.service.DashboardService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;

View File

@@ -17,10 +17,8 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.util.ArrayList; import jakarta.annotation.Resource;
import java.util.List; import jakarta.servlet.http.HttpServletResponse;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
@@ -41,6 +39,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
@Controller @Controller
@RequestMapping("/dlqMessage") @RequestMapping("/dlqMessage")
@Permission @Permission
@@ -61,7 +62,7 @@ public class DlqMessageController {
@GetMapping(value = "/exportDlqMessage.do") @GetMapping(value = "/exportDlqMessage.do")
public void exportDlqMessage(HttpServletResponse response, @RequestParam String consumerGroup, public void exportDlqMessage(HttpServletResponse response, @RequestParam String consumerGroup,
@RequestParam String msgId) { @RequestParam String msgId) {
MessageExt messageExt = null; MessageExt messageExt = null;
try { try {
String topic = MixAll.DLQ_GROUP_TOPIC_PREFIX + consumerGroup; String topic = MixAll.DLQ_GROUP_TOPIC_PREFIX + consumerGroup;

View File

@@ -17,6 +17,9 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.LoginInfo; import org.apache.rocketmq.dashboard.model.LoginInfo;
import org.apache.rocketmq.dashboard.model.LoginResult; import org.apache.rocketmq.dashboard.model.LoginResult;
@@ -32,12 +35,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller @Controller
@RequestMapping("/login") @RequestMapping("/login")
@@ -66,12 +65,11 @@ public class LoginController {
@RequestMapping(value = "/login.do", method = RequestMethod.POST) @RequestMapping(value = "/login.do", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public Object login(@RequestParam("username") String username, public Object login(org.apache.rocketmq.remoting.protocol.body.UserInfo userInfoRequest,
@RequestParam(value = "password") String password, HttpServletRequest request,
HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletResponse response) throws Exception { logger.info("user:{} login", userInfoRequest.getUsername());
logger.info("user:{} login", username); User user = userService.queryByUsernameAndPassword(userInfoRequest.getUsername(), userInfoRequest.getPassword());
User user = userService.queryByUsernameAndPassword(username, password);
if (user == null) { if (user == null) {
throw new IllegalArgumentException("Bad username or password!"); throw new IllegalArgumentException("Bad username or password!");
@@ -79,9 +77,9 @@ public class LoginController {
user.setPassword(null); user.setPassword(null);
UserInfo userInfo = WebUtil.setLoginInfo(request, response, user); UserInfo userInfo = WebUtil.setLoginInfo(request, response, user);
WebUtil.setSessionValue(request, WebUtil.USER_INFO, userInfo); WebUtil.setSessionValue(request, WebUtil.USER_INFO, userInfo);
WebUtil.setSessionValue(request, WebUtil.USER_NAME, username); WebUtil.setSessionValue(request, WebUtil.USER_NAME, userInfoRequest.getUsername());
userInfo.setSessionId(WebUtil.getSessionId(request)); userInfo.setSessionId(WebUtil.getSessionId(request));
LoginResult result = new LoginResult(username, user.getType(), contextPath); LoginResult result = new LoginResult(userInfoRequest.getUsername(), user.getType(), contextPath);
return result; return result;
} }
} }

View File

@@ -17,26 +17,26 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import org.apache.rocketmq.common.Pair; import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.dashboard.model.MessagePage; import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.MessageView; import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.request.MessageQuery; import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.MessageService; import org.apache.rocketmq.dashboard.service.MessageService;
import org.apache.rocketmq.dashboard.util.JsonUtil; import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.tools.admin.api.MessageTrack; import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@@ -18,11 +18,7 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.rocketmq.common.Pair; import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.dashboard.model.MessageView; import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph; import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph;
@@ -36,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
@Controller @Controller
@RequestMapping("/messageTrace") @RequestMapping("/messageTrace")
@Permission @Permission

View File

@@ -16,7 +16,7 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig; import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.MonitorService; import org.apache.rocketmq.dashboard.service.MonitorService;

View File

@@ -16,7 +16,7 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.aspect.admin.annotation.OriginalControllerReturnValue; import org.apache.rocketmq.dashboard.aspect.admin.annotation.OriginalControllerReturnValue;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.OpsService; import org.apache.rocketmq.dashboard.service.OpsService;

View File

@@ -17,7 +17,7 @@
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.OpsService; import org.apache.rocketmq.dashboard.service.OpsService;

View File

@@ -16,11 +16,12 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import javax.annotation.Resource;
import org.apache.rocketmq.remoting.protocol.body.ProducerConnection; import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.model.ConnectionInfo; import org.apache.rocketmq.dashboard.model.ConnectionInfo;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ProducerService; import org.apache.rocketmq.dashboard.service.ProducerService;
import org.apache.rocketmq.remoting.protocol.body.ProducerConnection;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;

View File

@@ -16,6 +16,7 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.permisssion.Permission; import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ProxyService; import org.apache.rocketmq.dashboard.service.ProxyService;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@@ -24,8 +25,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
@Controller @Controller
@RequestMapping("/proxy") @RequestMapping("/proxy")
@Permission @Permission
@@ -38,6 +37,7 @@ public class ProxyController {
return proxyService.getProxyHomePage(); return proxyService.getProxyHomePage();
} }
@RequestMapping(value = "/addProxyAddr.do", method = RequestMethod.POST) @RequestMapping(value = "/addProxyAddr.do", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public Object addProxyAddr(@RequestParam String newProxyAddr) { public Object addProxyAddr(@RequestParam String newProxyAddr) {

View File

@@ -16,6 +16,7 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import jakarta.annotation.Resource;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
@@ -26,11 +27,9 @@ import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere; import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.util.List;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.util.JsonUtil; import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@@ -38,6 +37,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller @Controller
@RequestMapping("/test") @RequestMapping("/test")
public class TestController { public class TestController {

View File

@@ -16,16 +16,17 @@
*/ */
package org.apache.rocketmq.dashboard.controller; package org.apache.rocketmq.dashboard.controller;
import com.google.common.base.Preconditions;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest; import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo; import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
import org.apache.rocketmq.dashboard.permisssion.Permission;
import org.apache.rocketmq.dashboard.service.ConsumerService; import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.service.TopicService; import org.apache.rocketmq.dashboard.service.TopicService;
import org.apache.rocketmq.dashboard.util.JsonUtil; import org.apache.rocketmq.dashboard.util.JsonUtil;
import com.google.common.base.Preconditions; import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@@ -33,8 +34,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @Controller

View File

@@ -17,27 +17,29 @@
package org.apache.rocketmq.dashboard.filter; package org.apache.rocketmq.dashboard.filter;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
@WebFilter(urlPatterns = "/*", filterName = "httpBasicAuthorizedFilter") @WebFilter(urlPatterns = "/*", filterName = "httpBasicAuthorizedFilter")
public class HttpBasicAuthorizedFilter implements Filter { public class HttpBasicAuthorizedFilter implements Filter {
@Override @Override
public void init(FilterConfig config) throws ServletException { public void init(FilterConfig config) throws ServletException {
} }
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) response; HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding("UTF-8"); httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json; charset=utf-8"); httpResponse.setContentType("application/json; charset=utf-8");

View File

@@ -17,22 +17,24 @@
package org.apache.rocketmq.dashboard.interceptor; package org.apache.rocketmq.dashboard.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.rocketmq.dashboard.service.LoginService; import org.apache.rocketmq.dashboard.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component @Component
public class AuthInterceptor extends HandlerInterceptorAdapter { public class AuthInterceptor implements HandlerInterceptor {
@Autowired @Autowired
private LoginService loginService; private LoginService loginService;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
throws Exception {
return loginService.login(request, response); return loginService.login(request, response);
} }
} }

View File

@@ -17,11 +17,12 @@
package org.apache.rocketmq.dashboard.model; package org.apache.rocketmq.dashboard.model;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.HashSet;
import org.apache.rocketmq.common.MQVersion; import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.remoting.protocol.body.Connection; import org.apache.rocketmq.remoting.protocol.body.Connection;
import java.util.Collection;
import java.util.HashSet;
public class ConnectionInfo extends Connection { public class ConnectionInfo extends Connection {
private String versionDesc; private String versionDesc;

View File

@@ -16,8 +16,8 @@
*/ */
package org.apache.rocketmq.dashboard.model; package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import java.util.List; import java.util.List;

View File

@@ -22,12 +22,13 @@ import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.metadata.BaseRowModel; import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.DateUtils;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import java.io.Serializable;
import java.util.Date;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import java.io.Serializable;
import java.util.Date;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
public class DlqMessageExcelModel extends BaseRowModel implements Serializable { public class DlqMessageExcelModel extends BaseRowModel implements Serializable {

View File

@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Setter
@Getter
public class Entry {
private List<String> resource;
private List<String> actions;
private List<String> sourceIps;
private String decision;
}

View File

@@ -16,8 +16,8 @@
*/ */
package org.apache.rocketmq.dashboard.model; package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.common.message.MessageExt;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import java.net.SocketAddress; import java.net.SocketAddress;

View File

@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Setter
@Getter
public class Policy {
private String policyType;
private List<Entry> entries;
}

View File

@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class PolicyRequest {
private String brokerAddress;
private String subject;
private List<Policy> policies;
}

View File

@@ -16,8 +16,8 @@
*/ */
package org.apache.rocketmq.dashboard.model; package org.apache.rocketmq.dashboard.model;
import org.apache.rocketmq.remoting.protocol.admin.OffsetWrapper;
import org.apache.rocketmq.common.message.MessageQueue; import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.protocol.admin.OffsetWrapper;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
public class QueueStatInfo { public class QueueStatInfo {

View File

@@ -17,7 +17,8 @@
package org.apache.rocketmq.dashboard.model.request; package org.apache.rocketmq.dashboard.model.request;
import lombok.Data; import lombok.Data;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.auth.migration.v1.PlainAccessConfig;
@Data @Data
public class AclRequest { public class AclRequest {

View File

@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class UserCreateRequest {
private String brokerAddress;
private UserInfoParam userInfo;
}

View File

@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import lombok.Data;
@Data
public class UserInfoParam {
private String username;
private String password;
private String userStatus;
private String userType;
}

View File

@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.model.request;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserUpdateRequest {
private String brokerAddress;
private UserInfoParam userInfo;
}

View File

@@ -16,10 +16,9 @@
*/ */
package org.apache.rocketmq.dashboard.permisssion; package org.apache.rocketmq.dashboard.permisssion;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.UserInfo; import org.apache.rocketmq.dashboard.model.UserInfo;
import org.apache.rocketmq.dashboard.service.PermissionService; import org.apache.rocketmq.dashboard.service.PermissionService;
import org.apache.rocketmq.dashboard.util.WebUtil; import org.apache.rocketmq.dashboard.util.WebUtil;
@@ -56,13 +55,13 @@ public class PermissionAspect {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String url = request.getRequestURI(); String url = request.getRequestURI();
UserInfo userInfo = (UserInfo) request.getSession().getAttribute(WebUtil.USER_INFO); UserInfo userInfo = (UserInfo) request.getSession().getAttribute(WebUtil.USER_INFO);
if (userInfo == null || userInfo.getUser() == null) { // if (userInfo == null || userInfo.getUser() == null) {
throw new ServiceException(-1, "user not login"); // throw new ServiceException(-1, "user not login");
} // }
boolean checkResult = permissionService.checkUrlAvailable(userInfo, url); // boolean checkResult = permissionService.checkUrlAvailable(userInfo, url);
if (!checkResult) { // if (!checkResult) {
throw new ServiceException(-1, "no permission"); // throw new ServiceException(-1, "no permission");
} // }
} }
return joinPoint.proceed(); return joinPoint.proceed();
} }

View File

@@ -16,14 +16,15 @@
*/ */
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
public abstract class AbstractCommonService { public abstract class AbstractCommonService {
@Resource @Resource

View File

@@ -14,34 +14,30 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.dashboard.model.PolicyRequest;
import org.apache.rocketmq.dashboard.model.request.UserInfoParam;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import java.util.List; import java.util.List;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.dashboard.model.request.AclRequest;
public interface AclService { public interface AclService {
List<UserInfo> listUsers(String brokerAddress);
AclConfig getAclConfig(boolean excludeSecretKey); Object listAcls(String brokerAddress, String searchParam);
void addAclConfig(PlainAccessConfig config); List<String> createAcl(PolicyRequest policyRequest);
void deleteAclConfig(PlainAccessConfig config); void deleteUser(String brokerAddress, String username);
void updateAclConfig(PlainAccessConfig config); void updateUser(String brokerAddress, UserInfoParam userParam);
void addOrUpdateAclTopicConfig(AclRequest request); void createUser(String brokerAddress, UserInfoParam userParam);
void addOrUpdateAclGroupConfig(AclRequest request); void deleteAcl(String brokerAddress, String subject, String resource);
void deletePermConfig(AclRequest request); void updateAcl(PolicyRequest policyRequest);
void syncData(PlainAccessConfig config);
void addWhiteList(List<String> whiteList);
void deleteWhiteAddr(String addr);
void synchronizeWhiteList(List<String> whiteList);
} }

View File

@@ -16,14 +16,14 @@
*/ */
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo; import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -33,7 +33,7 @@ import java.util.concurrent.atomic.AtomicReference;
@Service @Service
public class ClusterInfoService { public class ClusterInfoService {
@Resource @Autowired
private MQAdminExt mqAdminExt; private MQAdminExt mqAdminExt;
@Value("${rocketmq.cluster.cache.expire:60000}") @Value("${rocketmq.cluster.cache.expire:60000}")

View File

@@ -17,14 +17,14 @@
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo; import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest; import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest; import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection; import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.remoting.protocol.body.ConsumerRunningInfo; import org.apache.rocketmq.remoting.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@@ -17,6 +17,7 @@
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@@ -17,12 +17,13 @@
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import java.util.List;
import org.apache.rocketmq.dashboard.model.DlqMessageResendResult;
import org.apache.rocketmq.dashboard.model.DlqMessageRequest; import org.apache.rocketmq.dashboard.model.DlqMessageRequest;
import org.apache.rocketmq.dashboard.model.DlqMessageResendResult;
import org.apache.rocketmq.dashboard.model.MessagePage; import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.request.MessageQuery; import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import java.util.List;
public interface DlqMessageService { public interface DlqMessageService {
MessagePage queryDlqMessageByPage(MessageQuery query); MessagePage queryDlqMessageByPage(MessageQuery query);

View File

@@ -17,8 +17,9 @@
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public interface LoginService { public interface LoginService {
boolean login(HttpServletRequest request, HttpServletResponse response); boolean login(HttpServletRequest request, HttpServletResponse response);

View File

@@ -19,11 +19,11 @@ package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.common.Pair; import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.dashboard.model.MessagePage; import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.apache.rocketmq.dashboard.model.MessageView; import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.tools.admin.api.MessageTrack;
import java.util.List; import java.util.List;

View File

@@ -17,10 +17,11 @@
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import java.util.List;
import org.apache.rocketmq.dashboard.model.MessageTraceView; import org.apache.rocketmq.dashboard.model.MessageTraceView;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph; import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph;
import java.util.List;
public interface MessageTraceService { public interface MessageTraceService {
List<MessageTraceView> queryMessageTraceKey(final String key); List<MessageTraceView> queryMessageTraceKey(final String key);

View File

@@ -16,9 +16,10 @@
*/ */
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import java.util.Map;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig; import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
import java.util.Map;
public interface MonitorService { public interface MonitorService {
boolean createOrUpdateConsumerMonitor(String name, ConsumerMonitorConfig config); boolean createOrUpdateConsumerMonitor(String name, ConsumerMonitorConfig config);

View File

@@ -16,9 +16,10 @@
*/ */
package org.apache.rocketmq.dashboard.service; package org.apache.rocketmq.dashboard.service;
import java.util.Map;
import org.apache.rocketmq.dashboard.service.checker.CheckerType; import org.apache.rocketmq.dashboard.service.checker.CheckerType;
import java.util.Map;
public interface OpsService { public interface OpsService {
Map<String, Object> homePageInfo(); Map<String, Object> homePageInfo();

View File

@@ -19,13 +19,13 @@ package org.apache.rocketmq.dashboard.service;
import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
import org.apache.rocketmq.dashboard.model.request.TopicTypeList; import org.apache.rocketmq.dashboard.model.request.TopicTypeList;
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable; import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
import org.apache.rocketmq.remoting.protocol.body.GroupList; import org.apache.rocketmq.remoting.protocol.body.GroupList;
import org.apache.rocketmq.remoting.protocol.body.TopicList; import org.apache.rocketmq.remoting.protocol.body.TopicList;
import org.apache.rocketmq.remoting.protocol.route.TopicRouteData; import org.apache.rocketmq.remoting.protocol.route.TopicRouteData;
import org.apache.rocketmq.dashboard.model.request.SendTopicMessageRequest;
import org.apache.rocketmq.dashboard.model.request.TopicConfigInfo;
import java.util.List; import java.util.List;

View File

@@ -22,4 +22,5 @@ public interface UserService {
User queryByName(String name); User queryByName(String name);
User queryByUsernameAndPassword(String username, String password); User queryByUsernameAndPassword(String username, String password);
} }

View File

@@ -17,34 +17,34 @@
package org.apache.rocketmq.dashboard.service.client; package org.apache.rocketmq.dashboard.service.client;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.rocketmq.client.QueryResult; import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.exception.MQBrokerException; import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.MQAdminImpl; import org.apache.rocketmq.client.impl.MQAdminImpl;
import org.apache.rocketmq.common.AclConfig; import org.apache.rocketmq.common.CheckRocksdbCqWriteResult;
import org.apache.rocketmq.common.PlainAccessConfig; import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.common.TopicConfig; import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.remoting.protocol.admin.ConsumeStats;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
import org.apache.rocketmq.common.message.MessageClientIDSetter; import org.apache.rocketmq.common.message.MessageClientIDSetter;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue; import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.message.MessageRequestMode; import org.apache.rocketmq.common.message.MessageRequestMode;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.remoting.protocol.RequestCode; import org.apache.rocketmq.remoting.protocol.RequestCode;
import org.apache.rocketmq.remoting.protocol.ResponseCode; import org.apache.rocketmq.remoting.protocol.ResponseCode;
import org.apache.rocketmq.remoting.protocol.admin.ConsumeStats;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import org.apache.rocketmq.remoting.protocol.admin.TopicStatsTable;
import org.apache.rocketmq.remoting.protocol.body.AclInfo;
import org.apache.rocketmq.remoting.protocol.body.BrokerMemberGroup;
import org.apache.rocketmq.remoting.protocol.body.BrokerReplicasInfo; import org.apache.rocketmq.remoting.protocol.body.BrokerReplicasInfo;
import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData; import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData;
import org.apache.rocketmq.remoting.protocol.body.ClusterAclVersionInfo;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo; import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult; import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.remoting.protocol.body.ConsumeStatsList; import org.apache.rocketmq.remoting.protocol.body.ConsumeStatsList;
@@ -61,6 +61,8 @@ import org.apache.rocketmq.remoting.protocol.body.QueueTimeSpan;
import org.apache.rocketmq.remoting.protocol.body.SubscriptionGroupWrapper; import org.apache.rocketmq.remoting.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.remoting.protocol.body.TopicConfigSerializeWrapper; import org.apache.rocketmq.remoting.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.remoting.protocol.body.TopicList; import org.apache.rocketmq.remoting.protocol.body.TopicList;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.rocketmq.remoting.protocol.header.ExportRocksDBConfigToJsonRequestHeader;
import org.apache.rocketmq.remoting.protocol.header.controller.ElectMasterResponseHeader; import org.apache.rocketmq.remoting.protocol.header.controller.ElectMasterResponseHeader;
import org.apache.rocketmq.remoting.protocol.header.controller.GetMetaDataResponseHeader; import org.apache.rocketmq.remoting.protocol.header.controller.GetMetaDataResponseHeader;
import org.apache.rocketmq.remoting.protocol.heartbeat.SubscriptionData; import org.apache.rocketmq.remoting.protocol.heartbeat.SubscriptionData;
@@ -68,14 +70,6 @@ import org.apache.rocketmq.remoting.protocol.route.TopicRouteData;
import org.apache.rocketmq.remoting.protocol.statictopic.TopicQueueMappingDetail; import org.apache.rocketmq.remoting.protocol.statictopic.TopicQueueMappingDetail;
import org.apache.rocketmq.remoting.protocol.subscription.GroupForbidden; import org.apache.rocketmq.remoting.protocol.subscription.GroupForbidden;
import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig; import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.tools.admin.api.BrokerOperatorResult; import org.apache.rocketmq.tools.admin.api.BrokerOperatorResult;
import org.apache.rocketmq.tools.admin.api.MessageTrack; import org.apache.rocketmq.tools.admin.api.MessageTrack;
@@ -85,6 +79,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.apache.rocketmq.remoting.protocol.RemotingSerializable.decode; import static org.apache.rocketmq.remoting.protocol.RemotingSerializable.decode;
@Service @Service
@@ -114,34 +116,10 @@ public class MQAdminExtImpl implements MQAdminExt {
} }
@Override @Override
public void createAndUpdatePlainAccessConfig(String addr, public void createAndUpdateTopicConfigList(String s, List<TopicConfig> list) throws InterruptedException, RemotingException, MQClientException {
PlainAccessConfig plainAccessConfig) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().createAndUpdatePlainAccessConfig(addr, plainAccessConfig);
} }
@Override
public void deletePlainAccessConfig(String addr,
String accessKey) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().deletePlainAccessConfig(addr, accessKey);
}
@Override
public void updateGlobalWhiteAddrConfig(String addr,
String globalWhiteAddrs) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
MQAdminInstance.threadLocalMQAdminExt().updateGlobalWhiteAddrConfig(addr, globalWhiteAddrs);
}
@Override
public ClusterAclVersionInfo examineBrokerClusterAclVersionInfo(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return null;
}
@Override
public AclConfig examineBrokerClusterAclConfig(
String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().examineBrokerClusterAclConfig(addr);
}
@Override @Override
public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config) public void createAndUpdateSubscriptionGroupConfig(String addr, SubscriptionGroupConfig config)
@@ -149,6 +127,11 @@ public class MQAdminExtImpl implements MQAdminExt {
MQAdminInstance.threadLocalMQAdminExt().createAndUpdateSubscriptionGroupConfig(addr, config); MQAdminInstance.threadLocalMQAdminExt().createAndUpdateSubscriptionGroupConfig(addr, config);
} }
@Override
public void createAndUpdateSubscriptionGroupConfigList(String s, List<SubscriptionGroupConfig> list) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
}
@Override @Override
public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) throws MQBrokerException { public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group) throws MQBrokerException {
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient(); RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
@@ -228,12 +211,22 @@ public class MQAdminExtImpl implements MQAdminExt {
return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup); return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup);
} }
@Override
public CheckRocksdbCqWriteResult checkRocksdbCqWriteProgress(String s, String s1, long l) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException {
return null;
}
@Override @Override
public ConsumeStats examineConsumeStats(String consumerGroup, String topic) public ConsumeStats examineConsumeStats(String consumerGroup, String topic)
throws RemotingException, MQClientException, InterruptedException, MQBrokerException { throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup, topic); return MQAdminInstance.threadLocalMQAdminExt().examineConsumeStats(consumerGroup, topic);
} }
@Override
public ConsumeStats examineConsumeStats(String s, String s1, String s2) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return null;
}
@Override @Override
public ClusterInfo examineBrokerClusterInfo() public ClusterInfo examineBrokerClusterInfo()
throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException, throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException,
@@ -344,6 +337,11 @@ public class MQAdminExtImpl implements MQAdminExt {
return MQAdminInstance.threadLocalMQAdminExt().resetOffsetByTimestamp(topic, group, timestamp, isForce); return MQAdminInstance.threadLocalMQAdminExt().resetOffsetByTimestamp(topic, group, timestamp, isForce);
} }
@Override
public Map<MessageQueue, Long> resetOffsetByTimestamp(String s, String s1, String s2, long l, boolean b) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return Map.of();
}
@Override @Override
public void resetOffsetNew(String consumerGroup, String topic, long timestamp) public void resetOffsetNew(String consumerGroup, String topic, long timestamp)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException { throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
@@ -389,11 +387,6 @@ public class MQAdminExtImpl implements MQAdminExt {
return MQAdminInstance.threadLocalMQAdminExt().getConsumerRunningInfo(consumerGroup, clientId, jstack); return MQAdminInstance.threadLocalMQAdminExt().getConsumerRunningInfo(consumerGroup, clientId, jstack);
} }
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String consumerGroup, String clientId,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().consumeMessageDirectly(consumerGroup, clientId, msgId);
}
@Override @Override
public List<MessageTrack> messageTrackDetail(MessageExt msg) public List<MessageTrack> messageTrackDetail(MessageExt msg)
@@ -438,12 +431,6 @@ public class MQAdminExtImpl implements MQAdminExt {
return MQAdminInstance.threadLocalMQAdminExt().earliestMsgStoreTime(mq); return MQAdminInstance.threadLocalMQAdminExt().earliestMsgStoreTime(mq);
} }
@Override
public MessageExt viewMessage(String msgId)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
return MQAdminInstance.threadLocalMQAdminExt().viewMessage(msgId);
}
@Override @Override
public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end) public QueryResult queryMessage(String topic, String key, int maxNum, long begin, long end)
throws MQClientException, InterruptedException { throws MQClientException, InterruptedException {
@@ -478,10 +465,6 @@ public class MQAdminExtImpl implements MQAdminExt {
public MessageExt viewMessage(String topic, public MessageExt viewMessage(String topic,
String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
logger.info("MessageClientIDSetter.getNearlyTimeFromID(msgId)={} msgId={}", MessageClientIDSetter.getNearlyTimeFromID(msgId), msgId); logger.info("MessageClientIDSetter.getNearlyTimeFromID(msgId)={} msgId={}", MessageClientIDSetter.getNearlyTimeFromID(msgId), msgId);
try {
return viewMessage(msgId);
} catch (Exception e) {
}
MQAdminImpl mqAdminImpl = MQAdminInstance.threadLocalMqClientInstance().getMQAdminImpl(); MQAdminImpl mqAdminImpl = MQAdminInstance.threadLocalMqClientInstance().getMQAdminImpl();
Set<String> clusterList = MQAdminInstance.threadLocalMQAdminExt().getTopicClusterList(topic); Set<String> clusterList = MQAdminInstance.threadLocalMQAdminExt().getTopicClusterList(topic);
if (clusterList == null || clusterList.isEmpty()) { if (clusterList == null || clusterList.isEmpty()) {
@@ -508,6 +491,11 @@ public class MQAdminExtImpl implements MQAdminExt {
return MQAdminInstance.threadLocalMQAdminExt().consumeMessageDirectly(consumerGroup, clientId, topic, msgId); return MQAdminInstance.threadLocalMQAdminExt().consumeMessageDirectly(consumerGroup, clientId, topic, msgId);
} }
@Override
public ConsumeMessageDirectlyResult consumeMessageDirectly(String s, String s1, String s2, String s3, String s4) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return null;
}
@Override @Override
public Properties getBrokerConfig( public Properties getBrokerConfig(
String brokerAddr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException { String brokerAddr) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException {
@@ -603,11 +591,12 @@ public class MQAdminExtImpl implements MQAdminExt {
return null; return null;
} }
@Override public boolean resumeCheckHalfMessage( @Override
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { public void exportRocksDBConfigToJson(String s, List<ExportRocksDBConfigToJsonRequestHeader.ConfigType> list) throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQClientException {
return false;
} }
@Override public boolean resumeCheckHalfMessage(String topic, @Override public boolean resumeCheckHalfMessage(String topic,
String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException { String msgId) throws RemotingException, MQClientException, InterruptedException, MQBrokerException {
return false; return false;
@@ -628,12 +617,6 @@ public class MQAdminExtImpl implements MQAdminExt {
throw new UnsupportedOperationException("Unimplemented method 'removeBrokerFromContainer'"); throw new UnsupportedOperationException("Unimplemented method 'removeBrokerFromContainer'");
} }
@Override
public void updateGlobalWhiteAddrConfig(String addr, String globalWhiteAddrs, String aclFileFullPath)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'updateGlobalWhiteAddrConfig'");
}
@Override @Override
public TopicStatsTable examineTopicStats(String brokerAddr, String topic) public TopicStatsTable examineTopicStats(String brokerAddr, String topic)
@@ -851,10 +834,8 @@ public class MQAdminExtImpl implements MQAdminExt {
} }
@Override @Override
public ElectMasterResponseHeader electMaster(String controllerAddr, String clusterName, String brokerName, public Pair<ElectMasterResponseHeader, BrokerMemberGroup> electMaster(String s, String s1, String s2, Long aLong) throws RemotingException, InterruptedException, MQBrokerException {
String brokerAddr) throws RemotingException, InterruptedException, MQBrokerException { return null;
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'electMaster'");
} }
@Override @Override
@@ -864,4 +845,125 @@ public class MQAdminExtImpl implements MQAdminExt {
// TODO Auto-generated method stub // TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'cleanControllerBrokerData'"); throw new UnsupportedOperationException("Unimplemented method 'cleanControllerBrokerData'");
} }
@Override
public void updateColdDataFlowCtrGroupConfig(String brokerAddr, Properties properties)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
UnsupportedEncodingException, InterruptedException, MQBrokerException {
MQAdminInstance.threadLocalMQAdminExt().updateColdDataFlowCtrGroupConfig(brokerAddr, properties);
}
@Override
public void removeColdDataFlowCtrGroupConfig(String brokerAddr, String consumerGroup)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
UnsupportedEncodingException, InterruptedException, MQBrokerException {
MQAdminInstance.threadLocalMQAdminExt().removeColdDataFlowCtrGroupConfig(brokerAddr, consumerGroup);
}
@Override
public String getColdDataFlowCtrInfo(String brokerAddr)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
UnsupportedEncodingException, InterruptedException, MQBrokerException {
return MQAdminInstance.threadLocalMQAdminExt().getColdDataFlowCtrInfo(brokerAddr);
}
@Override
public String setCommitLogReadAheadMode(String brokerAddr, String mode)
throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,
InterruptedException, MQBrokerException, UnsupportedEncodingException {
return MQAdminInstance.threadLocalMQAdminExt().setCommitLogReadAheadMode(brokerAddr, mode);
}
@Override
public void createUser(String brokerAddr,
UserInfo userInfo) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().createUser(brokerAddr, userInfo);
}
@Override
public void createUser(String brokerAddr, String username, String password,
String userType) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().createUser(brokerAddr, username, password, userType);
}
@Override
public void updateUser(String brokerAddr, String username,
String password, String userType,
String userStatus) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().updateUser(brokerAddr, username, password, userType, userStatus);
}
@Override
public void updateUser(String brokerAddr,
UserInfo userInfo) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().updateUser(brokerAddr, userInfo);
}
@Override
public void deleteUser(String brokerAddr,
String username) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().deleteUser(brokerAddr, username);
}
@Override
public UserInfo getUser(String brokerAddr,
String username) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getUser(brokerAddr, username);
}
@Override
public List<UserInfo> listUser(String brokerAddr,
String filter) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().listUser(brokerAddr, filter);
}
@Override
public void createAcl(String brokerAddr, String subject, List<String> resources, List<String> actions,
List<String> sourceIps,
String decision) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().createAcl(brokerAddr, subject, resources, actions, sourceIps, decision);
}
@Override
public void createAcl(String brokerAddr,
AclInfo aclInfo) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().createAcl(brokerAddr, aclInfo);
}
@Override
public void updateAcl(String brokerAddr, String subject, List<String> resources, List<String> actions,
List<String> sourceIps,
String decision) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().updateAcl(brokerAddr, subject, resources, actions, sourceIps, decision);
}
@Override
public void updateAcl(String brokerAddr,
AclInfo aclInfo) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().updateAcl(brokerAddr, aclInfo);
}
@Override
public void deleteAcl(String brokerAddr, String subject,
String resource) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().deleteAcl(brokerAddr, subject, resource);
}
@Override
public AclInfo getAcl(String brokerAddr,
String subject) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().getAcl(brokerAddr, subject);
}
@Override
public List<AclInfo> listAcl(String brokerAddr, String subjectFilter,
String resourceFilter) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
return MQAdminInstance.threadLocalMQAdminExt().listAcl(brokerAddr, subjectFilter, resourceFilter);
}
@Override
public void exportPopRecords(String brokerAddr, long timeout) throws RemotingConnectException,
RemotingSendRequestException, RemotingTimeoutException, MQBrokerException, InterruptedException {
MQAdminInstance.threadLocalMQAdminExt().exportPopRecords(brokerAddr, timeout);
}
} }

View File

@@ -16,7 +16,6 @@
*/ */
package org.apache.rocketmq.dashboard.service.client; package org.apache.rocketmq.dashboard.service.client;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.client.impl.MQClientAPIImpl; import org.apache.rocketmq.client.impl.MQClientAPIImpl;
import org.apache.rocketmq.client.impl.factory.MQClientInstance; import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.remoting.RemotingClient; import org.apache.rocketmq.remoting.RemotingClient;
@@ -29,47 +28,69 @@ import org.slf4j.LoggerFactory;
public class MQAdminInstance { public class MQAdminInstance {
private static final Logger LOGGER = LoggerFactory.getLogger(MQAdminInstance.class); private static final Logger LOGGER = LoggerFactory.getLogger(MQAdminInstance.class);
// ThreadLocal to store the MQAdminExt instance for the current thread.
private static final ThreadLocal<MQAdminExt> MQ_ADMIN_EXT_THREAD_LOCAL = new ThreadLocal<>(); private static final ThreadLocal<MQAdminExt> MQ_ADMIN_EXT_THREAD_LOCAL = new ThreadLocal<>();
/**
* Retrieves the MQAdminExt instance associated with the current thread.
*
* @return The MQAdminExt instance.
* @throws IllegalStateException if no MQAdminExt instance has been set for the current thread.
*/
public static MQAdminExt threadLocalMQAdminExt() { public static MQAdminExt threadLocalMQAdminExt() {
MQAdminExt mqAdminExt = MQ_ADMIN_EXT_THREAD_LOCAL.get(); MQAdminExt mqAdminExt = MQ_ADMIN_EXT_THREAD_LOCAL.get();
if (mqAdminExt == null) { if (mqAdminExt == null) {
throw new IllegalStateException("defaultMQAdminExt should be init before you get this"); // This indicates a programming error: MQAdminExt was not set by the aspect.
throw new IllegalStateException("MQAdminExt instance should be set by MQAdminAspect before it's accessed.");
} }
return mqAdminExt; return mqAdminExt;
} }
public static RemotingClient threadLocalRemotingClient() { /**
* Retrieves the RemotingClient from the MQAdminExt instance in the current thread.
* This method relies on reflection and the internal structure of RocketMQ classes.
*
* @return The RemotingClient instance.
*/
public static RemotingClient threadLocalRemotingClient() { // Assuming RemotingClient is a type you have
MQClientInstance mqClientInstance = threadLocalMqClientInstance(); MQClientInstance mqClientInstance = threadLocalMqClientInstance();
// Use jOOQ-Reflect to access private field "mQClientAPIImpl" from mqClientInstance
MQClientAPIImpl mQClientAPIImpl = Reflect.on(mqClientInstance).get("mQClientAPIImpl"); MQClientAPIImpl mQClientAPIImpl = Reflect.on(mqClientInstance).get("mQClientAPIImpl");
// Use jOOQ-Reflect to access private field "remotingClient" from mQClientAPIImpl
return Reflect.on(mQClientAPIImpl).get("remotingClient"); return Reflect.on(mQClientAPIImpl).get("remotingClient");
} }
/**
* Retrieves the MQClientInstance from the MQAdminExt instance in the current thread.
* This method relies on reflection and the internal structure of RocketMQ classes.
*
* @return The MQClientInstance instance.
*/
public static MQClientInstance threadLocalMqClientInstance() { public static MQClientInstance threadLocalMqClientInstance() {
// Use jOOQ-Reflect to access private field "defaultMQAdminExtImpl" from threadLocalMQAdminExt()
DefaultMQAdminExtImpl defaultMQAdminExtImpl = Reflect.on(MQAdminInstance.threadLocalMQAdminExt()).get("defaultMQAdminExtImpl"); DefaultMQAdminExtImpl defaultMQAdminExtImpl = Reflect.on(MQAdminInstance.threadLocalMQAdminExt()).get("defaultMQAdminExtImpl");
// Use jOOQ-Reflect to access private field "mqClientInstance" from defaultMQAdminExtImpl
return Reflect.on(defaultMQAdminExtImpl).get("mqClientInstance"); return Reflect.on(defaultMQAdminExtImpl).get("mqClientInstance");
} }
public static void createMQAdmin(GenericObjectPool<MQAdminExt> mqAdminExtPool) { /**
try { * Sets the MQAdminExt instance for the current thread.
// Get the mqAdmin instance from the object pool * This method should be called by the aspect after borrowing an instance from the pool.
MQAdminExt mqAdminExt = mqAdminExtPool.borrowObject(); *
MQ_ADMIN_EXT_THREAD_LOCAL.set(mqAdminExt); * @param mqAdminExt The MQAdminExt instance to set.
} catch (Exception e) { */
LOGGER.error("get mqAdmin from pool error", e); public static void setCurrentMQAdminExt(MQAdminExt mqAdminExt) {
} MQ_ADMIN_EXT_THREAD_LOCAL.set(mqAdminExt);
LOGGER.debug("Set MQAdminExt instance for current thread: {}", mqAdminExt);
} }
public static void returnMQAdmin(GenericObjectPool<MQAdminExt> mqAdminExtPool) { /**
MQAdminExt mqAdminExt = MQ_ADMIN_EXT_THREAD_LOCAL.get(); * Clears the MQAdminExt instance from the current thread.
if (mqAdminExt != null) { * This method should be called by the aspect after returning the instance to the pool.
try { */
// After execution, return the mqAdmin instance to the object pool public static void clearCurrentMQAdminExt() {
mqAdminExtPool.returnObject(mqAdminExt);
} catch (Exception e) {
LOGGER.error("return mqAdmin to pool error", e);
}
}
MQ_ADMIN_EXT_THREAD_LOCAL.remove(); MQ_ADMIN_EXT_THREAD_LOCAL.remove();
LOGGER.debug("Cleared MQAdminExt instance from current thread.");
} }
} }

View File

@@ -17,7 +17,6 @@
package org.apache.rocketmq.dashboard.service.client; package org.apache.rocketmq.dashboard.service.client;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.client.exception.MQBrokerException; import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.remoting.RemotingClient; import org.apache.rocketmq.remoting.RemotingClient;
import org.apache.rocketmq.remoting.exception.RemotingConnectException; import org.apache.rocketmq.remoting.exception.RemotingConnectException;
@@ -26,8 +25,6 @@ import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.protocol.RemotingCommand; import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection; import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.remoting.protocol.header.GetConsumerConnectionListRequestHeader; import org.apache.rocketmq.remoting.protocol.header.GetConsumerConnectionListRequestHeader;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import static org.apache.rocketmq.remoting.protocol.RequestCode.GET_CONSUMER_CONNECTION_LIST; import static org.apache.rocketmq.remoting.protocol.RequestCode.GET_CONSUMER_CONNECTION_LIST;
@@ -35,13 +32,10 @@ import static org.apache.rocketmq.remoting.protocol.RequestCode.GET_CONSUMER_CON
@Slf4j @Slf4j
@Service @Service
public class ProxyAdminImpl implements ProxyAdmin { public class ProxyAdminImpl implements ProxyAdmin {
@Autowired
private GenericObjectPool<MQAdminExt> mqAdminExtPool;
@Override @Override
public ConsumerConnection examineConsumerConnectionInfo(String addr, String consumerGroup) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException { public ConsumerConnection examineConsumerConnectionInfo(String addr, String consumerGroup) throws RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, InterruptedException, MQBrokerException {
try { try {
MQAdminInstance.createMQAdmin(mqAdminExtPool);
RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient(); RemotingClient remotingClient = MQAdminInstance.threadLocalRemotingClient();
GetConsumerConnectionListRequestHeader requestHeader = new GetConsumerConnectionListRequestHeader(); GetConsumerConnectionListRequestHeader requestHeader = new GetConsumerConnectionListRequestHeader();
requestHeader.setConsumerGroup(consumerGroup); requestHeader.setConsumerGroup(consumerGroup);
@@ -53,8 +47,9 @@ public class ProxyAdminImpl implements ProxyAdmin {
default: default:
throw new MQBrokerException(response.getCode(), response.getRemark(), addr); throw new MQBrokerException(response.getCode(), response.getRemark(), addr);
} }
} finally { } catch (Exception e) {
MQAdminInstance.returnMQAdmin(mqAdminExtPool); log.error("examineConsumerConnectionInfo error", e);
throw e;
} }
} }
} }

View File

@@ -16,14 +16,15 @@
*/ */
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.srvutil.FileWatchService; import org.apache.rocketmq.srvutil.FileWatchService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public abstract class AbstractFileStore { public abstract class AbstractFileStore {
public final Logger log = LoggerFactory.getLogger(this.getClass()); public final Logger log = LoggerFactory.getLogger(this.getClass());

View File

@@ -14,357 +14,266 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Throwables; import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import java.util.Collection; import org.apache.rocketmq.dashboard.model.Entry;
import java.util.Collections; import org.apache.rocketmq.dashboard.model.Policy;
import java.util.HashSet; import org.apache.rocketmq.dashboard.model.PolicyRequest;
import java.util.Iterator; import org.apache.rocketmq.dashboard.model.request.UserInfoParam;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.AclConfig;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.dashboard.model.request.AclRequest;
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
import org.apache.rocketmq.dashboard.service.AclService; import org.apache.rocketmq.dashboard.service.AclService;
import org.apache.rocketmq.remoting.exception.RemotingConnectException; import org.apache.rocketmq.dashboard.service.ClusterInfoService;
import org.apache.rocketmq.remoting.exception.RemotingException; import org.apache.rocketmq.remoting.protocol.body.AclInfo;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException; import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service @Service
@Slf4j public class AclServiceImpl implements AclService {
public class AclServiceImpl extends AbstractCommonService implements AclService {
private Logger logger = LoggerFactory.getLogger(AclServiceImpl.class);
@Autowired
private MQAdminExt mqAdminExt;
@Autowired
private RMQConfigure rmqConfigure;
@Autowired
private ClusterInfoService clusterInfoService;
private static final String DEFAULT_BROKER_ADDRESS = "localhost:10911";
@Override @Override
public AclConfig getAclConfig(boolean excludeSecretKey) { public List<UserInfo> listUsers(String brokerAddress) {
List<UserInfo> userList;
try { try {
Optional<String> addr = getMasterSet().stream().findFirst(); String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
if (addr.isPresent()) { userList = mqAdminExt.listUser(address, "");
if (!excludeSecretKey) { } catch (Exception ex) {
return mqAdminExt.examineBrokerClusterAclConfig(addr.get()); logger.error("Failed to list users from broker: {}", brokerAddress, ex);
} else { throw new RuntimeException("Failed to list users", ex);
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr.get());
if (CollectionUtils.isNotEmpty(aclConfig.getPlainAccessConfigs())) {
aclConfig.getPlainAccessConfigs().forEach(pac -> pac.setSecretKey(null));
}
return aclConfig;
}
}
} catch (Exception e) {
log.error("getAclConfig error.", e);
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
} }
AclConfig aclConfig = new AclConfig(); if (userList == null || userList.isEmpty()) {
aclConfig.setGlobalWhiteAddrs(Collections.emptyList()); logger.warn("No users found for broker: {}", brokerAddress);
aclConfig.setPlainAccessConfigs(Collections.emptyList()); return new ArrayList<>();
return aclConfig; }
return userList;
} }
@Override @Override
public void addAclConfig(PlainAccessConfig config) { public Object listAcls(String brokerAddress, String searchParam) {
List<AclInfo> aclList;
try { try {
Set<String> masterSet = getMasterSet(); String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
String user = searchParam != null ? searchParam : "";
if (masterSet.isEmpty()) { String res = searchParam != null ? searchParam : "";
throw new IllegalStateException("broker addr list is empty"); aclList = mqAdminExt.listAcl(address, user, "");
if (aclList == null) {
aclList = new ArrayList<>();
} }
// check to see if account is exists List<AclInfo> resAclList = mqAdminExt.listAcl(address, "", res);
for (String addr : masterSet) { if (resAclList != null) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr); aclList.addAll(resAclList);
List<PlainAccessConfig> plainAccessConfigs = aclConfig.getPlainAccessConfigs();
for (PlainAccessConfig pac : plainAccessConfigs) {
if (pac.getAccessKey().equals(config.getAccessKey())) {
throw new IllegalArgumentException(String.format("broker: %s, exist accessKey: %s", addr, config.getAccessKey()));
}
}
} }
} catch (Exception ex) {
// all broker logger.error("Failed to list ACLs from broker: {}", brokerAddress, ex);
for (String addr : getBrokerAddrs()) { throw new RuntimeException("Failed to list ACLs", ex);
mqAdminExt.createAndUpdatePlainAccessConfig(addr, config);
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
} }
ObjectMapper mapper = new ObjectMapper();
Set<String> uniqueAclStrings = new HashSet<>();
List<AclInfo> resultAclList = new ArrayList<>();
for (AclInfo acl : aclList) {
try {
String aclString = mapper.writeValueAsString(acl);
if (uniqueAclStrings.add(aclString)) {
resultAclList.add(acl);
}
} catch (Exception e) {
logger.error("Error serializing AclInfo", e);
}
}
return resultAclList;
} }
@Override @Override
public void deleteAclConfig(PlainAccessConfig config) { public List<String> createAcl(PolicyRequest policyRequest) {
try { List<String> successfulResources = new ArrayList<>();
for (String addr : getBrokerAddrs()) {
log.info("Start to delete acl [{}] from broker [{}]", config.getAccessKey(), addr);
if (isExistAccessKey(config.getAccessKey(), addr)) {
mqAdminExt.deletePlainAccessConfig(addr, config.getAccessKey());
}
log.info("Delete acl [{}] from broker [{}] complete", config.getAccessKey(), addr);
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override if (policyRequest == null || policyRequest.getPolicies() == null || policyRequest.getPolicies().isEmpty()) {
public void updateAclConfig(PlainAccessConfig config) { logger.warn("Policy request is null or policies list is empty. No ACLs to create.");
try { return successfulResources;
for (String addr : getBrokerAddrs()) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr);
if (aclConfig.getPlainAccessConfigs() != null) {
PlainAccessConfig remoteConfig = null;
for (PlainAccessConfig pac : aclConfig.getPlainAccessConfigs()) {
if (pac.getAccessKey().equals(config.getAccessKey())) {
remoteConfig = pac;
break;
}
}
if (remoteConfig != null) {
remoteConfig.setSecretKey(config.getSecretKey());
remoteConfig.setAdmin(config.isAdmin());
config = remoteConfig;
}
}
mqAdminExt.createAndUpdatePlainAccessConfig(addr, config);
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
} }
}
@Override String brokerAddress = policyRequest.getBrokerAddress() != null && !policyRequest.getBrokerAddress().isEmpty() ?
public void addOrUpdateAclTopicConfig(AclRequest request) { policyRequest.getBrokerAddress() : DEFAULT_BROKER_ADDRESS;
try { String subject = policyRequest.getSubject();
PlainAccessConfig addConfig = request.getConfig();
for (String addr : getBrokerAddrs()) { if (subject == null || subject.isEmpty()) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr); throw new IllegalArgumentException("Subject cannot be null or empty.");
PlainAccessConfig remoteConfig = null; }
if (aclConfig.getPlainAccessConfigs() != null) {
for (PlainAccessConfig config : aclConfig.getPlainAccessConfigs()) { for (Policy policy : policyRequest.getPolicies()) {
if (config.getAccessKey().equals(addConfig.getAccessKey())) { if (policy.getEntries() != null && !policy.getEntries().isEmpty()) {
remoteConfig = config; for (Entry entry : policy.getEntries()) {
break; if (entry.getResource() != null && !entry.getResource().isEmpty()) {
for (String resource : entry.getResource()) {
AclInfo aclInfo = new AclInfo();
List<AclInfo.PolicyInfo> aclPolicies = new ArrayList<>();
AclInfo.PolicyInfo policyInfo = new AclInfo.PolicyInfo();
List<AclInfo.PolicyEntryInfo> entries = new ArrayList<>();
AclInfo.PolicyEntryInfo entryInfo = new AclInfo.PolicyEntryInfo();
entryInfo.setActions(entry.getActions());
entryInfo.setDecision(entry.getDecision());
entryInfo.setResource(resource);
entryInfo.setSourceIps(entry.getSourceIps());
entries.add(entryInfo);
policyInfo.setEntries(entries);
policyInfo.setPolicyType(policy.getPolicyType());
aclPolicies.add(policyInfo);
aclInfo.setPolicies(aclPolicies);
aclInfo.setSubject(subject);
try {
logger.info("Attempting to create ACL for subject: {}, resource: {} on broker: {}", subject, resource, brokerAddress);
mqAdminExt.createAcl(brokerAddress, aclInfo);
successfulResources.add(resource);
logger.info("Successfully created ACL for subject: {}, resource: {}", subject, resource);
} catch (Exception ex) {
logger.error("Failed to create ACL for subject: {}, resource: {} on broker: {}", subject, resource, brokerAddress, ex);
throw new RuntimeException("Failed to create ACL", ex);
}
} }
} }
} }
if (remoteConfig == null) {
// Maybe the broker no acl config of the access key, therefore add it;
mqAdminExt.createAndUpdatePlainAccessConfig(addr, addConfig);
} else {
if (remoteConfig.getTopicPerms() == null) {
remoteConfig.setTopicPerms(new ArrayList<>());
}
removeExist(remoteConfig.getTopicPerms(), request.getTopicPerm().split("=")[0]);
remoteConfig.getTopicPerms().add(request.getTopicPerm());
mqAdminExt.createAndUpdatePlainAccessConfig(addr, remoteConfig);
}
} }
} catch (Exception e) { }
Throwables.throwIfUnchecked(e); return successfulResources;
throw new RuntimeException(e); }
@Override
public void deleteUser(String brokerAddress, String username) {
try {
String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
mqAdminExt.deleteUser(address, username);
} catch (Exception ex) {
logger.error("Failed to delete user: {} from broker: {}", username, brokerAddress, ex);
throw new RuntimeException("Failed to delete user", ex);
} }
} }
@Override @Override
public void addOrUpdateAclGroupConfig(AclRequest request) { public void updateUser(String brokerAddress, UserInfoParam userParam) {
UserInfo user = new UserInfo();
user.setUsername(userParam.getUsername());
user.setPassword(userParam.getPassword());
user.setUserStatus(userParam.getUserStatus());
user.setUserType(userParam.getUserType());
try { try {
PlainAccessConfig addConfig = request.getConfig(); String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
for (String addr : getBrokerAddrs()) { mqAdminExt.updateUser(address, user);
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr); } catch (Exception ex) {
PlainAccessConfig remoteConfig = null; logger.error("Failed to update user: {} on broker: {}", userParam.getUsername(), brokerAddress, ex);
if (aclConfig.getPlainAccessConfigs() != null) { throw new RuntimeException("Failed to update user", ex);
for (PlainAccessConfig config : aclConfig.getPlainAccessConfigs()) { }
if (config.getAccessKey().equals(addConfig.getAccessKey())) { }
remoteConfig = config;
break; @Override
public void createUser(String brokerAddress, UserInfoParam userParam) {
UserInfo user = new UserInfo();
user.setUsername(userParam.getUsername());
user.setPassword(userParam.getPassword());
user.setUserStatus(userParam.getUserStatus());
user.setUserType(userParam.getUserType());
try {
String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
mqAdminExt.createUser(address, user);
} catch (Exception ex) {
logger.error("Failed to create user: {} on broker: {}", userParam.getUsername(), brokerAddress, ex);
throw new RuntimeException("Failed to create user", ex);
}
}
@Override
public void deleteAcl(String brokerAddress, String subject, String resource) {
try {
String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
String res = resource != null ? resource : "";
mqAdminExt.deleteAcl(address, subject, res);
} catch (Exception ex) {
logger.error("Failed to delete ACL for subject: {} and resource: {} on broker: {}", subject, resource, brokerAddress, ex);
throw new RuntimeException("Failed to delete ACL", ex);
}
}
@Override
public void updateAcl(PolicyRequest policyRequest) {
if (policyRequest == null || policyRequest.getPolicies() == null || policyRequest.getPolicies().isEmpty()) {
logger.warn("Policy request is null or policies list is empty. No ACLs to update.");
}
String brokerAddress = policyRequest.getBrokerAddress() != null && !policyRequest.getBrokerAddress().isEmpty() ?
policyRequest.getBrokerAddress() : DEFAULT_BROKER_ADDRESS;
String subject = policyRequest.getSubject();
if (subject == null || subject.isEmpty()) {
throw new IllegalArgumentException("Subject cannot be null or empty.");
}
for (Policy policy : policyRequest.getPolicies()) {
if (policy.getEntries() != null && !policy.getEntries().isEmpty()) {
for (Entry entry : policy.getEntries()) {
if (entry.getResource() != null && !entry.getResource().isEmpty()) {
for (String resource : entry.getResource()) {
AclInfo aclInfo = new AclInfo();
List<AclInfo.PolicyInfo> aclPolicies = new ArrayList<>();
AclInfo.PolicyInfo policyInfo = new AclInfo.PolicyInfo();
List<AclInfo.PolicyEntryInfo> entries = new ArrayList<>();
AclInfo.PolicyEntryInfo entryInfo = new AclInfo.PolicyEntryInfo();
entryInfo.setActions(entry.getActions());
entryInfo.setDecision(entry.getDecision());
entryInfo.setResource(resource);
entryInfo.setSourceIps(entry.getSourceIps());
entries.add(entryInfo);
policyInfo.setEntries(entries);
policyInfo.setPolicyType(policy.getPolicyType());
aclPolicies.add(policyInfo);
aclInfo.setPolicies(aclPolicies);
aclInfo.setSubject(subject);
try {
String address = brokerAddress != null && !brokerAddress.isEmpty() ? brokerAddress : DEFAULT_BROKER_ADDRESS;
mqAdminExt.updateAcl(address, aclInfo);
} catch (Exception ex) {
logger.error("Failed to update ACL for subject: {} on broker: {}", subject, brokerAddress, ex);
throw new RuntimeException("Failed to update ACL", ex);
}
} }
} }
} }
if (remoteConfig == null) {
// May be the broker no acl config of the access key, therefore add it;
mqAdminExt.createAndUpdatePlainAccessConfig(addr, addConfig);
} else {
if (remoteConfig.getGroupPerms() == null) {
remoteConfig.setGroupPerms(new ArrayList<>());
}
removeExist(remoteConfig.getGroupPerms(), request.getGroupPerm().split("=")[0]);
remoteConfig.getGroupPerms().add(request.getGroupPerm());
mqAdminExt.createAndUpdatePlainAccessConfig(addr, remoteConfig);
}
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void deletePermConfig(AclRequest request) {
try {
PlainAccessConfig deleteConfig = request.getConfig();
String topic = StringUtils.isNotEmpty(request.getTopicPerm()) ? request.getTopicPerm().split("=")[0] : null;
String group = StringUtils.isNotEmpty(request.getGroupPerm()) ? request.getGroupPerm().split("=")[0] : null;
if (deleteConfig.getTopicPerms() != null && topic != null) {
removeExist(deleteConfig.getTopicPerms(), topic);
}
if (deleteConfig.getGroupPerms() != null && group != null) {
removeExist(deleteConfig.getGroupPerms(), group);
}
for (String addr : getBrokerAddrs()) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr);
PlainAccessConfig remoteConfig = null;
if (aclConfig.getPlainAccessConfigs() != null) {
for (PlainAccessConfig config : aclConfig.getPlainAccessConfigs()) {
if (config.getAccessKey().equals(deleteConfig.getAccessKey())) {
remoteConfig = config;
break;
}
}
}
if (remoteConfig == null) {
// Maybe the broker no acl config of the access key, therefore add it;
mqAdminExt.createAndUpdatePlainAccessConfig(addr, deleteConfig);
} else {
if (remoteConfig.getTopicPerms() != null && topic != null) {
removeExist(remoteConfig.getTopicPerms(), topic);
}
if (remoteConfig.getGroupPerms() != null && group != null) {
removeExist(remoteConfig.getGroupPerms(), group);
}
mqAdminExt.createAndUpdatePlainAccessConfig(addr, remoteConfig);
}
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void syncData(PlainAccessConfig config) {
try {
for (String addr : getBrokerAddrs()) {
mqAdminExt.createAndUpdatePlainAccessConfig(addr, config);
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void addWhiteList(List<String> whiteList) {
if (whiteList == null) {
return;
}
try {
for (String addr : getBrokerAddrs()) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr);
if (aclConfig.getGlobalWhiteAddrs() != null) {
aclConfig.setGlobalWhiteAddrs(Stream.of(whiteList, aclConfig.getGlobalWhiteAddrs()).flatMap(Collection::stream).distinct().collect(Collectors.toList()));
} else {
aclConfig.setGlobalWhiteAddrs(whiteList);
}
mqAdminExt.updateGlobalWhiteAddrConfig(addr, StringUtils.join(aclConfig.getGlobalWhiteAddrs(), ","));
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void deleteWhiteAddr(String deleteAddr) {
try {
for (String addr : getBrokerAddrs()) {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr);
if (aclConfig.getGlobalWhiteAddrs() == null || aclConfig.getGlobalWhiteAddrs().isEmpty()) {
continue;
}
aclConfig.getGlobalWhiteAddrs().remove(deleteAddr);
mqAdminExt.updateGlobalWhiteAddrConfig(addr, StringUtils.join(aclConfig.getGlobalWhiteAddrs(), ","));
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
@Override
public void synchronizeWhiteList(List<String> whiteList) {
if (whiteList == null) {
return;
}
try {
for (String addr : getBrokerAddrs()) {
mqAdminExt.updateGlobalWhiteAddrConfig(addr, StringUtils.join(whiteList, ","));
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
private void removeExist(List<String> list, String name) {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String v = iterator.next();
String cmp = v.split("=")[0];
if (cmp.equals(name)) {
iterator.remove();
} }
} }
} }
private boolean isExistAccessKey(String accessKey,
String addr) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
AclConfig aclConfig = mqAdminExt.examineBrokerClusterAclConfig(addr);
List<PlainAccessConfig> plainAccessConfigs = aclConfig.getPlainAccessConfigs();
if (plainAccessConfigs == null || plainAccessConfigs.isEmpty()) {
return false;
}
for (PlainAccessConfig config : plainAccessConfigs) {
if (accessKey.equals(config.getAccessKey())) {
return true;
}
}
return false;
}
private Set<BrokerData> getBrokerDataSet() throws InterruptedException, RemotingConnectException, RemotingTimeoutException, RemotingSendRequestException, MQBrokerException {
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
Map<String, BrokerData> brokerDataMap = clusterInfo.getBrokerAddrTable();
return new HashSet<>(brokerDataMap.values());
}
private Set<String> getMasterSet() throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
return getBrokerDataSet().stream().map(data -> data.getBrokerAddrs().get(MixAll.MASTER_ID)).collect(Collectors.toSet());
}
private Set<String> getBrokerAddrs() throws InterruptedException, MQBrokerException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
Set<String> brokerAddrs = new HashSet<>();
getBrokerDataSet().forEach(data -> brokerAddrs.addAll(data.getBrokerAddrs().values()));
return brokerAddrs;
}
} }

View File

@@ -17,20 +17,20 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import org.apache.rocketmq.common.attribute.TopicMessageType; import org.apache.rocketmq.common.attribute.TopicMessageType;
import org.apache.rocketmq.dashboard.service.ClusterService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo; import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.KVTable; import org.apache.rocketmq.remoting.protocol.body.KVTable;
import org.apache.rocketmq.remoting.protocol.route.BrokerData; import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.dashboard.service.ClusterService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
@@ -61,10 +61,9 @@ public class ClusterServiceImpl implements ClusterService {
resultMap.put("brokerServer", brokerServer); resultMap.put("brokerServer", brokerServer);
// add messageType // add messageType
resultMap.put("messageTypes", Arrays.stream(TopicMessageType.values()).sorted() resultMap.put("messageTypes", Arrays.stream(TopicMessageType.values()).sorted()
.collect(Collectors.toMap(TopicMessageType::getValue, messageType ->String.format("MESSAGE_TYPE_%s",messageType.getValue())))); .collect(Collectors.toMap(TopicMessageType::getValue, messageType -> String.format("MESSAGE_TYPE_%s", messageType.getValue()))));
return resultMap; return resultMap;
} } catch (Exception err) {
catch (Exception err) {
Throwables.throwIfUnchecked(err); Throwables.throwIfUnchecked(err);
throw new RuntimeException(err); throw new RuntimeException(err);
} }
@@ -73,12 +72,16 @@ public class ClusterServiceImpl implements ClusterService {
@Override @Override
public Properties getBrokerConfig(String brokerAddr) { public Properties getBrokerConfig(String brokerAddr) {
Properties properties = null;
try { try {
return mqAdminExt.getBrokerConfig(brokerAddr); properties = mqAdminExt.getBrokerConfig(brokerAddr);
} if (properties == null) {
catch (Exception e) { throw new RuntimeException("get broker config failed, brokerAddr:" + brokerAddr);
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e); Throwables.throwIfUnchecked(e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return properties;
} }
} }

View File

@@ -23,7 +23,43 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.utils.ThreadUtils;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.QueueStatInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
import org.apache.rocketmq.dashboard.service.ClusterInfoService;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.service.client.ProxyAdmin;
import org.apache.rocketmq.remoting.protocol.ResponseCode;
import org.apache.rocketmq.remoting.protocol.admin.ConsumeStats;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.Connection;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.remoting.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.remoting.protocol.body.GroupList;
import org.apache.rocketmq.remoting.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -44,44 +80,6 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.dashboard.model.request.ConsumerConfigInfo;
import org.apache.rocketmq.dashboard.model.request.DeleteSubGroupRequest;
import org.apache.rocketmq.dashboard.model.request.ResetOffsetRequest;
import org.apache.rocketmq.dashboard.service.ClusterInfoService;
import org.apache.rocketmq.dashboard.service.client.ProxyAdmin;
import org.apache.rocketmq.remoting.protocol.admin.ConsumeStats;
import org.apache.rocketmq.remoting.protocol.admin.RollbackStats;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.protocol.ResponseCode;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.Connection;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.remoting.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.remoting.protocol.body.GroupList;
import org.apache.rocketmq.remoting.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.remoting.protocol.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.common.utils.ThreadUtils;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.ConsumerGroupRollBackStat;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.model.QueueStatInfo;
import org.apache.rocketmq.dashboard.model.TopicConsumerInfo;
import org.apache.rocketmq.dashboard.service.AbstractCommonService;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service @Service
public class ConsumerServiceImpl extends AbstractCommonService implements ConsumerService, InitializingBean, DisposableBean { public class ConsumerServiceImpl extends AbstractCommonService implements ConsumerService, InitializingBean, DisposableBean {
@@ -180,7 +178,7 @@ public class ConsumerServiceImpl extends AbstractCommonService implements Consum
try { try {
ClusterInfo clusterInfo = clusterInfoService.get(); ClusterInfo clusterInfo = clusterInfoService.get();
for (BrokerData brokerData : clusterInfo.getBrokerAddrTable().values()) { for (BrokerData brokerData : clusterInfo.getBrokerAddrTable().values()) {
subscriptionGroupWrapper = mqAdminExt.getAllSubscriptionGroup(brokerData.selectBrokerAddr(), 3000L); subscriptionGroupWrapper = mqAdminExt.getAllSubscriptionGroup(brokerData.selectBrokerAddr(), 30000L);
for (String groupName : subscriptionGroupWrapper.getSubscriptionGroupTable().keySet()) { for (String groupName : subscriptionGroupWrapper.getSubscriptionGroupTable().keySet()) {
if (!consumerGroupMap.containsKey(groupName)) { if (!consumerGroupMap.containsKey(groupName)) {
consumerGroupMap.putIfAbsent(groupName, new ArrayList<>()); consumerGroupMap.putIfAbsent(groupName, new ArrayList<>());

View File

@@ -29,18 +29,19 @@ import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.Files; import com.google.common.io.Files;
import java.io.File; import jakarta.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.DashboardCollectService; import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service @Service
public class DashboardCollectServiceImpl implements DashboardCollectService { public class DashboardCollectServiceImpl implements DashboardCollectService {

View File

@@ -18,15 +18,16 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.dashboard.service.DashboardService;
import org.springframework.stereotype.Service;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.dashboard.service.DashboardService;
import org.springframework.stereotype.Service;
@Service @Service
public class DashboardServiceImpl implements DashboardService { public class DashboardServiceImpl implements DashboardService {

View File

@@ -18,27 +18,28 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import java.util.ArrayList; import jakarta.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.remoting.protocol.ResponseCode;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.dashboard.model.DlqMessageResendResult;
import org.apache.rocketmq.dashboard.model.DlqMessageRequest; import org.apache.rocketmq.dashboard.model.DlqMessageRequest;
import org.apache.rocketmq.dashboard.model.DlqMessageResendResult;
import org.apache.rocketmq.dashboard.model.MessagePage; import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.MessageView; import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.request.MessageQuery; import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.dashboard.service.DlqMessageService; import org.apache.rocketmq.dashboard.service.DlqMessageService;
import org.apache.rocketmq.dashboard.service.MessageService; import org.apache.rocketmq.dashboard.service.MessageService;
import org.apache.rocketmq.remoting.protocol.ResponseCode;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@Service @Service
@Slf4j @Slf4j
public class DlqMessageServiceImpl implements DlqMessageService { public class DlqMessageServiceImpl implements DlqMessageService {

View File

@@ -17,18 +17,21 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.LoginService; import org.apache.rocketmq.dashboard.service.LoginService;
import org.apache.rocketmq.dashboard.service.UserService; import org.apache.rocketmq.dashboard.service.UserService;
import org.apache.rocketmq.dashboard.service.provider.UserInfoProvider;
import org.apache.rocketmq.dashboard.util.UserInfoContext;
import org.apache.rocketmq.dashboard.util.WebUtil; import org.apache.rocketmq.dashboard.util.WebUtil;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
@@ -43,13 +46,21 @@ public class LoginServiceImpl implements LoginService {
@Autowired @Autowired
private UserService userService; private UserService userService;
@Autowired
private UserInfoProvider userInfoProvider;
@Override @Override
public boolean login(HttpServletRequest request, HttpServletResponse response) { public boolean login(HttpServletRequest request, HttpServletResponse response) {
if (WebUtil.getValueFromSession(request, WebUtil.USER_NAME) != null) { String username = (String) WebUtil.getValueFromSession(request, WebUtil.USER_NAME);
if (username != null) {
UserInfo userInfo = userInfoProvider.getUserInfoByUsername(username);
if (userInfo == null) {
return false;
}
UserInfoContext.set(WebUtil.USER_NAME, userInfo);
return true; return true;
} }
auth(request, response); auth(request, response);
return false; return false;
} }

View File

@@ -25,6 +25,7 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.acl.common.SessionCredentials;
@@ -37,20 +38,20 @@ import org.apache.rocketmq.common.Pair;
import org.apache.rocketmq.common.message.MessageClientIDSetter; import org.apache.rocketmq.common.message.MessageClientIDSetter;
import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue; import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.dashboard.support.AutoCloseConsumerWrapper;
import org.apache.rocketmq.remoting.protocol.body.Connection;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException; import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.QueueOffsetInfo;
import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.MessagePage; import org.apache.rocketmq.dashboard.model.MessagePage;
import org.apache.rocketmq.dashboard.model.MessagePageTask; import org.apache.rocketmq.dashboard.model.MessagePageTask;
import org.apache.rocketmq.dashboard.model.MessageQueryByPage; import org.apache.rocketmq.dashboard.model.MessageQueryByPage;
import org.apache.rocketmq.dashboard.model.MessageView;
import org.apache.rocketmq.dashboard.model.QueueOffsetInfo;
import org.apache.rocketmq.dashboard.model.request.MessageQuery; import org.apache.rocketmq.dashboard.model.request.MessageQuery;
import org.apache.rocketmq.dashboard.service.MessageService; import org.apache.rocketmq.dashboard.service.MessageService;
import org.apache.rocketmq.dashboard.support.AutoCloseConsumerWrapper;
import org.apache.rocketmq.remoting.RPCHook; import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.protocol.body.Connection;
import org.apache.rocketmq.remoting.protocol.body.ConsumeMessageDirectlyResult;
import org.apache.rocketmq.remoting.protocol.body.ConsumerConnection;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.tools.admin.api.MessageTrack; import org.apache.rocketmq.tools.admin.api.MessageTrack;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -60,14 +61,13 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Comparator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View File

@@ -19,14 +19,8 @@ package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.trace.TraceType; import org.apache.rocketmq.client.trace.TraceType;
import org.apache.rocketmq.common.Pair; import org.apache.rocketmq.common.Pair;
@@ -35,11 +29,11 @@ import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException; import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.MessageTraceView; import org.apache.rocketmq.dashboard.model.MessageTraceView;
import org.apache.rocketmq.dashboard.model.trace.ProducerNode;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph; import org.apache.rocketmq.dashboard.model.trace.MessageTraceGraph;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceStatusEnum;
import org.apache.rocketmq.dashboard.model.trace.ProducerNode;
import org.apache.rocketmq.dashboard.model.trace.SubscriptionNode; import org.apache.rocketmq.dashboard.model.trace.SubscriptionNode;
import org.apache.rocketmq.dashboard.model.trace.TraceNode; import org.apache.rocketmq.dashboard.model.trace.TraceNode;
import org.apache.rocketmq.dashboard.model.trace.MessageTraceStatusEnum;
import org.apache.rocketmq.dashboard.service.MessageTraceService; import org.apache.rocketmq.dashboard.service.MessageTraceService;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -48,6 +42,11 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service @Service
public class MessageTraceServiceImpl implements MessageTraceService { public class MessageTraceServiceImpl implements MessageTraceService {

View File

@@ -18,12 +18,8 @@ package org.apache.rocketmq.dashboard.service.impl;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import java.io.File; import jakarta.annotation.PostConstruct;
import java.io.IOException; import jakarta.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig; import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
@@ -31,6 +27,11 @@ import org.apache.rocketmq.dashboard.service.MonitorService;
import org.apache.rocketmq.dashboard.util.JsonUtil; import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service @Service
public class MonitorServiceImpl implements MonitorService { public class MonitorServiceImpl implements MonitorService {

View File

@@ -17,9 +17,7 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import java.util.List; import jakarta.annotation.Resource;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.AbstractCommonService; import org.apache.rocketmq.dashboard.service.AbstractCommonService;
@@ -30,6 +28,9 @@ import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service @Service
public class OpsServiceImpl extends AbstractCommonService implements OpsService { public class OpsServiceImpl extends AbstractCommonService implements OpsService {

View File

@@ -17,12 +17,7 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import java.io.FileReader; import jakarta.annotation.Resource;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException; import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.UserInfo; import org.apache.rocketmq.dashboard.model.UserInfo;
@@ -32,6 +27,12 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import java.io.FileReader;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.apache.rocketmq.dashboard.permisssion.UserRoleEnum.ADMIN; import static org.apache.rocketmq.dashboard.permisssion.UserRoleEnum.ADMIN;
import static org.apache.rocketmq.dashboard.permisssion.UserRoleEnum.ORDINARY; import static org.apache.rocketmq.dashboard.permisssion.UserRoleEnum.ORDINARY;

View File

@@ -18,9 +18,9 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.rocketmq.remoting.protocol.body.ProducerConnection;
import org.apache.rocketmq.dashboard.service.ProducerService; import org.apache.rocketmq.dashboard.service.ProducerService;
import org.apache.rocketmq.remoting.protocol.body.ProducerConnection;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@@ -17,13 +17,13 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.ProxyService; import org.apache.rocketmq.dashboard.service.ProxyService;
import org.apache.rocketmq.dashboard.service.client.ProxyAdmin; import org.apache.rocketmq.dashboard.service.client.ProxyAdmin;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@@ -25,10 +25,10 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.AclClientRPCHook;
import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.acl.common.SessionCredentials;
import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionListener; import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.trace.TraceContext; import org.apache.rocketmq.client.trace.TraceContext;
import org.apache.rocketmq.client.trace.TraceDispatcher; import org.apache.rocketmq.client.trace.TraceDispatcher;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
@@ -80,10 +80,6 @@ import static org.apache.rocketmq.common.TopicAttributes.TOPIC_MESSAGE_TYPE_ATTR
@Service @Service
public class TopicServiceImpl extends AbstractCommonService implements TopicService { public class TopicServiceImpl extends AbstractCommonService implements TopicService {
private transient DefaultMQProducer systemTopicProducer;
private final Object producerLock = new Object();
private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@Autowired @Autowired
@@ -92,6 +88,10 @@ public class TopicServiceImpl extends AbstractCommonService implements TopicServ
private final ConcurrentMap<String, TopicRouteData> routeCache = new ConcurrentHashMap<>(); private final ConcurrentMap<String, TopicRouteData> routeCache = new ConcurrentHashMap<>();
private final Object cacheLock = new Object(); private final Object cacheLock = new Object();
private transient DefaultMQProducer systemTopicProducer;
private final Object producerLock = new Object();
@Autowired @Autowired
private RMQConfigure configure; private RMQConfigure configure;

View File

@@ -17,102 +17,74 @@
package org.apache.rocketmq.dashboard.service.impl; package org.apache.rocketmq.dashboard.service.impl;
import jakarta.annotation.Resource;
import org.apache.rocketmq.auth.authentication.enums.UserType;
import org.apache.rocketmq.dashboard.admin.UserMQAdminPoolManager;
import org.apache.rocketmq.dashboard.config.RMQConfigure; import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.apache.rocketmq.dashboard.model.User; import org.apache.rocketmq.dashboard.model.User;
import org.apache.rocketmq.dashboard.service.UserService; import org.apache.rocketmq.dashboard.service.UserService;
import org.springframework.beans.factory.InitializingBean; import org.apache.rocketmq.dashboard.service.provider.UserInfoProvider;
import org.apache.rocketmq.logging.org.slf4j.Logger;
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.FileReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@Service @Service
public class UserServiceImpl implements UserService, InitializingBean { public class UserServiceImpl implements UserService {
private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
@Resource @Resource
private RMQConfigure configure; private RMQConfigure configure;
private FileBasedUserInfoStore fileBasedUserInfoStore; @Autowired
private UserInfoProvider userInfoProvider;
@Autowired
private UserMQAdminPoolManager userMQAdminPoolManager;
@Override @Override
public User queryByName(String name) { public User queryByName(String name) {
return fileBasedUserInfoStore.queryByName(name); UserInfo userInfo = userInfoProvider.getUserInfoByUsername(name);
if (userInfo == null) {
return null;
}
return new User(userInfo.getUsername(), userInfo.getPassword(), UserType.getByName(userInfo.getUserType()).getCode());
} }
@Override @Override
public User queryByUsernameAndPassword(String username, String password) { public User queryByUsernameAndPassword(String username, String password) {
return fileBasedUserInfoStore.queryByUsernameAndPassword(username, password); User user = queryByName(username);
} if (user != null && !user.getPassword().equals(password)) {
@Override
public void afterPropertiesSet() throws Exception {
if (configure.isLoginRequired()) {
fileBasedUserInfoStore = new FileBasedUserInfoStore(configure);
}
}
public static class FileBasedUserInfoStore extends AbstractFileStore {
private static final String FILE_NAME = "users.properties";
private static Map<String, User> userMap = new ConcurrentHashMap<>();
public FileBasedUserInfoStore(RMQConfigure configure) {
super(configure, FILE_NAME);
}
@Override
public void load(InputStream inputStream) {
Properties prop = new Properties();
try {
if (inputStream == null) {
prop.load(new FileReader(filePath));
} else {
prop.load(inputStream);
}
} catch (Exception e) {
log.error("load user.properties failed", e);
throw new ServiceException(0, String.format("Failed to load loginUserInfo property file: %s", filePath));
}
Map<String, User> loadUserMap = new HashMap<>();
String[] arrs;
int role;
for (String key : prop.stringPropertyNames()) {
String v = prop.getProperty(key);
if (v == null)
continue;
arrs = v.split(",", 2);
if (arrs.length == 0) {
continue;
} else if (arrs.length == 1) {
role = 0;
} else {
role = Integer.parseInt(arrs[1].trim());
}
loadUserMap.put(key, new User(key, arrs[0].trim(), role));
}
userMap.clear();
userMap.putAll(loadUserMap);
}
public User queryByName(String name) {
return userMap.get(name);
}
public User queryByUsernameAndPassword(@NotNull String username, @NotNull String password) {
User user = queryByName(username);
if (user != null && password.equals(user.getPassword())) {
return user.cloneOne();
}
return null; return null;
} }
return user;
} }
public MQAdminExt getMQAdminExtForUser(User user) throws Exception {
if (user == null) {
throw new IllegalArgumentException("User object cannot be null when requesting MQAdminExt.");
}
return userMQAdminPoolManager.borrowMQAdminExt(user.getName(), user.getPassword());
}
public void returnMQAdminExtForUser(User user, MQAdminExt mqAdminExt) {
if (user == null || mqAdminExt == null) {
log.warn("Attempted to return MQAdminExt with null user or mqAdminExt object.");
return;
}
userMQAdminPoolManager.returnMQAdminExt(user.getName(), mqAdminExt);
}
public void onUserLogout(User user) {
if (user != null) {
userMQAdminPoolManager.shutdownUserPool(user.getName());
log.info("User {} logged out, their MQAdminExt pool has been shut down.", user.getName());
}
}
} }

View File

@@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.provider;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
public interface UserInfoProvider {
UserInfo getUserInfoByUsername(String username);
}

View File

@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.service.provider;
import org.apache.rocketmq.dashboard.service.ClusterInfoService;
import org.apache.rocketmq.logging.org.slf4j.Logger;
import org.apache.rocketmq.logging.org.slf4j.LoggerFactory;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.UserInfo;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserInfoProviderImpl implements UserInfoProvider {
private static final Logger log = LoggerFactory.getLogger(UserInfoProviderImpl.class);
@Autowired
private MQAdminExt mqAdminExt;
@Autowired
private ClusterInfoService clusterInfoService;
@Override
public UserInfo getUserInfoByUsername(String username) {
ClusterInfo clusterInfo = clusterInfoService.get();
if (clusterInfo == null || clusterInfo.getBrokerAddrTable() == null || clusterInfo.getBrokerAddrTable().isEmpty()) {
log.warn("Cluster information is not available or has no broker addresses.");
return null;
}
for (BrokerData brokerLiveInfo : clusterInfo.getBrokerAddrTable().values()) {
if (brokerLiveInfo == null || brokerLiveInfo.getBrokerAddrs() == null || brokerLiveInfo.getBrokerAddrs().isEmpty()) {
continue;
}
String brokerAddr = brokerLiveInfo.getBrokerAddrs().get(0L); // Assuming 0L is the primary address
if (brokerAddr == null) {
continue;
}
try {
UserInfo userInfo = mqAdminExt.getUser(brokerAddr, username);
if (userInfo != null) {
return userInfo;
}
} catch (Exception e) {
log.warn("Failed to get user {} from broker {}. Trying next broker if available. Error: {}", username, brokerAddr, e.getMessage());
}
}
return null;
}
}

View File

@@ -23,6 +23,7 @@ import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.remoting.RPCHook; import org.apache.rocketmq.remoting.RPCHook;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -49,7 +50,7 @@ public class AutoCloseConsumerWrapper {
} }
public DefaultMQPullConsumer getConsumer(RPCHook rpcHook,Boolean useTLS) { public DefaultMQPullConsumer getConsumer(RPCHook rpcHook, Boolean useTLS) {
lastUsedTime = Instant.now(); lastUsedTime = Instant.now();
DefaultMQPullConsumer consumer = CONSUMER_REF.get(); DefaultMQPullConsumer consumer = CONSUMER_REF.get();
@@ -57,7 +58,7 @@ public class AutoCloseConsumerWrapper {
synchronized (this) { synchronized (this) {
consumer = CONSUMER_REF.get(); consumer = CONSUMER_REF.get();
if (consumer == null) { if (consumer == null) {
consumer = createNewConsumer(rpcHook,useTLS); consumer = createNewConsumer(rpcHook, useTLS);
CONSUMER_REF.set(consumer); CONSUMER_REF.set(consumer);
} }
try { try {

View File

@@ -17,7 +17,7 @@
package org.apache.rocketmq.dashboard.support; package org.apache.rocketmq.dashboard.support;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.rocketmq.dashboard.exception.ServiceException; import org.apache.rocketmq.dashboard.exception.ServiceException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -45,4 +45,4 @@ public class GlobalExceptionHandler {
} }
return value; return value;
} }
} }

View File

@@ -17,7 +17,6 @@
package org.apache.rocketmq.dashboard.support; package org.apache.rocketmq.dashboard.support;
import java.lang.annotation.Annotation;
import org.apache.rocketmq.dashboard.aspect.admin.annotation.OriginalControllerReturnValue; import org.apache.rocketmq.dashboard.aspect.admin.annotation.OriginalControllerReturnValue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -29,6 +28,8 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.lang.annotation.Annotation;
@ControllerAdvice(basePackages = "org.apache.rocketmq.dashboard") @ControllerAdvice(basePackages = "org.apache.rocketmq.dashboard")
public class GlobalRestfulResponseBodyAdvice implements ResponseBodyAdvice<Object> { public class GlobalRestfulResponseBodyAdvice implements ResponseBodyAdvice<Object> {

View File

@@ -18,21 +18,22 @@ package org.apache.rocketmq.dashboard.task;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.stats.Stats; import org.apache.rocketmq.common.stats.Stats;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData; import org.apache.rocketmq.remoting.protocol.body.BrokerStatsData;
import org.apache.rocketmq.remoting.protocol.body.GroupList; import org.apache.rocketmq.remoting.protocol.body.GroupList;
import org.apache.rocketmq.remoting.protocol.route.BrokerData; import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.remoting.protocol.route.TopicRouteData; import org.apache.rocketmq.remoting.protocol.route.TopicRouteData;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.tools.admin.MQAdminExt; import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.apache.rocketmq.tools.command.stats.StatsAllSubCommand; import org.apache.rocketmq.tools.command.stats.StatsAllSubCommand;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
@Slf4j @Slf4j
public class CollectTaskRunnble implements Runnable { public class CollectTaskRunnble implements Runnable {

View File

@@ -21,6 +21,23 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.Files; import com.google.common.io.Files;
import jakarta.annotation.Resource;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.KVTable;
import org.apache.rocketmq.remoting.protocol.body.TopicList;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -32,22 +49,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.dashboard.service.ConsumerService;
import org.apache.rocketmq.remoting.protocol.body.ClusterInfo;
import org.apache.rocketmq.remoting.protocol.body.KVTable;
import org.apache.rocketmq.remoting.protocol.body.TopicList;
import org.apache.rocketmq.remoting.protocol.route.BrokerData;
import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.dashboard.config.RMQConfigure;
import org.apache.rocketmq.dashboard.service.DashboardCollectService;
import org.apache.rocketmq.dashboard.util.JsonUtil;
import org.apache.rocketmq.tools.admin.MQAdminExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component @Component
public class DashboardCollectTask { public class DashboardCollectTask {

View File

@@ -16,8 +16,7 @@
*/ */
package org.apache.rocketmq.dashboard.task; package org.apache.rocketmq.dashboard.task;
import java.util.Map; import jakarta.annotation.Resource;
import javax.annotation.Resource;
import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig; import org.apache.rocketmq.dashboard.model.ConsumerMonitorConfig;
import org.apache.rocketmq.dashboard.model.GroupConsumeInfo; import org.apache.rocketmq.dashboard.model.GroupConsumeInfo;
import org.apache.rocketmq.dashboard.service.ConsumerService; import org.apache.rocketmq.dashboard.service.ConsumerService;
@@ -27,6 +26,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Map;
@Component @Component
public class MonitorTask { public class MonitorTask {
private Logger logger = LoggerFactory.getLogger(MonitorTask.class); private Logger logger = LoggerFactory.getLogger(MonitorTask.class);

View File

@@ -21,11 +21,12 @@ import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
public class ExcelUtil { public class ExcelUtil {

View File

@@ -25,12 +25,13 @@ import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Map; import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class JsonUtil { public class JsonUtil {

View File

@@ -17,9 +17,6 @@
package org.apache.rocketmq.dashboard.util; package org.apache.rocketmq.dashboard.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.rocketmq.client.producer.LocalTransactionState; import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.trace.TraceBean; import org.apache.rocketmq.client.trace.TraceBean;
import org.apache.rocketmq.client.trace.TraceConstants; import org.apache.rocketmq.client.trace.TraceConstants;
@@ -29,6 +26,9 @@ import org.apache.rocketmq.common.message.MessageType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import static org.apache.rocketmq.client.trace.TraceType.Pub; import static org.apache.rocketmq.client.trace.TraceType.Pub;
public class MsgTraceDecodeUtil { public class MsgTraceDecodeUtil {

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.dashboard.util;
import java.util.HashMap;
import java.util.Map;
public class UserInfoContext {
private static final ThreadLocal<Map<String, Object>> USER_THREAD_LOCAL = ThreadLocal.withInitial(HashMap::new);
public static void set(String key, Object value) {
USER_THREAD_LOCAL.get().put(key, value);
}
public static Object get(String key) {
return USER_THREAD_LOCAL.get().get(key);
}
public static Map<String, Object> getAll() {
return new HashMap<>(USER_THREAD_LOCAL.get());
}
public static void clear() {
USER_THREAD_LOCAL.remove();
}
}

View File

@@ -17,14 +17,14 @@
package org.apache.rocketmq.dashboard.util; package org.apache.rocketmq.dashboard.util;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.dashboard.model.User; import org.apache.rocketmq.dashboard.model.User;
import org.apache.rocketmq.dashboard.model.UserInfo; import org.apache.rocketmq.dashboard.model.UserInfo;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;

View File

@@ -16,7 +16,7 @@
# #
server: server:
port: 8080 port: 8082
servlet: servlet:
encoding: encoding:
charset: UTF-8 charset: UTF-8
@@ -71,4 +71,4 @@ threadpool:
coreSize: 10 coreSize: 10
maxSize: 10 maxSize: 10
keepAliveTime: 3000 keepAliveTime: 3000
queueSize: 5000 queueSize: 5000