#!/usr/bin/env bash
#
# onx-modsec-custom-rule-write — özel SecRule'leri yaz. DRIVER-AWARE (v3.41).
#
#   Apache → /etc/httpd/modsecurity.d/onox-custom.d/rule-<id>.conf (mevcut davranış)
#   v3 (nginx/ols/caddy) → neutral 30-custom-<id>.conf
#
# Domain scoping: CONTAINER-FREE skipAfter/SecMarker tekniği (Apache <If> DEĞİL) —
# SERVER_NAME eşleşmezse kullanıcı kuralları skip edilir. Hem mod_security2 hem
# libmodsecurity v3 destekler.
#
# Input:  {rule_id, name, rule_content, is_enabled, domain_name, action:write|delete}
# Output: {ok, applied, file, driver, syntax_ok, 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 || onx_die 1 "stdin is not a valid JSON object"

rule_id=$(echo "$input" | jq -r '.rule_id // 0')
name=$(echo "$input"    | jq -r '.name // ""')
content=$(echo "$input" | jq -r '.rule_content // ""')
enabled=$(echo "$input" | jq -r '.is_enabled // true')
domain=$(echo "$input"  | jq -r '.domain_name // empty')
action=$(echo "$input"  | jq -r '.action // "write"')

if ! [[ "$rule_id" =~ ^[0-9]+$ ]]; then
    jq -nc '{ok:false,error:"valid rule_id required"}' >&2; exit 1
fi
if (( rule_id < 1 )); then
    jq -nc '{ok:false,error:"rule_id must be >= 1"}' >&2; exit 1
fi

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

# ── Delete ───────────────────────────────────────────────────────────────────
if [[ "$action" == "delete" ]]; then
    rm -f "$FILE"
    reloaded=$(onx_ws_modsec_reload "$DRIVER")
    jq -nc --arg driver "$DRIVER" --argjson reloaded "$reloaded" \
        '{ok:true, applied:true, action:"deleted", driver:$driver, reloaded:$reloaded}'
    exit 0
fi

# ── Write ────────────────────────────────────────────────────────────────────
if [[ -z "$content" ]]; then
    jq -nc '{ok:false,error:"rule_content required for write action"}' >&2; exit 1
fi
if ! echo "$content" | grep -qE '^[[:space:]]*Sec(Rule|Action|Marker)'; then
    jq -nc '{ok:false,error:"no valid SecRule/SecAction/SecMarker directive found"}' >&2; exit 3
fi

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

# Domain guard phase'i kullanıcı içeriğinden türet (yoksa 2 — request phase)
guard_phase=$(echo "$content" | grep -oE 'phase:[1-5]' | head -1 | cut -d: -f2 || true)
[[ "$guard_phase" =~ ^[1-5]$ ]] || guard_phase=2
guard_id=$((3000000 + rule_id))
marker="END-onox-custom-${rule_id}"

tmp="$(mktemp -t onx-modsec.XXXXXX)"
{
    echo "# Onoxsoft Panel custom rule — DO NOT EDIT (UI: Admin > ModSecurity > Özel Kurallar)"
    echo "# Name: ${name} | ID: ${rule_id} | Enabled: ${enabled} | Driver: ${DRIVER}"
    echo "# Generated $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo ""
    if [[ "$enabled" != "true" ]]; then
        echo "$content" | sed 's/^/# DISABLED: /'
    elif [[ -n "$domain" ]]; then
        # Container-free domain scope — SERVER_NAME eşleşmezse user rules skip
        echo "SecRule SERVER_NAME \"!@streq ${domain}\" \"id:${guard_id},phase:${guard_phase},nolog,pass,t:none,skipAfter:${marker}\""
        echo "$content"
        echo "SecMarker ${marker}"
    else
        echo "$content"
    fi
} > "$tmp"
chmod 0644 "$tmp"
mv -f "$tmp" "$FILE"

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

logger -t "onox-modsec-custom" "Wrote rule_id=${rule_id} name=${name} enabled=${enabled} driver=${DRIVER} reloaded=${reloaded}"

jq -nc --arg file "$FILE" --arg driver "$DRIVER" \
    '{ok:true, applied:true, file:$file, driver:$driver, syntax_ok:true, reloaded:true}'
