diff --git a/openhexa/toolbox/hexa/api.py b/openhexa/toolbox/hexa/api.py index ff1ede8..7be0142 100644 --- a/openhexa/toolbox/hexa/api.py +++ b/openhexa/toolbox/hexa/api.py @@ -29,6 +29,7 @@ def authenticate( mutation Login($input: LoginInput!) { login(input: $input) { success + errors } } """, @@ -41,10 +42,15 @@ def authenticate( ) resp.raise_for_status() data = resp.json()["data"] - if data["login"]["success"]: - self.session.headers["Cookie"] = resp.headers["Set-Cookie"] + + if not data["login"]["success"]: + if "OTP_REQUIRED" in data["login"]["errors"]: + raise Exception("Login failed : two-factor authentication needs to be disabled.") + + raise Exception(f"Login failed : {data['login']['errors']}") else: - raise Exception("Login failed : verify if two-factor authentication is enabled.") + self.session.headers["Cookie"] = resp.headers["Set-Cookie"] + elif with_token: self.session.headers.update({"Authorization": f"Bearer {with_token}"}) diff --git a/tests/hexa/test_hexa.py b/tests/hexa/test_hexa.py index 4d7b6c6..8f21826 100644 --- a/tests/hexa/test_hexa.py +++ b/tests/hexa/test_hexa.py @@ -1,4 +1,5 @@ import pytest + from unittest import mock from uuid import uuid4 @@ -12,31 +13,46 @@ class TestOpenHEXAClient: + def _mock_response(self, data): + mock_response = mock.MagicMock() + mock_response.json.return_value = data + return mock_response + def test_authenticate_with_creds_success(self): hexa = OpenHEXAClient("https://app.demo.openhexa.org") - mock_response = mock.MagicMock() - mock_response.status_code = 401 - mock_response.json.return_value = { - "data": { - "login": { - "success": True, + mock_response = self._mock_response( + { + "data": { + "login": { + "success": True, + } } - } - } + }, + ) with mock.patch.object(hexa, "_graphql_request", return_value=mock_response): assert hexa.authenticate(with_credentials=("username", "password")) is True def test_authenticate_with_creds_failed(self): hexa = OpenHEXAClient("https://app.demo.openhexa.org") - result = { - "login": { - "success": False, - } - } - with mock.patch.object(hexa, "_graphql_request", return_value=result): - with pytest.raises(Exception): + mock_response = self._mock_response( + {"data": {"login": {"success": False, "errors": ["INVALID_CREDENTIALS"]}}}, + ) + + with mock.patch.object(hexa, "_graphql_request", return_value=mock_response): + with pytest.raises(Exception) as e: + hexa.authenticate(with_credentials=("username", "password")) + assert str(e) == "Login failed : ['INVALID_CREDENTIALSS']" + + def test_authenticate_with_otq_enabled_failed(self): + hexa = OpenHEXAClient("https://app.demo.openhexa.org") + mock_response = self._mock_response( + {"data": {"login": {"success": False, "errors": ["OTP_REQUIRED"]}}}, + ) + with mock.patch.object(hexa, "_graphql_request", return_value=mock_response): + with pytest.raises(Exception) as e: hexa.authenticate(with_credentials=("username", "password")) + assert str(e) == "Login failed : you need to disable two-factor authentication." @mock.patch("openhexa.toolbox.hexa.hexa.OpenHEXAClient")