Skip to content

Commit

Permalink
Merge pull request #65 from rossumai/igor/no-reauth-without-credentials
Browse files Browse the repository at this point in the history
fix(api-client): do not reauth if no credentials are available
  • Loading branch information
bara-m committed Apr 5, 2024
2 parents c6db58b + 033063f commit 92697e6
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ help:
@echo "make install: Install all needed dependencies including tests"
@echo "make lint: Run linters"
@echo "make test: Run basic tests (not testing most integrations)"
@echo "make test-all: Run ALL tests (slow, closest to CI)"
@echo "make format: Run code formatters (destructive)"
@echo
@echo "Also make sure to read ./CONTRIBUTING.md"
Expand Down
2 changes: 2 additions & 0 deletions rossum_api/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ async def authenticate_if_needed(self: APIClient, *args, **kwargs):
except APIClientError as e:
if e.status_code != 401:
raise
if not (self.username and self.password): # no way to refresh token
raise
logger.debug("Token expired, authenticating user %s...", self.username)
await self._authenticate()
return await method(self, *args, **kwargs)
Expand Down
44 changes: 35 additions & 9 deletions tests/test_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@
}
],
}

USER = {
"id": 1,
"url": "https://elis.rossum.ai/api/v1/users/1",
"first_name": "John",
"last_name": "Doe",
}

EXPECTED_UPLOAD_CONTENT = b'--313131\r\nContent-Disposition: form-data; name="content"; filename="filename.pdf"\r\nContent-Type: application/octet-stream\r\n\r\nFake PDF.\r\n--313131\r\nContent-Disposition: form-data; name="values"\r\nContent-Type: application/json\r\n\r\n{"upload:organization_unit": "Sales"}\r\n--313131\r\nContent-Disposition: form-data; name="metadata"\r\nContent-Type: application/json\r\n\r\n{"project": "Market ABC"}\r\n--313131--\r\n'

CSV_EXPORT = b"meta_file_name,Invoice number\r\nfilename_1.pdf,11111\r\nfilename_2.pdf,22222"
Expand Down Expand Up @@ -187,8 +195,8 @@ async def test_init_token(httpx_mock):


@pytest.mark.asyncio
async def test_not_possible_to_reauth(httpx_mock):
"""Invalid token used, trying to to re-auth without password, get error. Transparently displays it."""
async def test_reauth_no_credentials(httpx_mock):
"""Invalid token used but no credentials available for re-authentication. Raise 401."""
client = APIClient(token=FAKE_TOKEN)

httpx_mock.add_response(
Expand All @@ -197,16 +205,34 @@ async def test_not_possible_to_reauth(httpx_mock):
status_code=401,
content=b"unauth!",
)
httpx_mock.add_response(
url="https://elis.rossum.ai/api/v1/auth/login",
status_code=400,
json={"password": ["This field may not be blank."]},
)
with pytest.raises(APIClientError) as err:
await client.fetch_one(Resource.User, 1)

assert err.value.status_code == 400
assert err.value.error == '{"password": ["This field may not be blank."]}'
assert err.value.status_code == 401


@pytest.mark.asyncio
async def test_reauth_success(login_mock, httpx_mock):
"""Invalid token used, credentials available => reauthenticate in the background. Fetch user without raising any errors."""
client = APIClient("username", "password", token=FAKE_TOKEN)

httpx_mock.add_response(
method="GET",
url="https://elis.rossum.ai/api/v1/users/1",
status_code=401,
match_headers={"Authorization": f"token {FAKE_TOKEN}"},
content=b"unauth!",
)

httpx_mock.add_response(
method="GET",
url="https://elis.rossum.ai/api/v1/users/1",
match_headers={"Authorization": f"token {NEW_TOKEN}"},
json=USER,
)

user = await client.fetch_one(Resource.User, 1)
assert user == USER


@pytest.mark.asyncio
Expand Down

0 comments on commit 92697e6

Please sign in to comment.