69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { Router } from 'express'
|
|
import axios from 'axios'
|
|
|
|
const router = Router()
|
|
|
|
router.get('/stats', async (_req, res) => {
|
|
try {
|
|
const host = process.env.CROWDSEC_HOST
|
|
const key = process.env.CROWDSEC_API_KEY
|
|
if (!host || !key) {
|
|
res.status(503).json({ error: 'CROWDSEC_HOST / CROWDSEC_API_KEY not configured' })
|
|
return
|
|
}
|
|
|
|
const headers = { 'X-Api-Key': key.trim() }
|
|
|
|
// Bouncers can only access /v1/decisions — alerts require machine/agent auth
|
|
const [activeRes, weekRes] = await Promise.all([
|
|
axios.get(`${host}/v1/decisions`, { headers, params: { limit: 500000 } }),
|
|
axios.get(`${host}/v1/decisions`, { headers, params: { limit: 500000, since: '168h' } }),
|
|
])
|
|
|
|
type Decision = {
|
|
id?: number
|
|
origin?: string
|
|
type?: string
|
|
scope?: string
|
|
value?: string
|
|
scenario?: string
|
|
created_at?: string
|
|
until?: string
|
|
}
|
|
|
|
const active: Decision[] = Array.isArray(activeRes.data) ? activeRes.data : []
|
|
const week: Decision[] = Array.isArray(weekRes.data) ? weekRes.data : []
|
|
|
|
const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
|
const alertsLast24h = active.filter(d => d.created_at && new Date(d.created_at) > oneDayAgo).length
|
|
|
|
const originCount: Record<string, number> = {}
|
|
for (const d of active) {
|
|
const o = d.origin ?? 'unknown'
|
|
originCount[o] = (originCount[o] ?? 0) + 1
|
|
}
|
|
const origins = Object.entries(originCount)
|
|
.sort((a, b) => b[1] - a[1])
|
|
.map(([name, count]) => ({ name, count }))
|
|
|
|
const recent = [...active]
|
|
.filter(d => d.created_at)
|
|
.sort((a, b) => new Date(b.created_at!).getTime() - new Date(a.created_at!).getTime())
|
|
.slice(0, 6)
|
|
.map(d => ({ value: d.value ?? '?', scenario: d.scenario ?? d.origin ?? '?', created_at: d.created_at! }))
|
|
|
|
res.json({
|
|
activeBans: active.length,
|
|
alertsLast24h,
|
|
blocksThisWeek: week.length,
|
|
origins,
|
|
recent,
|
|
})
|
|
} catch (err: unknown) {
|
|
const msg = err instanceof Error ? err.message : 'Unknown error'
|
|
res.status(500).json({ error: msg })
|
|
}
|
|
})
|
|
|
|
export default router
|