Share admin dashboard views through isolated read-only visitor access

This commit is contained in:
Codex
2026-09-22 20:18:00 -04:00
parent 7e19d82a02
commit 210b715a6f
6 changed files with 152 additions and 26 deletions
+17 -3
View File
@@ -3,6 +3,7 @@ import importlib.util
import json
import threading
import unittest
from unittest.mock import patch
import urllib.error
import urllib.request
from pathlib import Path
@@ -22,7 +23,11 @@ class SpectatorTests(unittest.TestCase):
('social-1', ['A', 'B'], 'SYNTHETIC_PROMPT'),
('social-1:reply', ['A', 'B'], 'Hello friend'),
('social-2:reply', ['HumanPlayer', 'A'], 'NOT_BOT_CHAT')]]
projected = m.project({'bots': bots, 'settings': {'token': 'SECRET'}, 'community': {'feed': feed}})
source={'bots': bots, 'settings': {'token': 'SECRET'}, 'community': {'feed': feed}}
projected = m.project(source)
public = m.public_state(source)
for forbidden in ['PRIVATE_MEMORY','PRIVATE_WHISPER','SYNTHETIC_PROMPT','NOT_BOT_CHAT','SECRET','accountId']:
self.assertNotIn(forbidden,json.dumps(public))
serialized = json.dumps(projected)
for private in ['PRIVATE_MEMORY', 'PRIVATE_WHISPER', 'SYNTHETIC_PROMPT', 'NOT_BOT_CHAT', 'HumanPlayer', 'SECRET', 'accountId', 'internal-guid']:
self.assertNotIn(private, serialized)
@@ -35,18 +40,27 @@ class SpectatorTests(unittest.TestCase):
worker.start()
base = 'http://127.0.0.1:' + str(server.server_port)
try:
for route in ['/', '/app.js', '/style.css', '/health']:
for route in ['/app.js', '/style.css', '/health']:
with urllib.request.urlopen(base + route) as response:
self.assertEqual(response.status, 200)
self.assertIn("default-src 'none'", response.headers['Content-Security-Policy'])
for path in ['/api/state', '/api/actions', '/api/ale/operator', '/api/operations', '/.dev.vars', '/../.dev.vars', '/%2e%2e/.dev.vars', '//api/state']:
for path in ['/api/actions', '/api/ale/operator', '/.dev.vars', '/../.dev.vars', '/%2e%2e/.dev.vars', '/api/bridge/ale/poll', '/assets/../../.dev.vars', '/assets/private.map']:
with self.assertRaises(urllib.error.HTTPError) as error:
urllib.request.urlopen(base + path)
self.assertEqual(error.exception.code, 404)
error.exception.close()
with patch.object(m,'local_get',return_value=b'<html>Visitor</html>') as upstream:
with urllib.request.urlopen(base+'/') as response:
self.assertEqual(response.read(),b'<html>Visitor</html>')
upstream.assert_called_once_with('/visitor')
with patch.object(m.SNAPSHOT,'get',return_value={'state':{'bots':[]}}):
with urllib.request.urlopen(base+'/api/state') as response:
self.assertEqual(json.load(response),{'bots':[]})
for method in ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'TRACE']:
with self.assertRaises(urllib.error.HTTPError) as error:
urllib.request.urlopen(urllib.request.Request(base + '/api/actions', method=method, data=b'{}'))
self.assertEqual(error.exception.code, 405)
error.exception.close()
finally:
server.shutdown()
server.server_close()