Spaces:
Running
Running
Commit ·
fdfa289
1
Parent(s): 7d9bf9a
add delete-user admin endpoint and manage_results command
Browse filesPOST /api/admin/clear-user removes all sessions and trials for a
named player without touching anyone else's data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- manage_results.sh +19 -1
- server.js +18 -1
manage_results.sh
CHANGED
|
@@ -44,7 +44,25 @@ elif [[ "$cmd" == "delete" ]]; then
|
|
| 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
|
|
|
|
| 44 |
"${auth_headers[@]}" "$HOST/api/admin/clear")
|
| 45 |
echo "Server responded: HTTP $http_code"
|
| 46 |
|
| 47 |
+
elif [[ "$cmd" == "delete-user" ]]; then
|
| 48 |
+
player="${2:-}"
|
| 49 |
+
if [[ -z "$player" ]]; then
|
| 50 |
+
read -rp "Player name to delete: " player
|
| 51 |
+
fi
|
| 52 |
+
read -rp "Delete all results for \"$player\"? Type YES to confirm: " confirm
|
| 53 |
+
if [[ "$confirm" != "YES" ]]; then echo "Aborted."; exit 0; fi
|
| 54 |
+
result=$(curl -sf -X POST \
|
| 55 |
+
"${auth_headers[@]}" \
|
| 56 |
+
-H "Content-Type: application/json" \
|
| 57 |
+
-d "{\"playerName\": \"$player\"}" \
|
| 58 |
+
"$HOST/api/admin/clear-user")
|
| 59 |
+
echo "$result" | python3 -c "
|
| 60 |
+
import sys, json
|
| 61 |
+
d = json.load(sys.stdin)
|
| 62 |
+
print(f\"Removed {d.get('removedSessions',0)} session(s) and {d.get('removedTrials',0)} trial(s) for \\\"$player\\\"\")
|
| 63 |
+
" 2>/dev/null || echo "$result"
|
| 64 |
+
|
| 65 |
else
|
| 66 |
+
echo "Usage: $0 <download|delete|delete-user [name]>"
|
| 67 |
exit 1
|
| 68 |
fi
|
server.js
CHANGED
|
@@ -132,12 +132,29 @@ app.get('/api/export', adminAuth, (req, res) => {
|
|
| 132 |
res.sendFile(DATA_FILE);
|
| 133 |
});
|
| 134 |
|
| 135 |
-
// POST /api/admin/clear — reset the data store (admin only)
|
| 136 |
app.post('/api/admin/clear', adminAuth, (req, res) => {
|
| 137 |
writeData({ sessions: [], trials: [] });
|
| 138 |
res.json({ ok: true, message: 'Results cleared' });
|
| 139 |
});
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
app.listen(PORT, () => {
|
| 142 |
console.log(`Microtubule Challenge → http://localhost:${PORT}`);
|
| 143 |
console.log(` Drop images into: images/real/ and images/fake/`);
|
|
|
|
| 132 |
res.sendFile(DATA_FILE);
|
| 133 |
});
|
| 134 |
|
| 135 |
+
// POST /api/admin/clear — reset the entire data store (admin only)
|
| 136 |
app.post('/api/admin/clear', adminAuth, (req, res) => {
|
| 137 |
writeData({ sessions: [], trials: [] });
|
| 138 |
res.json({ ok: true, message: 'Results cleared' });
|
| 139 |
});
|
| 140 |
|
| 141 |
+
// POST /api/admin/clear-user — remove all sessions and trials for one player (admin only)
|
| 142 |
+
app.post('/api/admin/clear-user', adminAuth, (req, res) => {
|
| 143 |
+
const { playerName } = req.body;
|
| 144 |
+
if (!playerName) return res.status(400).json({ error: 'playerName required' });
|
| 145 |
+
const data = readData();
|
| 146 |
+
const sessionsBefore = data.sessions.length;
|
| 147 |
+
const trialsBefore = data.trials.length;
|
| 148 |
+
data.sessions = data.sessions.filter(s => s.player_name !== playerName);
|
| 149 |
+
data.trials = data.trials.filter(t => t.player_name !== playerName);
|
| 150 |
+
writeData(data);
|
| 151 |
+
res.json({
|
| 152 |
+
ok: true,
|
| 153 |
+
removedSessions: sessionsBefore - data.sessions.length,
|
| 154 |
+
removedTrials: trialsBefore - data.trials.length
|
| 155 |
+
});
|
| 156 |
+
});
|
| 157 |
+
|
| 158 |
app.listen(PORT, () => {
|
| 159 |
console.log(`Microtubule Challenge → http://localhost:${PORT}`);
|
| 160 |
console.log(` Drop images into: images/real/ and images/fake/`);
|