Files
chenlin f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00

164 lines
7.3 KiB
Python

import asyncio
import time
import unittest
from unittest.mock import AsyncMock, patch
from aiohttp.test_utils import TestClient, TestServer
from decision_server.server import PREFIX
from decision_server.tests.test_service import plan_value, request_value
from decision_server.tests.test_web_config import config
from decision_server.web_config import COOKIE
from decision_server.web_server import CATALOG, MANAGER, create_website_app
from decision_server.web_sessions import Limits
class WebsiteTests(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.origin = "https://site.test"
self.app = create_website_app(self.origin)
self.client = TestClient(TestServer(self.app))
await self.client.start_server()
self.manager = self.app[MANAGER]
self.app[CATALOG].refresh = AsyncMock()
self.headers = {"Host": "site.test", "Origin": self.origin}
async def asyncTearDown(self):
await self.client.close()
async def visitor(self):
response = await self.client.post(PREFIX + "/session", json={}, headers=self.headers)
self.assertEqual(response.status, 200)
value = await response.json()
cookie = response.cookies[COOKIE]
self.assertTrue(cookie["httponly"])
self.assertTrue(cookie["secure"])
self.assertEqual(cookie["samesite"], "Strict")
self.assertEqual(cookie["domain"], "")
return {
**self.headers,
"Cookie": COOKIE + "=" + cookie.value,
"X-CSRF-Token": value["csrfToken"],
"X-Config-Version": "0",
}, self.manager.values[cookie.value]
async def save(self, headers):
response = await self.client.put(PREFIX + "/configuration", json=config(), headers=headers)
self.assertEqual(response.status, 200, await response.text())
headers["X-Config-Version"] = response.headers["X-Config-Version"]
return await response.json()
async def test_boundary_no_cookie_csrf_origin_host_or_cross_site(self):
response = await self.client.get(PREFIX + "/status", headers=self.headers)
self.assertEqual(response.status, 401)
headers, _ = await self.visitor()
for patch_headers in (
{"Origin": "https://evil.test"},
{"Origin": ""},
{"Host": "evil.test"},
{"X-CSRF-Token": "bad"},
{"Sec-Fetch-Site": "same-site"},
):
response = await self.client.put(
PREFIX + "/configuration", json=config(), headers={**headers, **patch_headers}
)
self.assertEqual(response.status, 403)
self.assertNotIn("Access-Control-Allow-Origin", response.headers)
self.assertEqual(response.headers["Cache-Control"], "no-store")
response = await self.client.post(
PREFIX + "/session", json={}, headers={"Host": "site.test"}
)
self.assertEqual(response.status, 403)
async def test_atomic_credentials_no_metadata_files_and_stale_tab(self):
a, av = await self.visitor()
b, bv = await self.visitor()
result = await self.save(a)
self.assertNotIn("secret-fixture", str(result))
self.assertFalse(bv.service.connections.values)
self.assertFalse(hasattr(av.service.connections, "path"))
response = await self.client.put(
PREFIX + "/configuration", json=config(), headers={**a, "X-Config-Version": "0"}
)
self.assertEqual(response.status, 409)
bad = config()
bad["jev"]["apiKey"] = "invalid key"
response = await self.client.put(PREFIX + "/configuration", json=bad, headers=a)
self.assertEqual(response.status, 400)
self.assertEqual(av.service.connections.values["jev"].key, "jev-secret-fixture")
response = await self.client.get(PREFIX + "/status", headers=b)
self.assertFalse((await response.json())["ready"])
async def test_two_visitors_identical_request_ids_and_cancel_isolation(self):
a, av = await self.visitor()
b, bv = await self.visitor()
await self.save(a)
await self.save(b)
started = asyncio.Event()
release = asyncio.Event()
async def provider(*_):
started.set()
await release.wait()
return plan_value(), {}
with patch("decision_server.providers.openai.plan", side_effect=provider):
pending = asyncio.create_task(
self.client.post(PREFIX + "/plan", json=request_value(), headers=b)
)
await asyncio.wait_for(started.wait(), 2)
response = await self.client.post(
PREFIX + "/cancel", json={"runId": "run1", "requestId": "r1"}, headers=a
)
self.assertFalse((await response.json())["cancelled"])
self.assertEqual(len(bv.service.active), 1)
await self.client.delete(PREFIX + "/session", headers=a)
self.assertTrue(av.closed)
self.assertTrue(bv.service.connections.values)
release.set()
self.assertEqual((await pending).status, 200)
self.assertEqual(self.manager.inference, 0)
async def test_ttl_status_does_not_refresh_and_credentials_destroyed(self):
headers, visitor = await self.visitor()
await self.save(headers)
touched = visitor.touched
await self.client.get(PREFIX + "/status", headers=headers)
await self.client.post(PREFIX + "/session", json={}, headers=headers)
self.assertEqual(visitor.touched, touched)
visitor.touched = time.monotonic() - 1801
response = await self.client.get(PREFIX + "/status", headers=headers)
self.assertEqual(response.status, 401)
self.assertFalse(visitor.service.connections.values)
self.assertTrue(visitor.closed)
async def test_limits_ip_spoof_does_not_bypass_and_no_implicit_cli(self):
self.manager.limits = Limits(ip_sessions=2, codex=1)
a, av = await self.visitor()
b, bv = await self.visitor()
response = await self.client.post(
PREFIX + "/session", json={}, headers={**self.headers, "X-Real-IP": "1.2.3.4"}
)
self.assertEqual(response.status, 429)
self.manager.reserve_codex(av)
with self.assertRaisesRegex(Exception, "subscription_capacity"):
self.manager.reserve_codex(bv)
av.codex_reserved = False
with patch.object(av.service.codex, "start", new_callable=AsyncMock) as start:
response = await self.client.get(PREFIX + "/codex/status", headers=a)
self.assertFalse((await response.json())["loggedIn"])
start.assert_not_called()
await self.save(b)
self.manager.inference = self.manager.limits.inference
response = await self.client.post(PREFIX + "/plan", json=request_value(), headers=b)
self.assertEqual(response.status, 429)
self.manager.inference = 0
async def test_no_arbitrary_rpc_or_local_connection_or_queries(self):
headers, _ = await self.visitor()
for path in ("/connections", "/codex/exec", "/codex/rpc"):
response = await self.client.post(PREFIX + path, json={}, headers=headers)
self.assertIn(response.status, (404, 405))
response = await self.client.get(PREFIX + "/status?key=fixture", headers=headers)
self.assertEqual(response.status, 400)