#!/usr/bin/env bash
# security/block-ip -- manual block list on top of the firewall
set -o pipefail
SELF=$(readlink -f "${BASH_SOURCE[0]}")
NV_BASE=$(cd "$(dirname "$SELF")/../../.." && pwd)
export NV_BASE
# shellcheck source=/dev/null
. "$NV_BASE/lib/core/bootstrap.sh"

nv_require_root || exit 1
ui_header "$(t sec_m_block)"

ui_section "$(t sec_current_blocks)"
blocks=$(ufw status 2>/dev/null | awk '/DENY/ {print $2}' | grep -E '^[0-9]+\.' | sort -u)
if [ -z "$blocks" ]; then
    ui_info "$(t sec_no_blocks)"
else
    printf '%s\n' "$blocks" | while read -r ip; do ui_info "$ip"; done
fi
ui_blank

printf '  %s (0 = %s): ' "$(t sec_prompt_ip)" "$(t menu_back)"
read -r ip || exit 130
case $ip in ''|0) exit 0 ;; esac
ip=$(nv_trim "$ip")

nv_valid_ipv4 "$ip" || { ui_err "$(t sec_bad_ip)"; exit 2; }

if printf '%s\n' "$blocks" | grep -qx "$ip"; then
    ui_confirm "$(t sec_unblock_q "$ip")" n || exit 0
    ufw delete deny from "$ip" >/dev/null 2>&1 || ufw delete deny from "$ip" to any >/dev/null 2>&1 || true
    nv_trace block-ip "unblock $ip"
    ui_ok "$(t sec_unblocked "$ip")"
    exit 0
fi

ui_confirm "$(t sec_block_q "$ip")" n || exit 0
ufw insert 1 deny from "$ip" >/dev/null 2>&1 || ufw deny from "$ip" >/dev/null 2>&1 \
    || { nv_fail 6105 "$(t sec_block_failed)"; exit 1; }

# also drop it from fail2ban's sshd jail when that jail exists
if nv_have fail2ban-client && fail2ban-client status sshd >/dev/null 2>&1; then
    fail2ban-client set sshd banip "$ip" >/dev/null 2>&1 || true
fi

nv_trace block-ip "block $ip"
ui_ok "$(t sec_blocked "$ip")"
ui_info "$(t sec_block_note)"
exit 0
