-
Notifications
You must be signed in to change notification settings - Fork 368
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
maint: update tests for recent change
- Loading branch information
1 parent
223c89b
commit 0e2352e
Showing
12 changed files
with
1,828 additions
and
1,208 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,97 @@ | ||
import logging | ||
from unittest.mock import Mock | ||
|
||
from pytest import fixture, mark | ||
from pytest import fixture, mark, raises | ||
from tornado import web | ||
from traitlets.config import Config | ||
|
||
from ..auth0 import Auth0OAuthenticator | ||
from ..oauth2 import OAuthLogoutHandler | ||
from .mocks import mock_handler, setup_oauth_mock | ||
|
||
auth0_subdomain = "jupyterhub-test" | ||
auth0_domain = "jupyterhub-test.auth0.com" | ||
|
||
|
||
def user_model(email, nickname=None): | ||
"""Return a user model""" | ||
return { | ||
'email': email, | ||
'nickname': nickname if nickname else email, | ||
'name': 'Hoban Washburn', | ||
} | ||
AUTH0_DOMAIN = "jupyterhub-test.auth0.com" | ||
|
||
|
||
@fixture | ||
def auth0_client(client): | ||
setup_oauth_mock( | ||
client, | ||
host=auth0_domain, | ||
host=AUTH0_DOMAIN, | ||
access_token_path='/oauth/token', | ||
user_path='/userinfo', | ||
) | ||
return client | ||
|
||
|
||
@mark.parametrize( | ||
'config', [{"auth0_domain": auth0_domain}, {"auth0_subdomain": auth0_subdomain}] | ||
) | ||
async def test_auth0(config, auth0_client): | ||
cfg = Config() | ||
cfg.Auth0OAuthenticator = Config(config) | ||
authenticator = Auth0OAuthenticator(config=cfg) | ||
|
||
handler = auth0_client.handler_for_user(user_model('[email protected]')) | ||
auth_model = await authenticator.get_authenticated_user(handler, None) | ||
assert sorted(auth_model) == ['admin', 'auth_state', 'name'] | ||
assert auth_model['name'] == '[email protected]' | ||
auth_state = auth_model['auth_state'] | ||
assert 'access_token' in auth_state | ||
assert 'auth0_user' in auth_state | ||
def user_model(): | ||
"""Return a user model""" | ||
return { | ||
"email": "[email protected]", | ||
"name": "user1", | ||
} | ||
|
||
|
||
@mark.parametrize( | ||
'config', [{"auth0_domain": auth0_domain}, {"auth0_subdomain": auth0_subdomain}] | ||
"test_variation_id,class_config,expect_allowed,expect_admin", | ||
[ | ||
# no allow config tested | ||
("00", {}, False, None), | ||
# allow config, individually tested | ||
("01", {"allow_all": True}, True, None), | ||
("02", {"allowed_users": {"user1"}}, True, None), | ||
("03", {"allowed_users": {"not-test-user"}}, False, None), | ||
("04", {"admin_users": {"user1"}}, True, True), | ||
("05", {"admin_users": {"not-test-user"}}, False, None), | ||
# allow config, some combinations of two tested | ||
( | ||
"10", | ||
{ | ||
"allow_all": False, | ||
"allowed_users": {"not-test-user"}, | ||
}, | ||
False, | ||
None, | ||
), | ||
( | ||
"11", | ||
{ | ||
"admin_users": {"user1"}, | ||
"allowed_users": {"not-test-user"}, | ||
}, | ||
True, | ||
True, | ||
), | ||
], | ||
) | ||
async def test_username_key(config, auth0_client): | ||
cfg = Config() | ||
cfg.Auth0OAuthenticator = Config(config) | ||
authenticator = Auth0OAuthenticator(config=cfg) | ||
authenticator.username_key = 'nickname' | ||
handler = auth0_client.handler_for_user(user_model('[email protected]', 'kayle')) | ||
async def test_auth0( | ||
auth0_client, | ||
test_variation_id, | ||
class_config, | ||
expect_allowed, | ||
expect_admin, | ||
): | ||
print(f"Running test variation id {test_variation_id}") | ||
c = Config() | ||
c.Auth0OAuthenticator = Config(class_config) | ||
c.Auth0OAuthenticator.auth0_domain = AUTH0_DOMAIN | ||
c.Auth0OAuthenticator.username_claim = "name" | ||
authenticator = Auth0OAuthenticator(config=c) | ||
|
||
handled_user_model = user_model() | ||
handler = auth0_client.handler_for_user(handled_user_model) | ||
auth_model = await authenticator.get_authenticated_user(handler, None) | ||
assert auth_model['name'] == 'kayle' | ||
|
||
if expect_allowed: | ||
assert auth_model | ||
assert set(auth_model) == {"name", "admin", "auth_state"} | ||
assert auth_model["admin"] == expect_admin | ||
auth_state = auth_model["auth_state"] | ||
assert "access_token" in auth_state | ||
user_info = auth_state[authenticator.user_auth_state_key] | ||
assert user_info == handled_user_model | ||
assert auth_model["name"] == user_info[authenticator.username_claim] | ||
else: | ||
assert auth_model == None | ||
|
||
|
||
async def test_custom_logout(monkeypatch): | ||
|
@@ -79,23 +110,51 @@ async def test_custom_logout(monkeypatch): | |
assert authenticator.logout_url('http://myhost') == 'http://myhost/logout' | ||
|
||
# Check redirection to the custom logout url | ||
authenticator.auth0_domain = auth0_domain | ||
authenticator.auth0_domain = AUTH0_DOMAIN | ||
await logout_handler.get() | ||
custom_logout_url = f'https://{auth0_domain}/v2/logout' | ||
custom_logout_url = f'https://{AUTH0_DOMAIN}/v2/logout' | ||
logout_handler.redirect.assert_called_with(custom_logout_url) | ||
|
||
|
||
async def test_deprecated_config(caplog): | ||
cfg = Config() | ||
cfg.Auth0OAuthenticator.username_key = 'nickname' | ||
log = logging.getLogger("testlog") | ||
authenticator = Auth0OAuthenticator(config=cfg, log=log) | ||
|
||
assert ( | ||
log.name, | ||
logging.WARNING, | ||
'Auth0OAuthenticator.username_key is deprecated in Auth0OAuthenticator 16.0.0, use ' | ||
'Auth0OAuthenticator.username_claim instead', | ||
) in caplog.record_tuples | ||
|
||
assert authenticator.username_claim == 'nickname' | ||
@mark.parametrize( | ||
"test_variation_id,class_config,expect_config,expect_loglevel,expect_message", | ||
[ | ||
( | ||
"username_key", | ||
{"username_key": "dummy"}, | ||
{"username_claim": "dummy"}, | ||
logging.WARNING, | ||
"Auth0OAuthenticator.username_key is deprecated in Auth0OAuthenticator 16.0.0, use Auth0OAuthenticator.username_claim instead", | ||
), | ||
], | ||
) | ||
async def test_deprecated_config( | ||
caplog, | ||
test_variation_id, | ||
class_config, | ||
expect_config, | ||
expect_loglevel, | ||
expect_message, | ||
): | ||
""" | ||
Tests that a warning is emitted when using a deprecated config and that | ||
configuring the old config ends up configuring the new config. | ||
""" | ||
print(f"Running test variation id {test_variation_id}") | ||
c = Config() | ||
c.Auth0OAuthenticator = Config(class_config) | ||
|
||
test_logger = logging.getLogger('testlog') | ||
if expect_loglevel == logging.ERROR: | ||
with raises(ValueError, match=expect_message): | ||
Auth0OAuthenticator(config=c, log=test_logger) | ||
else: | ||
authenticator = Auth0OAuthenticator(config=c, log=test_logger) | ||
for key, value in expect_config.items(): | ||
assert getattr(authenticator, key) == value | ||
|
||
captured_log_tuples = caplog.record_tuples | ||
print(captured_log_tuples) | ||
|
||
expected_log_tuple = (test_logger.name, expect_loglevel, expect_message) | ||
assert expected_log_tuple in captured_log_tuples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.