feat(mcp): câble le garde /_mcp + exemption CSRF dans l'app (scope B #111)
This commit is contained in:
+13
@@ -124,6 +124,19 @@ if _mcp_enabled:
|
||||
)
|
||||
import src.mcp.tools # noqa: E402,F401 # l'import enregistre les @mcp_enabled
|
||||
|
||||
# Les routes /_mcp existent maintenant : exempter du CSRF (POST JSON-RPC
|
||||
# externe sans jeton) puis brancher le garde d'abonnement.
|
||||
from src.mcp.auth import init_mcp_auth # noqa: E402
|
||||
|
||||
if _auth_csrf is not None:
|
||||
for _rule in app.server.url_map.iter_rules():
|
||||
if _rule.rule.startswith("/_mcp"):
|
||||
_vf = app.server.view_functions.get(_rule.endpoint)
|
||||
if _vf is not None:
|
||||
_auth_csrf.exempt(_vf)
|
||||
|
||||
init_mcp_auth(app.server)
|
||||
|
||||
from src.subscriptions.setup import init_subscriptions # noqa: E402
|
||||
|
||||
init_subscriptions(app.server)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import importlib
|
||||
|
||||
|
||||
def test_mcp_endpoint_guarded_and_csrf_exempt(monkeypatch, tmp_path):
|
||||
# DB éphémère + secrets requis par init_auth/init_subscriptions.
|
||||
monkeypatch.setenv("USERS_DB_PATH", str(tmp_path / "users.test.sqlite"))
|
||||
monkeypatch.setenv("SECRET_KEY", "test-secret-key")
|
||||
monkeypatch.setenv("APP_BASE_URL", "http://localhost:8050")
|
||||
monkeypatch.setenv("DASH_MCP_ENABLED", "true")
|
||||
|
||||
from src.auth import db as auth_db
|
||||
|
||||
auth_db.reset_conn_for_tests()
|
||||
|
||||
import src.app as app_module
|
||||
|
||||
app_module = importlib.reload(app_module)
|
||||
client = app_module.app.server.test_client()
|
||||
|
||||
# Pas de jeton : le garde renvoie 401 (et NON une erreur CSRF 400/403),
|
||||
# ce qui prouve exemption CSRF + garde câblés sur /_mcp.
|
||||
resp = client.post("/_mcp", json={"jsonrpc": "2.0", "method": "ping", "id": 1})
|
||||
assert resp.status_code == 401
|
||||
assert resp.headers.get("WWW-Authenticate") == 'Bearer realm="colibre-mcp"'
|
||||
|
||||
auth_db.reset_conn_for_tests()
|
||||
Reference in New Issue
Block a user