From f5b27d9b408db79b63297c9ff3b4e715130e9a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=99=93=E4=B8=9C?= <763795151@qq.com> Date: Sun, 20 Aug 2023 20:04:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B2=A1=E6=9C=89=E7=BC=96=E8=BE=91=E6=9D=83?= =?UTF-8?q?=E9=99=90=EF=BC=8C=E9=9A=90=E8=97=8F=E9=9B=86=E7=BE=A4=E5=B1=9E?= =?UTF-8?q?=E6=80=A7;=E6=89=93=E5=8D=B0=E5=85=A8=E9=83=A8=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../console/aspect/ControllerLogAspect.java | 20 +++++++++ .../console/aspect/PermissionAspect.java | 14 ++++++- .../xuxd/kafka/console/beans/Credentials.java | 5 +++ .../xuxd/kafka/console/config/AuthConfig.java | 4 ++ .../xuxd/kafka/console/config/LogConfig.java | 23 +++++++++++ .../console/controller/AclAuthController.java | 13 +++++- .../console/controller/AclUserController.java | 4 ++ .../controller/ClientQuotaController.java | 3 ++ .../console/controller/ClusterController.java | 5 +++ .../console/controller/ConfigController.java | 7 ++++ .../controller/ConsumerController.java | 4 ++ .../console/controller/MessageController.java | 4 ++ .../controller/OperationController.java | 8 ++++ .../console/controller/TopicController.java | 6 +++ .../service/impl/ClusterServiceImpl.java | 41 +++++++++++++------ src/main/resources/application.yml | 8 +++- src/main/resources/logback-test.xml | 7 +++- 18 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/xuxd/kafka/console/config/LogConfig.java diff --git a/README.md b/README.md index 511b4b6..571e25e 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ auth: # 登录用户token的过期时间,单位:小时 expire-hours: 24 ``` -默认有两个登录用户:super-admin/123465,admin/123456,登录成功后在个人设置修改密码。super-admin和admin的唯一区别是super-admin可以增加删除用户,admin不能。如果觉得不合适,请在用户菜单下删除相关用户或角色自行创建合适的角色或用户。 +默认有两个登录用户:super-admin/123456,admin/123456,登录成功后在个人设置修改密码。super-admin和admin的唯一区别是super-admin可以增加删除用户,admin不能。如果觉得不合适,请在用户菜单下删除相关用户或角色自行创建合适的角色或用户。 注意:不开启登录认证,页面不显示用户菜单,正常现象。 diff --git a/src/main/java/com/xuxd/kafka/console/aspect/ControllerLogAspect.java b/src/main/java/com/xuxd/kafka/console/aspect/ControllerLogAspect.java index 139fbf8..70f240a 100644 --- a/src/main/java/com/xuxd/kafka/console/aspect/ControllerLogAspect.java +++ b/src/main/java/com/xuxd/kafka/console/aspect/ControllerLogAspect.java @@ -1,6 +1,9 @@ package com.xuxd.kafka.console.aspect; import com.xuxd.kafka.console.aspect.annotation.ControllerLog; +import com.xuxd.kafka.console.beans.Credentials; +import com.xuxd.kafka.console.config.LogConfig; +import com.xuxd.kafka.console.filter.CredentialsContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; @@ -12,6 +15,7 @@ import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; @@ -28,6 +32,12 @@ public class ControllerLogAspect { private ReentrantLock lock = new ReentrantLock(); + private final LogConfig logConfig; + + public ControllerLogAspect(LogConfig logConfig) { + this.logConfig = logConfig; + } + @Pointcut("@annotation(com.xuxd.kafka.console.aspect.annotation.ControllerLog)") private void pointcut() { @@ -35,6 +45,9 @@ public class ControllerLogAspect { @Around("pointcut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + if (!logConfig.isPrintControllerLog()) { + return joinPoint.proceed(); + } StringBuilder params = new StringBuilder("["); try { String methodName = getMethodFullName(joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName()); @@ -56,6 +69,10 @@ public class ControllerLogAspect { String resStr = "[" + (res != null ? res.toString() : "") + "]"; StringBuilder sb = new StringBuilder(); + Credentials credentials = CredentialsContext.get(); + if (credentials != null) { + sb.append("[").append(credentials.getUsername()).append("] "); + } String shortMethodName = descMap.getOrDefault(methodName, ".-"); shortMethodName = shortMethodName.substring(shortMethodName.lastIndexOf(".") + 1); sb.append("[").append(shortMethodName) @@ -85,6 +102,9 @@ public class ControllerLogAspect { Class[] clzArr = new Class[args.length]; for (int i = 0; i < args.length; i++) { clzArr[i] = args[i].getClass(); + if (List.class.isAssignableFrom(clzArr[i])) { + clzArr[i] = List.class; + } } method = aClass.getDeclaredMethod(methodName, clzArr); diff --git a/src/main/java/com/xuxd/kafka/console/aspect/PermissionAspect.java b/src/main/java/com/xuxd/kafka/console/aspect/PermissionAspect.java index 29dfafd..07336b8 100644 --- a/src/main/java/com/xuxd/kafka/console/aspect/PermissionAspect.java +++ b/src/main/java/com/xuxd/kafka/console/aspect/PermissionAspect.java @@ -101,17 +101,27 @@ public class PermissionAspect { throw new UnAuthorizedException(credentials.getUsername() + ":" + allowPermSet); } + boolean unauthorized = true; + boolean notFoundHideProperty = true; String roleIds = userDO.getRoleIds(); List roleIdList = Arrays.stream(roleIds.split(",")).map(String::trim).filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList()); for (Long roleId : roleIdList) { Set permSet = rolePermCache.getRolePermCache().getOrDefault(roleId, Collections.emptySet()); for (String p : allowPermSet) { if (permSet.contains(p)) { - return; + unauthorized = false; } } + if (permSet.contains(authConfig.getHideClusterPropertyPerm())) { + notFoundHideProperty = false; + } + } + if (unauthorized) { + throw new UnAuthorizedException(credentials.getUsername() + ":" + allowPermSet); + } + if (authConfig.isHideClusterProperty() && notFoundHideProperty) { + credentials.setHideClusterProperty(true); } - throw new UnAuthorizedException(credentials.getUsername() + ":" + allowPermSet); } private Map> checkPermMap(String methodName, String[] value) { diff --git a/src/main/java/com/xuxd/kafka/console/beans/Credentials.java b/src/main/java/com/xuxd/kafka/console/beans/Credentials.java index fe6db9c..9db1581 100644 --- a/src/main/java/com/xuxd/kafka/console/beans/Credentials.java +++ b/src/main/java/com/xuxd/kafka/console/beans/Credentials.java @@ -15,6 +15,11 @@ public class Credentials { private long expiration; + /** + * 是否隐藏集群属性 + */ + private boolean hideClusterProperty; + public boolean isInvalid() { return this == INVALID; } diff --git a/src/main/java/com/xuxd/kafka/console/config/AuthConfig.java b/src/main/java/com/xuxd/kafka/console/config/AuthConfig.java index 04b2d42..695a8d9 100644 --- a/src/main/java/com/xuxd/kafka/console/config/AuthConfig.java +++ b/src/main/java/com/xuxd/kafka/console/config/AuthConfig.java @@ -18,4 +18,8 @@ public class AuthConfig { private String secret = "kafka-console-ui-default-secret"; private long expireHours; + + private boolean hideClusterProperty; + + private String hideClusterPropertyPerm = "op:cluster-switch:edit"; } diff --git a/src/main/java/com/xuxd/kafka/console/config/LogConfig.java b/src/main/java/com/xuxd/kafka/console/config/LogConfig.java new file mode 100644 index 0000000..4162a24 --- /dev/null +++ b/src/main/java/com/xuxd/kafka/console/config/LogConfig.java @@ -0,0 +1,23 @@ +package com.xuxd.kafka.console.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author: xuxd + * @since: 2023/8/20 20:00 + **/ +@Configuration +@ConfigurationProperties(prefix = "log") +public class LogConfig { + + private boolean printControllerLog = true; + + public boolean isPrintControllerLog() { + return printControllerLog; + } + + public void setPrintControllerLog(boolean printControllerLog) { + this.printControllerLog = printControllerLog; + } +} diff --git a/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java b/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java index 8bfdbbb..0ca4ff0 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.AclEntry; import com.xuxd.kafka.console.beans.dto.AddAuthDTO; @@ -46,6 +47,7 @@ public class AclAuthController { return aclService.getAclList(param.toEntry()); } + @ControllerLog("增加Acl") @Permission({"acl:authority:add-principal", "acl:authority:add", "acl:sasl-scram:add-auth"}) @PostMapping public Object addAcl(@RequestBody AddAuthDTO param) { @@ -58,6 +60,7 @@ public class AclAuthController { * @param param entry.topic && entry.username must. * @return */ + @ControllerLog("增加ProducerAcl") @Permission({"acl:authority:producer", "acl:sasl-scram:producer"}) @PostMapping("/producer") public Object addProducerAcl(@RequestBody ProducerAuthDTO param) { @@ -71,6 +74,7 @@ public class AclAuthController { * @param param entry.topic && entry.groupId entry.username must. * @return */ + @ControllerLog("增加ConsumerAcl") @Permission({"acl:authority:consumer", "acl:sasl-scram:consumer"}) @PostMapping("/consumer") public Object addConsumerAcl(@RequestBody ConsumerAuthDTO param) { @@ -84,6 +88,7 @@ public class AclAuthController { * @param entry entry * @return */ + @ControllerLog("删除Acl") @Permission({"acl:authority:clean", "acl:sasl-scram:pure"}) @DeleteMapping public Object deleteAclByUser(@RequestBody AclEntry entry) { @@ -96,6 +101,7 @@ public class AclAuthController { * @param param entry.username * @return */ + @ControllerLog("删除Acl") @Permission({"acl:authority:clean", "acl:sasl-scram:pure"}) @DeleteMapping("/user") public Object deleteAclByUser(@RequestBody DeleteAclDTO param) { @@ -103,11 +109,12 @@ public class AclAuthController { } /** - * add producer acl. + * delete producer acl. * * @param param entry.topic && entry.username must. * @return */ + @ControllerLog("删除ProducerAcl") @Permission({"acl:authority:clean", "acl:sasl-scram:pure"}) @DeleteMapping("/producer") public Object deleteProducerAcl(@RequestBody ProducerAuthDTO param) { @@ -116,11 +123,12 @@ public class AclAuthController { } /** - * add consumer acl. + * delete consumer acl. * * @param param entry.topic && entry.groupId entry.username must. * @return */ + @ControllerLog("删除ConsumerAcl") @Permission({"acl:authority:clean", "acl:sasl-scram:pure"}) @DeleteMapping("/consumer") public Object deleteConsumerAcl(@RequestBody ConsumerAuthDTO param) { @@ -134,6 +142,7 @@ public class AclAuthController { * @param param acl principal. * @return true or false. */ + @ControllerLog("清除Acl") @Permission({"acl:authority:clean", "acl:sasl-scram:pure"}) @DeleteMapping("/clear") public Object clearAcl(@RequestBody DeleteAclDTO param) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java b/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java index 04054fd..84774ce 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.AclEntry; import com.xuxd.kafka.console.beans.AclUser; @@ -33,12 +34,14 @@ public class AclUserController { return aclService.getUserList(); } + @ControllerLog("增加SaslUser") @Permission({"acl:sasl-scram:add-update", "acl:sasl-scram:add-auth"}) @PostMapping public Object addOrUpdateUser(@RequestBody AclUser user) { return aclService.addOrUpdateUser(user.getUsername(), user.getPassword()); } + @ControllerLog("删除SaslUser") @Permission({"acl:sasl-scram:del", "acl:sasl-scram:pure"}) @DeleteMapping public Object deleteUser(@RequestBody AclUser user) { @@ -46,6 +49,7 @@ public class AclUserController { } + @ControllerLog("删除SaslUser和Acl") @Permission({"acl:sasl-scram:del", "acl:sasl-scram:pure"}) @DeleteMapping("/auth") public Object deleteUserAndAuth(@RequestBody AclUser user) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/ClientQuotaController.java b/src/main/java/com/xuxd/kafka/console/controller/ClientQuotaController.java index e11da6e..df2ab88 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/ClientQuotaController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/ClientQuotaController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.beans.dto.AlterClientQuotaDTO; @@ -28,6 +29,7 @@ public class ClientQuotaController { return clientQuotaService.getClientQuotaConfigs(request.getTypes(), request.getNames()); } + @ControllerLog("增加限流配额") @Permission({"quota:user:add", "quota:client:add", "quota:user-client:add", "quota:edit"}) @PostMapping public Object alterClientQuotaConfigs(@RequestBody AlterClientQuotaDTO request) { @@ -41,6 +43,7 @@ public class ClientQuotaController { return clientQuotaService.alterClientQuotaConfigs(request); } + @ControllerLog("删除限流配额") @Permission("quota:del") @DeleteMapping public Object deleteClientQuotaConfigs(@RequestBody AlterClientQuotaDTO request) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/ClusterController.java b/src/main/java/com/xuxd/kafka/console/controller/ClusterController.java index 14e0a39..2fc090f 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/ClusterController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/ClusterController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.dto.ClusterInfoDTO; import com.xuxd.kafka.console.service.ClusterService; @@ -30,23 +31,27 @@ public class ClusterController { return clusterService.getClusterInfo(); } + @Permission("op:cluster-switch") @GetMapping("/info") public Object getClusterInfoList() { return clusterService.getClusterInfoList(); } + @ControllerLog("增加集群信息") @Permission("op:cluster-switch:add") @PostMapping("/info") public Object addClusterInfo(@RequestBody ClusterInfoDTO dto) { return clusterService.addClusterInfo(dto.to()); } + @ControllerLog("删除集群信息") @Permission("op:cluster-switch:del") @DeleteMapping("/info") public Object deleteClusterInfo(@RequestBody ClusterInfoDTO dto) { return clusterService.deleteClusterInfo(dto.getId()); } + @ControllerLog("编辑集群信息") @Permission("op:cluster-switch:edit") @PutMapping("/info") public Object updateClusterInfo(@RequestBody ClusterInfoDTO dto) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/ConfigController.java b/src/main/java/com/xuxd/kafka/console/controller/ConfigController.java index ffd37b9..4c84b0a 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/ConfigController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/ConfigController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.beans.dto.AlterConfigDTO; @@ -48,12 +49,14 @@ public class ConfigController { return configService.getTopicConfig(topic); } + @ControllerLog("编辑topic配置") @Permission("topic:property-config:edit") @PostMapping("/topic") public Object setTopicConfig(@RequestBody AlterConfigDTO dto) { return configService.alterTopicConfig(dto.getEntity(), dto.to(), AlterType.SET); } + @ControllerLog("删除topic配置") @Permission("topic:property-config:del") @DeleteMapping("/topic") public Object deleteTopicConfig(@RequestBody AlterConfigDTO dto) { @@ -66,12 +69,14 @@ public class ConfigController { return configService.getBrokerConfig(brokerId); } + @ControllerLog("设置broker配置") @Permission("cluster:edit") @PostMapping("/broker") public Object setBrokerConfig(@RequestBody AlterConfigDTO dto) { return configService.alterBrokerConfig(dto.getEntity(), dto.to(), AlterType.SET); } + @ControllerLog("编辑broker配置") @Permission("cluster:edit") @DeleteMapping("/broker") public Object deleteBrokerConfig(@RequestBody AlterConfigDTO dto) { @@ -84,12 +89,14 @@ public class ConfigController { return configService.getBrokerLoggerConfig(brokerId); } + @ControllerLog("编辑broker日志配置") @Permission("cluster:edit") @PostMapping("/broker/logger") public Object setBrokerLoggerConfig(@RequestBody AlterConfigDTO dto) { return configService.alterBrokerLoggerConfig(dto.getEntity(), dto.to(), AlterType.SET); } + @ControllerLog("删除broker日志配置") @Permission("cluster:edit") @DeleteMapping("/broker/logger") public Object deleteBrokerLoggerConfig(@RequestBody AlterConfigDTO dto) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/ConsumerController.java b/src/main/java/com/xuxd/kafka/console/controller/ConsumerController.java index a18c225..409e5c7 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/ConsumerController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/ConsumerController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.beans.dto.AddSubscriptionDTO; @@ -43,6 +44,7 @@ public class ConsumerController { return consumerService.getConsumerGroupList(groupIdList, stateSet); } + @ControllerLog("删除消费组") @Permission("group:del") @DeleteMapping("/group") public Object deleteConsumerGroup(@RequestParam("groupId") String groupId) { @@ -61,12 +63,14 @@ public class ConsumerController { return consumerService.getConsumerDetail(groupId); } + @ControllerLog("新增消费组") @Permission("group:add") @PostMapping("/subscription") public Object addSubscription(@RequestBody AddSubscriptionDTO subscriptionDTO) { return consumerService.addSubscription(subscriptionDTO.getGroupId(), subscriptionDTO.getTopic()); } + @ControllerLog("重置消费位点") @Permission({"group:consumer-detail:min", "group:consumer-detail:last", "group:consumer-detail:timestamp", diff --git a/src/main/java/com/xuxd/kafka/console/controller/MessageController.java b/src/main/java/com/xuxd/kafka/console/controller/MessageController.java index 29f3670..3c927b4 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/MessageController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/MessageController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.QueryMessage; import com.xuxd.kafka.console.beans.ResponseData; @@ -48,18 +49,21 @@ public class MessageController { return messageService.deserializerList(); } + @ControllerLog("在线发送消息") @Permission("message:send") @PostMapping("/send") public Object send(@RequestBody SendMessage message) { return messageService.send(message); } + @ControllerLog("重新发送消息") @Permission("message:resend") @PostMapping("/resend") public Object resend(@RequestBody SendMessage message) { return messageService.resend(message); } + @ControllerLog("在线删除消息") @Permission("message:del") @DeleteMapping public Object delete(@RequestBody List messages) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/OperationController.java b/src/main/java/com/xuxd/kafka/console/controller/OperationController.java index 6847b45..0ffcf36 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/OperationController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/OperationController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.TopicPartition; import com.xuxd.kafka.console.beans.dto.BrokerThrottleDTO; @@ -24,12 +25,14 @@ public class OperationController { @Autowired private OperationService operationService; + @ControllerLog("同步消费位点") @PostMapping("/sync/consumer/offset") public Object syncConsumerOffset(@RequestBody SyncDataDTO dto) { dto.getProperties().put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, dto.getAddress()); return operationService.syncConsumerOffset(dto.getGroupId(), dto.getTopic(), dto.getProperties()); } + @ControllerLog("重新位点对齐") @PostMapping("/sync/min/offset/alignment") public Object minOffsetAlignment(@RequestBody SyncDataDTO dto) { dto.getProperties().put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, dto.getAddress()); @@ -41,23 +44,27 @@ public class OperationController { return operationService.getAlignmentList(); } + @ControllerLog("deleteAlignment") @DeleteMapping("/sync/alignment") public Object deleteAlignment(@RequestParam("id") Long id) { return operationService.deleteAlignmentById(id); } + @ControllerLog("优先副本leader") @Permission({"topic:partition-detail:preferred", "op:replication-preferred"}) @PostMapping("/replication/preferred") public Object electPreferredLeader(@RequestBody ReplicationDTO dto) { return operationService.electPreferredLeader(dto.getTopic(), dto.getPartition()); } + @ControllerLog("配置同步限流") @Permission("op:config-throttle") @PostMapping("/broker/throttle") public Object configThrottle(@RequestBody BrokerThrottleDTO dto) { return operationService.configThrottle(dto.getBrokerList(), dto.getUnit().toKb(dto.getThrottle())); } + @ControllerLog("移除限流配置") @Permission("op:remove-throttle") @DeleteMapping("/broker/throttle") public Object removeThrottle(@RequestBody BrokerThrottleDTO dto) { @@ -70,6 +77,7 @@ public class OperationController { return operationService.currentReassignments(); } + @ControllerLog("取消副本重分配") @Permission("op:replication-update-detail:cancel") @DeleteMapping("/replication/reassignments") public Object cancelReassignment(@RequestBody TopicPartition partition) { diff --git a/src/main/java/com/xuxd/kafka/console/controller/TopicController.java b/src/main/java/com/xuxd/kafka/console/controller/TopicController.java index d41ae1f..535100c 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/TopicController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/TopicController.java @@ -1,5 +1,6 @@ package com.xuxd.kafka.console.controller; +import com.xuxd.kafka.console.aspect.annotation.ControllerLog; import com.xuxd.kafka.console.aspect.annotation.Permission; import com.xuxd.kafka.console.beans.ReplicaAssignment; import com.xuxd.kafka.console.beans.dto.AddPartitionDTO; @@ -39,6 +40,7 @@ public class TopicController { return topicService.getTopicList(topic, TopicType.valueOf(type.toUpperCase())); } + @ControllerLog("删除topic") @Permission({"topic:batch-del", "topic:del"}) @DeleteMapping public Object deleteTopic(@RequestBody List topics) { @@ -51,12 +53,14 @@ public class TopicController { return topicService.getTopicPartitionInfo(topic.trim()); } + @ControllerLog("创建topic") @Permission("topic:add") @PostMapping("/new") public Object createNewTopic(@RequestBody NewTopicDTO topicDTO) { return topicService.createTopic(topicDTO.toNewTopic()); } + @ControllerLog("增加topic分区") @Permission("topic:partition-add") @PostMapping("/partition/new") public Object addPartition(@RequestBody AddPartitionDTO partitionDTO) { @@ -80,12 +84,14 @@ public class TopicController { return topicService.getCurrentReplicaAssignment(topic); } + @ControllerLog("更新副本") @Permission({"topic:replication-modify", "op:replication-reassign"}) @PostMapping("/replica/assignment") public Object updateReplicaAssignment(@RequestBody ReplicaAssignment assignment) { return topicService.updateReplicaAssignment(assignment); } + @ControllerLog("配置限流") @Permission("topic:replication-sync-throttle") @PostMapping("/replica/throttle") public Object configThrottle(@RequestBody TopicThrottleDTO dto) { diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/ClusterServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/ClusterServiceImpl.java index 4d5661e..00aa58f 100644 --- a/src/main/java/com/xuxd/kafka/console/service/impl/ClusterServiceImpl.java +++ b/src/main/java/com/xuxd/kafka/console/service/impl/ClusterServiceImpl.java @@ -3,15 +3,14 @@ package com.xuxd.kafka.console.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.xuxd.kafka.console.beans.BrokerNode; import com.xuxd.kafka.console.beans.ClusterInfo; +import com.xuxd.kafka.console.beans.Credentials; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.beans.dos.ClusterInfoDO; import com.xuxd.kafka.console.beans.vo.BrokerApiVersionVO; import com.xuxd.kafka.console.beans.vo.ClusterInfoVO; import com.xuxd.kafka.console.dao.ClusterInfoMapper; +import com.xuxd.kafka.console.filter.CredentialsContext; import com.xuxd.kafka.console.service.ClusterService; - -import java.util.*; -import java.util.stream.Collectors; import kafka.console.ClusterConsole; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; @@ -21,6 +20,9 @@ import org.apache.kafka.common.Node; import org.springframework.beans.factory.ObjectProvider; import org.springframework.stereotype.Service; +import java.util.*; +import java.util.stream.Collectors; + /** * kafka-console-ui. * @@ -36,12 +38,13 @@ public class ClusterServiceImpl implements ClusterService { private final ClusterInfoMapper clusterInfoMapper; public ClusterServiceImpl(ObjectProvider clusterConsole, - ObjectProvider clusterInfoMapper) { + ObjectProvider clusterInfoMapper) { this.clusterConsole = clusterConsole.getIfAvailable(); this.clusterInfoMapper = clusterInfoMapper.getIfAvailable(); } - @Override public ResponseData getClusterInfo() { + @Override + public ResponseData getClusterInfo() { ClusterInfo clusterInfo = clusterConsole.clusterInfo(); Set nodes = clusterInfo.getNodes(); if (nodes == null) { @@ -52,12 +55,22 @@ public class ClusterServiceImpl implements ClusterService { return ResponseData.create().data(clusterInfo).success(); } - @Override public ResponseData getClusterInfoList() { + @Override + public ResponseData getClusterInfoList() { + // 如果开启权限管理,当前用户没有集群切换->集群信息的编辑权限,隐藏集群的属性信息,避免ACL属性暴露出来 + Credentials credentials = CredentialsContext.get(); return ResponseData.create().data(clusterInfoMapper.selectList(null) - .stream().map(ClusterInfoVO::from).collect(Collectors.toList())).success(); + .stream().map(e -> { + ClusterInfoVO vo = ClusterInfoVO.from(e); + if (credentials != null && credentials.isHideClusterProperty()) { + vo.setProperties(Collections.emptyList()); + } + return vo; + }).collect(Collectors.toList())).success(); } - @Override public ResponseData addClusterInfo(ClusterInfoDO infoDO) { + @Override + public ResponseData addClusterInfo(ClusterInfoDO infoDO) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("cluster_name", infoDO.getClusterName()); if (clusterInfoMapper.selectCount(queryWrapper) > 0) { @@ -67,12 +80,14 @@ public class ClusterServiceImpl implements ClusterService { return ResponseData.create().success(); } - @Override public ResponseData deleteClusterInfo(Long id) { + @Override + public ResponseData deleteClusterInfo(Long id) { clusterInfoMapper.deleteById(id); return ResponseData.create().success(); } - @Override public ResponseData updateClusterInfo(ClusterInfoDO infoDO) { + @Override + public ResponseData updateClusterInfo(ClusterInfoDO infoDO) { if (infoDO.getProperties() == null) { // null 的话不更新,这个是bug,设置为空字符串解决 infoDO.setProperties(""); @@ -81,7 +96,8 @@ public class ClusterServiceImpl implements ClusterService { return ResponseData.create().success(); } - @Override public ResponseData peekClusterInfo() { + @Override + public ResponseData peekClusterInfo() { List dos = clusterInfoMapper.selectList(null); if (CollectionUtils.isEmpty(dos)) { return ResponseData.create().failed("No Cluster Info."); @@ -89,7 +105,8 @@ public class ClusterServiceImpl implements ClusterService { return ResponseData.create().data(dos.stream().findFirst().map(ClusterInfoVO::from)).success(); } - @Override public ResponseData getBrokerApiVersionInfo() { + @Override + public ResponseData getBrokerApiVersionInfo() { HashMap map = clusterConsole.listBrokerVersionInfo(); List list = new ArrayList<>(map.size()); map.forEach(((node, versions) -> { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 304feee..97967c0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -52,4 +52,10 @@ cron: auth: enable: false # 登录用户token的过期时间,单位:小时 - expire-hours: 24 \ No newline at end of file + expire-hours: 24 + # 隐藏集群的属性信息,如果当前用户没有集群切换里的编辑权限,就不能看集群的属性信息,有开启ACL的集群需要开启这个 + hide-cluster-property: true + +log: + # 是否打印操作日志(增加、删除、编辑) + print-controller-log: true \ No newline at end of file diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml index 7783f53..73490f5 100644 --- a/src/main/resources/logback-test.xml +++ b/src/main/resources/logback-test.xml @@ -45,7 +45,12 @@ - + + + + + +