Smail/test/frontend/security-setup.test.mjs
smail 67931eab5d
Some checks are pending
Security Checks / security (push) Waiting to run
强制超级管理员配置安全验证并保护本机密码重置
2026-09-19 00:24:27 +08:00

119 lines
5.1 KiB
JavaScript

import assert from 'node:assert/strict'
import test from 'node:test'
import { readFileSync } from 'node:fs'
import { compileFunction } from 'node:vm'
import { computed, reactive, ref } from './vue.mjs'
const source = readFileSync(new URL('../../frontend/src/views/components/SecuritySetupPrompt/SecuritySetupPrompt.js', import.meta.url), 'utf8')
const createPage = compileFunction(
source.replace(/^import .*$/gm, '').replace('export function usePage', 'function usePage') + '\nreturn usePage()',
['computed', 'ref', 'http', 'useGlobalStatusStore']
)
function fixture(post = async () => ({ errorNo: 0 })) {
const store = reactive({
isLogin: true,
role: 'super_admin',
userInfos: { account: 'root', showSecuritySetupPrompt: true, must_change_password: 0, webAuthnEnabled: false },
settingsDrawerVisible: false,
dismissRecoveryPrompt() { this.recoveryPromptDismissed = true }
})
return { store, page: createPage(computed, ref, { post }, () => store) }
}
test('超级管理员三种方式任选其一,强制改密时延后', () => {
const { store, page } = fixture()
assert.equal(page.visible.value, true)
assert.deepEqual(Array.from(page.options.value, item => item.key), ['recovery', 'external-email', 'totp'])
store.userInfos.must_change_password = 1
assert.equal(page.visible.value, false)
store.userInfos.must_change_password = 0
assert.equal(page.visible.value, true)
})
test('强制设置不可跳过,关闭设置窗口后继续要求完成', async () => {
let calls = 0
const { store, page } = fixture(async () => { calls++; return { errorNo: 0 } })
store.userInfos.securitySetupRequired = true
await page.acknowledge()
assert.equal(page.visible.value, true)
await page.acknowledge('totp')
assert.equal(calls, 0)
assert.equal(page.visible.value, false)
assert.equal(store.securityActiveSection, 'totp')
store.settingsDrawerVisible = false
assert.equal(page.visible.value, true)
store.userInfos.securitySetupRequired = false
store.userInfos.showSecuritySetupPrompt = false
assert.equal(page.visible.value, false)
})
test('确认仅关闭本次提醒,下次登录未完成设置仍提醒', async () => {
const requests = []
const { store, page } = fixture(async path => { requests.push(path); return { errorNo: 0 } })
await page.acknowledge('external-email')
assert.equal(page.visible.value, false)
assert.equal(store.settingsActiveTab, 'security')
assert.equal(store.securityActiveSection, 'external-email')
assert.equal(store.settingsDrawerVisible, true)
assert.deepEqual(requests, ['/api/v1/security/setup/acknowledge'])
store.userInfos = { account: 'root', showSecuritySetupPrompt: false }
assert.equal(page.visible.value, false)
store.settingsDrawerVisible = false
store.userInfos = { account: 'root', showSecuritySetupPrompt: true }
assert.equal(page.visible.value, true)
})
test('管理员和普通用户只显示尚未完成的安全码与邮箱', () => {
for (const role of ['admin', 'user']) {
const { store, page } = fixture()
store.role = role
assert.deepEqual(Array.from(page.options.value, item => item.key), ['recovery', 'external-email'])
store.userInfos.recoveryCodesConfigured = true
assert.deepEqual(Array.from(page.options.value, item => item.key), ['external-email'])
store.userInfos.externalEmailConfigured = true
store.userInfos.recoveryCodesConfigured = false
assert.deepEqual(Array.from(page.options.value, item => item.key), ['recovery'])
store.userInfos.recoveryCodesConfigured = true
store.userInfos.showSecuritySetupPrompt = false
assert.deepEqual(Array.from(page.options.value, item => item.key), [])
assert.equal(page.visible.value, false)
}
})
test('我知道了只关闭弹窗,去设置打开第一个未完成项', async () => {
const { store, page } = fixture()
store.role = 'user'
await page.acknowledge()
assert.equal(page.visible.value, false)
assert.equal(store.settingsDrawerVisible, false)
store.userInfos.showSecuritySetupPrompt = true
await page.acknowledge(page.options.value[0].key)
assert.equal(store.securityActiveSection, 'recovery')
assert.equal(store.settingsDrawerVisible, true)
})
test('保存失败保留引导,可重试且不将查看状态误记为设置完成', async () => {
const { store, page } = fixture(async () => { throw new Error('请求失败') })
await page.acknowledge()
assert.equal(page.visible.value, true)
assert.equal(page.error.value, '请求失败')
assert.equal(page.saving.value, false)
assert.equal(store.settingsDrawerVisible, false)
assert.equal(store.userInfos.recoveryCodesConfigured, undefined)
})
test('并发点击只提交一次,切换账号后不修改新账号状态', async () => {
let finish
let calls = 0
const { store, page } = fixture(() => { calls++; return new Promise(resolve => { finish = resolve }) })
const pending = page.acknowledge('recovery')
await page.acknowledge('external-email')
assert.equal(calls, 1)
store.userInfos = { account: 'alice', showSecuritySetupPrompt: true }
finish({ errorNo: 0 })
await pending
assert.equal(page.visible.value, true)
assert.equal(store.settingsDrawerVisible, false)
})