mirror of
https://github.com/rustfs/console.git
synced 2026-08-30 17:14:47 +08:00
feat : 用户 用户组状态
This commit is contained in:
@@ -1,67 +1,3 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { makeRandomString } from '~/utils/functions';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
}
|
||||
const { visible } = defineProps<Props>();
|
||||
const message = useMessage();
|
||||
const { $api } = useNuxtApp();
|
||||
const { createServiceAccountCreds } = useAccessKeys();
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
const defaultFormModal = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
name: '',
|
||||
description: '',
|
||||
comment: '',
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
};
|
||||
const formModel = ref({ ...defaultFormModal });
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
(e: 'search'): void;
|
||||
(e: 'notice', data: object): void;
|
||||
}
|
||||
|
||||
const modalVisible = computed({
|
||||
get() {
|
||||
return visible;
|
||||
},
|
||||
set(visible) {
|
||||
closeModal(visible);
|
||||
},
|
||||
});
|
||||
function closeModal(visible = false) {
|
||||
emit('update:visible', visible);
|
||||
}
|
||||
|
||||
function dateDisabled(ts: number) {
|
||||
const date = new Date(ts);
|
||||
return date < new Date();
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
try {
|
||||
const res = await createServiceAccountCreds({
|
||||
...formModel.value,
|
||||
expiry: new Date(formModel.value.expiry || '').toISOString(),
|
||||
});
|
||||
message.success('添加成功');
|
||||
emit('notice', res);
|
||||
closeModal();
|
||||
emit('search');
|
||||
} catch (error) {
|
||||
message.error('添加失败');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
v-model:show="modalVisible"
|
||||
@@ -71,17 +7,32 @@ async function submitForm() {
|
||||
class="max-w-screen-md"
|
||||
:segmented="{
|
||||
content: true,
|
||||
action: true,
|
||||
action: true
|
||||
}">
|
||||
<n-card>
|
||||
<n-form label-placement="left" :model="formModel" label-align="center" :label-width="130">
|
||||
<n-form
|
||||
label-placement="left"
|
||||
:model="formModel"
|
||||
label-align="center"
|
||||
:label-width="130">
|
||||
<n-grid :cols="24" :x-gap="18">
|
||||
<n-form-item-grid-item :span="24" label="Access Key" path="accesskey">
|
||||
<n-input v-model:value="formModel.accesskey" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item :span="24" label="Secret Key" path="secretkey">
|
||||
<n-input v-model:value="formModel.secretkey" show-password-on="mousedown" type="password" />
|
||||
<n-input
|
||||
v-model:value="formModel.secretkey"
|
||||
show-password-on="mousedown"
|
||||
type="password" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item :span="24" label="策略" path="policy">
|
||||
<n-select
|
||||
v-model:value="formModel.policy"
|
||||
filterable
|
||||
multiple
|
||||
:options="polices" />
|
||||
</n-form-item-grid-item>
|
||||
|
||||
<!-- TODO: 时间格式有问题 -->
|
||||
<n-form-item-grid-item :span="24" label="有效期" path="expiry">
|
||||
<n-date-picker
|
||||
@@ -95,18 +46,25 @@ async function submitForm() {
|
||||
<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">
|
||||
<!-- <n-form-item-grid-item :span="24" label="描述" path="comment">
|
||||
<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">
|
||||
<!-- <n-form-item-grid-item
|
||||
:span="24"
|
||||
label="限制超出用户策略"
|
||||
path="flag">
|
||||
<n-switch v-model:value="formModel.flag" />
|
||||
</n-form-item-grid-item>
|
||||
<n-form-item-grid-item v-if="formModel.flag" :span="24" label="策略详情" path="policy">
|
||||
<n-form-item-grid-item
|
||||
v-if="formModel.flag"
|
||||
:span="24"
|
||||
label="策略详情"
|
||||
path="policy">
|
||||
<json-editor v-model="formModel.policy" />
|
||||
</n-form-item-grid-item>
|
||||
</n-form-item-grid-item> -->
|
||||
</n-grid>
|
||||
</n-form>
|
||||
</n-card>
|
||||
@@ -118,5 +76,85 @@ async function submitForm() {
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { makeRandomString } from '~/utils/functions'
|
||||
|
||||
interface Props {
|
||||
visible: boolean
|
||||
}
|
||||
const { visible } = defineProps<Props>()
|
||||
const message = useMessage()
|
||||
const { $api } = useNuxtApp()
|
||||
const { createServiceAccountCreds } = useAccessKeys()
|
||||
const { listPolicies } = usePolicies()
|
||||
const { credentials } = useAuth()
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
const defaultFormModal = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
name: '',
|
||||
description: '',
|
||||
comment: '',
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false
|
||||
}
|
||||
const formModel = ref({ ...defaultFormModal })
|
||||
|
||||
interface Emits {
|
||||
(e: 'update:visible', visible: boolean): void
|
||||
(e: 'search'): void
|
||||
(e: 'notice', data: object): void
|
||||
}
|
||||
|
||||
const modalVisible = computed({
|
||||
get() {
|
||||
return visible
|
||||
},
|
||||
set(visible) {
|
||||
closeModal(visible)
|
||||
}
|
||||
})
|
||||
function closeModal(visible = false) {
|
||||
emit('update:visible', visible)
|
||||
}
|
||||
|
||||
function dateDisabled(ts: number) {
|
||||
const date = new Date(ts)
|
||||
return date < new Date()
|
||||
}
|
||||
async function submitForm() {
|
||||
try {
|
||||
const res = await createServiceAccountCreds({
|
||||
...formModel.value,
|
||||
targetUser: credentials.value?.AccessKeyId,
|
||||
status: 'enabled'
|
||||
// expiry: new Date(formModel.value.expiry || '').toISOString()
|
||||
})
|
||||
message.success('添加成功')
|
||||
emit('notice', res)
|
||||
closeModal()
|
||||
emit('search')
|
||||
} catch (error) {
|
||||
message.error('添加失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 策略列表
|
||||
const polices = ref<any[]>([])
|
||||
|
||||
const getPoliciesList = async () => {
|
||||
const res = await listPolicies()
|
||||
polices.value = Object.keys(res).map((key) => {
|
||||
return {
|
||||
label: key,
|
||||
value: key
|
||||
}
|
||||
})
|
||||
}
|
||||
getPoliciesList()
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<script setup lang="ts">
|
||||
// import { groupMembers, groupPolicies } from './';
|
||||
const visible = ref(false)
|
||||
const { getGroup, updateGroup } = useGroups()
|
||||
const { getGroup, updateGroupStatus } = useGroups()
|
||||
|
||||
interface GroupInfo {
|
||||
name: string
|
||||
@@ -56,7 +56,7 @@ const group = ref<GroupInfo>({
|
||||
|
||||
// 用户组的状态发生变化
|
||||
const handerGroupStatusChange = async (val: string) => {
|
||||
await updateGroup(group.value.name, { ...group.value, status: val })
|
||||
await updateGroupStatus(group.value.name, { ...group.value, status: val })
|
||||
await getGroupData(group.value.name)
|
||||
}
|
||||
async function openDialog(row: any) {
|
||||
|
||||
@@ -124,7 +124,6 @@ const members = ref(props.group.members)
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
// 删除不存在的
|
||||
|
||||
await updateGroupMembers({
|
||||
group: props.group.name,
|
||||
members: props.group.members.filter((item: string) => {
|
||||
|
||||
@@ -8,15 +8,19 @@
|
||||
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
|
||||
@@ -42,45 +46,51 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
// import { userPolicies, userAccount, userGroups } from './components';
|
||||
const visible = ref(false);
|
||||
const { getUser, updateUser } = useUsers();
|
||||
const visible = ref(false)
|
||||
const { getUser, updateUser, changeUserStatus } = useUsers()
|
||||
interface UserInfo {
|
||||
accessKey: string;
|
||||
memberOf: string[];
|
||||
policy: string[];
|
||||
status: string;
|
||||
accessKey: string
|
||||
memberOf: string[]
|
||||
policy: string[]
|
||||
status: string
|
||||
}
|
||||
|
||||
const user = ref<UserInfo>({
|
||||
accessKey: '',
|
||||
memberOf: [],
|
||||
policy: [],
|
||||
status: 'enabled',
|
||||
});
|
||||
status: 'enabled'
|
||||
})
|
||||
|
||||
// 用户的状态发生变化
|
||||
const handerUserStatusChange = async (val: string) => {
|
||||
await updateUser(user.value.accessKey, { ...user.value, groups: user.value.memberOf, status: val });
|
||||
await getUserData(user.value.accessKey);
|
||||
};
|
||||
await changeUserStatus(user.value.accessKey, {
|
||||
accessKey: user.value.accessKey,
|
||||
status: val
|
||||
})
|
||||
await getUserData(user.value.accessKey)
|
||||
}
|
||||
async function openDialog(row: any) {
|
||||
await getUserData(row.accessKey);
|
||||
visible.value = true;
|
||||
await getUserData(row.accessKey)
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
async function getUserData(name: string) {
|
||||
user.value = await getUser(name);
|
||||
setTimeout(async () => {
|
||||
user.value = await getUser(name)
|
||||
user.value.accessKey = name
|
||||
}, 200)
|
||||
}
|
||||
// 添加之后的反馈弹窗
|
||||
const noticeRef = ref();
|
||||
const noticeRef = ref()
|
||||
function noticeDialog(data: any) {
|
||||
noticeRef.value.openDialog(data);
|
||||
noticeRef.value.openDialog(data)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openDialog,
|
||||
});
|
||||
openDialog
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
+165
-119
@@ -1,7 +1,12 @@
|
||||
<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" />
|
||||
@@ -9,12 +14,12 @@
|
||||
|
||||
<n-space>
|
||||
<NFlex>
|
||||
<NButton secondary @click="deleteByList" :disabled="checkedKeys.length == 0">
|
||||
<!-- <NButton secondary @click="deleteByList" :disabled="checkedKeys.length == 0">
|
||||
<template #icon>
|
||||
<Icon name="ri:delete-bin-5-line"></Icon>
|
||||
</template>
|
||||
删除所选
|
||||
</NButton>
|
||||
</NButton> -->
|
||||
<NButton secondary @click="addItem">
|
||||
<template #icon>
|
||||
<Icon name="ri:add-line"></Icon>
|
||||
@@ -25,13 +30,29 @@
|
||||
</n-space>
|
||||
</n-flex>
|
||||
</n-form>
|
||||
<n-form v-else label-placement="left" :model="formModel" label-align="right" :label-width="130">
|
||||
<n-form
|
||||
v-else
|
||||
label-placement="left"
|
||||
:model="formModel"
|
||||
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-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">
|
||||
@@ -46,20 +67,39 @@
|
||||
<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 :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-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-grid-item
|
||||
v-if="formModel.flag || editType == 'edit'"
|
||||
: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-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-grid-item>
|
||||
</n-grid>
|
||||
<n-space>
|
||||
@@ -90,69 +130,74 @@ import {
|
||||
type DataTableRowKey,
|
||||
NButton,
|
||||
NPopconfirm,
|
||||
NSpace,
|
||||
} from 'naive-ui';
|
||||
import { Icon } from '#components';
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { Icon } from '#components'
|
||||
// 随机字符串函数
|
||||
import { makeRandomString } from '~/utils/functions';
|
||||
const { listAllUserServiceAccounts, createServiceAccountCredentials } = useUsers();
|
||||
const { getServiceAccount, updateServiceAccount, deleteServiceAccount, deleteMultipleServiceAccounts } =
|
||||
useAccessKeys();
|
||||
import { makeRandomString } from '~/utils/functions'
|
||||
const { listUserServiceAccounts, createServiceAccount } = useAccessKeys()
|
||||
|
||||
const dialog = useDialog();
|
||||
const message = useMessage();
|
||||
const {
|
||||
getServiceAccount,
|
||||
updateServiceAccount,
|
||||
deleteServiceAccount
|
||||
// deleteMultipleServiceAccounts
|
||||
} = useAccessKeys()
|
||||
|
||||
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;
|
||||
expiration: string;
|
||||
name: string;
|
||||
description: string;
|
||||
accountStatus: string;
|
||||
actions: string;
|
||||
accessKey: string
|
||||
expiration: string
|
||||
name: string
|
||||
description: string
|
||||
accountStatus: string
|
||||
actions: string
|
||||
}
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
type: 'selection',
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: 'Access Key',
|
||||
align: 'center',
|
||||
key: 'accessKey',
|
||||
filter(value, row) {
|
||||
return !!row.accessKey.includes(value.toString());
|
||||
},
|
||||
return !!row.accessKey.includes(value.toString())
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '有效期',
|
||||
align: 'center',
|
||||
key: 'expiration',
|
||||
key: 'expiration'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
key: 'accountStatus',
|
||||
render: (row: any) => {
|
||||
return row.accountStatus === 'on' ? '可用' : '禁用';
|
||||
},
|
||||
return row.accountStatus === 'on' ? '可用' : '禁用'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
align: 'center',
|
||||
key: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
align: 'center',
|
||||
key: 'description',
|
||||
key: 'description'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
@@ -163,7 +208,7 @@ const columns: DataTableColumns<RowData> = [
|
||||
return h(
|
||||
NSpace,
|
||||
{
|
||||
justify: 'center',
|
||||
justify: 'center'
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
@@ -172,11 +217,11 @@ const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
size: 'small',
|
||||
secondary: true,
|
||||
onClick: () => openEditItem(row),
|
||||
onClick: () => openEditItem(row)
|
||||
},
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' }),
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' })
|
||||
}
|
||||
),
|
||||
h(
|
||||
@@ -190,36 +235,36 @@ const columns: DataTableColumns<RowData> = [
|
||||
{ size: 'small', secondary: true },
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' }),
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' })
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value],
|
||||
});
|
||||
name: [value]
|
||||
})
|
||||
}
|
||||
const listData = ref([]);
|
||||
const listData = ref([])
|
||||
const getUserList = async () => {
|
||||
const res = await listAllUserServiceAccounts(props.user.accessKey);
|
||||
listData.value = res;
|
||||
};
|
||||
getUserList();
|
||||
const res = await listUserServiceAccounts(props.user.accessKey)
|
||||
listData.value = res
|
||||
}
|
||||
getUserList()
|
||||
|
||||
/** ***********************************编辑、新增 */
|
||||
const editStatus = ref(false);
|
||||
const editType = ref('add');
|
||||
const editStatus = ref(false)
|
||||
const editType = ref('add')
|
||||
|
||||
const formModel = ref({
|
||||
accesskey: makeRandomString(20),
|
||||
@@ -230,13 +275,13 @@ const formModel = ref({
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on',
|
||||
});
|
||||
status: 'on'
|
||||
})
|
||||
|
||||
// 新增
|
||||
function addItem() {
|
||||
editType.value = 'add';
|
||||
editStatus.value = true;
|
||||
editType.value = 'add'
|
||||
editStatus.value = true
|
||||
formModel.value = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
@@ -246,25 +291,25 @@ function addItem() {
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on',
|
||||
};
|
||||
status: 'on'
|
||||
}
|
||||
}
|
||||
// 编辑
|
||||
async function openEditItem(row: any) {
|
||||
editType.value = 'edit';
|
||||
editStatus.value = true;
|
||||
const res = await getServiceAccount(row.accessKey);
|
||||
editType.value = 'edit'
|
||||
editStatus.value = true
|
||||
const res = await getServiceAccount(row.accessKey)
|
||||
formModel.value = {
|
||||
...res,
|
||||
};
|
||||
formModel.value.accesskey = row.accessKey;
|
||||
formModel.value.expiry = res.expiration;
|
||||
formModel.value.status = res.accountStatus;
|
||||
...res
|
||||
}
|
||||
formModel.value.accesskey = row.accessKey
|
||||
formModel.value.expiry = res.expiration
|
||||
formModel.value.status = res.accountStatus
|
||||
}
|
||||
|
||||
function cancelAdd() {
|
||||
editStatus.value = false;
|
||||
editType.value === 'add';
|
||||
editStatus.value = false
|
||||
editType.value === 'add'
|
||||
formModel.value = {
|
||||
accesskey: makeRandomString(20),
|
||||
secretkey: makeRandomString(40),
|
||||
@@ -274,71 +319,72 @@ function cancelAdd() {
|
||||
expiry: null,
|
||||
policy: '',
|
||||
flag: false,
|
||||
status: 'on',
|
||||
};
|
||||
status: 'on'
|
||||
}
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'search'): void;
|
||||
(e: 'notice', data: object): void;
|
||||
(e: 'search'): void
|
||||
(e: 'notice', data: object): void
|
||||
}
|
||||
const emit = defineEmits<Emits>();
|
||||
const emit = defineEmits<Emits>()
|
||||
async function submitForm() {
|
||||
if (editType.value === 'add') {
|
||||
try {
|
||||
console.log(formModel.value);
|
||||
const res = await createServiceAccountCredentials(props.user.accessKey, {
|
||||
console.log(formModel.value)
|
||||
const res = await createServiceAccount({
|
||||
...formModel.value,
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString() || '',
|
||||
});
|
||||
targetUser: props.user.accessKey,
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString() || ''
|
||||
})
|
||||
|
||||
message.success('添加成功');
|
||||
cancelAdd();
|
||||
emit('notice', res);
|
||||
getUserList();
|
||||
message.success('添加成功')
|
||||
cancelAdd()
|
||||
emit('notice', res)
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
message.error('添加失败');
|
||||
console.log(error)
|
||||
message.error('添加失败')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const res = await updateServiceAccount(formModel.value.accesskey, {
|
||||
...formModel.value,
|
||||
policy: formModel.value.policy || '{}',
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString(),
|
||||
});
|
||||
message.success('修改成功');
|
||||
cancelAdd();
|
||||
getUserList();
|
||||
expiry: new Date(formModel.value.expiry || 0).toISOString()
|
||||
})
|
||||
message.success('修改成功')
|
||||
cancelAdd()
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
message.error('修改失败');
|
||||
message.error('修改失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
function dateDisabled(ts: number) {
|
||||
const date = new Date(ts);
|
||||
return date < new Date();
|
||||
const date = new Date(ts)
|
||||
return date < new Date()
|
||||
}
|
||||
/** ***********************************删除 */
|
||||
async function deleteItem(row: any) {
|
||||
try {
|
||||
const res = await deleteServiceAccount(row.accessKey);
|
||||
message.success('删除成功');
|
||||
getUserList();
|
||||
const res = await deleteServiceAccount(row.accessKey)
|
||||
message.success('删除成功')
|
||||
getUserList()
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
message.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** ************************************批量删除 */
|
||||
function rowKey(row: any): string {
|
||||
return row.accessKey;
|
||||
return row.accessKey
|
||||
}
|
||||
|
||||
const checkedKeys = ref<DataTableRowKey[]>([]);
|
||||
const checkedKeys = ref<DataTableRowKey[]>([])
|
||||
function handleCheck(keys: DataTableRowKey[]) {
|
||||
checkedKeys.value = keys;
|
||||
return checkedKeys;
|
||||
checkedKeys.value = keys
|
||||
return checkedKeys
|
||||
}
|
||||
function deleteByList() {
|
||||
dialog.error({
|
||||
@@ -348,21 +394,21 @@ function deleteByList() {
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (!checkedKeys.value.length) {
|
||||
message.error('请至少选择一项');
|
||||
return;
|
||||
message.error('请至少选择一项')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await deleteMultipleServiceAccounts({
|
||||
body: checkedKeys.value,
|
||||
});
|
||||
checkedKeys.value = [];
|
||||
getUserList();
|
||||
message.success('删除成功');
|
||||
// const res = await deleteMultipleServiceAccounts({
|
||||
// body: checkedKeys.value
|
||||
// })
|
||||
checkedKeys.value = []
|
||||
getUserList()
|
||||
message.success('删除成功')
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
message.error('删除失败')
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<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" />
|
||||
@@ -20,7 +24,11 @@
|
||||
</n-flex>
|
||||
<n-flex justify="space-between" v-else>
|
||||
<n-form-item class="!w-96" label="选择分组" path="group">
|
||||
<n-select v-model:value="group" filterable multiple :options="groupList" />
|
||||
<n-select
|
||||
v-model:value="group"
|
||||
filterable
|
||||
multiple
|
||||
:options="groupList" />
|
||||
</n-form-item>
|
||||
<n-space>
|
||||
<NFlex>
|
||||
@@ -41,23 +49,29 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from 'naive-ui';
|
||||
const { listGroup } = useGroups();
|
||||
const { updateUserGroups } = useUsers();
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
const { listGroup } = useGroups()
|
||||
// const { updateUserGroups } = useUsers()
|
||||
const { updateGroupMembers } = useGroups()
|
||||
|
||||
const messge = useMessage();
|
||||
const messge = useMessage()
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
});
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
name: string;
|
||||
name: string
|
||||
}
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
@@ -65,63 +79,82 @@ const columns: DataTableColumns<RowData> = [
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString());
|
||||
},
|
||||
},
|
||||
];
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
name: [value],
|
||||
});
|
||||
name: [value]
|
||||
})
|
||||
}
|
||||
const listData = computed(() => {
|
||||
return (
|
||||
props.user.memberOf?.map((item: string) => {
|
||||
return {
|
||||
name: item,
|
||||
};
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
/********************编辑****************/
|
||||
const editStatus = ref(false);
|
||||
const editStatus = ref(false)
|
||||
// 用户组
|
||||
const groupList = ref([]);
|
||||
const groupList = ref([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void;
|
||||
}>();
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
const getGroupList = async () => {
|
||||
const res = await listGroup();
|
||||
console.log(res);
|
||||
groupList.value = res.groups.map((item: any) => {
|
||||
const res = await listGroup()
|
||||
groupList.value = res.map((item: any) => {
|
||||
return {
|
||||
label: item,
|
||||
value: item,
|
||||
};
|
||||
});
|
||||
};
|
||||
getGroupList();
|
||||
value: item
|
||||
}
|
||||
})
|
||||
}
|
||||
getGroupList()
|
||||
|
||||
const group = ref(props.user.memberOf)
|
||||
// 监听props.user.memberOf变化 并修改group
|
||||
|
||||
const group = ref(props.user.memberOf);
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
await updateUserGroups(props.user.accessKey, {
|
||||
...props.user,
|
||||
groups: group.value,
|
||||
});
|
||||
messge.success('修改成功');
|
||||
editStatus.value = false;
|
||||
emit('search');
|
||||
} catch {
|
||||
messge.error('修改失败');
|
||||
props.user.memberOf.filter(async (item: string) => {
|
||||
if (!group.value.includes(item)) {
|
||||
// 删除不存在的
|
||||
await updateGroupMembers({
|
||||
group: item,
|
||||
members: [props.user.accessKey],
|
||||
isRemove: true,
|
||||
groupStatus: 'enabled'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 修改组的成员
|
||||
group.value.map(async (element: string) => {
|
||||
await updateGroupMembers({
|
||||
group: element,
|
||||
members: [props.user.accessKey],
|
||||
isRemove: false,
|
||||
groupStatus: 'enabled'
|
||||
})
|
||||
})
|
||||
|
||||
messge.success('修改成功')
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
} catch (e) {
|
||||
messge.error('修改失败')
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<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" />
|
||||
@@ -20,7 +24,11 @@
|
||||
</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>
|
||||
@@ -41,23 +49,27 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type DataTableColumns, type DataTableInst, NButton, NSpace } from 'naive-ui';
|
||||
const { listPolicies } = usePolicies();
|
||||
const { setPolicy } = useUsers();
|
||||
import {
|
||||
type DataTableColumns,
|
||||
type DataTableInst,
|
||||
NButton,
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
const { listPolicies, setUserOrGroupPolicy } = usePolicies()
|
||||
|
||||
const messge = useMessage();
|
||||
const messge = useMessage()
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
});
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
name: string;
|
||||
name: string
|
||||
}
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
@@ -65,64 +77,65 @@ const columns: DataTableColumns<RowData> = [
|
||||
align: 'left',
|
||||
key: 'name',
|
||||
filter(value, row) {
|
||||
return !!row.name.includes(value.toString());
|
||||
},
|
||||
},
|
||||
];
|
||||
return !!row.name.includes(value.toString())
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
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.policy.map((item: string) => {
|
||||
props.user?.policyName?.split(',').map((item: string) => {
|
||||
return {
|
||||
name: item,
|
||||
};
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
/********************编辑****************/
|
||||
const editStatus = ref(false);
|
||||
const editStatus = ref(false)
|
||||
// 策略列表
|
||||
const policyList = ref([]);
|
||||
const policyList = ref<any[]>([])
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search'): void;
|
||||
}>();
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
const getPoliciesList = async () => {
|
||||
const res = await listPolicies();
|
||||
console.log(res);
|
||||
policyList.value = res.policies.map((item: any) => {
|
||||
const res = await listPolicies()
|
||||
policyList.value = Object.keys(res).map((key) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.name,
|
||||
};
|
||||
});
|
||||
};
|
||||
getPoliciesList();
|
||||
label: key,
|
||||
value: key
|
||||
}
|
||||
})
|
||||
}
|
||||
getPoliciesList()
|
||||
|
||||
const policy = ref(props.user.policy);
|
||||
const policy = ref(props.user.policyName.split(','))
|
||||
const changeMebers = async () => {
|
||||
try {
|
||||
await setPolicy({
|
||||
name: policy.value,
|
||||
entityType: 'user',
|
||||
entityName: props.user.accessKey,
|
||||
});
|
||||
messge.success('修改成功');
|
||||
editStatus.value = false;
|
||||
emit('search');
|
||||
await setUserOrGroupPolicy({
|
||||
policyName: policy.value || '',
|
||||
userOrGroup: encodeURIComponent(props.user.accessKey),
|
||||
isGroup: false
|
||||
})
|
||||
messge.success('修改成功')
|
||||
editStatus.value = false
|
||||
emit('search')
|
||||
} catch {
|
||||
messge.error('修改失败');
|
||||
messge.error('修改失败')
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,33 +1,39 @@
|
||||
import { name } from './../node_modules/@jsep-plugin/regex/types/tsd.d'
|
||||
export const useAccessKeys = () => {
|
||||
const { $api } = useNuxtApp();
|
||||
const { $api } = useNuxtApp()
|
||||
|
||||
const listUserServiceAccounts = async () => {
|
||||
return await $api.get('/service-accounts');
|
||||
};
|
||||
const listUserServiceAccounts = async (name: string) => {
|
||||
return await $api.get('/list-service-accounts?user=' + name)
|
||||
}
|
||||
|
||||
const createServiceAccount = async (data: any) => {
|
||||
return await $api.post('/service-accounts', data);
|
||||
};
|
||||
return await $api.put('/add-service-accounts', data)
|
||||
}
|
||||
|
||||
const deleteMultipleServiceAccounts = async (data: any) => {
|
||||
return await $api.delete('/service-accounts/delete-multi', data);
|
||||
};
|
||||
// const deleteMultipleServiceAccounts = async (data: any) => {
|
||||
// return await $api.delete('/delete-service-accounts', data)
|
||||
// }
|
||||
|
||||
const getServiceAccount = async (name: string) => {
|
||||
return await $api.get(`/service-accounts/${encodeURIComponent(name)}`);
|
||||
};
|
||||
return await $api.get(
|
||||
`/info-service-account?accessKey=${encodeURIComponent(name)}`
|
||||
)
|
||||
}
|
||||
|
||||
const updateServiceAccount = async (name: string, data: any) => {
|
||||
return await $api.put(`/service-accounts/${encodeURIComponent(name)}`, data);
|
||||
};
|
||||
return await $api.post(`/update-service-account`, data)
|
||||
}
|
||||
|
||||
const deleteServiceAccount = async (name: string) => {
|
||||
return await $api.delete(`/service-accounts/${encodeURIComponent(name)}`, {});
|
||||
};
|
||||
return await $api.delete(
|
||||
`/delete-service-accounts?accessKey==${encodeURIComponent(name)}`,
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
const createServiceAccountCreds = async (data: any) => {
|
||||
return await $api.post(`/service-account-credentials`, data);
|
||||
};
|
||||
return await $api.post(`/service-account-credentials`, data)
|
||||
}
|
||||
|
||||
return {
|
||||
listUserServiceAccounts,
|
||||
@@ -35,7 +41,7 @@ export const useAccessKeys = () => {
|
||||
deleteServiceAccount,
|
||||
createServiceAccountCreds,
|
||||
updateServiceAccount,
|
||||
getServiceAccount,
|
||||
deleteMultipleServiceAccounts,
|
||||
};
|
||||
};
|
||||
getServiceAccount
|
||||
// deleteMultipleServiceAccounts
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,12 @@ export const useGroups = () => {
|
||||
* @returns
|
||||
*/
|
||||
const updateGroupStatus = async (name: string, data: any) => {
|
||||
return await $api.put(`/group/set-group-status`, data)
|
||||
return await $api.put(
|
||||
`/set-group-status?group=${encodeURIComponent(name)}&status=${
|
||||
data.status
|
||||
}`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+35
-7
@@ -1,4 +1,4 @@
|
||||
import { AccessKeys } from "./../.nuxt/components.d"
|
||||
import { AccessKeys } from './../.nuxt/components.d'
|
||||
export const useUsers = () => {
|
||||
const { $api } = useNuxtApp()
|
||||
|
||||
@@ -8,13 +8,16 @@ export const useUsers = () => {
|
||||
* @returns
|
||||
*/
|
||||
const listUsers = async () => {
|
||||
return await $api.get("/list-users")
|
||||
return await $api.get('/list-users')
|
||||
}
|
||||
|
||||
const createUser = async (data: any) => {
|
||||
const { accessKey } = data
|
||||
delete data.accessKey
|
||||
return await $api.put("/add-user" + `?accessKey=${encodeURIComponent(accessKey)}`, data)
|
||||
return await $api.put(
|
||||
'/add-user' + `?accessKey=${encodeURIComponent(accessKey)}`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
const getUser = async (name: string) => {
|
||||
@@ -25,8 +28,26 @@ export const useUsers = () => {
|
||||
return await $api.put(`/user/${encodeURIComponent(name)}`, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
* @param name
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
const changeUserStatus = async (name: string, data: any) => {
|
||||
return await $api.put(
|
||||
`/set-user-status?accessKey=${encodeURIComponent(name)}&status=${
|
||||
data.status
|
||||
}`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
const deleteUser = async (name: string) => {
|
||||
return await $api.delete(`/remove-user?accessKey=${encodeURIComponent(name)}`, {})
|
||||
return await $api.delete(
|
||||
`/remove-user?accessKey=${encodeURIComponent(name)}`,
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
const updateUserGroups = async (name: string, data: any) => {
|
||||
@@ -57,11 +78,17 @@ export const useUsers = () => {
|
||||
}
|
||||
|
||||
const createAUserServiceAccount = async (name: string, data: any) => {
|
||||
return await $api.post(`/user/${encodeURIComponent(name)}/service-accounts`, data)
|
||||
return await $api.post(
|
||||
`/user/${encodeURIComponent(name)}/service-accounts`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
const createServiceAccountCredentials = async (name: string, data: any) => {
|
||||
return await $api.post(`/user/${encodeURIComponent(name)}/service-account-credentials`, data)
|
||||
return await $api.post(
|
||||
`/user/${encodeURIComponent(name)}/service-account-credentials`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -69,6 +96,7 @@ export const useUsers = () => {
|
||||
createUser,
|
||||
getUser,
|
||||
deleteUser,
|
||||
changeUserStatus,
|
||||
updateUser,
|
||||
updateUserGroups,
|
||||
getUserPolicy,
|
||||
@@ -76,6 +104,6 @@ export const useUsers = () => {
|
||||
getSaUserPolicy,
|
||||
listAllUserServiceAccounts,
|
||||
createAUserServiceAccount,
|
||||
createServiceAccountCredentials,
|
||||
createServiceAccountCredentials
|
||||
}
|
||||
}
|
||||
|
||||
+102
-82
@@ -6,18 +6,21 @@
|
||||
</template>
|
||||
<template #actions>
|
||||
<NFlex>
|
||||
<NButton :disabled="!checkedKeys.length" secondary @click="deleteByList">
|
||||
<NButton
|
||||
:disabled="!checkedKeys.length"
|
||||
secondary
|
||||
@click="deleteByList">
|
||||
<template #icon>
|
||||
<Icon name="ri:delete-bin-5-line"></Icon>
|
||||
</template>
|
||||
删除选中项
|
||||
</NButton>
|
||||
<NButton secondary @click="changePassword">
|
||||
<!-- <NButton secondary @click="changePassword">
|
||||
<template #icon>
|
||||
<Icon name="ri:key-2-line"></Icon>
|
||||
</template>
|
||||
修改秘钥
|
||||
</NButton>
|
||||
</NButton> -->
|
||||
<NButton secondary @click="addItem">
|
||||
<template #icon>
|
||||
<Icon name="ri:add-line"></Icon>
|
||||
@@ -29,7 +32,12 @@
|
||||
</page-header>
|
||||
|
||||
<page-content>
|
||||
<n-form class="mb-4" ref="formRef" :model="searchForm" label-placement="left" :show-feedback="false">
|
||||
<n-form
|
||||
class="mb-4"
|
||||
ref="formRef"
|
||||
:model="searchForm"
|
||||
label-placement="left"
|
||||
:show-feedback="false">
|
||||
<n-flex justify="space-between">
|
||||
<n-form-item label="" path="name">
|
||||
<n-input placeholder="搜索访问秘钥" @input="filterName" />
|
||||
@@ -50,9 +58,16 @@
|
||||
:row-key="rowKey"
|
||||
@update:checked-row-keys="handleCheck" />
|
||||
</page-content>
|
||||
<NewItem ref="newItemRef" v-model:visible="newItemVisible" @search="getDataList" @notice="noticeDialog" />
|
||||
<NewItem
|
||||
ref="newItemRef"
|
||||
v-model:visible="newItemVisible"
|
||||
@search="getDataList"
|
||||
@notice="noticeDialog" />
|
||||
<EditItem ref="editItemRef" @search="getDataList" />
|
||||
<ChangePassword ref="changePasswordModalRef" v-model:visible="changePasswordVisible" @search="getDataList" />
|
||||
<ChangePassword
|
||||
ref="changePasswordModalRef"
|
||||
v-model:visible="changePasswordVisible"
|
||||
@search="getDataList" />
|
||||
<users-user-notice ref="noticeRef"></users-user-notice>
|
||||
</div>
|
||||
</template>
|
||||
@@ -64,61 +79,62 @@ import {
|
||||
type DataTableRowKey,
|
||||
NButton,
|
||||
NPopconfirm,
|
||||
NSpace,
|
||||
} from 'naive-ui';
|
||||
import { Icon } from '#components';
|
||||
import { ChangePassword, EditItem, NewItem } from '~/components/access-keys';
|
||||
NSpace
|
||||
} from 'naive-ui'
|
||||
import { Icon } from '#components'
|
||||
import { ChangePassword, EditItem, NewItem } from '~/components/access-keys'
|
||||
|
||||
const { $api } = useNuxtApp();
|
||||
const dialog = useDialog();
|
||||
const message = useMessage();
|
||||
const { $api } = useNuxtApp()
|
||||
const dialog = useDialog()
|
||||
const message = useMessage()
|
||||
const { listUserServiceAccounts, deleteServiceAccount } = useAccessKeys()
|
||||
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
});
|
||||
name: ''
|
||||
})
|
||||
interface RowData {
|
||||
accessKey: string;
|
||||
expiration: string;
|
||||
name: string;
|
||||
description: string;
|
||||
accountStatus: string;
|
||||
actions: string;
|
||||
accessKey: string
|
||||
expiration: string
|
||||
name: string
|
||||
description: string
|
||||
accountStatus: string
|
||||
actions: string
|
||||
}
|
||||
|
||||
const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
type: 'selection',
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: 'Access Key',
|
||||
align: 'center',
|
||||
key: 'accessKey',
|
||||
filter(value, row) {
|
||||
return !!row.accessKey.includes(value.toString());
|
||||
},
|
||||
return !!row.accessKey.includes(value.toString())
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '有效期',
|
||||
align: 'center',
|
||||
key: 'expiration',
|
||||
key: 'expiration'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
key: 'accountStatus',
|
||||
render: (row: any) => {
|
||||
return row.accountStatus === 'on' ? '可用' : '禁用';
|
||||
},
|
||||
return row.accountStatus === 'on' ? '可用' : '禁用'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
align: 'center',
|
||||
key: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
align: 'center',
|
||||
key: 'description',
|
||||
key: 'description'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
@@ -129,7 +145,7 @@ const columns: DataTableColumns<RowData> = [
|
||||
return h(
|
||||
NSpace,
|
||||
{
|
||||
justify: 'center',
|
||||
justify: 'center'
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
@@ -138,11 +154,11 @@ const columns: DataTableColumns<RowData> = [
|
||||
{
|
||||
size: 'small',
|
||||
secondary: true,
|
||||
onClick: () => openEditItem(row),
|
||||
onClick: () => openEditItem(row)
|
||||
},
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' }),
|
||||
icon: () => h(Icon, { name: 'ri:edit-2-line' })
|
||||
}
|
||||
),
|
||||
h(
|
||||
@@ -156,96 +172,100 @@ const columns: DataTableColumns<RowData> = [
|
||||
{ size: 'small', secondary: true },
|
||||
{
|
||||
default: () => '',
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' }),
|
||||
icon: () => h(Icon, { name: 'ri:delete-bin-5-line' })
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 搜索过滤
|
||||
const tableRef = ref<DataTableInst>();
|
||||
const tableRef = ref<DataTableInst>()
|
||||
function filterName(value: string) {
|
||||
tableRef.value &&
|
||||
tableRef.value.filter({
|
||||
accessKey: [value],
|
||||
});
|
||||
accessKey: [value]
|
||||
})
|
||||
}
|
||||
const listData = ref<any[]>([]);
|
||||
const listData = ref<any[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
getDataList();
|
||||
});
|
||||
getDataList()
|
||||
})
|
||||
// 获取数据
|
||||
const getDataList = async () => {
|
||||
try {
|
||||
const res = await $api.get('service-accounts');
|
||||
listData.value = res || [];
|
||||
const res = await listUserServiceAccounts('')
|
||||
listData.value =
|
||||
res.accounts.map((item: string) => {
|
||||
return {
|
||||
name: item
|
||||
}
|
||||
}) || []
|
||||
} catch (error) {
|
||||
message.error('获取数据失败');
|
||||
message.error('获取数据失败')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 刷新
|
||||
const refresh = () => {
|
||||
getDataList();
|
||||
};
|
||||
getDataList()
|
||||
}
|
||||
|
||||
/** **********************************添加 */
|
||||
const newItemRef = ref();
|
||||
const newItemVisible = ref(false);
|
||||
const newItemRef = ref()
|
||||
const newItemVisible = ref(false)
|
||||
|
||||
function addItem() {
|
||||
newItemVisible.value = true;
|
||||
newItemVisible.value = true
|
||||
}
|
||||
|
||||
// 添加之后的反馈弹窗
|
||||
const noticeRef = ref();
|
||||
const noticeRef = ref()
|
||||
function noticeDialog(data: any) {
|
||||
console.log(data);
|
||||
noticeRef.value.openDialog(data);
|
||||
console.log(data)
|
||||
noticeRef.value.openDialog(data)
|
||||
}
|
||||
|
||||
/** **********************************修改 */
|
||||
const editItemRef = ref();
|
||||
const editItemRef = ref()
|
||||
function openEditItem(row: any) {
|
||||
editItemRef.value.openDialog(row);
|
||||
editItemRef.value.openDialog(row)
|
||||
}
|
||||
/** **********************************修改密码 */
|
||||
const changePasswordModalRef = ref();
|
||||
const changePasswordVisible = ref(false);
|
||||
const changePasswordModalRef = ref()
|
||||
const changePasswordVisible = ref(false)
|
||||
|
||||
function changePassword() {
|
||||
changePasswordVisible.value = true;
|
||||
changePasswordVisible.value = true
|
||||
}
|
||||
|
||||
/** ***********************************删除 */
|
||||
async function deleteItem(row: any) {
|
||||
try {
|
||||
const res = await $api.delete('/service-accounts/delete-multi', {
|
||||
body: [row.accessKey],
|
||||
});
|
||||
message.success('删除成功');
|
||||
getDataList();
|
||||
const res = deleteServiceAccount(row.accessKey)
|
||||
|
||||
message.success('删除成功')
|
||||
getDataList()
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
message.error('删除失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** ************************************批量删除 */
|
||||
function rowKey(row: any): string {
|
||||
return row.accessKey;
|
||||
return row.accessKey
|
||||
}
|
||||
|
||||
const checkedKeys = ref<DataTableRowKey[]>([]);
|
||||
const checkedKeys = ref<DataTableRowKey[]>([])
|
||||
function handleCheck(keys: DataTableRowKey[]) {
|
||||
checkedKeys.value = keys;
|
||||
return checkedKeys;
|
||||
checkedKeys.value = keys
|
||||
return checkedKeys
|
||||
}
|
||||
function deleteByList() {
|
||||
dialog.error({
|
||||
@@ -255,19 +275,19 @@ function deleteByList() {
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (!checkedKeys.value.length) {
|
||||
message.error('请至少选择一项');
|
||||
return;
|
||||
message.error('请至少选择一项')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await $api.delete('/service-accounts/delete-multi', {
|
||||
body: checkedKeys.value,
|
||||
});
|
||||
message.success('删除成功');
|
||||
getDataList();
|
||||
body: checkedKeys.value
|
||||
})
|
||||
message.success('删除成功')
|
||||
getDataList()
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
message.error('删除失败')
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
+12
-14
@@ -1,28 +1,26 @@
|
||||
import { AwsClient } from "aws4fetch"
|
||||
import ApiClient from "~/lib/api-client"
|
||||
import { AwsClient } from 'aws4fetch'
|
||||
import ApiClient from '~/lib/api-client'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const runtimeConfig = useRuntimeConfig().public
|
||||
const { isAuthenticated, credentials } = useAuth()
|
||||
|
||||
console.log("credentials", credentials.value)
|
||||
|
||||
if (!isAuthenticated.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const accessKeyId = credentials.value?.AccessKeyId || ""
|
||||
const secretAccessKey = credentials.value?.SecretAccessKey || ""
|
||||
const sessionToken = credentials.value?.SessionToken || ""
|
||||
const region = runtimeConfig.s3.region || "us-east-1"
|
||||
const service = "s3"
|
||||
const accessKeyId = credentials.value?.AccessKeyId || ''
|
||||
const secretAccessKey = credentials.value?.SecretAccessKey || ''
|
||||
const sessionToken = credentials.value?.SessionToken || ''
|
||||
const region = runtimeConfig.s3.region || 'us-east-1'
|
||||
const service = 's3'
|
||||
|
||||
const adminApiClient = new AwsClient({
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
sessionToken,
|
||||
region,
|
||||
service,
|
||||
service
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -30,9 +28,9 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
api: new ApiClient(adminApiClient, {
|
||||
baseUrl: runtimeConfig.api.baseURL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}),
|
||||
},
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user