feat: 资产授权.
This commit is contained in:
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 主机 缓存对象
|
||||
@@ -35,4 +36,10 @@ public class HostCacheDTO implements LongCacheIdModel, Serializable {
|
||||
@Schema(description = "主机地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 主机身份缓存
|
||||
@@ -32,4 +33,13 @@ public class HostIdentityCacheDTO implements LongCacheIdModel, Serializable {
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "秘钥id")
|
||||
private Long keyId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 主机秘钥缓存
|
||||
@@ -29,4 +30,10 @@ public class HostKeyCacheDTO implements LongCacheIdModel, Serializable {
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export function getAuthorizedHostGroup(params: AssetAuthorizedDataQueryRequest)
|
||||
* 主机秘钥授权
|
||||
*/
|
||||
export function grantHostKey(request: AssetDataGrantRequest) {
|
||||
return axios.put('/asset/host-group/grant-host-key', request);
|
||||
return axios.put('/asset/data-grant/grant-host-key', request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ export function getAuthorizedHostKey(params: AssetAuthorizedDataQueryRequest) {
|
||||
* 主机身份授权
|
||||
*/
|
||||
export function grantHostIdentity(request: AssetDataGrantRequest) {
|
||||
return axios.put('/asset/host-group/grant-host-identity', request);
|
||||
return axios.put('/asset/data-grant/grant-host-identity', request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,6 +73,14 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sticky-list {
|
||||
.arco-list-header {
|
||||
position: sticky;
|
||||
background: var(--color-bg-2);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.arco-table-td-content {
|
||||
color: rgba(var(--gray-9), .95);
|
||||
font-size: 13px;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
title: String,
|
||||
options: {
|
||||
type: Array as PropType<OptionsProps[]>,
|
||||
default: []
|
||||
default: () => []
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
},
|
||||
options: {
|
||||
type: Array as PropType<Array<RadioOption | SelectOption>>,
|
||||
default: []
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(['inputChange']);
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
const props = defineProps({
|
||||
itemData: {
|
||||
type: Object as PropType<TagProps>,
|
||||
default: [],
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
},
|
||||
checkedKeys: {
|
||||
type: Array<Number>,
|
||||
default: []
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(['loading', 'selectNode', 'update:checkedKeys']);
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
@select-node="e => selectedGroup = e"
|
||||
@update:checked-keys="updateCheckedGroups" />
|
||||
<!-- 主机列表 -->
|
||||
<host-list class="group-main-hosts"
|
||||
:group="selectedGroup" />
|
||||
<host-list class="group-main-hosts sticky-list" :group="selectedGroup" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -57,9 +56,9 @@
|
||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||
import { AdminRoleCode } from '@/types/const';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
import HostList from './host-list.vue';
|
||||
import RouterRoles from './router-roles.vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<!-- 主题部分 -->
|
||||
<div class="group-main">
|
||||
<!-- 分组 -->
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
<host-group-tree outer-class="group-main-tree sticky-list"
|
||||
:checked-keys="checkedGroups"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@@ -36,8 +36,7 @@
|
||||
@select-node="e => selectedGroup = e"
|
||||
@update:checked-keys="updateCheckedGroups" />
|
||||
<!-- 主机列表 -->
|
||||
<host-list class="group-main-hosts"
|
||||
:group="selectedGroup" />
|
||||
<host-list class="group-main-hosts" :group="selectedGroup" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -52,12 +51,12 @@
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import HostList from './host-list.vue';
|
||||
import RouterUsers from './router-users.vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<a-table row-key="id"
|
||||
class="host-identity-main-table"
|
||||
label-align="left"
|
||||
:columns="hostIdentityColumns"
|
||||
v-model:selected-keys="selectedKeys"
|
||||
:row-selection="rowSelection"
|
||||
:sticky-header="true"
|
||||
:data="hostIdentities"
|
||||
:pagination="false"
|
||||
:bordered="false">
|
||||
<!-- 秘钥名称 -->
|
||||
<template #keyId="{ record }">
|
||||
<a-tag color="arcoblue" v-if="record.keyName">{{ record.keyName }}</a-tag>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'host-identity-grant-table'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import type { HostIdentityQueryResponse } from '@/api/asset/host-identity';
|
||||
import { hostIdentityColumns } from '../types/table.columns';
|
||||
import { useRowSelection } from '@/types/table';
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(['loading', 'update:modelValue']);
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const rowSelection = useRowSelection();
|
||||
|
||||
const hostIdentities = ref<Array<HostIdentityQueryResponse>>([]);
|
||||
|
||||
const selectedKeys = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
set(e) {
|
||||
emits('update:modelValue', e);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化数据
|
||||
onMounted(async () => {
|
||||
emits('loading', true);
|
||||
try {
|
||||
const keys = await cacheStore.loadHostKeys();
|
||||
const identities = await cacheStore.loadHostIdentities();
|
||||
hostIdentities.value = identities.map(s => {
|
||||
return {
|
||||
...s,
|
||||
keyName: s.keyId ? keys.find(k => k.id === s.keyId)?.name : undefined
|
||||
};
|
||||
});
|
||||
} catch (e) {
|
||||
} finally {
|
||||
emits('loading', false);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@@ -3,11 +3,11 @@
|
||||
<!-- 角色列表 -->
|
||||
<router-roles outer-class="roles-router-wrapper"
|
||||
v-model="roleId"
|
||||
@change="fetchAuthorizedGroup" />
|
||||
@change="fetchAuthorizedHostIdentity" />
|
||||
<!-- 分组列表 -->
|
||||
<div class="group-container">
|
||||
<div class="host-identity-container">
|
||||
<!-- 顶部 -->
|
||||
<div class="group-header">
|
||||
<div class="host-identity-header">
|
||||
<!-- 提示信息 -->
|
||||
<a-alert class="alert-wrapper" :show-icon="false">
|
||||
<span v-if="currentRole" class="alert-message">
|
||||
@@ -26,19 +26,9 @@
|
||||
</a-button>
|
||||
</div>
|
||||
<!-- 主体部分 -->
|
||||
<div class="group-main">
|
||||
<!-- 分组 -->
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
:checkable="true"
|
||||
:checked-keys="checkedGroups"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@loading="setLoading"
|
||||
@select-node="e => selectedGroup = e"
|
||||
@update:checked-keys="updateCheckedGroups" />
|
||||
<!-- 主机列表 -->
|
||||
<host-list class="group-main-hosts"
|
||||
:group="selectedGroup" />
|
||||
<div class="host-identity-main">
|
||||
<host-identity-grant-table v-model="selectedIdentities"
|
||||
@loading="setLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -51,53 +41,45 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||
import { getAuthorizedHostIdentity, grantHostIdentity } from '@/api/asset/asset-data-grant';
|
||||
import { AdminRoleCode } from '@/types/const';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
import HostList from './host-list.vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useCacheStore } from '@/store';
|
||||
import RouterRoles from './router-roles.vue';
|
||||
import HostIdentityGrantTable from './host-identity-grant-table.vue';
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
const roleId = ref();
|
||||
const currentRole = ref();
|
||||
const authorizedGroups = ref<Array<number>>([]);
|
||||
const checkedGroups = ref<Array<number>>([]);
|
||||
const selectedGroup = ref<TreeNodeData>({});
|
||||
const selectedIdentities = ref<Array<number>>([]);
|
||||
|
||||
// 获取授权列表
|
||||
const fetchAuthorizedGroup = async (id: number, role: any) => {
|
||||
const fetchAuthorizedHostIdentity = async (id: number, role: any) => {
|
||||
roleId.value = id;
|
||||
currentRole.value = role;
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getAuthorizedHostGroup({
|
||||
const { data } = await getAuthorizedHostIdentity({
|
||||
roleId: roleId.value
|
||||
});
|
||||
authorizedGroups.value = data;
|
||||
checkedGroups.value = data;
|
||||
selectedIdentities.value = data;
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 选择分组
|
||||
const updateCheckedGroups = (e: Array<number>) => {
|
||||
checkedGroups.value = e;
|
||||
};
|
||||
|
||||
// 授权
|
||||
const doGrant = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await grantHostGroup({
|
||||
await grantHostIdentity({
|
||||
roleId: roleId.value,
|
||||
idList: checkedGroups.value
|
||||
idList: selectedIdentities.value
|
||||
});
|
||||
Message.success('授权成功');
|
||||
} catch (e) {
|
||||
@@ -121,12 +103,12 @@
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
}
|
||||
|
||||
.group-container {
|
||||
.host-identity-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.group-header {
|
||||
.host-identity-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
@@ -146,20 +128,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.group-main {
|
||||
.host-identity-main {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
|
||||
&-tree {
|
||||
width: calc(60% - 16px);
|
||||
&-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
&-hosts {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<!-- 用户列表 -->
|
||||
<router-users outer-class="users-router-wrapper"
|
||||
v-model="userId"
|
||||
@change="fetchAuthorizedGroup" />
|
||||
@change="fetchAuthorizedHostIdentity" />
|
||||
<!-- 分组列表 -->
|
||||
<div class="group-container">
|
||||
<div class="host-identity-container">
|
||||
<!-- 顶部 -->
|
||||
<div class="group-header">
|
||||
<div class="host-identity-header">
|
||||
<!-- 提示信息 -->
|
||||
<a-alert class="alert-wrapper" :show-icon="false">
|
||||
<span v-if="currentUser" class="alert-message">
|
||||
当前选择的用户为 <span class="span-blue mr4">{{ currentUser?.text }}</span>
|
||||
<span class="ml4">若当前选择的用户角色包含管理员则无需配置 (管理员拥有全部权限)</span>
|
||||
<span class="ml4">若当前选择的用户用户包含管理员则无需配置 (管理员拥有全部权限)</span>
|
||||
</span>
|
||||
</a-alert>
|
||||
<!-- 授权 -->
|
||||
@@ -25,19 +25,10 @@
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
<!-- 主题部分 -->
|
||||
<div class="group-main">
|
||||
<!-- 分组 -->
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
:checked-keys="checkedGroups"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@loading="setLoading"
|
||||
@select-node="e => selectedGroup = e"
|
||||
@update:checked-keys="updateCheckedGroups" />
|
||||
<!-- 主机列表 -->
|
||||
<host-list class="group-main-hosts"
|
||||
:group="selectedGroup" />
|
||||
<!-- 主体部分 -->
|
||||
<div class="host-identity-main">
|
||||
<host-identity-grant-table v-model="selectedIdentities"
|
||||
@loading="setLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -50,52 +41,44 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||
import { getAuthorizedHostIdentity, grantHostIdentity } from '@/api/asset/asset-data-grant';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
import HostList from './host-list.vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useCacheStore } from '@/store';
|
||||
import RouterUsers from './router-users.vue';
|
||||
import HostIdentityGrantTable from '@/views/asset/grant/components/host-identity-grant-table.vue';
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
const userId = ref();
|
||||
const currentUser = ref();
|
||||
const authorizedGroups = ref<Array<number>>([]);
|
||||
const checkedGroups = ref<Array<number>>([]);
|
||||
const selectedGroup = ref<TreeNodeData>({});
|
||||
const selectedIdentities = ref<Array<number>>([]);
|
||||
|
||||
// 获取授权列表
|
||||
const fetchAuthorizedGroup = async (id: number, user: any) => {
|
||||
const fetchAuthorizedHostIdentity = async (id: number, user: any) => {
|
||||
userId.value = id;
|
||||
currentUser.value = user;
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getAuthorizedHostGroup({
|
||||
const { data } = await getAuthorizedHostIdentity({
|
||||
userId: userId.value
|
||||
});
|
||||
authorizedGroups.value = data;
|
||||
checkedGroups.value = data;
|
||||
selectedIdentities.value = data;
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 选择分组
|
||||
const updateCheckedGroups = (e: Array<number>) => {
|
||||
checkedGroups.value = e;
|
||||
};
|
||||
|
||||
// 授权
|
||||
const doGrant = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await grantHostGroup({
|
||||
await grantHostIdentity({
|
||||
userId: userId.value,
|
||||
idList: checkedGroups.value
|
||||
idList: selectedIdentities.value
|
||||
});
|
||||
Message.success('授权成功');
|
||||
} catch (e) {
|
||||
@@ -119,12 +102,12 @@
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
}
|
||||
|
||||
.group-container {
|
||||
.host-identity-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.group-header {
|
||||
.host-identity-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
@@ -144,20 +127,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.group-main {
|
||||
.host-identity-main {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
|
||||
&-tree {
|
||||
width: calc(60% - 16px);
|
||||
&-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
&-hosts {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<a-table row-key="id"
|
||||
class="host-key-main-table"
|
||||
label-align="left"
|
||||
:columns="hostKeyColumns"
|
||||
v-model:selected-keys="selectedKeys"
|
||||
:row-selection="rowSelection"
|
||||
:sticky-header="true"
|
||||
:data="hostKeys"
|
||||
:pagination="false"
|
||||
:bordered="false" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'host-key-grant-table'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
||||
import { hostKeyColumns } from '../types/table.columns';
|
||||
import { useRowSelection } from '@/types/table';
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { useCacheStore } from '@/store';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(['loading', 'update:modelValue']);
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const rowSelection = useRowSelection();
|
||||
|
||||
const hostKeys = ref<Array<HostKeyQueryResponse>>([]);
|
||||
|
||||
const selectedKeys = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
set(e) {
|
||||
emits('update:modelValue', e);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化数据
|
||||
onMounted(async () => {
|
||||
emits('loading', true);
|
||||
try {
|
||||
hostKeys.value = await cacheStore.loadHostKeys();
|
||||
} catch (e) {
|
||||
} finally {
|
||||
emits('loading', false);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@@ -27,17 +27,8 @@
|
||||
</div>
|
||||
<!-- 主体部分 -->
|
||||
<div class="host-key-main">
|
||||
<a-table row-key="id"
|
||||
class="host-key-main-table"
|
||||
label-align="left"
|
||||
:loading="loading"
|
||||
:columns="hostKeyColumns"
|
||||
v-model:selected-keys="selectedKeys"
|
||||
:row-selection="rowSelection"
|
||||
:sticky-header="true"
|
||||
:data="hostKeys"
|
||||
:pagination="false"
|
||||
:bordered="false" />
|
||||
<host-key-grant-table v-model="selectedKeys"
|
||||
@loading="setLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -55,13 +46,11 @@
|
||||
import { getAuthorizedHostKey, grantHostKey } from '@/api/asset/asset-data-grant';
|
||||
import { AdminRoleCode } from '@/types/const';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { hostKeyColumns } from '../types/table.columns';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useRowSelection } from '@/types/table';
|
||||
import { useCacheStore } from '@/store';
|
||||
import RouterRoles from './router-roles.vue';
|
||||
import HostKeyGrantTable from './host-key-grant-table.vue';
|
||||
|
||||
const rowSelection = useRowSelection();
|
||||
const cacheStore = useCacheStore();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
<!-- 用户列表 -->
|
||||
<router-users outer-class="users-router-wrapper"
|
||||
v-model="userId"
|
||||
@change="fetchAuthorizedGroup" />
|
||||
@change="fetchAuthorizedHostKey" />
|
||||
<!-- 分组列表 -->
|
||||
<div class="group-container">
|
||||
<div class="host-key-container">
|
||||
<!-- 顶部 -->
|
||||
<div class="group-header">
|
||||
<div class="host-key-header">
|
||||
<!-- 提示信息 -->
|
||||
<a-alert class="alert-wrapper" :show-icon="false">
|
||||
<span v-if="currentUser" class="alert-message">
|
||||
当前选择的用户为 <span class="span-blue mr4">{{ currentUser?.text }}</span>
|
||||
<span class="ml4">若当前选择的用户角色包含管理员则无需配置 (管理员拥有全部权限)</span>
|
||||
<span class="ml4">若当前选择的用户用户包含管理员则无需配置 (管理员拥有全部权限)</span>
|
||||
</span>
|
||||
</a-alert>
|
||||
<!-- 授权 -->
|
||||
@@ -25,19 +25,10 @@
|
||||
</template>
|
||||
</a-button>
|
||||
</div>
|
||||
<!-- 主题部分 -->
|
||||
<div class="group-main">
|
||||
<!-- 分组 -->
|
||||
<host-group-tree outer-class="group-main-tree"
|
||||
:checked-keys="checkedGroups"
|
||||
:editable="false"
|
||||
:loading="loading"
|
||||
@loading="setLoading"
|
||||
@select-node="e => selectedGroup = e"
|
||||
@update:checked-keys="updateCheckedGroups" />
|
||||
<!-- 主机列表 -->
|
||||
<host-list class="group-main-hosts"
|
||||
:group="selectedGroup" />
|
||||
<!-- 主体部分 -->
|
||||
<div class="host-key-main">
|
||||
<host-key-grant-table v-model="selectedKeys"
|
||||
@loading="setLoading" />
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@@ -50,52 +41,46 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TreeNodeData } from '@arco-design/web-vue';
|
||||
import { ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { getAuthorizedHostGroup, grantHostGroup } from '@/api/asset/asset-data-grant';
|
||||
import type { HostKeyQueryResponse } from '@/api/asset/host-key';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { getAuthorizedHostKey, grantHostKey } from '@/api/asset/asset-data-grant';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import HostGroupTree from '@/components/asset/host-group/host-group-tree.vue';
|
||||
import HostList from './host-list.vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { useCacheStore } from '@/store';
|
||||
import RouterUsers from './router-users.vue';
|
||||
import HostKeyGrantTable from './host-key-grant-table.vue';
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
const userId = ref();
|
||||
const currentUser = ref();
|
||||
const authorizedGroups = ref<Array<number>>([]);
|
||||
const checkedGroups = ref<Array<number>>([]);
|
||||
const selectedGroup = ref<TreeNodeData>({});
|
||||
const hostKeys = ref<Array<HostKeyQueryResponse>>([]);
|
||||
const selectedKeys = ref<Array<number>>([]);
|
||||
|
||||
// 获取授权列表
|
||||
const fetchAuthorizedGroup = async (id: number, user: any) => {
|
||||
const fetchAuthorizedHostKey = async (id: number, user: any) => {
|
||||
userId.value = id;
|
||||
currentUser.value = user;
|
||||
setLoading(true);
|
||||
try {
|
||||
const { data } = await getAuthorizedHostGroup({
|
||||
const { data } = await getAuthorizedHostKey({
|
||||
userId: userId.value
|
||||
});
|
||||
authorizedGroups.value = data;
|
||||
checkedGroups.value = data;
|
||||
selectedKeys.value = data;
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 选择分组
|
||||
const updateCheckedGroups = (e: Array<number>) => {
|
||||
checkedGroups.value = e;
|
||||
};
|
||||
|
||||
// 授权
|
||||
const doGrant = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await grantHostGroup({
|
||||
await grantHostKey({
|
||||
userId: userId.value,
|
||||
idList: checkedGroups.value
|
||||
idList: selectedKeys.value
|
||||
});
|
||||
Message.success('授权成功');
|
||||
} catch (e) {
|
||||
@@ -104,6 +89,17 @@
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化数据
|
||||
onMounted(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
hostKeys.value = await cacheStore.loadHostKeys();
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -119,12 +115,12 @@
|
||||
border-right: 1px var(--color-neutral-3) solid;
|
||||
}
|
||||
|
||||
.group-container {
|
||||
.host-key-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.group-header {
|
||||
.host-key-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
@@ -144,20 +140,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.group-main {
|
||||
.host-key-main {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(100% - 48px);
|
||||
|
||||
&-tree {
|
||||
width: calc(60% - 16px);
|
||||
&-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
&-hosts {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
// 卸载时清除 cache
|
||||
onUnmounted(() => {
|
||||
cacheStore.reset('users', 'roles', 'hosts', 'hostGroups');
|
||||
cacheStore.reset('users', 'roles', 'hosts', 'hostGroups', 'hostKeys', 'hostIdentities');
|
||||
});
|
||||
|
||||
// 跳转到指定页
|
||||
|
||||
@@ -32,3 +32,45 @@ export const hostKeyColumns = [
|
||||
},
|
||||
},
|
||||
] as TableColumnData[];
|
||||
|
||||
// 主机身份列
|
||||
export const hostIdentityColumns = [
|
||||
{
|
||||
title: 'id',
|
||||
dataIndex: 'id',
|
||||
slotName: 'id',
|
||||
width: 70,
|
||||
align: 'left',
|
||||
fixed: 'left',
|
||||
}, {
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
slotName: 'name',
|
||||
}, {
|
||||
title: '用户名',
|
||||
dataIndex: 'username',
|
||||
slotName: 'username',
|
||||
}, {
|
||||
title: '主机秘钥',
|
||||
dataIndex: 'keyId',
|
||||
slotName: 'keyId',
|
||||
}, {
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
slotName: 'createTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
render: ({ record }) => {
|
||||
return dateFormat(new Date(record.createTime));
|
||||
},
|
||||
}, {
|
||||
title: '修改时间',
|
||||
dataIndex: 'updateTime',
|
||||
slotName: 'updateTime',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
render: ({ record }) => {
|
||||
return dateFormat(new Date(record.updateTime));
|
||||
},
|
||||
},
|
||||
] as TableColumnData[];
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array<string>,
|
||||
default: []
|
||||
default: () => []
|
||||
},
|
||||
group: {
|
||||
type: Object as PropType<TreeNodeData>,
|
||||
|
||||
Reference in New Issue
Block a user