fix: align external pool POST and stats responses with external API contract

This commit is contained in:
胡绍康 committed 2026-03-17 10:40:14 +08:00
1 parent 0c0dc40750
commit 6d95c74272
4 files changed
+60 -25

No files matched your search

+1 -1
View File
@@ -134,7 +134,7 @@ def create_app(*, autostart_scheduler: Optional[bool] = None):
app.register_blueprint(system.create_blueprint())
app.register_blueprint(audit.create_blueprint())
app.register_blueprint(pool.create_blueprint())
app.register_blueprint(external_pool.create_blueprint())
app.register_blueprint(external_pool.create_blueprint(csrf_exempt=csrf_exempt))
# 打印初始化信息
print("=" * 60)
+1 -2
View File
@@ -272,10 +272,9 @@ def get_stats(conn: sqlite3.Connection) -> dict:
"cooldown": 0,
"frozen": 0,
"retired": 0,
"not_in_pool": 0,
}
for row in rows:
key = row["pool_status"] if row["pool_status"] is not None else "not_in_pool"
key = row["pool_status"]
if key in pool_counts:
pool_counts[key] = row["cnt"]
+29 -21
View File
@@ -1,30 +1,38 @@
from __future__ import annotations
from typing import Callable, Optional
from flask import Blueprint
from outlook_web.controllers import external_pool as external_pool_controller
def create_blueprint() -> Blueprint:
def create_blueprint(csrf_exempt: Optional[Callable] = None) -> Blueprint:
bp = Blueprint("external_pool", __name__)
bp.add_url_rule(
"/api/external/pool/claim-random",
view_func=external_pool_controller.api_external_pool_claim_random,
methods=["POST"],
)
bp.add_url_rule(
"/api/external/pool/claim-release",
view_func=external_pool_controller.api_external_pool_claim_release,
methods=["POST"],
)
bp.add_url_rule(
"/api/external/pool/claim-complete",
view_func=external_pool_controller.api_external_pool_claim_complete,
methods=["POST"],
)
bp.add_url_rule(
"/api/external/pool/stats",
view_func=external_pool_controller.api_external_pool_stats,
methods=["GET"],
)
handlers = [
(
"/api/external/pool/claim-random",
external_pool_controller.api_external_pool_claim_random,
["POST"],
),
(
"/api/external/pool/claim-release",
external_pool_controller.api_external_pool_claim_release,
["POST"],
),
(
"/api/external/pool/claim-complete",
external_pool_controller.api_external_pool_claim_complete,
["POST"],
),
(
"/api/external/pool/stats",
external_pool_controller.api_external_pool_stats,
["GET"],
),
]
for path, handler, methods in handlers:
view_func = csrf_exempt(handler) if csrf_exempt else handler
bp.add_url_rule(path, view_func=view_func, methods=methods)
return bp
+29 -1
View File
@@ -161,6 +161,30 @@ class ExternalPoolApiTests(unittest.TestCase):
self.assertIn("claim_token", payload)
self.assertIn("lease_expires_at", payload)
def test_external_pool_post_does_not_require_csrf(self):
client = self.app.test_client()
self._set_external_api_key("abc123")
with self.app.app_context():
from outlook_web.repositories import settings as settings_repo
settings_repo.set_setting("pool_external_enabled", "true")
self._insert_pool_account(provider="outlook")
resp = client.post(
"/api/external/pool/claim-random",
headers=self._auth_headers(),
json={
"caller_id": "csrf-free-worker",
"task_id": "csrf-free-task",
"provider": "outlook",
},
)
self.assertEqual(resp.status_code, 200)
data = resp.get_json()
self.assertTrue(data.get("success"))
self.assertEqual(data.get("code"), "OK")
def test_external_pool_claim_release_caller_mismatch(self):
client = self.app.test_client()
self._set_external_api_key("abc123")
@@ -254,7 +278,11 @@ class ExternalPoolApiTests(unittest.TestCase):
data = resp.get_json()
self.assertTrue(data.get("success"))
self.assertEqual(data.get("code"), "OK")
self.assertIn("pool_counts", data.get("data", {}))
pool_counts = data.get("data", {}).get("pool_counts", {})
self.assertEqual(
set(pool_counts.keys()),
{"available", "claimed", "used", "cooldown", "frozen", "retired"},
)
def test_external_pool_stats_returns_feature_disabled_when_switch_off(self):
client = self.app.test_client()