- Restore CLAUDE.md with project conventions - ESLint config with vue3-recommended + typescript - Image upload endpoint (POST /api/admin/upload) with 5MB limit - Admin product form now supports image upload/preview/removal - Vitest config + 19 tests (crypto, validation, btcpay webhook, types) - Restore .claude/ security hooks (block-risky-bash, protect-files) - Logo splash now shows "EVERYTHING YOU LOVE IS A PSYOP" tagline - Add .vite/ to gitignore Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
39 lines
1.4 KiB
TypeScript
39 lines
1.4 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import crypto from 'node:crypto'
|
|
import { validateWebhookSignature } from '../../server/lib/btcpay.js'
|
|
|
|
describe('BTCPay webhook validation', () => {
|
|
const secret = 'test-webhook-secret-key'
|
|
|
|
it('validates correct HMAC signature', () => {
|
|
process.env.BTCPAY_WEBHOOK_SECRET = secret
|
|
const body = '{"type":"InvoiceSettled","invoiceId":"test123"}'
|
|
const hmac = crypto.createHmac('sha256', secret).update(body).digest('hex')
|
|
|
|
expect(validateWebhookSignature(body, `sha256=${hmac}`)).toBe(true)
|
|
})
|
|
|
|
it('rejects incorrect signature', () => {
|
|
process.env.BTCPAY_WEBHOOK_SECRET = secret
|
|
const body = '{"type":"InvoiceSettled","invoiceId":"test123"}'
|
|
|
|
expect(validateWebhookSignature(body, 'sha256=deadbeef00112233445566778899aabbccddeeff00112233445566778899aabb')).toBe(false)
|
|
})
|
|
|
|
it('rejects when no secret configured', () => {
|
|
delete process.env.BTCPAY_WEBHOOK_SECRET
|
|
const body = '{"type":"InvoiceSettled"}'
|
|
|
|
expect(validateWebhookSignature(body, 'sha256=anything')).toBe(false)
|
|
})
|
|
|
|
it('rejects tampered body', () => {
|
|
process.env.BTCPAY_WEBHOOK_SECRET = secret
|
|
const body = '{"type":"InvoiceSettled","invoiceId":"test123"}'
|
|
const hmac = crypto.createHmac('sha256', secret).update(body).digest('hex')
|
|
|
|
const tamperedBody = '{"type":"InvoiceSettled","invoiceId":"hacked"}'
|
|
expect(validateWebhookSignature(tamperedBody, `sha256=${hmac}`)).toBe(false)
|
|
})
|
|
})
|