Skip to content

Commit

Permalink
authentication: test handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
oliver-sanders committed Apr 12, 2021
1 parent fc02448 commit 5654eea
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
4 changes: 2 additions & 2 deletions cylc/uiserver/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def authorised(fun):
def _inner(self, *args, **kwargs):
nonlocal fun
if not _authorised(self):
raise web.HTTPError(403)
raise web.HTTPError(403, reason='authorisation insufficient')
return fun(self, *args, **kwargs)
return _inner

Expand All @@ -73,7 +73,7 @@ def async_authorised(fun):
async def _inner(self, *args, **kwargs):
nonlocal fun
if not _authorised(self):
raise web.HTTPError(403)
raise web.HTTPError(403, reason='authorisation insufficient')
return await fun(self, *args, **kwargs)
return _inner

Expand Down
16 changes: 14 additions & 2 deletions cylc/uiserver/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,13 @@ def authorisation_true(monkeypatch):
@pytest.fixture
def mock_authentication(monkeypatch):

def _mock_authentication(username=None, server=None):
def _mock_authentication(user=None, server=None, none=False):
ret = {
'name': username or getuser(),
'name': user or getuser(),
'server': server or gethostname()
}
if none:
ret = None
monkeypatch.setattr(
'cylc.uiserver.handlers.BaseHandler.get_current_user',
lambda x: ret
Expand All @@ -210,3 +212,13 @@ def _mock_authentication(username=None, server=None):
_mock_authentication()

return _mock_authentication


@pytest.fixture
def mock_authentication_yossarian(mock_authentication):
mock_authentication(user='yossarian')


@pytest.fixture
def mock_authentication_none(mock_authentication):
mock_authentication(none=True)
78 changes: 62 additions & 16 deletions cylc/uiserver/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,27 @@ def test_jupyterhub_version_returned(self):
assert response.body == b"TESTING!"
assert "X-JupyterHub-Version" in response.headers

@pytest.mark.usefixtures("mock_authentication", autouse=True)
def test_authorised_and_authenticated(self):
"""Test 500 HTTP response (because index.html missing)."""
response = self.fetch('/')
assert response.code == 500

# TODO: can't get this test to run due to handler setup?
# @pytest.mark.usefixtures("mock_authentication_none", autouse=True)
# def test_unauthenticated(self) -> None:
# """Test 403 HTTP response (unauthenticated)."""
# response = self.fetch('/')
# assert response.code == 403
# # assert response.reason == 'Forbidden'

@pytest.mark.usefixtures("mock_authentication_yossarian", autouse=True)
def test_unauthorised(self):
"""Test 403 HTTP response (unauthorised)."""
response = self.fetch('/')
assert response.code == 403
assert response.reason == 'authorisation insufficient'

def tearDown(self) -> None:
if self.tempdir:
shutil.rmtree(self.tempdir, ignore_errors=True)
Expand All @@ -80,6 +101,27 @@ def test_user_profile_handler_cors_headers(self):
assert "Content-Type" in response.headers
assert getuser() in str(response.body)

@pytest.mark.usefixtures("mock_authentication", autouse=True)
def test_authorised_and_authenticated(self):
"""Test 200 HTTP response."""
response = self.fetch('/userprofile')
assert response.code == 200

# TODO: can't get this test to run due to handler setup?
# @pytest.mark.usefixtures("mock_authentication_none", autouse=True)
# def test_unauthenticated(self) -> None:
# """Test 403 HTTP response (unauthenticated)."""
# response = self.fetch('/userprofile')
# assert response.code == 403
# # assert response.reason == 'Forbidden'

@pytest.mark.usefixtures("mock_authentication_yossarian", autouse=True)
def test_unauthorised(self):
"""Test 403 HTTP response (unauthorised)."""
response = self.fetch('/userprofile')
assert response.code == 403
assert response.reason == 'authorisation insufficient'


class SubscriptionHandlerTest(AsyncHTTPTestCase):
"""Test for SubscriptionHandler"""
Expand All @@ -92,12 +134,6 @@ def get_app(self) -> Application:
]
)

@pytest.mark.usefixtures("mock_authentication", autouse=True)
def test_websockets_reject_get_requests(self):
response = self.fetch('/subscriptions')
assert 400 == response.code
assert b"WebSocket" in response.body

def _create_handler(self, logged_in=True):
app = self.get_app()
request = HTTPServerRequest(method='GET', uri='/subscriptions')
Expand Down Expand Up @@ -165,13 +201,23 @@ def test_assert_callback_handler_gets_called(self):
get_async_test_timeout())
handler.subscription_server.handle.assert_called_once()

def test_unauthenticated_request_http_403_error(self) -> None:
"""
When the user is not logged-in, the open function for
WebSockets should raise an HTTPError with status code 403.
"""
handler = self._create_handler(logged_in=False)
with self.assertRaises(HTTPError) as cm:
self.io_loop.run_sync(handler.open,
get_async_test_timeout())
assert 403 == cm.exception.status_code
@pytest.mark.usefixtures("mock_authentication", autouse=True)
def test_authorised_and_authenticated(self):
"""Test 400 HTTP response (upgrade to websocket)."""
response = self.fetch('/subscriptions')
assert response.code == 400
assert b"WebSocket" in response.body

@pytest.mark.usefixtures("mock_authentication_none", autouse=True)
def test_unauthenticated(self) -> None:
"""Test 403 HTTP response (unauthenticated)."""
response = self.fetch('/subscriptions')
assert response.code == 403
assert response.reason == 'Forbidden'

@pytest.mark.usefixtures("mock_authentication_yossarian", autouse=True)
def test_unauthorised(self):
"""Test 403 HTTP response (unauthorised)."""
response = self.fetch('/subscriptions')
assert response.code == 403
assert response.reason == 'authorisation insufficient'

0 comments on commit 5654eea

Please sign in to comment.