add user detail module

This commit is contained in:
许晓东
2021-09-07 17:28:11 +08:00
parent 139037ef26
commit 9e01d244f9
8 changed files with 147 additions and 85 deletions

View File

@@ -0,0 +1,21 @@
package com.xuxd.kafka.console.beans.vo;
import lombok.Data;
/**
* kafka-console-ui.
*
* @author xuxd
* @date 2021-09-07 14:10:10
**/
@Data
public class KafkaUserDetailVO {
private String username;
private String password;
private String credentialInfos;
private String consistencyDescription;
}

View File

@@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
@@ -43,4 +44,9 @@ public class AclUserController {
public Object deleteUserAndAuth(@RequestBody AclUser user) {
return aclService.deleteUserAndAuth(user.getUsername());
}
@GetMapping("/detail")
public Object getUserDetail(@RequestParam String username) {
return aclService.getUserDetail(username);
}
}

View File

@@ -5,6 +5,7 @@ import com.xuxd.kafka.console.beans.CounterList;
import com.xuxd.kafka.console.beans.CounterMap;
import com.xuxd.kafka.console.beans.ResponseData;
import com.xuxd.kafka.console.beans.dos.KafkaUserDO;
import com.xuxd.kafka.console.beans.vo.KafkaUserDetailVO;
import com.xuxd.kafka.console.config.KafkaConfig;
import com.xuxd.kafka.console.dao.KafkaUserMapper;
import com.xuxd.kafka.console.service.AclService;
@@ -77,7 +78,7 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
map.put("username", name);
kafkaUserMapper.deleteByMap(map);
kafkaUserMapper.insert(userDO);
}catch (Exception e) {
} catch (Exception e) {
log.error("kafkaUserMapper.insert error.", e);
return ResponseData.create().failed(e.getMessage());
}
@@ -107,7 +108,7 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
}
@Override public ResponseData getAclDetailList(AclEntry entry) {
List<AclBinding> aclBindingList = entry ==null || entry.isNull() ? aclConsole.getAclList(null) : aclConsole.getAclList(entry);
List<AclBinding> aclBindingList = entry == null || entry.isNull() ? aclConsole.getAclList(null) : aclConsole.getAclList(entry);
return ResponseData.create().data(new CounterList<>(aclBindingList.stream().map(x -> AclEntry.valueOf(x)).collect(Collectors.toList()))).success();
}
@@ -182,15 +183,26 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
}
@Override public ResponseData getUserDetail(String username) {
KafkaUserDetailVO vo = new KafkaUserDetailVO();
vo.setUsername(username);
Map<String, UserScramCredentialsDescription> detailList = configConsole.getUserDetailList(Collections.singletonList(username));
if (!detailList.isEmpty() && detailList.containsKey(username)) {
UserScramCredentialsDescription description = detailList.get(username);
String credentialInfo = StringUtils.join(description.credentialInfos(), ";");
vo.setCredentialInfos(credentialInfo);
}
Map<String, Object> param = new HashMap<>();
param.put("username", username);
List<KafkaUserDO> dos = kafkaUserMapper.selectByMap(param);
if (dos.isEmpty()) {
return ResponseData.create().data(new CounterList<>(dos)).success("Retrieved the user info is null.");
vo.setConsistencyDescription("Password is null.");
} else {
vo.setPassword(dos.stream().findFirst().get().getPassword());
}
// check for consistency.
return null;
return ResponseData.create().data(vo).success();
}
@Override public void afterSingletonsInstantiated() {

View File

@@ -3,6 +3,10 @@ export const KafkaAclApi = {
url: "/user",
method: "post",
},
getKafkaUserDetail: {
url: "/user/detail",
method: "get",
},
deleteKafkaUser: {
url: "/user/auth",
method: "delete",

View File

@@ -63,10 +63,6 @@
@click="onUserDetail(username)"
>详情</a-button
>
<UserDetail
:visible="openUserDetailDialog"
@userDetailDialog="closeUserDetailDialog"
></UserDetail>
</div>
<div slot="topicList" slot-scope="topicList, record">
@@ -77,11 +73,6 @@
@click="onTopicDetail(t, record.username)"
><div style="border-bottom: 1px solid #e5e1e1">{{ t }}</div>
</a>
<AclDetail
:visible="openAclDetailDialog"
:selectDetail="selectDetail"
@aclDetailDialog="closeAclDetailDialog"
></AclDetail>
</div>
<div slot="groupList" slot-scope="groupList, record">
@@ -115,11 +106,6 @@
class="operation-btn"
@click="onManageProducerAuth(record)"
>管理生产权限
<ManageProducerAuth
:visible="openManageProducerAuthDialog"
:record="selectRow"
@manageProducerAuthDialog="closeManageProducerAuthDialog"
></ManageProducerAuth>
</a-button>
<a-button
@@ -128,11 +114,6 @@
class="operation-btn"
@click="onManageConsumerAuth(record)"
>管理消费权限
<ManageConsumerAuth
:visible="openManageConsumerAuthDialog"
:record="selectRow"
@manageConsumerAuthDialog="closeManageConsumerAuthDialog"
></ManageConsumerAuth>
</a-button>
<a-button
size="small"
@@ -140,14 +121,34 @@
class="operation-btn"
@click="onAddAuth(record)"
>增加权限
<AddAuth
:visible="openAddAuthDialog"
:record="selectRow"
@addAuthDialog="closeAddAuthDialog"
></AddAuth>
</a-button>
</div>
</a-table>
<UserDetail
:visible="openUserDetailDialog"
:username="selectDetail.username"
@userDetailDialog="closeUserDetailDialog"
></UserDetail>
<AclDetail
:visible="openAclDetailDialog"
:selectDetail="selectDetail"
@aclDetailDialog="closeAclDetailDialog"
></AclDetail>
<ManageProducerAuth
:visible="openManageProducerAuthDialog"
:record="selectRow"
@manageProducerAuthDialog="closeManageProducerAuthDialog"
></ManageProducerAuth>
<ManageConsumerAuth
:visible="openManageConsumerAuthDialog"
:record="selectRow"
@manageConsumerAuthDialog="closeManageConsumerAuthDialog"
></ManageConsumerAuth>
<AddAuth
:visible="openAddAuthDialog"
:record="selectRow"
@addAuthDialog="closeAddAuthDialog"
></AddAuth>
</div>
</div>
</template>
@@ -283,13 +284,17 @@ export default {
this.openManageConsumerAuthDialog = false;
getAclList(this.data, this.queryParam);
},
closeAddAuthDialog() {
closeAddAuthDialog(p) {
this.openAddAuthDialog = false;
getAclList(this.data, this.queryParam);
if (p.refresh) {
getAclList(this.data, this.queryParam);
}
},
closeAclDetailDialog() {
closeAclDetailDialog(p) {
this.openAclDetailDialog = false;
getAclList(this.data, this.queryParam);
if (p.refresh) {
getAclList(this.data, this.queryParam);
}
},
closeUserDetailDialog() {
this.openUserDetailDialog = false;

View File

@@ -4,10 +4,7 @@
:visible="show"
:confirm-loading="confirmLoading"
:width="1200"
@ok="handleOk"
@cancel="handleCancel"
okText="提交"
cancelText="取消"
:mask="false"
:destroyOnClose="true"
:footer="null"
@@ -69,32 +66,8 @@ export default {
},
},
methods: {
handleOk() {
const form = this.form;
form.validateFields((e, v) => {
if (e) {
return;
}
const param = Object.assign({}, v);
const api = KafkaAclApi.addAclAuth;
this.confirmLoading = true;
request({
url: api.url,
method: api.method,
data: param,
}).then((res) => {
this.confirmLoading = false;
if (res.code == 0) {
this.$message.success(res.msg);
this.$emit("aclDetailDialog", v);
} else {
this.$message.error(res.msg);
}
});
});
},
handleCancel() {
this.$emit("aclDetailDialog", {});
this.$emit("aclDetailDialog", { refresh: true });
},
getAclDetail() {
const api = KafkaAclApi.getAclDetailList;

View File

@@ -98,7 +98,12 @@ export default {
},
watch: {
visible(v) {
this.show = v;
if (this.show != v) {
this.show = v;
if (this.show) {
this.getOperationList();
}
}
},
},
methods: {
@@ -119,7 +124,7 @@ export default {
this.confirmLoading = false;
if (res.code == 0) {
this.$message.success(res.msg);
this.$emit("addAuthDialog", v);
this.$emit("addAuthDialog", { refresh: true });
} else {
this.$message.error(res.msg);
}
@@ -127,21 +132,21 @@ export default {
});
},
handleCancel() {
this.$emit("addAuthDialog", {});
this.$emit("addAuthDialog", { refresh: false });
},
getOperationList() {
request({
url: KafkaAclApi.getOperationList.url,
method: KafkaAclApi.getOperationList.method,
}).then((res) => {
if (res.code != 0) {
this.$message.error(res.msg);
} else {
operationList.splice(0, operationList.length);
operationList.push(...res.data);
}
});
},
},
beforeMount() {
request({
url: KafkaAclApi.getOperationList.url,
method: KafkaAclApi.getOperationList.method,
}).then((res) => {
if (res.code != 0) {
this.$message.error(res.msg);
} else {
operationList.splice(0, operationList.length);
operationList.push(...res.data);
}
});
},
};
const operationList = [];

View File

@@ -8,12 +8,31 @@
:footer="null"
@cancel="handleCancel"
>
<a-form
:form="form"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 12 }"
@submit="handleSubmit"
>
<a-form-item label="用户名">
<span>{{ user.username }}</span>
</a-form-item>
<a-form-item label="密码">
<span>{{ user.password }}</span>
</a-form-item>
<a-form-item label="凭证信息">
<span>{{ user.credentialInfos }}</span>
</a-form-item>
<a-form-item label="数据一致性说明">
<strong>{{ user.consistencyDescription }}</strong>
</a-form-item>
</a-form>
</a-modal>
</template>
<script>
// import { KafkaAclApi } from "@/utils/api";
// import request from "@/utils/request";
import { KafkaAclApi } from "@/utils/api";
import request from "@/utils/request";
export default {
name: "UserDetail",
@@ -22,21 +41,24 @@ export default {
type: Boolean,
default: false,
},
username: {
type: String,
},
},
components: {
// KafkaAclApi, request,
},
components: {},
data() {
return {
formLayout: "horizontal",
show: this.visible,
form: this.$form.createForm(this, { name: "UserDetailForm" }),
user: {},
};
},
watch: {
visible(v) {
this.show = v;
if (this.show) {
this.getAclDetail();
visible(n, o) {
this.show = n;
if (n != o && this.show) {
this.getUserDetail();
}
},
},
@@ -44,6 +66,20 @@ export default {
handleCancel() {
this.$emit("userDetailDialog", {});
},
getUserDetail() {
const api = KafkaAclApi.getKafkaUserDetail;
request({
url: api.url,
method: api.method,
params: { username: this.username },
}).then((res) => {
if (res.code != 0) {
this.$message.error(res.msg);
} else {
this.user = res.data;
}
});
},
},
};
</script>