#!/usr/bin/env bash # ============================================ # Help # ============================================ function cmd::preset::help() { cat < [options] Manage firewall presets. Subcommands: list, ls List available presets add, new, create Add a new preset remove, rm, del Remove a preset Options for add: --name Preset name (e.g. no-jellyfin) --desc Human readable description --block-ip Block specific IP (repeatable) --block-subnet Block subnet (repeatable) --block-port Block specific port (repeatable) Examples: wgctl preset list wgctl preset add --name no-jellyfin --desc "Block Jellyfin" --block-ip 10.0.0.210 --block-port 10.0.0.210:8096:tcp wgctl preset remove --name no-jellyfin EOF } # ============================================ # Run # ============================================ function cmd::preset::run() { local subcmd="${1:-help}" shift || true case "$subcmd" in list|ls) cmd::preset::list "$@" ;; add|new|create) cmd::preset::add "$@" ;; remove|rm|del|delete) cmd::preset::remove "$@" ;; help) cmd::preset::help ;; *) log::error "Unknown subcommand: '${subcmd}'" cmd::preset::help return 1 ;; esac } # ============================================ # List # ============================================ function cmd::preset::list() { local dir dir="$(ctx::presets)" local presets=("${dir}"/*.preset) if [[ ! -f "${presets[0]}" ]]; then log::wg_preset "No presets configured" return 0 fi log::section "Available Presets" printf "\n %-25s %-40s %s\n" "NAME" "DESCRIPTION" "RULES" printf " %s\n" "$(printf '─%.0s' {1..75})" for preset_file in "${dir}"/*.preset; do [[ -f "$preset_file" ]] || continue # Reset vars before sourcing local PRESET_NAME="" PRESET_DESC="" local BLOCK_IPS="" BLOCK_SUBNETS="" BLOCK_PORTS="" source "$preset_file" local rules="" [[ -n "$BLOCK_IPS" ]] && rules+="IPs:$(echo "$BLOCK_IPS" | wc -w) " [[ -n "$BLOCK_SUBNETS" ]] && rules+="Subnets:$(echo "$BLOCK_SUBNETS" | wc -w) " [[ -n "$BLOCK_PORTS" ]] && rules+="Ports:$(echo "$BLOCK_PORTS" | wc -w)" printf " %-25s %-40s %s\n" \ "$PRESET_NAME" \ "${PRESET_DESC:-—}" \ "${rules:-—}" done printf "\n" } # ============================================ # Add # ============================================ function cmd::preset::add() { local name="" local desc="" local block_ips=() local block_subnets=() local block_ports=() while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --desc) desc="$2"; shift 2 ;; --block-ip) block_ips+=("$2"); shift 2 ;; --block-subnet) block_subnets+=("$2"); shift 2 ;; --block-port) block_ports+=("$2"); shift 2 ;; --help) cmd::preset::help; return ;; *) log::error "Unknown flag: $1" cmd::preset::help return 1 ;; esac done if [[ -z "$name" ]]; then log::error "Missing required flag: --name" return 1 fi if [[ ${#block_ips[@]} -eq 0 && ${#block_subnets[@]} -eq 0 && ${#block_ports[@]} -eq 0 ]]; then log::error "At least one of --block-ip, --block-subnet, or --block-port is required" return 1 fi local preset_file preset_file="$(ctx::preset::path "${name}.preset")" if [[ -f "$preset_file" ]]; then log::error "Preset already exists: ${name}" return 1 fi cat > "$preset_file" <