#!/usr/bin/env bash
# ArchForge External Status 1.0.6 - ArchForge-based admin login recovery.
# Never resets admin accounts, sessions, tokens, Caddy or SQLite data.
set -Eeuo pipefail
umask 077
log(){ printf '[*] %s\n' "$*"; }
fail(){ printf '[ERROR] %s\n' "$*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || fail 'Run as root: bash ./repair-admin-login.sh'
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
[[ -f "$ROOT/package.json" && -f "$ROOT/src/server.js" ]] || fail 'Start from your ArchForge checkout'
[[ "$(/usr/bin/node -p 'require(process.argv[1]).version' "$ROOT/package.json")" == '1.0.6' ]] || fail 'ArchForge checkout is not 1.0.6; commit/push/pull the update first'
[[ "$ROOT" != '/opt/archforge-status/app' ]] || fail 'Run this from the ArchForge checkout, not from /opt'
CFG=/etc/archforge-status/status.env
[[ -f "$CFG" && ! -L "$CFG" ]] || fail 'Missing /etc/archforge-status/status.env'
[[ -r "$ROOT/scripts/domain-lib.sh" ]] || fail 'Missing domain configuration helper'
source "$ROOT/scripts/domain-lib.sh"
DOMAIN='status.archforge.nl'
if ! grep -Eqs "^[[:space:]]*${DOMAIN//./\\.}[[:space:]]*\\{" /etc/caddy/Caddyfile /etc/caddy/conf.d/*.caddy 2>/dev/null; then
  fail 'Caddy is not configured for status.archforge.nl; no changes made'
fi
if ! curl --fail --silent --show-error --max-time 5 http://127.0.0.1:3000/healthz >/dev/null;then
  fail 'Status service unavailable on 127.0.0.1:3000; check systemctl status archforge-status'
fi
SNAP=$(mktemp -d /root/.archforge-login-repair.XXXXXXXX)
cp -a -- "$CFG" "$SNAP/status.env"
log "Private .env backup created ($SNAP/status.env)"
CURRENT=$(grep -m1 '^STATUS_PUBLIC_URL=' "$CFG" | cut -d= -f2- || true)
if [[ "$CURRENT" != "https://$DOMAIN" && "$CURRENT" != "https://$DOMAIN/" ]];then
  log 'Synchronizing public URL with the Caddy HTTPS domain'
  af_set_public_domain "$CFG" "$DOMAIN" || fail 'Cannot safely update public URL'
fi
log 'Deploying version 1.0.6 via the existing backup/rollback installer'
if ! bash "$ROOT/scripts/deploy.sh" "$ROOT";then
  log 'Deployment failed; restoring the previous status.env'
  cp -a -- "$SNAP/status.env" "$CFG"
  systemctl restart archforge-status || true
  fail 'Deployment was rolled back. The old release should still be in service.'
fi
version=$(curl --fail --silent --show-error --max-time 5 http://127.0.0.1:3000/healthz | /usr/bin/node -p 'try { JSON.parse(require("fs").readFileSync(0,"utf8")).version } catch { "" }')
[[ "$version" == '1.0.6' ]] || fail "Installed version verification failed (${version:-unknown}); inspect journalctl -u archforge-status"
log 'Running safe login tests locally (no passwords or 2FA codes needed)'
# Reuse a freshly issued double-submit cookie, with a dummy username.
curl --silent --show-error --max-time 5 -D "$SNAP/headers" -o /dev/null http://127.0.0.1:3000/admin/login
CSRF=$(sed -nE 's/^[Ss]et-[Cc]ookie: af_csrf=([^;]+).*/\1/p' "$SNAP/headers" | tr -d '\r' | head -n 1)
[[ "$CSRF" =~ ^[A-Za-z0-9_-]{32,100}$ ]] || fail 'Could not obtain form token from local status app'
post_login(){
  local output_name=$1 site=$2 origin=$3 expected=$4 code
  code=$(curl --silent --show-error --max-time 6 -o "$SNAP/$output_name" -w '%{http_code}' \
    -H "Cookie: af_csrf=$CSRF" \
    -H "Origin: $origin" \
    -H "Sec-Fetch-Site: $site" \
    -H 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode "csrf=$CSRF" \
    --data-urlencode 'username=__archforge_test_nonexistent__' \
    --data-urlencode 'password=never-a-valid-password' \
    --data-urlencode 'totp=000000' \
    http://127.0.0.1:3000/admin/login)
  [[ "$code" == "$expected" ]] || fail "Login $output_name returned HTTP $code (expected $expected); inspect installed version and logs"
}
post_login canonical 'same-origin' "https://$DOMAIN" 401
post_login privacy 'same-origin' 'null' 401
post_login blocked 'cross-site' "https://$DOMAIN" 403
log 'PASS: canonical and privacy-protected same-origin login reach credential validation'
log 'PASS: cross-site login is still blocked; CSRF verification remains mandatory'
log 'Installed release: 1.0.6. Refresh https://status.archforge.nl/admin/login and try again.'
log 'No credentials, monitoring database or Caddy configuration changed.'
