Harden auth, CSRF, and email log UX
This commit is contained in:
23
admin-frontend/package-lock.json
generated
23
admin-frontend/package-lock.json
generated
@@ -1206,23 +1206,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/element-plus": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.12.0.tgz",
|
||||
"integrity": "sha512-M9YLSn2np9OnqrSKWsiXvGe3qnF8pd94+TScsHj1aTMCD+nSEvucXermf807qNt6hOP040le0e5Aft7E9ZfHmA==",
|
||||
"version": "2.11.3",
|
||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.11.3.tgz",
|
||||
"integrity": "sha512-769xsjLR4B9Vf9cl5PDXnwTEdmFJvMgAkYtthdJKPhjVjU3hdAwTJ+gXKiO+PUyo2KWFwOYKZd4Ywh6PHfkbJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.4.1",
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@floating-ui/dom": "^1.0.1",
|
||||
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
|
||||
"@types/lodash": "^4.17.20",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@vueuse/core": "^9.1.0",
|
||||
"async-validator": "^4.2.5",
|
||||
"dayjs": "^1.11.19",
|
||||
"dayjs": "^1.11.13",
|
||||
"escape-html": "^1.0.3",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lodash-unified": "^1.0.3",
|
||||
"lodash-unified": "^1.0.2",
|
||||
"memoize-one": "^6.0.0",
|
||||
"normalize-wheel-es": "^1.2.0"
|
||||
},
|
||||
@@ -1329,6 +1330,12 @@
|
||||
"@esbuild/win32-x64": "0.25.12"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
|
||||
@@ -12,12 +12,30 @@ function toastErrorOnce(key, message, minIntervalMs = 1500) {
|
||||
ElMessage.error(message)
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const escaped = String(name || '').replace(/([.*+?^${}()|[\]\\])/g, '\\$1')
|
||||
const match = document.cookie.match(new RegExp(`(?:^|; )${escaped}=([^;]*)`))
|
||||
return match ? decodeURIComponent(match[1]) : ''
|
||||
}
|
||||
|
||||
export const api = axios.create({
|
||||
baseURL: '/yuyx/api',
|
||||
timeout: 30_000,
|
||||
withCredentials: true,
|
||||
})
|
||||
|
||||
api.interceptors.request.use((config) => {
|
||||
const method = String(config?.method || 'GET').toUpperCase()
|
||||
if (!['GET', 'HEAD', 'OPTIONS'].includes(method)) {
|
||||
const token = getCookie('csrf_token')
|
||||
if (token) {
|
||||
config.headers = config.headers || {}
|
||||
config.headers['X-CSRF-Token'] = token
|
||||
}
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
api.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
|
||||
@@ -477,6 +477,12 @@ function emailTypeLabel(type) {
|
||||
return map[type] || type
|
||||
}
|
||||
|
||||
function emailLogUserLabel(row) {
|
||||
if (row?.username && row?.user_id) return `${row.username} (#${row.user_id})`
|
||||
if (row?.user_id) return `用户#${row.user_id}`
|
||||
return '系统'
|
||||
}
|
||||
|
||||
async function loadEmailStats() {
|
||||
emailStatsLoading.value = true
|
||||
try {
|
||||
@@ -709,6 +715,11 @@ onMounted(refreshAll)
|
||||
<el-table :data="emailLogs" v-loading="emailLogsLoading" style="width: 100%">
|
||||
<el-table-column prop="created_at" label="时间" width="180" />
|
||||
<el-table-column prop="email_to" label="收件人" min-width="180" />
|
||||
<el-table-column label="来源用户" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<span class="ellipsis" :title="emailLogUserLabel(row)">{{ emailLogUserLabel(row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="120">
|
||||
<template #default="{ row }">{{ emailTypeLabel(row.email_type) }}</template>
|
||||
</el-table-column>
|
||||
|
||||
Reference in New Issue
Block a user