feat: 添加安全模块 + Dockerfile添加curl支持健康检查
主要更新: - 新增 security/ 安全模块 (风险评估、威胁检测、蜜罐等) - Dockerfile 添加 curl 以支持 Docker 健康检查 - 前端页面更新 (管理后台、用户端) - 数据库迁移和 schema 更新 - 新增 kdocs 上传服务 - 添加安全相关测试用例 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,19 +11,14 @@ import {
|
||||
removeUserVip,
|
||||
setUserVip,
|
||||
} from '../api/users'
|
||||
import { approvePasswordReset, fetchPasswordResets, rejectPasswordReset } from '../api/passwordResets'
|
||||
import { parseSqliteDateTime } from '../utils/datetime'
|
||||
import { validatePasswordStrength } from '../utils/password'
|
||||
|
||||
const refreshStats = inject('refreshStats', null)
|
||||
const refreshNavBadges = inject('refreshNavBadges', null)
|
||||
|
||||
const loading = ref(false)
|
||||
const users = ref([])
|
||||
|
||||
const resetLoading = ref(false)
|
||||
const passwordResets = ref([])
|
||||
|
||||
function isVip(user) {
|
||||
const expire = user?.vip_expire_time
|
||||
if (!expire) return false
|
||||
@@ -58,21 +53,8 @@ async function loadUsers() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadResets() {
|
||||
resetLoading.value = true
|
||||
try {
|
||||
const list = await fetchPasswordResets()
|
||||
passwordResets.value = Array.isArray(list) ? list : []
|
||||
} catch {
|
||||
passwordResets.value = []
|
||||
} finally {
|
||||
resetLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
await Promise.all([loadUsers(), loadResets()])
|
||||
await refreshNavBadges?.({ pendingResets: passwordResets.value.length })
|
||||
await loadUsers()
|
||||
}
|
||||
|
||||
async function onEnableUser(row) {
|
||||
@@ -117,48 +99,6 @@ async function onDisableUser(row) {
|
||||
}
|
||||
}
|
||||
|
||||
async function onApproveReset(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定批准「${row.username}」的密码重置申请吗?`, '批准重置', {
|
||||
confirmButtonText: '批准',
|
||||
cancelButtonText: '取消',
|
||||
type: 'success',
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await approvePasswordReset(row.id)
|
||||
ElMessage.success(res?.message || '密码重置申请已批准')
|
||||
await loadResets()
|
||||
await refreshNavBadges?.({ pendingResets: passwordResets.value.length })
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function onRejectReset(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定拒绝「${row.username}」的密码重置申请吗?`, '拒绝重置', {
|
||||
confirmButtonText: '拒绝',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await rejectPasswordReset(row.id)
|
||||
ElMessage.success(res?.message || '密码重置申请已拒绝')
|
||||
await loadResets()
|
||||
await refreshNavBadges?.({ pendingResets: passwordResets.value.length })
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function onDelete(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
@@ -338,27 +278,6 @@ onMounted(refreshAll)
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
|
||||
<h3 class="section-title">密码重置申请</h3>
|
||||
<div class="table-wrap">
|
||||
<el-table :data="passwordResets" v-loading="resetLoading" style="width: 100%">
|
||||
<el-table-column prop="id" label="申请ID" width="90" />
|
||||
<el-table-column prop="username" label="用户名" min-width="200" />
|
||||
<el-table-column prop="email" label="邮箱" min-width="220">
|
||||
<template #default="{ row }">{{ row.email || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="created_at" label="申请时间" min-width="180" />
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="success" size="small" @click="onApproveReset(row)">批准</el-button>
|
||||
<el-button type="danger" size="small" @click="onRejectReset(row)">拒绝</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="help app-muted">当未启用邮件找回密码时,用户会提交申请,由管理员在此处处理。</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user