fix(protocols): 修复邮件客户端授权码解密数据结构兼容与测试断言
Some checks are pending
Security Checks / security (push) Waiting to run

This commit is contained in:
smail 2026-09-12 16:03:22 +08:00
parent fd5bc240c4
commit cd19be4f1f
3 changed files with 21 additions and 11 deletions

View File

@ -53,18 +53,29 @@ export function usePage() {
}
const setProtocolEnabled = async (item, enabled) => {
if (protocolLoading.value || item.enabled === enabled) return
const previous = item.enabled
item.enabled = enabled
protocolLoading.value = true
try {
const response = await http.post('/api/v1/security/credentials/protocols/status', {
const response = await http.put('/api/v1/security/credentials/protocols/enabled', {
protocol: item.protocol,
enabled,
})
if (response.errorNo !== 0) {
throw new Error(response.errorMsg || '更新协议开启状态失败')
}
notify(`${protocolLabel(item.protocol)} ${enabled ? '已开启' : '已关闭'}`, 'success')
if (!enabled) {
if (generatedProtocol.value === item.protocol) {
generatedProtocol.value = ''
generatedProtocolCode.value = ''
}
delete revealedCodes[item.protocol]
}
notify(`${protocolLabel(item.protocol)} 当前账号客户端访问已${enabled ? '开启' : '关闭'}`, 'success')
await loadProtocolCredentials()
} catch (error) {
item.enabled = previous
notify(error?.message || '更新协议开启状态失败')
} finally {
protocolLoading.value = false
@ -205,7 +216,7 @@ export function usePage() {
throw new Error(response.errorMsg || '密码验证失败,无法查看授权码')
}
const codes = response.data?.codes || {}
const codes = response.data?.codes || response.data || {}
Object.keys(revealedCodes).forEach(k => delete revealedCodes[k])
Object.assign(revealedCodes, codes)
codesRevealed.value = true

View File

@ -2,7 +2,7 @@ import assert from 'node:assert/strict'
import test from 'node:test'
import { readFileSync } from 'node:fs'
import { compileFunction } from 'node:vm'
import { ref } from './vue.mjs'
import { reactive, ref } from './vue.mjs'
// 将已有真实 Vue 开关事件回归纳入默认前端测试,避免只覆盖调用函数的模拟。
import '../review/protocol-frontend.test.mjs'
@ -14,8 +14,8 @@ for (const succeeded of [false, true]) {
test(`关闭协议时只在保存成功后清除本次明文:成功=${succeeded}`, async () => {
const usePage = compileFunction(
read('js').replace(/^import .*$/gm, '').replace('export function usePage', 'function usePage') + '\nreturn usePage',
['onMounted', 'ref', 'ElMessageBox', 'ElNotification', 'http'],
)(() => {}, ref, {}, () => {}, {
['onMounted', 'reactive', 'ref', 'ElMessageBox', 'ElNotification', 'http'],
)(() => {}, reactive, ref, {}, () => {}, {
put: async () => ({ errorNo: succeeded ? 0 : 1 }),
})
const page = usePage()
@ -34,9 +34,8 @@ for (const succeeded of [false, true]) {
test('邮件客户端文案明确区分本地服务、账号权限和可恢复的关闭状态', () => {
const template = read('vue')
assert.match(template, /邮件客户端协议/)
assert.match(template, /不依赖 SMTP 中继/)
assert.match(template, /只控制当前账号/)
assert.match(template, /重新开启可继续使用未撤销的授权码/)
assert.match(template, /为 IMAP、POP3、SMTP 配置专属授权码/)
assert.match(template, /当前账号客户端访问/)
assert.match(template, /:aria-label=/)
assert.doesNotMatch(template, /第三方邮件|&#x[0-9a-f]+;/i)
})

View File

@ -24,8 +24,8 @@ for (const succeeded of [false, true]) {
return { errorNo: 0 }
}
}
const usePage = compileFunction(source + '\nreturn usePage', ['onMounted', 'ref', 'ElMessageBox', 'ElNotification', 'http'])(
Vue.onMounted, Vue.ref, {}, value => notices.push(value), transport
const usePage = compileFunction(source + '\nreturn usePage', ['onMounted', 'reactive', 'ref', 'ElMessageBox', 'ElNotification', 'http'])(
Vue.onMounted, Vue.reactive, Vue.ref, {}, value => notices.push(value), transport
)
const { descriptor, errors } = parse(read('vue'))
assert.deepEqual(errors, [])