/** * Jails API module. * * Wraps all backend endpoints under `/api/jails`, `/api/bans`, and * `/api/geo` that relate to jail management. */ import { del, get, post } from "./client"; import { ENDPOINTS } from "./endpoints"; import type { ActiveBanListResponse, IpLookupResponse, JailCommandResponse, JailDetailResponse, JailListResponse, UnbanAllResponse, } from "../types/jail"; // --------------------------------------------------------------------------- // Jail overview // --------------------------------------------------------------------------- /** * Fetch the list of all fail2ban jails. * * @returns A {@link JailListResponse} containing summary info for each jail. * @throws {ApiError} On non-2xx responses. */ export async function fetchJails(): Promise { return get(ENDPOINTS.jails); } /** * Fetch full detail for a single jail. * * @param name - Jail name (e.g. `"sshd"`). * @returns A {@link JailDetailResponse} with config, ignore list, and status. * @throws {ApiError} On non-2xx responses (404 if the jail does not exist). */ export async function fetchJail(name: string): Promise { return get(ENDPOINTS.jail(name)); } // --------------------------------------------------------------------------- // Jail controls // --------------------------------------------------------------------------- /** * Start a stopped jail. * * @param name - Jail name. * @returns A {@link JailCommandResponse} confirming the operation. * @throws {ApiError} On non-2xx responses. */ export async function startJail(name: string): Promise { return post(ENDPOINTS.jailStart(name), {}); } /** * Stop a running jail. * * @param name - Jail name. * @returns A {@link JailCommandResponse} confirming the operation. * @throws {ApiError} On non-2xx responses. */ export async function stopJail(name: string): Promise { return post(ENDPOINTS.jailStop(name), {}); } /** * Toggle idle mode for a jail. * * @param name - Jail name. * @param on - `true` to enable idle mode, `false` to disable. * @returns A {@link JailCommandResponse} confirming the toggle. * @throws {ApiError} On non-2xx responses. */ export async function setJailIdle( name: string, on: boolean, ): Promise { return post(ENDPOINTS.jailIdle(name), on); } /** * Reload configuration for a single jail. * * @param name - Jail name. * @returns A {@link JailCommandResponse} confirming the reload. * @throws {ApiError} On non-2xx responses. */ export async function reloadJail(name: string): Promise { return post(ENDPOINTS.jailReload(name), {}); } /** * Reload configuration for **all** jails at once. * * @returns A {@link JailCommandResponse} confirming the operation. * @throws {ApiError} On non-2xx responses. */ export async function reloadAllJails(): Promise { return post(ENDPOINTS.jailsReloadAll, {}); } // --------------------------------------------------------------------------- // Ignore list // --------------------------------------------------------------------------- /** * Return the ignore list for a jail. * * @param name - Jail name. * @returns Array of IP addresses / CIDR networks on the ignore list. * @throws {ApiError} On non-2xx responses. */ export async function fetchIgnoreList(name: string): Promise { return get(ENDPOINTS.jailIgnoreIp(name)); } /** * Add an IP or CIDR network to a jail's ignore list. * * @param name - Jail name. * @param ip - IP address or CIDR network to add. * @returns A {@link JailCommandResponse} confirming the addition. * @throws {ApiError} On non-2xx responses. */ export async function addIgnoreIp( name: string, ip: string, ): Promise { return post(ENDPOINTS.jailIgnoreIp(name), { ip }); } /** * Remove an IP or CIDR network from a jail's ignore list. * * @param name - Jail name. * @param ip - IP address or CIDR network to remove. * @returns A {@link JailCommandResponse} confirming the removal. * @throws {ApiError} On non-2xx responses. */ export async function delIgnoreIp( name: string, ip: string, ): Promise { return del(ENDPOINTS.jailIgnoreIp(name), { ip }); } // --------------------------------------------------------------------------- // Ban / unban // --------------------------------------------------------------------------- /** * Manually ban an IP address in a specific jail. * * @param jail - Jail name. * @param ip - IP address to ban. * @returns A {@link JailCommandResponse} confirming the ban. * @throws {ApiError} On non-2xx responses. */ export async function banIp( jail: string, ip: string, ): Promise { return post(ENDPOINTS.bans, { jail, ip }); } /** * Unban an IP address from a specific jail or all jails. * * @param ip - IP address to unban. * @param jail - Target jail name, or `undefined` to unban from all jails. * @param unbanAll - When `true`, remove the IP from every jail. * @returns A {@link JailCommandResponse} confirming the unban. * @throws {ApiError} On non-2xx responses. */ export async function unbanIp( ip: string, jail?: string, unbanAll = false, ): Promise { return del(ENDPOINTS.bans, { ip, jail, unban_all: unbanAll }); } // --------------------------------------------------------------------------- // Active bans // --------------------------------------------------------------------------- /** * Fetch all currently active bans across every jail. * * @returns An {@link ActiveBanListResponse} with geo-enriched entries. * @throws {ApiError} On non-2xx responses. */ export async function fetchActiveBans(): Promise { return get(ENDPOINTS.bansActive); } /** * Unban every currently banned IP across all jails in a single operation. * * Uses fail2ban's global `unban --all` command. * * @returns An {@link UnbanAllResponse} with the count of unbanned IPs. * @throws {ApiError} On non-2xx responses. */ export async function unbanAllBans(): Promise { return del(ENDPOINTS.bansAll); } // --------------------------------------------------------------------------- // Geo / IP lookup // --------------------------------------------------------------------------- /** * Look up ban status and geo-location for an IP address. * * @param ip - IP address to look up. * @returns An {@link IpLookupResponse} with ban history and geo info. * @throws {ApiError} On non-2xx responses (400 for invalid IP). */ export async function lookupIp(ip: string): Promise { return get(ENDPOINTS.geoLookup(ip)); }