68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
/** @jest-environment node */
|
||
|
||
import { execFile } from 'child_process'
|
||
import { NextRequest } from 'next/server'
|
||
import { getServerSession } from 'next-auth'
|
||
import { GET } from '@/app/api/admin/system-logs/route'
|
||
|
||
jest.mock('next-auth', () => ({
|
||
getServerSession: jest.fn(),
|
||
}))
|
||
|
||
jest.mock('@/lib/auth', () => ({ authOptions: {} }))
|
||
|
||
jest.mock('@/lib/department-permission', () => ({
|
||
isSuperAdmin: jest.fn().mockResolvedValue(false),
|
||
hasSystemAdminPermission: jest.fn((role: string, isSuperAdmin: boolean) =>
|
||
isSuperAdmin || role === 'ADMIN' || role === 'SYSTEM_ADMIN'),
|
||
}))
|
||
|
||
jest.mock('child_process', () => ({
|
||
execFile: jest.fn(),
|
||
}))
|
||
|
||
describe('admin system-logs route', () => {
|
||
beforeEach(() => {
|
||
jest.clearAllMocks()
|
||
;(getServerSession as jest.Mock).mockResolvedValue({
|
||
user: { id: 'admin-1', role: 'ADMIN' },
|
||
})
|
||
;(execFile as unknown as jest.Mock).mockImplementation(
|
||
(_file: string, _args: string[], _options: unknown, callback: Function) =>
|
||
callback(null, 'INFO ready\nERROR failed\n', ''),
|
||
)
|
||
})
|
||
|
||
test('关键词和行数不得进入 shell,并在进程输出后过滤', async () => {
|
||
const keyword = '"; touch /tmp/pwn; #'
|
||
const request = new NextRequest(
|
||
`http://localhost/api/admin/system-logs?lines=999999&keyword=${encodeURIComponent(keyword)}`,
|
||
)
|
||
|
||
const response = await GET(request)
|
||
const body = await response.json()
|
||
|
||
expect(response.status).toBe(200)
|
||
expect(execFile).toHaveBeenCalledWith(
|
||
'docker',
|
||
['logs', '--tail', '5000', 'youyidian-3d-material'],
|
||
expect.objectContaining({ encoding: 'utf8' }),
|
||
expect.any(Function),
|
||
)
|
||
expect((execFile as unknown as jest.Mock).mock.calls[0][2]).not.toHaveProperty('shell')
|
||
expect(JSON.stringify((execFile as unknown as jest.Mock).mock.calls[0].slice(0, 3))).not.toContain(keyword)
|
||
expect(body.logs).toBe('')
|
||
})
|
||
|
||
test('普通用户不得调用 docker', async () => {
|
||
;(getServerSession as jest.Mock).mockResolvedValue({
|
||
user: { id: 'user-1', role: 'USER' },
|
||
})
|
||
|
||
const response = await GET(new NextRequest('http://localhost/api/admin/system-logs'))
|
||
|
||
expect(response.status).toBe(403)
|
||
expect(execFile).not.toHaveBeenCalled()
|
||
})
|
||
})
|