function cmd::remove::run() { local name="" local type="" local force=false while [[ $# -gt 0 ]]; do case "$1" in --name) name="$2"; shift 2 ;; --type) type="$2"; shift 2 ;; --force) force=true; shift ;; --help) cmd::remove::help; return ;; *) log::error "Unknown flag: $1" cmd::remove::help return 1 ;; esac done if [[ -z "$name" ]]; then log::error "Missing required flag: --name" cmd::remove::help return 1 fi name=$(peers::resolve_and_require "$name" "$type") || return 1 # Confirmation prompt unless --force if ! $force; then read -r -p "Are you sure you want to permanently remove '${name}'? [y/N] " confirm case "$confirm" in [yY][eE][sS]|[yY]) ;; *) log::info "Aborted" return 0 ;; esac fi log::section "Removing client: ${name}" # Extract IP before removing anything local client_ip client_ip=$(grep "^Address" "$(ctx::clients)/${name}.conf" 2>/dev/null | awk '{print $3}' | cut -d'/' -f1) local was_blocked=false peers::is_blocked "$name" && was_blocked=true # Unapply rule if assigned local assigned_rule assigned_rule=$(peers::get_meta "$name" "rule") if [[ -z "$assigned_rule" ]]; then assigned_rule=$(peers::default_rule "$name") fi if [[ -n "$assigned_rule" ]] && [[ -n "$client_ip" ]]; then rule::unapply "$assigned_rule" "$client_ip" fi # Remove peer from server config peers::remove_from_server "$name" || return 1 # Remove client config peers::remove_client_config "$name" || return 1 # Remove keys keys::remove "$name" || return 1 # Remove block rules only if client was fully blocked if [[ -n "$client_ip" ]] && $was_blocked; then firewall::unblock_all "$client_ip" fi firewall::remove_block_file "$name" 2>/dev/null || true # If this was a guest type, check if any guests remain # If no guests left, remove guest firewall rules local type type=$(echo "$name" | cut -d'-' -f1) if [[ "$type" == "guest" ]]; then local remaining_guests=0 local guest_confs=("$(ctx::clients)"/guest-*.conf) if [[ -f "${guest_confs[0]}" ]]; then remaining_guests=${#guest_confs[@]} fi if [[ "$remaining_guests" -eq 0 ]]; then firewall::remove_guest_rules log::wg "No guests remaining — removed guest firewall rules" fi fi peers::remove_meta "$name" 2>/dev/null || true # Reload WireGuard peers::reload || return 1 log::wg_success "Client removed: ${name}" }