#!/usr/bin/env bash
#
# onx-modsec-whitelist-write — IP allowlist (WAF bypass). DRIVER-AWARE (v3.41).
#
#   Apache → /etc/httpd/modsecurity.d/onox-whitelist.conf (mevcut davranış)
#   v3 (nginx/ols/caddy) → neutral 10-whitelist.conf
#
# CONTAINER-FREE: per-domain kapsam için chained SecRule SERVER_NAME kullanılır
# (Apache <LocationMatch> DEĞİL) — böylece libmodsecurity v3 de parse edebilir.
# allow + phase:1 → güvenilen IP tüm WAF kontrolünü bypass eder.
#
# Input:  {"ips":[{"ip_or_cidr":"1.2.3.4","domain_name":"example.com|null"}]}
# Output: {ok, applied, count, driver, file, reloaded}

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

require_root

input="$(cat 2>/dev/null || echo '{}')"
echo "$input" | jq -e 'type == "object"' >/dev/null 2>&1 || input='{}'
count=$(echo "$input" | jq '.ips // [] | length')

DRIVER=$(onx_ws_active_driver)
if [[ "$DRIVER" == "apache" ]]; then
    CONF_FILE="/etc/httpd/modsecurity.d/onox-whitelist.conf"
elif [[ "$DRIVER" == "unknown" ]]; then
    onx_die 2 "Aktif web sunucusu tespit edilemedi (apache/ols/nginx/caddy hiçbiri active değil)"
else
    CONF_FILE="${ONX_MODSEC_NEUTRAL_DIR}/${ONX_MODSEC_NEUTRAL_SUBDIR}/10-whitelist.conf"
    mkdir -p "$(dirname "$CONF_FILE")" 2>/dev/null || true
fi

backup=""
if [[ -f "$CONF_FILE" ]]; then
    backup="${CONF_FILE}.onx-bak.$$"
    cp -p "$CONF_FILE" "$backup"
fi

# Rule ID aralığı 1000-1999 (ModSecurity user-range; CRS 900000+ ile çakışmaz)
tmp="$(mktemp -t onx-modsec.XXXXXX)"
{
    echo "# Onoxsoft Panel managed — DO NOT EDIT (UI: Admin > ModSecurity > IP Whitelist)"
    echo "# Driver: ${DRIVER} | Auto-generated $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo ""
    rule_id=1000
    echo "$input" | jq -c '.ips[]?' | while IFS= read -r entry; do
        ip=$(echo "$entry" | jq -r '.ip_or_cidr // empty')
        domain=$(echo "$entry" | jq -r '.domain_name // empty')
        [[ -z "$ip" ]] && continue

        # IP/CIDR doğrula
        if [[ "$ip" == *:* ]]; then
            [[ "$ip" =~ ^[0-9a-fA-F:]+(/[0-9]{1,3})?$ ]] || continue
        else
            [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$ ]] || continue
        fi

        if [[ -n "$domain" ]]; then
            # Domain-scoped — chained (container-free, v2+v3 uyumlu)
            echo "SecRule SERVER_NAME \"@streq ${domain}\" \"id:${rule_id},phase:1,nolog,allow,t:none,msg:'onox-whitelist',chain\""
            echo "    SecRule REMOTE_ADDR \"@ipMatch ${ip}\""
        else
            echo "SecRule REMOTE_ADDR \"@ipMatch ${ip}\" \"id:${rule_id},phase:1,nolog,allow,t:none,msg:'onox-whitelist'\""
        fi
        rule_id=$((rule_id + 1))
    done
} > "$tmp"
chmod 0644 "$tmp"
mv -f "$tmp" "$CONF_FILE"

reloaded=$(onx_ws_modsec_reload "$DRIVER")
if [[ "$reloaded" != "true" ]]; then
    if [[ -n "$backup" ]]; then
        mv -f "$backup" "$CONF_FILE" 2>/dev/null || true
    else
        rm -f "$CONF_FILE" 2>/dev/null || true
    fi
    onx_ws_modsec_reload "$DRIVER" >/dev/null 2>&1 || true
    onx_log "modsec-whitelist-write: driver=${DRIVER} reload FAILED — rolled back"
    jq -nc --arg driver "$DRIVER" '{ok:false,error:"reload failed — rolled back",driver:$driver}' >&2
    exit 4
fi
[[ -n "$backup" ]] && rm -f "$backup" 2>/dev/null || true

logger -t "onox-modsec" "Whitelist written driver=${DRIVER} count=${count} reloaded=${reloaded}"

jq -nc --argjson count "$count" --arg driver "$DRIVER" --arg file "$CONF_FILE" \
    '{ok:true, applied:true, count:$count, driver:$driver, file:$file, reloaded:true}'
