Koddenbrock Claude Sonnet 4.6 commited on
Commit
7d9bf9a
·
1 Parent(s): ff50e8c

fix admin auth for private HF Space; add manage_results script

Browse files

The HF Space is private, so its proxy requires a valid HF token as the
Authorization Bearer header, preventing our ADMIN_TOKEN from reaching
Express. adminAuth now also accepts the token via X-Admin-Token header.
manage_results.sh sends both headers (HF_TOKEN as Bearer, ADMIN_TOKEN
as X-Admin-Token) so downloads and deletes work through the proxy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (3) hide show
  1. manage_results.sh +50 -0
  2. server.js +7 -2
  3. start.sh +32 -0
manage_results.sh ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+
6
+ # Load .env
7
+ if [[ -f "$SCRIPT_DIR/.env" ]]; then
8
+ set -a; source "$SCRIPT_DIR/.env"; set +a
9
+ else
10
+ echo "Error: .env file not found"; exit 1
11
+ fi
12
+
13
+ HOST="${DIFFMT_HOST:-https://htw-ki-werkstatt-diffmt.hf.space}"
14
+
15
+ # The Space is private, so HF's proxy requires a valid HF_TOKEN as Bearer.
16
+ # Our ADMIN_TOKEN travels in X-Admin-Token to avoid the conflict.
17
+ auth_headers=(-H "Authorization: Bearer ${HF_TOKEN}" -H "X-Admin-Token: ${ADMIN_TOKEN}")
18
+
19
+ cmd="${1:-}"
20
+
21
+ if [[ "$cmd" == "download" ]]; then
22
+ OUT="$SCRIPT_DIR/results_$(date +%Y%m%d_%H%M%S).json"
23
+ echo "Downloading results from $HOST …"
24
+ http_code=$(curl -sf -w "%{http_code}" -o "$OUT" \
25
+ "${auth_headers[@]}" "$HOST/api/export")
26
+ if [[ "$http_code" == "200" ]]; then
27
+ echo "Saved to $OUT"
28
+ python3 -c "
29
+ import json, sys
30
+ d = json.load(open('$OUT'))
31
+ print(f\"Sessions: {len(d.get('sessions',[]))}\")
32
+ print(f\"Trials: {len(d.get('trials',[]))}\")
33
+ "
34
+ else
35
+ rm -f "$OUT"
36
+ echo "Error: server returned HTTP $http_code"
37
+ exit 1
38
+ fi
39
+
40
+ elif [[ "$cmd" == "delete" ]]; then
41
+ read -rp "Delete ALL results on the server? Type YES to confirm: " confirm
42
+ if [[ "$confirm" != "YES" ]]; then echo "Aborted."; exit 0; fi
43
+ http_code=$(curl -sf -w "%{http_code}" -o /dev/null -X POST \
44
+ "${auth_headers[@]}" "$HOST/api/admin/clear")
45
+ echo "Server responded: HTTP $http_code"
46
+
47
+ else
48
+ echo "Usage: $0 <download|delete>"
49
+ exit 1
50
+ fi
server.js CHANGED
@@ -13,8 +13,13 @@ function adminAuth(req, res, next) {
13
  if (!ADMIN_TOKEN) {
14
  return res.status(503).json({ error: 'Admin access disabled: ADMIN_TOKEN not set' });
15
  }
16
- const auth = req.headers.authorization || '';
17
- if (auth !== `Bearer ${ADMIN_TOKEN}`) {
 
 
 
 
 
18
  return res.status(401).json({ error: 'Unauthorized' });
19
  }
20
  next();
 
13
  if (!ADMIN_TOKEN) {
14
  return res.status(503).json({ error: 'Admin access disabled: ADMIN_TOKEN not set' });
15
  }
16
+ // Accept token via Authorization Bearer OR X-Admin-Token header.
17
+ // The X-Admin-Token header is needed when the HF Space is private:
18
+ // HF's proxy requires a valid HF token as the Bearer header, so the
19
+ // admin token must travel in a separate header.
20
+ const bearer = (req.headers.authorization || '').replace(/^Bearer\s+/i, '');
21
+ const custom = req.headers['x-admin-token'] || '';
22
+ if (bearer !== ADMIN_TOKEN && custom !== ADMIN_TOKEN) {
23
  return res.status(401).json({ error: 'Unauthorized' });
24
  }
25
  next();
start.sh ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+ cd "$SCRIPT_DIR"
6
+
7
+ # Load .env if present
8
+ if [[ -f .env ]]; then
9
+ set -a; source .env; set +a
10
+ fi
11
+
12
+ # Locate node — try nvm, then Homebrew, then PATH
13
+ if [[ -z "$(command -v node 2>/dev/null)" ]]; then
14
+ [[ -s "$HOME/.nvm/nvm.sh" ]] && source "$HOME/.nvm/nvm.sh"
15
+ for p in /opt/homebrew/bin /usr/local/bin; do
16
+ [[ -x "$p/node" ]] && export PATH="$p:$PATH" && break
17
+ done
18
+ fi
19
+
20
+ NODE="$(command -v node 2>/dev/null)" \
21
+ || { echo "Error: node not found. Install Node.js and try again."; exit 1; }
22
+
23
+ # Use local data dir instead of HF bucket
24
+ export DATA_PATH="$SCRIPT_DIR/data/results.json"
25
+
26
+ PORT="${PORT:-3000}"
27
+ URL="http://localhost:$PORT"
28
+
29
+ echo "Starting DiffMT on $URL (node: $NODE)"
30
+ open "$URL" 2>/dev/null || true # open browser on macOS; silently skipped elsewhere
31
+
32
+ "$NODE" server.js