diff --git a/src/main/java/com/xuxd/kafka/console/beans/dto/AddAuthDTO.java b/src/main/java/com/xuxd/kafka/console/beans/dto/AddAuthDTO.java new file mode 100644 index 0000000..8f4e3d9 --- /dev/null +++ b/src/main/java/com/xuxd/kafka/console/beans/dto/AddAuthDTO.java @@ -0,0 +1,37 @@ +package com.xuxd.kafka.console.beans.dto; + +import com.xuxd.kafka.console.beans.AclEntry; +import lombok.Data; + +/** + * kafka-console-ui. + * + * @author xuxd + * @date 2021-09-03 19:07:11 + **/ +@Data +public class AddAuthDTO { + + private String resourceType; + + private String resourceName = null; + + private String username = null; + + private String host; + + private String operation; + + private String permissionType; + + public AclEntry toAclEntry() { + AclEntry entry = new AclEntry(); + entry.setResourceType(resourceType); + entry.setName(resourceName); + entry.setPrincipal(username); + entry.setHost(host); + entry.setOperation(operation); + entry.setPermissionType(permissionType); + return entry; + } +} 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 efead86..b35c16c 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/AclAuthController.java @@ -1,6 +1,7 @@ package com.xuxd.kafka.console.controller; import com.xuxd.kafka.console.beans.AclEntry; +import com.xuxd.kafka.console.beans.dto.AddAuthDTO; import com.xuxd.kafka.console.beans.dto.ConsumerAuthDTO; import com.xuxd.kafka.console.beans.dto.DeleteAclDTO; import com.xuxd.kafka.console.beans.dto.ProducerAuthDTO; @@ -32,14 +33,19 @@ public class AclAuthController { return aclService.getAclList(); } + @GetMapping("/operation/list") + public Object getAclOperationList() { + return aclService.getOperationList(); + } + @PostMapping("/list") public Object getAclList(@RequestBody QueryAclDTO param) { return aclService.getAclList(param.toEntry()); } @PostMapping - public Object addAcl(@RequestBody AclEntry entry) { - return aclService.addAcl(entry); + public Object addAcl(@RequestBody AddAuthDTO param) { + return aclService.addAcl(param.toAclEntry()); } /** diff --git a/src/main/java/com/xuxd/kafka/console/service/AclService.java b/src/main/java/com/xuxd/kafka/console/service/AclService.java index ab1553f..4dcbdd0 100644 --- a/src/main/java/com/xuxd/kafka/console/service/AclService.java +++ b/src/main/java/com/xuxd/kafka/console/service/AclService.java @@ -38,4 +38,6 @@ public interface AclService { ResponseData deleteUserAcl(AclEntry entry); + ResponseData getOperationList(); + } diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java index a99c055..74c4bf6 100644 --- a/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java +++ b/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java @@ -6,6 +6,7 @@ import com.xuxd.kafka.console.beans.CounterMap; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.config.KafkaConfig; import com.xuxd.kafka.console.service.AclService; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -18,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.kafka.clients.admin.UserScramCredentialsDescription; import org.apache.kafka.common.acl.AclBinding; +import org.apache.kafka.common.acl.AclOperation; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -59,16 +61,16 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton { @Override public ResponseData deleteUser(String name) { log.info("delete user: {}", name); Tuple2 tuple2 = configConsole.deleteUser(name); - return (boolean)tuple2._1() ? ResponseData.create().success() : ResponseData.create().failed(tuple2._2()); + return (boolean) tuple2._1() ? ResponseData.create().success() : ResponseData.create().failed(tuple2._2()); } @Override public ResponseData deleteUserAndAuth(String name) { log.info("delete user and authority: {}", name); AclEntry entry = new AclEntry(); entry.setPrincipal(name); - if ( aclConsole.deleteUserAcl(entry)) { + if (aclConsole.deleteUserAcl(entry)) { Tuple2 delUR = configConsole.deleteUser(name); - if (!((boolean)delUR._1())) { + if (!((boolean) delUR._1())) { return ResponseData.create().failed("用户权限删除成功,但是用户信息删除失败: " + delUR._2()); } } else { @@ -148,6 +150,11 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton { return aclConsole.deleteUserAcl(entry) ? ResponseData.create().success() : ResponseData.create().failed(); } + @Override public ResponseData getOperationList() { + Set operations = Arrays.stream(AclOperation.values()).filter(o -> o != AclOperation.ANY && o != AclOperation.UNKNOWN).map(AclOperation::name).collect(Collectors.toSet()); + return ResponseData.create().data(operations).success(); + } + @Override public void afterSingletonsInstantiated() { if (kafkaConfig.isAdminCreate()) { log.info("Start create admin user, username: {}, password: {}", kafkaConfig.getAdminUsername(), kafkaConfig.getAdminPassword()); diff --git a/ui/src/utils/api.js b/ui/src/utils/api.js index 06ae9bd..1cec088 100644 --- a/ui/src/utils/api.js +++ b/ui/src/utils/api.js @@ -27,4 +27,12 @@ export const KafkaAclApi = { url: "/acl/consumer", method: "delete", }, + getOperationList: { + url: "/acl/operation/list", + method: "get", + }, + addAclAuth: { + url: "/acl", + method: "post", + }, }; diff --git a/ui/src/views/acl/Acl.vue b/ui/src/views/acl/Acl.vue index 78bc53f..73a333b 100644 --- a/ui/src/views/acl/Acl.vue +++ b/ui/src/views/acl/Acl.vue @@ -89,7 +89,17 @@ @manageConsumerAuthDialog="closeManageConsumerAuthDialog" > - 增加权限 + 增加权限 + + @@ -127,10 +137,11 @@ import UpdateUser from "@/views/acl/UpdateUser"; import { KafkaAclApi } from "@/utils/api"; import ManageProducerAuth from "@/views/acl/ManageProducerAuth"; import ManageConsumerAuth from "@/views/acl/ManageConsumerAuth"; +import AddAuth from "@/views/acl/AddAuth"; export default { name: "Acl", - components: { UpdateUser, ManageProducerAuth, ManageConsumerAuth }, + components: { UpdateUser, ManageProducerAuth, ManageConsumerAuth, AddAuth }, data() { return { queryParam: {}, @@ -144,6 +155,7 @@ export default { deleteUserConfirm: false, openManageProducerAuthDialog: false, openManageConsumerAuthDialog: false, + openAddAuthDialog: false, }; }, methods: { @@ -205,6 +217,12 @@ export default { Object.assign(rowData, row); this.selectRow = rowData; }, + onAddAuth(row) { + this.openAddAuthDialog = true; + const rowData = {}; + Object.assign(rowData, row); + this.selectRow = rowData; + }, closeManageProducerAuthDialog() { this.openManageProducerAuthDialog = false; getAclList(this.data, this.queryParam); @@ -213,6 +231,10 @@ export default { this.openManageConsumerAuthDialog = false; getAclList(this.data, this.queryParam); }, + closeAddAuthDialog() { + this.openAddAuthDialog = false; + getAclList(this.data, this.queryParam); + }, }, created() { getAclList(this.data, this.queryParam); diff --git a/ui/src/views/acl/AddAuth.vue b/ui/src/views/acl/AddAuth.vue new file mode 100644 index 0000000..9e7ce83 --- /dev/null +++ b/ui/src/views/acl/AddAuth.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/ui/src/views/acl/ManageProducerAuth.vue b/ui/src/views/acl/ManageProducerAuth.vue index 07258b8..d448579 100644 --- a/ui/src/views/acl/ManageProducerAuth.vue +++ b/ui/src/views/acl/ManageProducerAuth.vue @@ -40,7 +40,7 @@ import { KafkaAclApi } from "@/utils/api"; import request from "@/utils/request"; export default { - name: "AddProducerAuth", + name: "ManageProducerAuth", props: { visible: { type: Boolean,