#!/usr/bin/env bash
# v1.0.5 one-shot safe repair of admin POST 403 Invalid origin.
# Does not delete/recreate admin accounts, SQLite, monitoring or Caddy.
set -Eeuo pipefail
umask 077
say(){ printf '[*] %s\n' "$*"; }
fail(){ printf '[ERROR] %s\n' "$*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || fail 'Run this fix as root: bash ./fix-admin-origin.sh'
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
source "$ROOT/scripts/domain-lib.sh"
[[ -r "$ROOT/package.json" && -r "$ROOT/src/server.js" ]] || fail 'Missing status project source checkout'
/usr/bin/node -e 'if(require(process.argv[1]).version!=="1.0.5")process.exit(1)' "$ROOT/package.json" || fail 'Expected ArchForge checkout v1.0.5. Run git pull --ff-only first.'
CFG=/etc/archforge-status/status.env
[[ -f "$CFG" && ! -L "$CFG" ]] || fail 'Existing status.env not found (or unsafe symlink)'
[[ -f /etc/caddy/Caddyfile ]] || fail 'Caddyfile not found'
DOMAIN=status.archforge.nl
# Verify that this VPS actually has an intended HTTPS site for our domain.
if ! grep -Eqs "^[[:space:]]*${DOMAIN//./\\.}[[:space:]]*\\{" /etc/caddy/Caddyfile /etc/caddy/conf.d/*.caddy 2>/dev/null; then
  fail 'Caddy has no configured site for status.archforge.nl. Refusing to change public URL.'
fi
if ! curl -fsS --max-time 6 http://127.0.0.1:3000/healthz >/dev/null;then
  fail 'Installed status app is not running at localhost:3000. No changes made.'
fi
BACKUP=$(mktemp -d /root/.archforge-origin-fix.XXXXXXXX)
cp -a -- "$CFG" "$BACKUP/status.env"
say "Configuration backup: $BACKUP/status.env (private)"
CHANGED=false
CURRENT=$(grep -m1 '^STATUS_PUBLIC_URL=' "$CFG" | cut -d= -f2- || true)
if [[ "$CURRENT" != "https://$DOMAIN" && "$CURRENT" != "https://$DOMAIN/" ]]; then
  say "Synchronizing STATUS_PUBLIC_URL with Caddy's HTTPS domain."
  af_set_public_domain "$CFG" "$DOMAIN" || fail 'Failed updating STATUS_PUBLIC_URL'
  CHANGED=true
else
  say 'Configured public hostname already matches the domain.'
fi
say 'Deploying tested v1.0.5 code with built-in database backup and rollback...'
if ! bash "$ROOT/scripts/deploy.sh" "$ROOT";then
  say 'Code deployment failed. Restoring original status configuration.'
  cp -a -- "$BACKUP/status.env" "$CFG"
  systemctl restart archforge-status || true
  fail 'Deployment failed and configuration restored.'
fi
say 'Checking login POST through HTTPS without sending any credentials...'
# Invalid CSRF MUST be rejected, but valid Origin MUST NOT receive Invalid origin.
OUT=$(mktemp "$BACKUP/response.XXXXXXXX")
if ! curl -sS --max-time 12 --resolve "$DOMAIN:443:127.0.0.1" \
  -H "Origin: https://$DOMAIN" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'csrf=deliberately-invalid' "https://$DOMAIN/admin/login" > "$OUT";then
  say 'HTTPS local POST could not be verified; inspect Caddy/SSL separately.'
elif grep -q 'Invalid origin' "$OUT"; then
  fail 'Origin check still rejects canonical host; see service journal: journalctl -u archforge-status -n 50'
elif grep -q 'Invalid or expired form token' "$OUT"; then
  say 'PASS: same-origin login form reaches CSRF validation (as intended).'
else
  say 'The HTTPS response was received but its form result was unexpected; inspect the login page.'
fi
say 'Finished. Open https://status.archforge.nl/admin/login and sign in again.'
say 'All admin credentials, SQLite data and Caddy settings were preserved.'
