mirror of
https://github.com/rustfs/console.git
synced 2026-08-30 17:14:47 +08:00
feat: fix some bugs
This commit is contained in:
@@ -84,7 +84,6 @@ const defaultFormModal = {
|
||||
description: "",
|
||||
// comment: "",
|
||||
expiry: null,
|
||||
datetimeValue: null,
|
||||
policy: "",
|
||||
impliedPolicy: true,
|
||||
}
|
||||
|
||||
@@ -5,6 +5,19 @@ import "vanilla-jsoneditor/themes/jse-theme-dark.css"
|
||||
|
||||
// const validator = createAjvValidator({ schema, schemaDefinitions })
|
||||
const attrs = useAttrs()
|
||||
const model = defineModel()
|
||||
const value = ref(model.value)
|
||||
// 监听model变化
|
||||
watch(
|
||||
model,
|
||||
(newValue) => {
|
||||
value.value = JSON.stringify(JSON.parse(newValue), null, 2)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -13,6 +26,7 @@ const attrs = useAttrs()
|
||||
<JsonEditorVue
|
||||
v-bind="attrs"
|
||||
mode="text"
|
||||
v-model="value"
|
||||
:mainMenuBar="false"
|
||||
selection="TextSelection"
|
||||
class="editor w-full jse-theme-dark" />
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-form ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-flex justify="space-between" v-if="!editStatus">
|
||||
<n-form-item class="!w-64" label="" path="name">
|
||||
<n-input placeholder="搜索用户" @input="filterName" />
|
||||
@@ -24,11 +20,7 @@
|
||||
</n-flex>
|
||||
<n-flex justify="space-between" v-else>
|
||||
<n-form-item class="!w-96" label="选择用户组的成员" path="members">
|
||||
<n-select
|
||||
v-model:value="members"
|
||||
filterable
|
||||
multiple
|
||||
:options="users" />
|
||||
<n-select v-model:value="members" filterable multiple :options="users" />
|
||||
</n-form-item>
|
||||
<n-space>
|
||||
<NFlex>
|
||||
@@ -49,12 +41,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from "naive-ui"
|
||||
const { listUsers } = useUsers()
|
||||
const { updateGroupMembers } = useGroups()
|
||||
|
||||
@@ -62,12 +49,12 @@ const messge = useMessage()
|
||||
const props = defineProps({
|
||||
group: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: ''
|
||||
name: "",
|
||||
})
|
||||
interface RowData {
|
||||
name: string
|
||||
@@ -75,13 +62,13 @@ interface RowData {
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
title: '名称',
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
title: "名称",
|
||||
align: "left",
|
||||
key: "name",
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
@@ -89,14 +76,14 @@ const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value]
|
||||
name: [value],
|
||||
})
|
||||
}
|
||||
const listData = computed(() => {
|
||||
return (
|
||||
props.group.members.map((item: string) => {
|
||||
return {
|
||||
name: item
|
||||
name: item,
|
||||
}
|
||||
}) || []
|
||||
)
|
||||
@@ -108,43 +95,47 @@ const editStatus = ref(false)
|
||||
const users = ref<any[]>([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void
|
||||
(e: "search"): void
|
||||
}>()
|
||||
const getUserList = async () => {
|
||||
const res = await listUsers()
|
||||
users.value = Object.entries(res).map(([username, info]) => ({
|
||||
label: username,
|
||||
value: username,
|
||||
...(typeof info === 'object' ? info : {}) // 展开用户信息
|
||||
...(typeof info === "object" ? info : {}), // 展开用户信息
|
||||
}))
|
||||
}
|
||||
getUserList()
|
||||
|
||||
const members = ref(props.group.members)
|
||||
const members = ref([...props.group.members])
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
// 删除不存在的
|
||||
await updateGroupMembers({
|
||||
group: props.group.name,
|
||||
members: props.group.members.filter((item: string) => {
|
||||
return !members.value.includes(item)
|
||||
}),
|
||||
isRemove: true,
|
||||
groupStatus: 'enabled'
|
||||
const nowRemoveMembers = props.group.members.filter((item: string) => {
|
||||
return !members.value.includes(item)
|
||||
})
|
||||
if (nowRemoveMembers.length) {
|
||||
await updateGroupMembers({
|
||||
group: props.group.name,
|
||||
members: nowRemoveMembers,
|
||||
isRemove: true,
|
||||
groupStatus: "enabled",
|
||||
})
|
||||
}
|
||||
|
||||
// 修改组的成员
|
||||
await updateGroupMembers({
|
||||
group: props.group.name,
|
||||
members: members.value,
|
||||
isRemove: false,
|
||||
groupStatus: 'enabled'
|
||||
groupStatus: "enabled",
|
||||
})
|
||||
|
||||
messge.success('修改成功')
|
||||
messge.success("修改成功")
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
emit("search")
|
||||
} catch {
|
||||
messge.error('修改失败')
|
||||
messge.error("修改失败")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -195,11 +195,9 @@ function deleteByList() {
|
||||
}
|
||||
try {
|
||||
// 循环遍历删除
|
||||
checkedKeys.value.map(async (item) => {
|
||||
const res = await deleteUser(item as string)
|
||||
})
|
||||
message.success("删除成功")
|
||||
await Promise.all(checkedKeys.value.map((item) => deleteUser(item as string)))
|
||||
checkedKeys.value = []
|
||||
message.success("删除成功")
|
||||
nextTick(() => {
|
||||
getDataList()
|
||||
})
|
||||
|
||||
@@ -8,19 +8,15 @@
|
||||
class="max-w-screen-md"
|
||||
:segmented="{
|
||||
content: true,
|
||||
action: true
|
||||
action: true,
|
||||
}">
|
||||
<n-card>
|
||||
<n-tabs type="card">
|
||||
<n-tab-pane name="groups" tab="分组">
|
||||
<users-user-groups
|
||||
:user="user"
|
||||
@search="getUserData(user.accessKey)"></users-user-groups>
|
||||
<users-user-groups :user="user" @search="getUserData(user.accessKey)"></users-user-groups>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="policy" tab="策略">
|
||||
<users-user-policies
|
||||
:user="user"
|
||||
@search="getUserData(user.accessKey)"></users-user-policies>
|
||||
<users-user-policies :user="user" @search="getUserData(user.accessKey)"></users-user-policies>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="accesskey" tab="账号">
|
||||
<users-user-account
|
||||
@@ -38,9 +34,7 @@
|
||||
:on-update:value="handerUserStatusChange"></n-switch>
|
||||
</template>
|
||||
</n-tabs>
|
||||
<users-user-notice
|
||||
ref="noticeRef"
|
||||
@search="getUserData"></users-user-notice>
|
||||
<users-user-notice ref="noticeRef" @search="getUserData(user.accessKey)"></users-user-notice>
|
||||
</n-card>
|
||||
</n-modal>
|
||||
</div>
|
||||
@@ -58,17 +52,17 @@ interface UserInfo {
|
||||
}
|
||||
|
||||
const user = ref<UserInfo>({
|
||||
accessKey: '',
|
||||
accessKey: "",
|
||||
memberOf: [],
|
||||
policy: [],
|
||||
status: 'enabled'
|
||||
status: "enabled",
|
||||
})
|
||||
|
||||
// 用户的状态发生变化
|
||||
const handerUserStatusChange = async (val: string) => {
|
||||
await changeUserStatus(user.value.accessKey, {
|
||||
accessKey: user.value.accessKey,
|
||||
status: val
|
||||
status: val,
|
||||
})
|
||||
await getUserData(user.value.accessKey)
|
||||
}
|
||||
@@ -91,7 +85,7 @@ function noticeDialog(data: any) {
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openDialog
|
||||
openDialog,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
+169
-163
@@ -1,12 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false"
|
||||
v-if="!editStatus">
|
||||
<n-form ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false" v-if="!editStatus">
|
||||
<n-flex justify="space-between">
|
||||
<n-form-item class="!w-64" label="" path="name">
|
||||
<n-input placeholder="搜索账号" @input="filterName" />
|
||||
@@ -31,30 +26,20 @@
|
||||
</n-flex>
|
||||
</n-form>
|
||||
<n-form
|
||||
ref="subFormRef"
|
||||
v-else
|
||||
label-placement="left"
|
||||
:model="formModel"
|
||||
:rules="rules"
|
||||
label-align="right"
|
||||
:label-width="130">
|
||||
<n-grid :cols="24" :x-gap="18">
|
||||
<n-form-item-grid-item
|
||||
:span="24"
|
||||
label="Access Key"
|
||||
path="accesskey"
|
||||
v-if="editType == 'add'">
|
||||
<n-input v-model:value="formModel.accesskey" />
|
||||
<n-form-item-grid-item :span="24" label="Access Key" path="accessKey" v-if="editType == 'add'">
|
||||
<n-input v-model:value="formModel.accessKey" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item
|
||||
:span="24"
|
||||
label="Secret Key"
|
||||
path="secretkey"
|
||||
v-if="editType == 'add'">
|
||||
<n-input
|
||||
v-model:value="formModel.secretkey"
|
||||
show-password-on="mousedown"
|
||||
type="password" />
|
||||
<n-form-item-grid-item :span="24" label="Secret Key" path="secretKey" v-if="editType == 'add'">
|
||||
<n-input v-model:value="formModel.secretKey" show-password-on="mousedown" type="password" />
|
||||
</n-form-item-grid-item>
|
||||
<!-- TODO: 时间格式有问题 -->
|
||||
<n-form-item-grid-item :span="24" label="有效期" path="expiry">
|
||||
<n-date-picker
|
||||
class="!w-full"
|
||||
@@ -67,39 +52,20 @@
|
||||
<n-form-item-grid-item :span="24" label="名称" path="name">
|
||||
<n-input v-model:value="formModel.name" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item
|
||||
:span="24"
|
||||
label="描述"
|
||||
path="comment"
|
||||
v-if="editType == 'add'">
|
||||
<!-- <n-form-item-grid-item :span="24" label="描述" path="comment" v-if="editType == 'add'">
|
||||
<n-input v-model:value="formModel.comment" />
|
||||
</n-form-item-grid-item>
|
||||
</n-form-item-grid-item> -->
|
||||
<n-form-item-grid-item :span="24" label="注释" path="description">
|
||||
<n-input v-model:value="formModel.description" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item
|
||||
:span="24"
|
||||
label="限制超出用户策略"
|
||||
path="flag"
|
||||
v-if="editType == 'add'">
|
||||
<n-switch v-model:value="formModel.flag" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item
|
||||
v-if="formModel.flag || editType == 'edit'"
|
||||
:span="24"
|
||||
label="策略详情"
|
||||
path="policy">
|
||||
<n-form-item-gi :span="24" label="使用主账户策略" path="impliedPolicy">
|
||||
<n-switch v-model:value="formModel.impliedPolicy" />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi v-if="!formModel.impliedPolicy" :span="24" label="当前用户策略" path="policy">
|
||||
<json-editor v-model="formModel.policy" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item
|
||||
:span="24"
|
||||
label="状态"
|
||||
v-if="editType == 'edit'"
|
||||
path="status">
|
||||
<n-switch
|
||||
v-model:value="formModel.status"
|
||||
checked-value="on"
|
||||
unchecked-value="off" />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-grid-item :span="24" label="状态" v-if="editType == 'edit'" path="accountStatus">
|
||||
<n-switch v-model:value="formModel.accountStatus" checked-value="on" unchecked-value="off" />
|
||||
</n-form-item-grid-item>
|
||||
</n-grid>
|
||||
<n-space>
|
||||
@@ -128,33 +94,61 @@ import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
type DataTableRowKey,
|
||||
type FormItemRule,
|
||||
type FormInst,
|
||||
NButton,
|
||||
NPopconfirm,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { Icon } from '#components'
|
||||
NSpace,
|
||||
} from "naive-ui"
|
||||
import { Icon } from "#components"
|
||||
// 随机字符串函数
|
||||
import { makeRandomString } from '~/utils/functions'
|
||||
import { makeRandomString } from "~/utils/functions"
|
||||
const { listUserServiceAccounts, createServiceAccount } = useAccessKeys()
|
||||
const { $api } = useNuxtApp()
|
||||
|
||||
const {
|
||||
getServiceAccount,
|
||||
updateServiceAccount,
|
||||
deleteServiceAccount
|
||||
deleteServiceAccount,
|
||||
// deleteMultipleServiceAccounts
|
||||
} = useAccessKeys()
|
||||
|
||||
const { getPolicyByUserName } = usePolicies()
|
||||
// 验证
|
||||
const rules = ref({
|
||||
accessKey: {
|
||||
required: true,
|
||||
trigger: ["blur", "input"],
|
||||
message: "请输入Access Key",
|
||||
},
|
||||
secretKey: {
|
||||
required: true,
|
||||
trigger: ["blur", "input"],
|
||||
message: "请输入Secret Key",
|
||||
},
|
||||
expiry: {
|
||||
required: true,
|
||||
trigger: ["blur", "change"],
|
||||
// message: "请选择有效期",
|
||||
validator(rule: FormItemRule, value: string) {
|
||||
if (!value) {
|
||||
return new Error("请选择有效期")
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
})
|
||||
const dialog = useDialog()
|
||||
const message = useMessage()
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: ''
|
||||
name: "",
|
||||
})
|
||||
interface RowData {
|
||||
accessKey: string
|
||||
@@ -166,85 +160,85 @@ interface RowData {
|
||||
}
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
type: 'selection'
|
||||
type: "selection",
|
||||
},
|
||||
{
|
||||
title: 'Access Key',
|
||||
align: 'center',
|
||||
key: 'accessKey',
|
||||
title: "Access Key",
|
||||
align: "center",
|
||||
key: "accessKey",
|
||||
filter(value, row) {
|
||||
return !!row.accessKey.includes(value.toString())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '有效期',
|
||||
align: 'center',
|
||||
key: 'expiration'
|
||||
title: "有效期",
|
||||
align: "center",
|
||||
key: "expiration",
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
key: 'accountStatus',
|
||||
title: "状态",
|
||||
align: "center",
|
||||
key: "accountStatus",
|
||||
render: (row: any) => {
|
||||
return row.accountStatus === 'on' ? '可用' : '禁用'
|
||||
}
|
||||
return row.accountStatus === "on" ? "可用" : "禁用"
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
align: 'center',
|
||||
key: 'name'
|
||||
title: "名称",
|
||||
align: "center",
|
||||
key: "name",
|
||||
},
|
||||
// {
|
||||
// title: "描述",
|
||||
// align: "center",
|
||||
// key: "description",
|
||||
// },
|
||||
{
|
||||
title: '描述',
|
||||
align: 'center',
|
||||
key: 'description'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
align: 'center',
|
||||
title: "操作",
|
||||
key: "actions",
|
||||
align: "center",
|
||||
width: 125,
|
||||
render: (row: any) => {
|
||||
return h(
|
||||
NSpace,
|
||||
{
|
||||
justify: 'center'
|
||||
justify: "center",
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
size: "small",
|
||||
secondary: true,
|
||||
onClick: () => openEditItem(row)
|
||||
onClick: () => openEditItem(row),
|
||||
},
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' })
|
||||
default: () => "",
|
||||
icon: () => h(Icon, { name: "ri:edit-2-line" }),
|
||||
}
|
||||
),
|
||||
h(
|
||||
NPopconfirm,
|
||||
{ onPositiveClick: () => deleteItem(row) },
|
||||
{
|
||||
default: () => '确认删除',
|
||||
default: () => "确认删除",
|
||||
trigger: () =>
|
||||
h(
|
||||
NButton,
|
||||
{ size: 'small', secondary: true },
|
||||
{ size: "small", secondary: true },
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' })
|
||||
default: () => "",
|
||||
icon: () => h(Icon, { name: "ri:delete-bin-5-line" }),
|
||||
}
|
||||
)
|
||||
),
|
||||
}
|
||||
)
|
||||
]
|
||||
),
|
||||
],
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
@@ -252,112 +246,124 @@ const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value]
|
||||
name: [value],
|
||||
})
|
||||
}
|
||||
const listData = ref([])
|
||||
const getUserList = async () => {
|
||||
const res = await listUserServiceAccounts(props.user.accessKey)
|
||||
listData.value = res
|
||||
const res = await listUserServiceAccounts({ user: props.user.accessKey })
|
||||
listData.value = res.accounts
|
||||
console.log("🚀 ~ getUserList ~ listData.value:", listData.value)
|
||||
}
|
||||
getUserList()
|
||||
|
||||
/** ***********************************编辑、新增 */
|
||||
const editStatus = ref(false)
|
||||
const editType = ref('add')
|
||||
const editType = ref("add")
|
||||
|
||||
const formModel = ref({
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
name: '',
|
||||
description: '',
|
||||
comment: '',
|
||||
accessKey: makeRandomString(20),
|
||||
secretKey: makeRandomString(40),
|
||||
name: "",
|
||||
description: "",
|
||||
impliedPolicy: true,
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on'
|
||||
policy: "",
|
||||
accountStatus: "on",
|
||||
})
|
||||
|
||||
const parentPolicy = ref("")
|
||||
// 默认策略原文
|
||||
const getPolicie = async () => {
|
||||
parentPolicy.value = JSON.stringify(await getPolicyByUserName(props.user.accessKey))
|
||||
}
|
||||
getPolicie()
|
||||
// 新增
|
||||
function addItem() {
|
||||
editType.value = 'add'
|
||||
editType.value = "add"
|
||||
editStatus.value = true
|
||||
formModel.value = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
name: '',
|
||||
description: '',
|
||||
comment: '',
|
||||
accessKey: makeRandomString(20),
|
||||
secretKey: makeRandomString(40),
|
||||
name: "",
|
||||
description: "",
|
||||
impliedPolicy: true,
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on'
|
||||
accountStatus: "on",
|
||||
policy: parentPolicy.value,
|
||||
}
|
||||
}
|
||||
// 编辑
|
||||
async function openEditItem(row: any) {
|
||||
editType.value = 'edit'
|
||||
editType.value = "edit"
|
||||
editStatus.value = true
|
||||
const res = await getServiceAccount(row.accessKey)
|
||||
formModel.value = {
|
||||
...res
|
||||
...res,
|
||||
}
|
||||
formModel.value.accesskey = row.accessKey
|
||||
formModel.value.accessKey = row.accessKey
|
||||
formModel.value.expiry = res.expiration
|
||||
formModel.value.status = res.accountStatus
|
||||
formModel.value.accountStatus = res.accountStatus
|
||||
}
|
||||
|
||||
function cancelAdd() {
|
||||
editStatus.value = false
|
||||
editType.value === 'add'
|
||||
editType.value === "add"
|
||||
formModel.value = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
name: '',
|
||||
description: '',
|
||||
comment: '',
|
||||
accessKey: makeRandomString(20),
|
||||
secretKey: makeRandomString(40),
|
||||
name: "",
|
||||
description: "",
|
||||
impliedPolicy: true,
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on'
|
||||
policy: "",
|
||||
accountStatus: "on",
|
||||
}
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'search'): void
|
||||
(e: 'notice', data: object): void
|
||||
(e: "search"): void
|
||||
(e: "notice", data: object): void
|
||||
}
|
||||
const emit = defineEmits<Emits>()
|
||||
const subFormRef = ref<FormInst | null>(null)
|
||||
async function submitForm() {
|
||||
if (editType.value === 'add') {
|
||||
try {
|
||||
console.log(formModel.value)
|
||||
const res = await createServiceAccount({
|
||||
...formModel.value,
|
||||
targetUser: props.user.accessKey,
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString() || ''
|
||||
})
|
||||
if (editType.value === "add") {
|
||||
subFormRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
const res = await createServiceAccount({
|
||||
...formModel.value,
|
||||
targetUser: props.user.accessKey,
|
||||
policy: !formModel.value.impliedPolicy ? JSON.stringify(JSON.parse(formModel.value.policy)) : null,
|
||||
expiration: formModel.value.expiry ? new Date(formModel.value.expiry).toISOString() : null,
|
||||
})
|
||||
|
||||
message.success('添加成功')
|
||||
cancelAdd()
|
||||
emit('notice', res)
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
message.error('添加失败')
|
||||
}
|
||||
message.success("添加成功")
|
||||
cancelAdd()
|
||||
emit("notice", res)
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
message.error("添加失败")
|
||||
}
|
||||
} else {
|
||||
console.log(errors)
|
||||
message.error("请填写正确的格式")
|
||||
}
|
||||
})
|
||||
} else {
|
||||
try {
|
||||
const res = await updateServiceAccount(formModel.value.accesskey, {
|
||||
const res = await updateServiceAccount(formModel.value.secretKey, {
|
||||
...formModel.value,
|
||||
policy: formModel.value.policy || '{}',
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString()
|
||||
policy: formModel.value.policy || "{}",
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString(),
|
||||
})
|
||||
message.success('修改成功')
|
||||
message.success("修改成功")
|
||||
cancelAdd()
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
message.error('修改失败')
|
||||
message.error("修改失败")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -369,10 +375,10 @@ function dateDisabled(ts: number) {
|
||||
async function deleteItem(row: any) {
|
||||
try {
|
||||
const res = await deleteServiceAccount(row.accessKey)
|
||||
message.success('删除成功')
|
||||
message.success("删除成功")
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
message.error('删除失败')
|
||||
message.error("删除失败")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,13 +394,13 @@ function handleCheck(keys: DataTableRowKey[]) {
|
||||
}
|
||||
function deleteByList() {
|
||||
dialog.error({
|
||||
title: '警告',
|
||||
content: '你确定要删除所有选中的秘钥吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
title: "警告",
|
||||
content: "你确定要删除所有选中的秘钥吗?",
|
||||
positiveText: "确定",
|
||||
negativeText: "取消",
|
||||
onPositiveClick: async () => {
|
||||
if (!checkedKeys.value.length) {
|
||||
message.error('请至少选择一项')
|
||||
message.error("请至少选择一项")
|
||||
return
|
||||
}
|
||||
try {
|
||||
@@ -403,11 +409,11 @@ function deleteByList() {
|
||||
// })
|
||||
checkedKeys.value = []
|
||||
getUserList()
|
||||
message.success('删除成功')
|
||||
message.success("删除成功")
|
||||
} catch (error) {
|
||||
message.error('删除失败')
|
||||
message.error("删除失败")
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -153,7 +153,7 @@ const groupsList = ref([])
|
||||
const getGroupsList = async () => {
|
||||
const res = await listGroup()
|
||||
groupsList.value =
|
||||
res.groups.map((item: any) => {
|
||||
res.groups?.map((item: any) => {
|
||||
return {
|
||||
label: item,
|
||||
value: item,
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-card>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-form ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-flex justify="space-between" v-if="!editStatus">
|
||||
<n-form-item class="!w-64" label="" path="name">
|
||||
<n-input placeholder="搜索策略" @input="filterName" />
|
||||
@@ -24,11 +20,7 @@
|
||||
</n-flex>
|
||||
<n-flex justify="space-between" v-else>
|
||||
<n-form-item class="!w-96" label="选择策略" path="policy">
|
||||
<n-select
|
||||
v-model:value="policy"
|
||||
filterable
|
||||
multiple
|
||||
:options="policyList" />
|
||||
<n-select v-model:value="policy" filterable multiple :options="policyList" />
|
||||
</n-form-item>
|
||||
<n-space>
|
||||
<NFlex>
|
||||
@@ -49,37 +41,32 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from "naive-ui"
|
||||
const { listPolicies, setUserOrGroupPolicy } = usePolicies()
|
||||
|
||||
const messge = useMessage()
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: ''
|
||||
name: "",
|
||||
})
|
||||
interface RowData {
|
||||
name: string
|
||||
}
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
title: '名称',
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
title: "名称",
|
||||
align: "left",
|
||||
key: "name",
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
@@ -87,16 +74,16 @@ const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value]
|
||||
name: [value],
|
||||
})
|
||||
}
|
||||
const listData = computed(() => {
|
||||
if (!props.user?.policyName) return []
|
||||
|
||||
return (
|
||||
props.user?.policyName?.split(',').map((item: string) => {
|
||||
props.user?.policyName?.split(",").map((item: string) => {
|
||||
return {
|
||||
name: item
|
||||
name: item,
|
||||
}
|
||||
}) || []
|
||||
)
|
||||
@@ -108,32 +95,32 @@ const editStatus = ref(false)
|
||||
const policyList = ref<any[]>([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void
|
||||
(e: "search"): void
|
||||
}>()
|
||||
const getPoliciesList = async () => {
|
||||
const res = await listPolicies()
|
||||
policyList.value = Object.keys(res).map((key) => {
|
||||
return {
|
||||
label: key,
|
||||
value: key
|
||||
value: key,
|
||||
}
|
||||
})
|
||||
}
|
||||
getPoliciesList()
|
||||
|
||||
const policy = ref(props.user.policyName.split(','))
|
||||
const policy = ref(props.user?.policyName?.split(","))
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
await setUserOrGroupPolicy({
|
||||
policyName: policy.value || '',
|
||||
policyName: policy.value || "",
|
||||
userOrGroup: encodeURIComponent(props.user.accessKey),
|
||||
isGroup: false
|
||||
isGroup: false,
|
||||
})
|
||||
messge.success('修改成功')
|
||||
messge.success("修改成功")
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
emit("search")
|
||||
} catch {
|
||||
messge.error('修改失败')
|
||||
messge.error("修改失败")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -72,6 +72,59 @@ export const usePolicies = () => {
|
||||
return await $api.put(`/set-user-or-group-policy`, {}, { params: data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户的名称获取策略原文
|
||||
* @param userName
|
||||
* @returns
|
||||
*/
|
||||
const getPolicyByUserName = async (userName: string) => {
|
||||
// 获取用户策略组
|
||||
const userInfo = await $api.get(`/user-info?accessKey=${userName}`)
|
||||
const policyName = userInfo?.policyName?.split(",") || []
|
||||
|
||||
// 获取用户所在分组
|
||||
const memberOf = userInfo?.memberOf
|
||||
// 获取分组的策略
|
||||
if (memberOf && memberOf.length > 0) {
|
||||
const promises = memberOf.map(async (element: string) => {
|
||||
const groupInfo: { policy?: string } = await $api.get(`/group?group=${encodeURIComponent(element)}`)
|
||||
const groupPolicyName: string[] = groupInfo.policy ? groupInfo.policy.split(",") : []
|
||||
return groupPolicyName
|
||||
})
|
||||
const results = await Promise.all(promises)
|
||||
results.forEach((policyNames) => {
|
||||
policyName.push(...policyNames)
|
||||
})
|
||||
}
|
||||
|
||||
// 去重
|
||||
let uniquePolicyName: string[] = []
|
||||
if (policyName.length) {
|
||||
uniquePolicyName = Array.from(new Set(policyName))
|
||||
}
|
||||
|
||||
let policyStatement: any = []
|
||||
// 获取所有剩余的策略策略原文
|
||||
if (uniquePolicyName.length) {
|
||||
const policyPromises = uniquePolicyName.map(async (element: any) => {
|
||||
const policyInfo = await getPolicy(element)
|
||||
// 格式化policy
|
||||
let policyRes = JSON.parse(policyInfo.policy)
|
||||
if (policyRes?.Statement) {
|
||||
policyStatement.push(...policyRes.Statement)
|
||||
}
|
||||
})
|
||||
// 等待所有的请求完成
|
||||
await Promise.all(policyPromises)
|
||||
}
|
||||
|
||||
return {
|
||||
ID: "",
|
||||
Version: "2012-10-17",
|
||||
Statement: policyStatement,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
listPolicies,
|
||||
getPolicy,
|
||||
@@ -81,5 +134,6 @@ export const usePolicies = () => {
|
||||
listGroupsForPolicy,
|
||||
setPolicyMultiple,
|
||||
setUserOrGroupPolicy,
|
||||
getPolicyByUserName,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user