Skip to content

Commit d87e09c

Browse files
authored
Merge pull request #8 from dualentry/feat/user-agent
feat(user-agent): identify cli tool through user-agent header
2 parents d6d9feb + 6026bc0 commit d87e09c

5 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎src/dualentry_cli/__init__.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
"""DualEntry CLI - command-line interface for DualEntry accounting."""
22

33
__version__ = "0.1.0"
4+
USER_AGENT = f"dualentry-cli/{__version__}"

‎src/dualentry_cli/auth.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import keyring
1717
import typer
1818

19+
from dualentry_cli import USER_AGENT
20+
1921
_SERVICE_NAME = "dualentry-cli"
2022
_KEY_NAME_API_KEY = "api_key"
2123

@@ -86,6 +88,7 @@ def _authorize(api_url: str, redirect_uri: str, code_challenge: str, state: str)
8688
"code_challenge_method": "S256",
8789
"state": state,
8890
},
91+
headers={"User-Agent": USER_AGENT},
8992
timeout=30.0,
9093
)
9194
try:
@@ -110,6 +113,7 @@ def _exchange_code(api_url: str, code: str, code_verifier: str, redirect_uri: st
110113
"code_verifier": code_verifier,
111114
"redirect_uri": redirect_uri,
112115
},
116+
headers={"User-Agent": USER_AGENT},
113117
timeout=30.0,
114118
)
115119
try:

‎src/dualentry_cli/client.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import httpx
99

10+
from dualentry_cli import USER_AGENT
11+
1012

1113
class APIError(Exception):
1214
def __init__(self, status_code: int, detail: str):
@@ -21,7 +23,10 @@ def __init__(self, api_url: str, *, api_key: str):
2123
self._base_url = f"{self._api_url}/public/v2"
2224
self._client = httpx.Client(
2325
base_url=self._base_url,
24-
headers={"X-API-KEY": api_key},
26+
headers={
27+
"X-API-KEY": api_key,
28+
"User-Agent": USER_AGENT,
29+
},
2530
timeout=30.0,
2631
)
2732

‎tests/test_auth.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ def test_authorize_returns_url(self):
5454
assert url == "https://auth.example.com/authorize?state=abc"
5555
assert route.called
5656

57+
@respx.mock
58+
def test_authorize_sends_user_agent(self):
59+
from dualentry_cli import USER_AGENT
60+
from dualentry_cli.auth import _authorize
61+
62+
route = respx.post("https://api.dualentry.com/public/v2/oauth/authorize/").mock(
63+
return_value=httpx.Response(200, json={"authorization_url": "https://auth.example.com/authorize"})
64+
)
65+
_authorize("https://api.dualentry.com", "http://localhost:9876/callback", "challenge", "state")
66+
assert route.calls[0].request.headers["User-Agent"] == USER_AGENT
67+
5768

5869
class TestExchangeCode:
5970
@respx.mock

‎tests/test_client.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ def test_sets_api_key_header(self):
1010
client = DualEntryClient(api_url="https://api.dualentry.com", api_key="org_live_xxxx_secret")
1111
assert client._client.headers["X-API-KEY"] == "org_live_xxxx_secret"
1212

13+
def test_sets_user_agent_header(self):
14+
from dualentry_cli import USER_AGENT
15+
from dualentry_cli.client import DualEntryClient
16+
17+
client = DualEntryClient(api_url="https://api.dualentry.com", api_key="test_key")
18+
assert client._client.headers["User-Agent"] == USER_AGENT
19+
1320
@respx.mock
1421
def test_get_request(self):
1522
from dualentry_cli.client import DualEntryClient

0 commit comments

Comments
 (0)