mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
feat: describe device authorization requests
This commit is contained in:
parent
70c67b9c01
commit
8b930d207e
2 changed files with 30 additions and 0 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import sys
|
||||
import webbrowser
|
||||
from typing import Annotated, NoReturn
|
||||
|
|
@ -9,6 +10,7 @@ from typing import Annotated, NoReturn
|
|||
from cyclopts import Parameter
|
||||
from rich.status import Status
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.cli.deploy.authentication import (
|
||||
DeviceAuthorizationDeniedError,
|
||||
DeviceAuthorizationError,
|
||||
|
|
@ -25,6 +27,7 @@ from fastmcp.cli.deploy.credentials import (
|
|||
)
|
||||
from fastmcp.cli.deploy.horizon_client import (
|
||||
DeviceAuthorization,
|
||||
DeviceMetadata,
|
||||
HorizonClient,
|
||||
HorizonResponseError,
|
||||
HorizonUnauthorizedError,
|
||||
|
|
@ -64,6 +67,15 @@ def _can_open_browser() -> bool:
|
|||
return sys.stdin.isatty() and sys.stdout.isatty()
|
||||
|
||||
|
||||
def _device_metadata() -> DeviceMetadata:
|
||||
return DeviceMetadata(
|
||||
device_name=platform.node() or None,
|
||||
platform=platform.system().lower() or None,
|
||||
architecture=platform.machine().lower() or None,
|
||||
client_version=fastmcp.__version__,
|
||||
)
|
||||
|
||||
|
||||
def _fail(
|
||||
command: CommandName,
|
||||
category: ErrorCategory,
|
||||
|
|
@ -193,6 +205,7 @@ async def login(
|
|||
async with HorizonClient(configuration.api_origin) as client:
|
||||
return await authorize_device(
|
||||
client,
|
||||
metadata=_device_metadata(),
|
||||
on_challenge=show_challenge,
|
||||
open_browser=not json_output and _can_open_browser(),
|
||||
browser_opener=webbrowser.open,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
from collections.abc import Callable
|
||||
from unittest.mock import Mock
|
||||
from urllib.parse import parse_qs
|
||||
|
||||
import httpx2
|
||||
import pytest
|
||||
|
|
@ -111,6 +112,10 @@ async def test_json_login_writes_one_result_and_challenge_to_stderr(
|
|||
use_horizon_api(api)
|
||||
browser_open = Mock()
|
||||
monkeypatch.setattr(command_module.webbrowser, "open", browser_open)
|
||||
monkeypatch.setattr(command_module.platform, "node", lambda: "Avery's laptop")
|
||||
monkeypatch.setattr(command_module.platform, "system", lambda: "Darwin")
|
||||
monkeypatch.setattr(command_module.platform, "machine", lambda: "arm64")
|
||||
monkeypatch.setattr(command_module.fastmcp, "__version__", "4.0.0")
|
||||
|
||||
await login(json_output=True)
|
||||
|
||||
|
|
@ -135,6 +140,18 @@ async def test_json_login_writes_one_result_and_challenge_to_stderr(
|
|||
"userCode": "ABCD-EFGH",
|
||||
}
|
||||
browser_open.assert_not_called()
|
||||
authorization_request = next(
|
||||
request
|
||||
for request in api.requests
|
||||
if request.url.path == "/api/v0/oauth/device/authorization"
|
||||
)
|
||||
assert parse_qs(authorization_request.content.decode()) == {
|
||||
"client_id": ["fastmcp-cli"],
|
||||
"device_name": ["Avery's laptop"],
|
||||
"platform": ["darwin"],
|
||||
"architecture": ["arm64"],
|
||||
"client_version": ["4.0.0"],
|
||||
}
|
||||
|
||||
state = json.loads(CredentialStore().path.read_text())
|
||||
assert state == {"schemaVersion": 1, "apiKey": "fmcp_device_key"}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue