This commit is contained in:
parent
581e70b2ca
commit
6146ddba5d
@ -90,10 +90,15 @@ export function readDevelopmentRuntime(root = runtimeRoot, { previous = false }
|
||||
if (typeof webDomain !== 'string' || !/^[a-z0-9.-]+(?::\d+)?$/i.test(webDomain)) {
|
||||
throw new Error('请先在 yunx-test/config/config.json 配置有效的 Web 域名')
|
||||
}
|
||||
const mailDomain = config.domains?.primary || webDomain
|
||||
if (typeof mailDomain !== 'string' || !/^[a-z0-9.-]+(?::\d+)?$/i.test(mailDomain)) {
|
||||
throw new Error('请先在 yunx-test/config/config.json 配置有效的主邮件域名')
|
||||
}
|
||||
const certificatePath = resolveDevelopmentCertificate(root, previous ? ssl.tls?.previousCertificateRef : ssl.tls?.certificateRef)
|
||||
const privateKeyPath = resolveDevelopmentCertificate(root, previous ? ssl.tls?.previousPrivateKeyRef : ssl.tls?.privateKeyRef, true)
|
||||
return {
|
||||
origin: `https://${webDomain}`,
|
||||
mailOrigin: `https://${mailDomain}`,
|
||||
certificatePath,
|
||||
privateKeyPath,
|
||||
generation: config.generation
|
||||
|
||||
@ -30,6 +30,21 @@ const developmentHTTPRedirect = (frontendOrigin, host = '127.0.0.1', port = 80)
|
||||
}
|
||||
})
|
||||
|
||||
const developmentBackendProxy = (backendUrl, backendOrigin) => ({
|
||||
target: backendUrl,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
configure: (proxy) => {
|
||||
proxy.on('proxyReq', (proxyRequest) => {
|
||||
const originURL = new URL(backendOrigin)
|
||||
proxyRequest.setHeader('origin', backendOrigin)
|
||||
proxyRequest.setHeader('host', originURL.host)
|
||||
proxyRequest.setHeader('x-forwarded-proto', originURL.protocol.replace(':', ''))
|
||||
proxyRequest.removeHeader('referer')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
@ -37,6 +52,7 @@ export default defineConfig(({ mode, command }) => {
|
||||
const developmentTLS = command === 'serve' ? readDevelopmentTLS() : undefined
|
||||
const runtime = developmentTLS?.runtime
|
||||
const backendOrigin = runtime?.origin
|
||||
const publicRecoveryOrigin = runtime?.mailOrigin
|
||||
const frontendOrigin = runtime?.origin
|
||||
|
||||
return {
|
||||
@ -64,20 +80,10 @@ export default defineConfig(({ mode, command }) => {
|
||||
https: developmentTLS?.options,
|
||||
cors: true,
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: backendUrl,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
configure: (proxy) => {
|
||||
proxy.on('proxyReq', (proxyRequest) => {
|
||||
const originURL = new URL(backendOrigin)
|
||||
proxyRequest.setHeader('origin', backendOrigin)
|
||||
proxyRequest.setHeader('host', originURL.host)
|
||||
proxyRequest.setHeader('x-forwarded-proto', originURL.protocol.replace(':', ''))
|
||||
proxyRequest.removeHeader('referer')
|
||||
})
|
||||
}
|
||||
},
|
||||
"/api": developmentBackendProxy(backendUrl, backendOrigin),
|
||||
// 匿名恢复入口由后端按 Web 域名计算跳转,恢复 API 则必须保持主邮件域名的同源校验。
|
||||
"/public-password-recovery": developmentBackendProxy(backendUrl, backendOrigin),
|
||||
"/rest/api/recovery": developmentBackendProxy(backendUrl, publicRecoveryOrigin),
|
||||
"/attachments": {
|
||||
target: backendUrl,
|
||||
changeOrigin: true,
|
||||
|
||||
@ -30,16 +30,24 @@ test('前端构建必须自动同步 Go 嵌入资源', async () => {
|
||||
|
||||
test('前端入口按需加载 Element Plus,并延迟设置页和写信编辑器', async () => {
|
||||
const main = await read('frontend/src/main.js')
|
||||
const mainApp = await read('frontend/src/main-app.js')
|
||||
const vite = await read('frontend/vite.config.js')
|
||||
const header = await read('frontend/src/views/components/HomeHeader/HomeHeader.js')
|
||||
assert.doesNotMatch(main, /app\.use\(ElementPlus\)/)
|
||||
assert.doesNotMatch(main, /element-plus\/dist\/index\.css/)
|
||||
assert.match(main, /element-services\.css/)
|
||||
assert.match(main, /public-recovery\.js/)
|
||||
assert.match(mainApp, /element-services\.css/)
|
||||
assert.match(vite, /manualChunks\(id\)/)
|
||||
assert.match(header, /defineAsyncComponent/)
|
||||
assert.match(header, /import\('\.\.\/ConfigSettings\/ConfigSettings\.vue'\)/)
|
||||
})
|
||||
|
||||
test('开发服务器将匿名恢复入口和接口安全转发到后端', async () => {
|
||||
const vite = await read('frontend/vite.config.js')
|
||||
assert.match(vite, /"\/public-password-recovery": developmentBackendProxy\(backendUrl, backendOrigin\)/)
|
||||
assert.match(vite, /"\/rest\/api\/recovery": developmentBackendProxy\(backendUrl, publicRecoveryOrigin\)/)
|
||||
})
|
||||
|
||||
test('开发启动必须固定运行配置根目录并集中保存日志', async () => {
|
||||
const content = await read('deploy/start-dev.ps1')
|
||||
assert.match(content, /\$env:SMAIL_ROOT = \$runtime\r?\n/)
|
||||
|
||||
@ -21,6 +21,7 @@ test('开发配置只从模拟部署目录读取且不返回凭据字段', async
|
||||
await writeFile(path.join(root, 'ssl/private.key'), 'key', { mode: 0o600 })
|
||||
const runtime = readDevelopmentRuntime(root)
|
||||
assert.equal(runtime.origin, 'https://mail.example.test')
|
||||
assert.equal(runtime.mailOrigin, 'https://mail.example.test')
|
||||
assert.equal(runtime.generation, 9)
|
||||
assert.equal(runtime.privateKeyPath, path.join(root, 'ssl/private.key'))
|
||||
assert.equal(JSON.stringify(runtime).includes('not-exported'), false)
|
||||
@ -31,6 +32,26 @@ test('开发配置只从模拟部署目录读取且不返回凭据字段', async
|
||||
assert.throws(() => readDevelopmentRuntime(root), /事务尚未完成/)
|
||||
})
|
||||
|
||||
test('开发运行配置单独保留主邮件域名供匿名恢复接口校验', async () => {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), 'smail-runtime-recovery-domain-'))
|
||||
await mkdir(path.join(root, 'config'))
|
||||
await mkdir(path.join(root, 'ssl'))
|
||||
await writeFile(path.join(root, 'config/config.json'), JSON.stringify({
|
||||
generation: 5,
|
||||
domains: { web: 'web.example.test', primary: 'mail.example.test' }
|
||||
}))
|
||||
await writeFile(path.join(root, 'config/ssl.json'), JSON.stringify({
|
||||
meta: { generation: 5 },
|
||||
tls: { certificateRef: 'ssl/public.crt', privateKeyRef: 'ssl/private.key' }
|
||||
}))
|
||||
await writeFile(path.join(root, 'ssl/public.crt'), 'certificate')
|
||||
await writeFile(path.join(root, 'ssl/private.key'), 'key', { mode: 0o600 })
|
||||
|
||||
const runtime = readDevelopmentRuntime(root)
|
||||
assert.equal(runtime.origin, 'https://web.example.test')
|
||||
assert.equal(runtime.mailOrigin, 'https://mail.example.test')
|
||||
})
|
||||
|
||||
test('源码指纹检测编辑且忽略编译嵌入目录', async () => {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), 'smail-build-state-'))
|
||||
for (const name of ['backend', 'frontend', 'plugins/pmail_telegram_push', 'deploy']) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user