feat(members): split username/display_name, sync updates to authentik, add password reset API and refresh docs
This commit is contained in:
@@ -3,6 +3,7 @@ import { adminHttp } from './http'
|
|||||||
export const getMembers = () => adminHttp.get('/admin/members')
|
export const getMembers = () => adminHttp.get('/admin/members')
|
||||||
export const upsertMember = (data) => adminHttp.post('/admin/members/upsert', data)
|
export const upsertMember = (data) => adminHttp.post('/admin/members/upsert', data)
|
||||||
export const updateMember = (authentikSub, data) => adminHttp.patch(`/admin/members/${authentikSub}`, data)
|
export const updateMember = (authentikSub, data) => adminHttp.patch(`/admin/members/${authentikSub}`, data)
|
||||||
|
export const resetMemberPassword = (authentikSub) => adminHttp.post(`/admin/members/${authentikSub}/password/reset`)
|
||||||
export const getMemberPermissionGroups = (authentikSub) => adminHttp.get(`/admin/members/${authentikSub}/permission-groups`)
|
export const getMemberPermissionGroups = (authentikSub) => adminHttp.get(`/admin/members/${authentikSub}/permission-groups`)
|
||||||
export const setMemberPermissionGroups = (authentikSub, groupKeys) =>
|
export const setMemberPermissionGroups = (authentikSub, groupKeys) =>
|
||||||
adminHttp.put(`/admin/members/${authentikSub}/permission-groups`, { group_keys: groupKeys })
|
adminHttp.put(`/admin/members/${authentikSub}/permission-groups`, { group_keys: groupKeys })
|
||||||
|
|||||||
@@ -14,20 +14,23 @@
|
|||||||
<el-table v-else :data="members" stripe border class="w-full shadow-sm">
|
<el-table v-else :data="members" stripe border class="w-full shadow-sm">
|
||||||
<template #empty><el-empty description="目前無會員" /></template>
|
<template #empty><el-empty description="目前無會員" /></template>
|
||||||
<el-table-column prop="authentik_sub" label="Authentik Sub" min-width="260" />
|
<el-table-column prop="authentik_sub" label="Authentik Sub" min-width="260" />
|
||||||
|
<el-table-column prop="username" label="Username" min-width="160" />
|
||||||
<el-table-column prop="email" label="Email" min-width="220" />
|
<el-table-column prop="email" label="Email" min-width="220" />
|
||||||
<el-table-column prop="display_name" label="顯示名稱" min-width="180" />
|
<el-table-column prop="display_name" label="顯示名稱" min-width="180" />
|
||||||
<el-table-column prop="is_active" label="啟用" width="100">
|
<el-table-column prop="is_active" label="啟用" width="100">
|
||||||
<template #default="{ row }">{{ row.is_active ? '是' : '否' }}</template>
|
<template #default="{ row }">{{ row.is_active ? '是' : '否' }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="120">
|
<el-table-column label="操作" width="220">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button size="small" @click="openEdit(row)">編輯</el-button>
|
<el-button size="small" @click="openEdit(row)">編輯</el-button>
|
||||||
|
<el-button size="small" type="warning" @click="handleResetPassword(row)">重設密碼</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-dialog v-model="showCreateDialog" title="新增會員" @close="resetCreateForm">
|
<el-dialog v-model="showCreateDialog" title="新增會員" @close="resetCreateForm">
|
||||||
<el-form ref="createFormRef" :model="createForm" :rules="createRules" label-width="120px">
|
<el-form ref="createFormRef" :model="createForm" :rules="createRules" label-width="120px">
|
||||||
|
<el-form-item label="Username" prop="username"><el-input v-model="createForm.username" /></el-form-item>
|
||||||
<el-form-item label="Email" prop="email"><el-input v-model="createForm.email" /></el-form-item>
|
<el-form-item label="Email" prop="email"><el-input v-model="createForm.email" /></el-form-item>
|
||||||
<el-form-item label="顯示名稱" prop="display_name"><el-input v-model="createForm.display_name" /></el-form-item>
|
<el-form-item label="顯示名稱" prop="display_name"><el-input v-model="createForm.display_name" /></el-form-item>
|
||||||
<el-form-item label="權限群組">
|
<el-form-item label="權限群組">
|
||||||
@@ -47,6 +50,7 @@
|
|||||||
<el-dialog v-model="showEditDialog" title="編輯會員" @close="resetEditForm">
|
<el-dialog v-model="showEditDialog" title="編輯會員" @close="resetEditForm">
|
||||||
<el-form :model="editForm" label-width="120px">
|
<el-form :model="editForm" label-width="120px">
|
||||||
<el-form-item label="Authentik Sub"><el-input :model-value="editForm.authentik_sub" disabled /></el-form-item>
|
<el-form-item label="Authentik Sub"><el-input :model-value="editForm.authentik_sub" disabled /></el-form-item>
|
||||||
|
<el-form-item label="Username"><el-input v-model="editForm.username" /></el-form-item>
|
||||||
<el-form-item label="Email"><el-input v-model="editForm.email" /></el-form-item>
|
<el-form-item label="Email"><el-input v-model="editForm.email" /></el-form-item>
|
||||||
<el-form-item label="顯示名稱"><el-input v-model="editForm.display_name" /></el-form-item>
|
<el-form-item label="顯示名稱"><el-input v-model="editForm.display_name" /></el-form-item>
|
||||||
<el-form-item label="權限群組">
|
<el-form-item label="權限群組">
|
||||||
@@ -73,6 +77,7 @@ import {
|
|||||||
getMembers,
|
getMembers,
|
||||||
upsertMember,
|
upsertMember,
|
||||||
updateMember,
|
updateMember,
|
||||||
|
resetMemberPassword,
|
||||||
getMemberPermissionGroups,
|
getMemberPermissionGroups,
|
||||||
setMemberPermissionGroups
|
setMemberPermissionGroups
|
||||||
} from '@/api/members'
|
} from '@/api/members'
|
||||||
@@ -88,6 +93,7 @@ const showCreateDialog = ref(false)
|
|||||||
const createFormRef = ref()
|
const createFormRef = ref()
|
||||||
const creating = ref(false)
|
const creating = ref(false)
|
||||||
const createForm = ref({
|
const createForm = ref({
|
||||||
|
username: '',
|
||||||
email: '',
|
email: '',
|
||||||
display_name: '',
|
display_name: '',
|
||||||
group_keys: [],
|
group_keys: [],
|
||||||
@@ -95,6 +101,7 @@ const createForm = ref({
|
|||||||
sync_to_authentik: true
|
sync_to_authentik: true
|
||||||
})
|
})
|
||||||
const createRules = {
|
const createRules = {
|
||||||
|
username: [{ required: true, message: '請輸入 Username', trigger: 'blur' }],
|
||||||
email: [{ required: true, message: '請輸入 Email', trigger: 'blur' }]
|
email: [{ required: true, message: '請輸入 Email', trigger: 'blur' }]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +109,7 @@ const showEditDialog = ref(false)
|
|||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
const editForm = ref({
|
const editForm = ref({
|
||||||
authentik_sub: '',
|
authentik_sub: '',
|
||||||
|
username: '',
|
||||||
email: '',
|
email: '',
|
||||||
display_name: '',
|
display_name: '',
|
||||||
group_keys: [],
|
group_keys: [],
|
||||||
@@ -126,6 +134,7 @@ async function load() {
|
|||||||
|
|
||||||
function resetCreateForm() {
|
function resetCreateForm() {
|
||||||
createForm.value = {
|
createForm.value = {
|
||||||
|
username: '',
|
||||||
email: '',
|
email: '',
|
||||||
display_name: '',
|
display_name: '',
|
||||||
group_keys: [],
|
group_keys: [],
|
||||||
@@ -137,6 +146,7 @@ function resetCreateForm() {
|
|||||||
async function openEdit(row) {
|
async function openEdit(row) {
|
||||||
editForm.value = {
|
editForm.value = {
|
||||||
authentik_sub: row.authentik_sub,
|
authentik_sub: row.authentik_sub,
|
||||||
|
username: row.username || '',
|
||||||
email: row.email || '',
|
email: row.email || '',
|
||||||
display_name: row.display_name || '',
|
display_name: row.display_name || '',
|
||||||
group_keys: [],
|
group_keys: [],
|
||||||
@@ -155,6 +165,7 @@ async function openEdit(row) {
|
|||||||
function resetEditForm() {
|
function resetEditForm() {
|
||||||
editForm.value = {
|
editForm.value = {
|
||||||
authentik_sub: '',
|
authentik_sub: '',
|
||||||
|
username: '',
|
||||||
email: '',
|
email: '',
|
||||||
display_name: '',
|
display_name: '',
|
||||||
group_keys: [],
|
group_keys: [],
|
||||||
@@ -189,6 +200,7 @@ async function handleEdit() {
|
|||||||
saving.value = true
|
saving.value = true
|
||||||
try {
|
try {
|
||||||
await updateMember(editForm.value.authentik_sub, {
|
await updateMember(editForm.value.authentik_sub, {
|
||||||
|
username: editForm.value.username || null,
|
||||||
email: editForm.value.email || null,
|
email: editForm.value.email || null,
|
||||||
display_name: editForm.value.display_name || null,
|
display_name: editForm.value.display_name || null,
|
||||||
is_active: editForm.value.is_active,
|
is_active: editForm.value.is_active,
|
||||||
@@ -206,5 +218,21 @@ async function handleEdit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleResetPassword(row) {
|
||||||
|
try {
|
||||||
|
const res = await resetMemberPassword(row.authentik_sub)
|
||||||
|
const pwd = res.data?.temporary_password || ''
|
||||||
|
if (!pwd) {
|
||||||
|
ElMessage.success('密碼已重設')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await navigator.clipboard.writeText(pwd)
|
||||||
|
ElMessage.success(`已重設密碼,臨時密碼已複製:${pwd}`)
|
||||||
|
} catch (err) {
|
||||||
|
const detail = err.response?.data?.detail
|
||||||
|
ElMessage.error(detail || '重設密碼失敗')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(load)
|
onMounted(load)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user