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 16bce79..37118c6 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/AclUserController.java @@ -37,4 +37,10 @@ public class AclUserController { public Object deleteUser(@RequestBody AclUser user) { return aclService.deleteUser(user.getUsername()); } + + + @DeleteMapping("/auth") + public Object deleteUserAndAuth(@RequestBody AclUser user) { + return aclService.deleteUserAndAuth(user.getUsername()); + } } 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 d011683..ab1553f 100644 --- a/src/main/java/com/xuxd/kafka/console/service/AclService.java +++ b/src/main/java/com/xuxd/kafka/console/service/AclService.java @@ -18,6 +18,8 @@ public interface AclService { ResponseData deleteUser(String name); + ResponseData deleteUserAndAuth(String name); + ResponseData getAclList(); ResponseData getAclList(AclEntry entry); 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 50bc8e8..77c9f37 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 @@ -21,6 +21,7 @@ import org.apache.kafka.common.acl.AclBinding; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import scala.Tuple2; /** * kafka-console-ui. @@ -57,7 +58,24 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton { @Override public ResponseData deleteUser(String name) { log.info("delete user: {}", name); - return configConsole.deleteUser(name) ? ResponseData.create().success() : ResponseData.create().failed(); + Tuple2 tuple2 = configConsole.deleteUser(name); + 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)) { + Tuple2 delUR = configConsole.deleteUser(name); + if (!((boolean)delUR._1())) { + return ResponseData.create().failed("用户权限删除成功,但是用户信息删除失败: " + delUR._2()); + } + } else { + return ResponseData.create().failed("删除用户权限失败"); + } + + return ResponseData.create().success(); } @Override public ResponseData getAclList() { diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml new file mode 100644 index 0000000..adc5289 --- /dev/null +++ b/src/main/resources/logback-test.xml @@ -0,0 +1,24 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/scala/kafka/console/KafkaAclConsole.scala b/src/main/scala/kafka/console/KafkaAclConsole.scala index 590edf4..1aef66d 100644 --- a/src/main/scala/kafka/console/KafkaAclConsole.scala +++ b/src/main/scala/kafka/console/KafkaAclConsole.scala @@ -123,8 +123,8 @@ class KafkaAclConsole(config: KafkaConfig) extends KafkaConsole(config: KafkaCon def deleteUserAcl(entry: AclEntry): Boolean = { val filter: AclBindingFilter = entry.toAclBindingFilter - val delFilter = new AclBindingFilter(new ResourcePatternFilter(ResourceType.ANY, ResourcePattern.WILDCARD_RESOURCE, filter.patternFilter().patternType()), - new AccessControlEntryFilter(filter.entryFilter().principal(), filter.entryFilter().host(), AclOperation.ANY, AclPermissionType.ANY)) + val delFilter = new AclBindingFilter(new ResourcePatternFilter(ResourceType.ANY, null, filter.patternFilter().patternType()), + new AccessControlEntryFilter(filter.entryFilter().principal(), null, AclOperation.ANY, AclPermissionType.ANY)) deleteAcl(Collections.singleton(delFilter)) } diff --git a/src/main/scala/kafka/console/KafkaConfigConsole.scala b/src/main/scala/kafka/console/KafkaConfigConsole.scala index aa0749a..1e92126 100644 --- a/src/main/scala/kafka/console/KafkaConfigConsole.scala +++ b/src/main/scala/kafka/console/KafkaConfigConsole.scala @@ -74,18 +74,18 @@ class KafkaConfigConsole(config: KafkaConfig) extends KafkaConsole(config: Kafka } } - def deleteUser(name: String): Boolean = { + def deleteUser(name: String): (Boolean, String) = { withAdminClient(adminClient => { try { adminClient.alterUserScramCredentials(util.Arrays.asList( new UserScramCredentialDeletion(name, ScramMechanism.fromMechanismName(config.getSaslMechanism)))) .all().get(3000, TimeUnit.MILLISECONDS) - true + (true, null) } catch { case ex: Exception => log.error("deleteUser error", ex) - false + (false, ex.getMessage) } - }).asInstanceOf[Boolean] + }).asInstanceOf[(Boolean, String)] } } diff --git a/ui/src/utils/api.js b/ui/src/utils/api.js new file mode 100644 index 0000000..f0adf50 --- /dev/null +++ b/ui/src/utils/api.js @@ -0,0 +1,14 @@ +export const KafkaAclApi = { + addKafkaUser: { + url: "/user", + method: "post", + }, + deleteKafkaUser: { + url: "/user/auth", + method: "delete", + }, + getAclList: { + url: "/acl/list", + method: "post", + }, +}; diff --git a/ui/src/utils/constants.js b/ui/src/utils/constants.js new file mode 100644 index 0000000..63b747a --- /dev/null +++ b/ui/src/utils/constants.js @@ -0,0 +1,3 @@ +export const ConstantEvent = { + updateUserDialogData: "updateUserDialogData", +}; diff --git a/ui/src/views/acl/Acl.vue b/ui/src/views/acl/Acl.vue index ba6615f..bb6fe4f 100644 --- a/ui/src/views/acl/Acl.vue +++ b/ui/src/views/acl/Acl.vue @@ -37,7 +37,7 @@ - 搜索 + 搜索 重置 @@ -49,23 +49,29 @@ 新增/更新用户 - - 删除 - 授予生产权限 - 收回生产权限 - 授予消费权限 - 收回消费权限 - 增加权限 - - - - - - + + + 删除 + + 授予生产权限 + 收回生产权限 + 授予消费权限 + 收回消费权限 + 增加权限 @@ -100,6 +106,7 @@ import request from "@/utils/request"; import notification from "ant-design-vue/es/notification"; import UpdateUser from "@/views/acl/UpdateUser"; +import { KafkaAclApi } from "@/utils/api"; export default { name: "Acl", @@ -113,6 +120,7 @@ export default { innerData, form: this.$form.createForm(this, { name: "advanced_search" }), showUpdateUser: false, + deleteUserConfirm: false, }; }, methods: { @@ -149,25 +157,38 @@ export default { } }, onDeleteUser(row) { - console.log("delete user:", row) - } + request({ + url: KafkaAclApi.deleteKafkaUser.url, + method: KafkaAclApi.deleteKafkaUser.method, + data: { username: row.username }, + }).then((res) => { + getAclList(this.data, this.queryParam); + if (res.code == 0) { + this.$message.success(res.msg); + } else { + this.$message.error(res.msg); + } + }); + }, + onAddProducerAuth(row) { + const rowData = {}; + Object.assign(rowData, row); + console.log("onAddProducerAuth user:", rowData); + }, + cancel(e) { + console.log(e); + this.$message.error("Click on No"); + }, }, created() { getAclList(this.data, this.queryParam); }, }; -const api = { - getAclList: { - url: "/acl/list", - method: "post", - }, -}; - function getAclList(data, requestParameters) { request({ - url: api.getAclList.url, - method: api.getAclList.method, + url: KafkaAclApi.getAclList.url, + method: KafkaAclApi.getAclList.method, data: requestParameters, }).then((response) => { data.splice(0, data.length); @@ -274,6 +295,7 @@ for (let i = 0; i < 3; ++i) { height: 4%; text-align: left; } + .operation-btn { margin-right: 1%; } diff --git a/ui/src/views/acl/UpdateUser.vue b/ui/src/views/acl/UpdateUser.vue index 68b268f..b9c6cb5 100644 --- a/ui/src/views/acl/UpdateUser.vue +++ b/ui/src/views/acl/UpdateUser.vue @@ -57,7 +57,7 @@ export default { }, beforeCreate() { //创建表单 - this.form = this.$form.createForm(this, { name: "form_in_modal" }); + this.form = this.$form.createForm(this, { name: "addOrUpdateUserModal" }); }, data() { return { @@ -90,7 +90,7 @@ export default { message: res.msg, }); form.resetFields(); - this.$emit("updateDialogData", { ok: true, show: false }); + this.$emit("updateUserDialogData", { ok: true, show: false }); } else { notification.error({ message: res.msg, @@ -100,7 +100,7 @@ export default { }); }, handleCancel() { - this.$emit("updateDialogData", { ok: false, show: false }); + this.$emit("updateUserDialogData", { ok: false, show: false }); }, }, }; diff --git a/ui/src/views/utils/ConfirmDialog.vue b/ui/src/views/utils/ConfirmDialog.vue new file mode 100644 index 0000000..6e2e3f4 --- /dev/null +++ b/ui/src/views/utils/ConfirmDialog.vue @@ -0,0 +1,36 @@ + + + +