mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-18 05:02:15 +03:00
bin/restore-policies.sh used readarray (bash 4+), which fails on macOS bash 3.2. Replace with a compatible while-read loop. machineId.test.ts disableWindowsRegistryStrategy() did not neutralize the macOS ioreg strategy, so mocked os.hostname() was never reached on macOS and both ladder tests failed. Stub execSync for ioreg commands so the fallback chain reaches os.hostname() as intended. Production src/shared/utils/machineId.ts is correct and unchanged. Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
79 lines
3.0 KiB
Bash
Executable File
79 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# bin/restore-policies.sh — restore ONLY the API-key policy tables from a
|
|
# snapshot, leaving request/audit/runtime state intact. Used by the auth-layer
|
|
# incident-recovery flow when policies_active is empty
|
|
# but the rest of the database is healthy (so a full restore-data is overkill).
|
|
#
|
|
# "Policy" tables = api_key* definition tables (the key + its limits/allowed
|
|
# quotas/context sources), EXCLUDING usage counters and reset logs so a restore
|
|
# never rewinds live usage accounting.
|
|
set -euo pipefail
|
|
SCRIPT_NAME="restore-policies"
|
|
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/_ops-common.sh"
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: bin/restore-policies.sh <snapshot-id> [--data-dir <path>] [--yes|-y] [-h|--help]
|
|
|
|
Replaces the API-key policy tables (api_key*, excluding *counter* / *_log*) in
|
|
the live DB with the copies from a snapshot, inside one transaction. The live DB
|
|
is snapshotted to $DB_BACKUPS_DIR/pre-policy-restore_<UTC> first. Requires sqlite3.
|
|
EOF
|
|
}
|
|
|
|
ID=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--yes | -y) ASSUME_YES=1; shift ;;
|
|
--data-dir) ops_set_data_dir "${2:?--data-dir needs a value}"; shift 2 ;;
|
|
-h | --help) usage; exit 0 ;;
|
|
-*) ops_die "unknown argument: $1 (see --help)" ;;
|
|
*) ID="$1"; shift ;;
|
|
esac
|
|
done
|
|
|
|
[ -n "$ID" ] || ops_die "snapshot id required (see --help)"
|
|
ops_require_cmd sqlite3
|
|
snap="$(ops_find_snapshot "$ID")"
|
|
[ -f "$OMNIROUTE_SQLITE" ] || ops_die "no live DB at $OMNIROUTE_SQLITE (use restore-data.sh for a full restore)"
|
|
|
|
# Policy definition tables present in BOTH the snapshot and the live DB. GLOB
|
|
# keeps `_` literal; we drop usage counters / logs so accounting isn't rewound.
|
|
tables=()
|
|
while IFS= read -r t; do tables+=("$t"); done < <(
|
|
sqlite3 "$snap/storage.sqlite" \
|
|
"SELECT name FROM sqlite_master WHERE type='table' AND name GLOB 'api_key*' \
|
|
AND name NOT GLOB '*counter*' AND name NOT GLOB '*_log*' ORDER BY name;"
|
|
)
|
|
[ "${#tables[@]}" -gt 0 ] || ops_die "snapshot has no api_key* policy tables"
|
|
|
|
ops_log "policy tables to restore: ${tables[*]}"
|
|
ops_confirm "Replace ${#tables[@]} policy table(s) in $OMNIROUTE_SQLITE from $snap?" || ops_die "aborted"
|
|
|
|
# Safety snapshot of the live DB before mutating it.
|
|
safety="$OMNIROUTE_BACKUPS_DIR/pre-policy-restore_$(date -u +%Y%m%dT%H%M%SZ)"
|
|
mkdir -p "$safety"
|
|
sqlite3 "$OMNIROUTE_SQLITE" "VACUUM INTO '$safety/storage.sqlite'"
|
|
ops_log "live DB saved to $safety"
|
|
|
|
# Replace each policy table inside a single transaction, attaching the snapshot
|
|
# (only tables that also exist in the live DB are touched).
|
|
sql="ATTACH DATABASE '$snap/storage.sqlite' AS snap;
|
|
PRAGMA foreign_keys=OFF;
|
|
BEGIN;"
|
|
for t in "${tables[@]}"; do
|
|
if [ -n "$(sqlite3 "$OMNIROUTE_SQLITE" "SELECT 1 FROM sqlite_master WHERE type='table' AND name='$t' LIMIT 1;")" ]; then
|
|
sql="$sql
|
|
DELETE FROM main.\"$t\";
|
|
INSERT INTO main.\"$t\" SELECT * FROM snap.\"$t\";"
|
|
else
|
|
ops_log "skipping '$t' — not present in live DB"
|
|
fi
|
|
done
|
|
sql="$sql
|
|
COMMIT;
|
|
DETACH DATABASE snap;"
|
|
|
|
printf '%s\n' "$sql" | sqlite3 "$OMNIROUTE_SQLITE"
|
|
ops_log "policies restored from $snap — restart OmniRoute to apply"
|