Skip to content

Commit c3377a5

Browse files
authored
Check authentication before authenticating (#95)
1 parent a80d4af commit c3377a5

File tree

2 files changed

+94
-8
lines changed

2 files changed

+94
-8
lines changed

src/python_opensky/opensky.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,35 @@ class OpenSky:
3737
_auth: BasicAuth | None = None
3838
_contributing_user: bool = False
3939

40-
def authenticate(self, auth: BasicAuth, *, contributing_user: bool = False) -> None:
40+
async def authenticate(
41+
self,
42+
auth: BasicAuth,
43+
*,
44+
contributing_user: bool = False,
45+
) -> None:
4146
"""Authenticate the user."""
4247
self._auth = auth
48+
try:
49+
await self.get_states()
50+
except OpenSkyUnauthenticatedError as exc:
51+
self._auth = None
52+
raise OpenSkyUnauthenticatedError from exc
4353
self._contributing_user = contributing_user
4454
if contributing_user:
4555
self.opensky_credits = 8000
4656
else:
4757
self.opensky_credits = 4000
4858

59+
@property
60+
def is_contributing_user(self) -> bool:
61+
"""Return if the user is contributing to OpenSky."""
62+
return self._contributing_user
63+
64+
@property
65+
def is_authenticated(self) -> bool:
66+
"""Return if the user is correctly authenticated."""
67+
return self._auth is not None
68+
4969
async def _request(
5070
self,
5171
uri: str,
@@ -107,6 +127,8 @@ async def _request(
107127
ClientResponseError,
108128
socket.gaierror,
109129
) as exception:
130+
if isinstance(exception, ClientResponseError) and exception.status == 401:
131+
raise OpenSkyUnauthenticatedError from exception
110132
msg = "Error occurred while communicating with OpenSky API"
111133
raise OpenSkyConnectionError(msg) from exception
112134

tests/test_states.py

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ async def test_own_states(
9191
aresponses: ResponsesMockServer,
9292
) -> None:
9393
"""Test retrieving own states."""
94+
aresponses.add(
95+
OPENSKY_URL,
96+
"/api/states/all",
97+
"GET",
98+
aresponses.Response(
99+
status=200,
100+
headers={"Content-Type": "application/json"},
101+
text=load_fixture("states.json"),
102+
),
103+
)
94104
aresponses.add(
95105
OPENSKY_URL,
96106
"/api/states/own",
@@ -103,17 +113,31 @@ async def test_own_states(
103113
)
104114
async with aiohttp.ClientSession() as session:
105115
opensky = OpenSky(session=session)
106-
opensky.authenticate(BasicAuth(login="test", password="test"))
116+
await opensky.authenticate(
117+
BasicAuth(login="test", password="test"),
118+
contributing_user=True,
119+
)
107120
response: StatesResponse = await opensky.get_own_states()
108121
assert len(response.states) == 4
109-
assert opensky.remaining_credits() == opensky.opensky_credits
122+
assert opensky.opensky_credits == 8000
123+
assert opensky.remaining_credits() == 7996
110124
await opensky.close()
111125

112126

113127
async def test_unavailable_own_states(
114128
aresponses: ResponsesMockServer,
115129
) -> None:
116130
"""Test retrieving no own states."""
131+
aresponses.add(
132+
OPENSKY_URL,
133+
"/api/states/all",
134+
"GET",
135+
aresponses.Response(
136+
status=200,
137+
headers={"Content-Type": "application/json"},
138+
text=load_fixture("states.json"),
139+
),
140+
)
117141
aresponses.add(
118142
OPENSKY_URL,
119143
"/api/states/own",
@@ -126,7 +150,10 @@ async def test_unavailable_own_states(
126150
)
127151
async with aiohttp.ClientSession() as session:
128152
opensky = OpenSky(session=session)
129-
opensky.authenticate(BasicAuth(login="test", password="test"))
153+
await opensky.authenticate(
154+
BasicAuth(login="test", password="test"),
155+
contributing_user=True,
156+
)
130157
response: StatesResponse = await opensky.get_own_states()
131158
assert response.states is not None
132159
assert len(response.states) == 0
@@ -244,27 +271,64 @@ def response_handler(request: BaseRequest) -> Response:
244271
"/api/states/all",
245272
"GET",
246273
response_handler,
274+
repeat=2,
247275
)
248276

249277
async with aiohttp.ClientSession() as session:
250278
opensky = OpenSky(session=session)
251-
opensky.authenticate(BasicAuth(login="test", password="test"))
279+
await opensky.authenticate(BasicAuth(login="test", password="test"))
252280
await opensky.get_states()
253281
await opensky.close()
254282

255283

256-
async def test_user_credits() -> None:
284+
async def test_unauthorized(aresponses: ResponsesMockServer) -> None:
285+
"""Test request authentication."""
286+
aresponses.add(
287+
OPENSKY_URL,
288+
"/api/states/all",
289+
"GET",
290+
aresponses.Response(
291+
status=401,
292+
headers={"Content-Type": "application/json"},
293+
text=load_fixture("states.json"),
294+
),
295+
)
296+
297+
async with aiohttp.ClientSession() as session:
298+
opensky = OpenSky(session=session)
299+
try:
300+
await opensky.authenticate(BasicAuth(login="test", password="test"))
301+
pytest.fail("Should've thrown exception")
302+
except OpenSkyUnauthenticatedError:
303+
pass
304+
assert opensky.is_authenticated is False
305+
await opensky.close()
306+
307+
308+
async def test_user_credits(aresponses: ResponsesMockServer) -> None:
257309
"""Test authenticated user credits."""
310+
aresponses.add(
311+
OPENSKY_URL,
312+
"/api/states/all",
313+
"GET",
314+
aresponses.Response(
315+
status=200,
316+
headers={"Content-Type": "application/json"},
317+
text=load_fixture("states.json"),
318+
),
319+
repeat=2,
320+
)
258321
async with aiohttp.ClientSession() as session:
259322
opensky = OpenSky(session=session)
260323
assert opensky.opensky_credits == 400
261-
opensky.authenticate(BasicAuth(login="test", password="test"))
324+
await opensky.authenticate(BasicAuth(login="test", password="test"))
262325
assert opensky.opensky_credits == 4000
263-
opensky.authenticate(
326+
await opensky.authenticate(
264327
BasicAuth(login="test", password="test"),
265328
contributing_user=True,
266329
)
267330
assert opensky.opensky_credits == 8000
331+
assert opensky.is_contributing_user is True
268332
await opensky.close()
269333

270334

0 commit comments

Comments
 (0)