Skip to content

Commit d35fd23

Browse files
committed
test: add Vitest coverage for allowlist
1 parent bb22735 commit d35fd23

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

src/allowlist/index.test.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest'
2+
import { isQueryAllowed } from './index'
3+
import { DataSource } from '../types'
4+
import { StarbaseDBConfiguration } from '../handler'
5+
6+
describe('allowlist', () => {
7+
let mockDataSource: DataSource
8+
let mockConfig: StarbaseDBConfiguration
9+
10+
beforeEach(() => {
11+
mockDataSource = {
12+
source: 'test-source',
13+
type: 'sqlite',
14+
config: {},
15+
rpc: {
16+
executeQuery: vi.fn(),
17+
executeExternalQuery: vi.fn(),
18+
}
19+
} as unknown as DataSource
20+
21+
mockConfig = {
22+
role: 'user',
23+
api: {
24+
enabled: true
25+
}
26+
} as unknown as StarbaseDBConfiguration
27+
})
28+
29+
it('allows query if allowlist feature is disabled', async () => {
30+
const result = await isQueryAllowed({
31+
sql: 'SELECT * FROM users',
32+
isEnabled: false,
33+
dataSource: mockDataSource,
34+
config: mockConfig
35+
})
36+
expect(result).toBe(true)
37+
expect(mockDataSource.rpc.executeQuery).not.toHaveBeenCalled()
38+
})
39+
40+
it('allows query if role is admin', async () => {
41+
mockConfig.role = 'admin'
42+
const result = await isQueryAllowed({
43+
sql: 'SELECT * FROM users',
44+
isEnabled: true,
45+
dataSource: mockDataSource,
46+
config: mockConfig
47+
})
48+
expect(result).toBe(true)
49+
expect(mockDataSource.rpc.executeQuery).not.toHaveBeenCalled()
50+
})
51+
52+
it('rejects empty query', async () => {
53+
mockDataSource.rpc.executeQuery = vi.fn().mockResolvedValue([])
54+
55+
const result = await isQueryAllowed({
56+
sql: '',
57+
isEnabled: true,
58+
dataSource: mockDataSource,
59+
config: mockConfig
60+
})
61+
expect(result).toBeInstanceOf(Error)
62+
expect((result as Error).message).toBe('No SQL provided for allowlist check')
63+
})
64+
65+
it('allows a query that exactly matches the allowlist', async () => {
66+
mockDataSource.rpc.executeQuery = vi.fn().mockResolvedValue([
67+
{ sql_statement: 'SELECT * FROM users', source: 'test-source' }
68+
])
69+
70+
const result = await isQueryAllowed({
71+
sql: 'SELECT * FROM users;', // with semicolon
72+
isEnabled: true,
73+
dataSource: mockDataSource,
74+
config: mockConfig
75+
})
76+
expect(result).toBe(true)
77+
})
78+
79+
it('rejects a query that is not in the allowlist and logs rejection', async () => {
80+
mockDataSource.rpc.executeQuery = vi.fn()
81+
// First call for loadAllowlist
82+
.mockResolvedValueOnce([
83+
{ sql_statement: 'SELECT * FROM valid_table', source: 'test-source' }
84+
])
85+
// Second call for addRejectedQuery
86+
.mockResolvedValueOnce([])
87+
88+
await expect(isQueryAllowed({
89+
sql: 'SELECT * FROM invalid_table',
90+
isEnabled: true,
91+
dataSource: mockDataSource,
92+
config: mockConfig
93+
})).rejects.toThrow('Query not allowed')
94+
95+
// Verify that addRejectedQuery was called
96+
expect(mockDataSource.rpc.executeQuery).toHaveBeenCalledTimes(2)
97+
expect(mockDataSource.rpc.executeQuery).toHaveBeenNthCalledWith(2, {
98+
sql: 'INSERT INTO tmp_allowlist_rejections (sql_statement, source) VALUES (?, ?)',
99+
params: ['SELECT * FROM invalid_table', 'test-source']
100+
})
101+
})
102+
103+
it('handles query execution error when loading allowlist', async () => {
104+
mockDataSource.rpc.executeQuery = vi.fn().mockRejectedValue(new Error('DB error'))
105+
106+
await expect(isQueryAllowed({
107+
sql: 'SELECT * FROM users',
108+
isEnabled: true,
109+
dataSource: mockDataSource,
110+
config: mockConfig
111+
})).rejects.toThrow('Query not allowed')
112+
})
113+
})

0 commit comments

Comments
 (0)