#!/usr/bin/env bash # Analyze NPMplus certificates and identify duplicates # Uses Node.js to query database directly set -euo pipefail # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } PROXMOX_HOST="${1:-192.168.11.11}" CONTAINER_ID="${2:-10233}" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "🔍 NPMplus Certificate Analysis" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Query certificates log_info "Querying certificates from database..." CERT_JSON=$(ssh root@"$PROXMOX_HOST" "pct exec $CONTAINER_ID -- docker exec npmplus node -e \" const Database = require('better-sqlite3'); const db = new Database('/data/npmplus/database.sqlite', { readonly: true }); const certs = db.prepare('SELECT id, domain_names, provider, expires_on, created_on, is_deleted FROM certificate WHERE is_deleted = 0 ORDER BY id').all(); console.log(JSON.stringify(certs)); db.close(); \" 2>&1" || echo "[]") if [ "$CERT_JSON" = "[]" ] || [ -z "$CERT_JSON" ]; then log_warn "No certificates found" exit 0 fi CERT_COUNT=$(echo "$CERT_JSON" | jq 'length' 2>/dev/null || echo "0") log_info "Found $CERT_COUNT certificates" echo "" # Display all certificates echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "📋 All Certificates:" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" declare -A CERT_GROUPS declare -A CERT_DETAILS echo "$CERT_JSON" | jq -c '.[]' 2>/dev/null | while IFS= read -r cert; do cert_id=$(echo "$cert" | jq -r '.id') domain_names=$(echo "$cert" | jq -r '.domain_names' | jq -r 'join(",")' 2>/dev/null || echo "") provider=$(echo "$cert" | jq -r '.provider') expires_on=$(echo "$cert" | jq -r '.expires_on') created_on=$(echo "$cert" | jq -r '.created_on') echo " ID: $cert_id" echo " Domains: $domain_names" echo " Provider: $provider" echo " Expires: $expires_on" echo " Created: $created_on" echo "" # Normalize for grouping normalized=$(echo "$domain_names" | tr '[:upper:]' '[:lower:]' | tr ',' ' ' | xargs -n1 | sort | xargs | tr ' ' ',') if [ -z "${CERT_GROUPS[$normalized]:-}" ]; then CERT_GROUPS[$normalized]="$cert_id" else CERT_GROUPS[$normalized]="${CERT_GROUPS[$normalized]},$cert_id" fi CERT_DETAILS[$cert_id]="$domain_names|$provider|$expires_on|$created_on" done # Analyze duplicates echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "🔍 Duplicate Analysis:" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" # Use a temporary file to store results since we're in a subshell TEMP_FILE=$(mktemp) echo "$CERT_JSON" > "$TEMP_FILE" # Analyze for duplicates DUPLICATES=$(echo "$CERT_JSON" | jq -r 'group_by(.domain_names | tostring) | map(select(length > 1)) | .[] | "\(.[0].domain_names | tostring)|\(map(.id) | join(","))"' 2>/dev/null || echo "") if [ -z "$DUPLICATES" ]; then log_success "✅ No duplicate certificates found!" rm -f "$TEMP_FILE" exit 0 fi duplicate_count=0 echo "$DUPLICATES" | while IFS='|' read -r domains cert_ids; do duplicate_count=$((duplicate_count + 1)) cert_array=(${cert_ids//,/ }) log_warn "Duplicate certificates found:" log_info " Domains: $domains" log_info " Certificate IDs: $cert_ids" echo "" # Find best certificate to keep (most recent) best_id="" best_created="" for cert_id in "${cert_array[@]}"; do cert_info=$(echo "$CERT_JSON" | jq -r ".[] | select(.id == $cert_id) | \"\(.id)|\(.created_on)\"" 2>/dev/null || echo "") IFS='|' read -r id created <<< "$cert_info" if [ -z "$best_id" ] || [ "$created" \> "$best_created" ]; then best_id="$id" best_created="$created" fi done log_success " → Keep Certificate ID: $best_id (created: $best_created)" for cert_id in "${cert_array[@]}"; do if [ "$cert_id" != "$best_id" ]; then log_warn " → Delete Certificate ID: $cert_id" fi done echo "" done rm -f "$TEMP_FILE" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" log_info "Summary:" log_info " Total certificates: $CERT_COUNT" log_warn " Duplicates found - see analysis above" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo ""