test: add ip-gate plugin tests
This commit is contained in:
@@ -0,0 +1,154 @@
|
|||||||
|
import Fastify from 'fastify'
|
||||||
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||||
|
import { registerIpGate } from '../ip-gate.js'
|
||||||
|
|
||||||
|
function buildApp() {
|
||||||
|
const app = Fastify({ logger: false, trustProxy: true })
|
||||||
|
app.get('/test', async () => ({ ok: true }))
|
||||||
|
app.get('/api/webhooks/yookassa', async () => ({ ok: true }))
|
||||||
|
app.get('/api/auth/oauth/vk/callback', async () => ({ ok: true }))
|
||||||
|
app.get('/api/auth/oauth/yandex/callback', async () => ({ ok: true }))
|
||||||
|
app.get('/api/admin/notifications/telegram/webhook', async () => ({ ok: true }))
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('registerIpGate', () => {
|
||||||
|
let app
|
||||||
|
const originalIps = process.env.SITE_ACCESS_IPS
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = buildApp()
|
||||||
|
await registerIpGate(app)
|
||||||
|
await app.ready()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.close()
|
||||||
|
process.env.SITE_ACCESS_IPS = originalIps
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает запрос если SITE_ACCESS_IPS не задан', async () => {
|
||||||
|
delete process.env.SITE_ACCESS_IPS
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/test', remoteAddress: '1.2.3.4' })
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
expect(res.json()).toEqual({ ok: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает запрос с разрешённого IP', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4,5.6.7.8'
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/test', remoteAddress: '1.2.3.4' })
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает запрос с IPv6-mapped разрешённого IP', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/test', remoteAddress: '::ffff:1.2.3.4' })
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('блокирует запрос с неразрешённого IP (403)', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/test', remoteAddress: '9.9.9.9' })
|
||||||
|
expect(res.statusCode).toBe(403)
|
||||||
|
expect(res.headers['content-type']).toMatch(/text\/html/)
|
||||||
|
expect(res.body).toContain('Любимый Креатив')
|
||||||
|
expect(res.body).toContain('9.9.9.9')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('403-страница показывает IP по умолчанию (127.0.0.1) когда remoteAddress не указан', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({ method: 'GET', url: '/test' })
|
||||||
|
expect(res.statusCode).toBe(403)
|
||||||
|
expect(res.body).toContain('127.0.0.1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает исключённые пути с любым IP (webhook yookassa)', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/webhooks/yookassa',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает исключённые пути с любым IP (vk callback)', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/auth/oauth/vk/callback',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает исключённые пути с любым IP (yandex callback)', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/auth/oauth/yandex/callback',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает исключённые пути с любым IP (telegram webhook)', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/admin/notifications/telegram/webhook',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('корректно тримит пробелы в списке IP', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = ' 1.2.3.4 , 5.6.7.8 '
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test',
|
||||||
|
remoteAddress: '5.6.7.8',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('нормализует IPv6-mapped адреса в whitelist', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '::ffff:1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test',
|
||||||
|
remoteAddress: '1.2.3.4',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('пропускает если после трима список IP пуст', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = ' , , '
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('путь с query-параметрами проверяется корректно', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test?foo=bar',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(403)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('исключённый путь с query-параметрами тоже пропускается', async () => {
|
||||||
|
process.env.SITE_ACCESS_IPS = '1.2.3.4'
|
||||||
|
const res = await app.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/api/webhooks/yookassa?foo=bar',
|
||||||
|
remoteAddress: '9.9.9.9',
|
||||||
|
})
|
||||||
|
expect(res.statusCode).toBe(200)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user