The Status() handler was only checking if the CrowdSec process was running, not if LAPI was actually responding. This caused the CrowdSecConfig page to always show "LAPI is initializing" even when LAPI was fully operational. Changes: - Backend: Add lapi_ready field to /admin/crowdsec/status response - Frontend: Add CrowdSecStatus TypeScript interface - Frontend: Update conditional logic to check lapi_ready not running - Frontend: Separate warnings for "initializing" vs "not running" - Tests: Add unit tests for Status handler LAPI check Fixes regression from crowdsec_lapi_error_diagnostic.md fixes.
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import client from './client'
|
|
|
|
export interface CrowdSecDecision {
|
|
id: string
|
|
ip: string
|
|
reason: string
|
|
duration: string
|
|
created_at: string
|
|
source: string
|
|
}
|
|
|
|
export async function startCrowdsec(): Promise<{ status: string; pid: number; lapi_ready?: boolean }> {
|
|
const resp = await client.post('/admin/crowdsec/start')
|
|
return resp.data
|
|
}
|
|
|
|
export async function stopCrowdsec() {
|
|
const resp = await client.post('/admin/crowdsec/stop')
|
|
return resp.data
|
|
}
|
|
|
|
export interface CrowdSecStatus {
|
|
running: boolean
|
|
pid: number
|
|
lapi_ready: boolean
|
|
}
|
|
|
|
export async function statusCrowdsec(): Promise<CrowdSecStatus> {
|
|
const resp = await client.get<CrowdSecStatus>('/admin/crowdsec/status')
|
|
return resp.data
|
|
}
|
|
|
|
export async function importCrowdsecConfig(file: File) {
|
|
const fd = new FormData()
|
|
fd.append('file', file)
|
|
const resp = await client.post('/admin/crowdsec/import', fd, {
|
|
headers: { 'Content-Type': 'multipart/form-data' },
|
|
})
|
|
return resp.data
|
|
}
|
|
|
|
export async function exportCrowdsecConfig() {
|
|
const resp = await client.get('/admin/crowdsec/export', { responseType: 'blob' })
|
|
return resp.data
|
|
}
|
|
|
|
export async function listCrowdsecFiles() {
|
|
const resp = await client.get<{ files: string[] }>('/admin/crowdsec/files')
|
|
return resp.data
|
|
}
|
|
|
|
export async function readCrowdsecFile(path: string) {
|
|
const resp = await client.get<{ content: string }>(`/admin/crowdsec/file?path=${encodeURIComponent(path)}`)
|
|
return resp.data
|
|
}
|
|
|
|
export async function writeCrowdsecFile(path: string, content: string) {
|
|
const resp = await client.post('/admin/crowdsec/file', { path, content })
|
|
return resp.data
|
|
}
|
|
|
|
export async function listCrowdsecDecisions(): Promise<{ decisions: CrowdSecDecision[] }> {
|
|
const resp = await client.get<{ decisions: CrowdSecDecision[] }>('/admin/crowdsec/decisions')
|
|
return resp.data
|
|
}
|
|
|
|
export async function banIP(ip: string, duration: string, reason: string): Promise<void> {
|
|
await client.post('/admin/crowdsec/ban', { ip, duration, reason })
|
|
}
|
|
|
|
export async function unbanIP(ip: string): Promise<void> {
|
|
await client.delete(`/admin/crowdsec/ban/${encodeURIComponent(ip)}`)
|
|
}
|
|
|
|
export default { startCrowdsec, stopCrowdsec, statusCrowdsec, importCrowdsecConfig, exportCrowdsecConfig, listCrowdsecFiles, readCrowdsecFile, writeCrowdsecFile, listCrowdsecDecisions, banIP, unbanIP }
|