mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 14:33:00 +00:00
Allow Authenticators to return an admin
flag for users.
This commit is contained in:
@@ -235,6 +235,7 @@ class Authenticator(LoggingConfigurable):
|
||||
'name': authenticated,
|
||||
}
|
||||
authenticated.setdefault('auth_state', None)
|
||||
authenticated.setdefault('admin', None)
|
||||
|
||||
# normalize the username
|
||||
authenticated['name'] = username = self.normalize_username(authenticated['name'])
|
||||
@@ -269,10 +270,10 @@ class Authenticator(LoggingConfigurable):
|
||||
Returns:
|
||||
user (str or dict or None): The username of the authenticated user,
|
||||
or None if Authentication failed.
|
||||
If the Authenticator has state associated with the user,
|
||||
it can return a dict with the keys 'name' and 'auth_state',
|
||||
where 'name' is the username and 'auth_state' is a dictionary
|
||||
of auth state that will be persisted.
|
||||
The Authenticator may return a dict instead, which MUST have a
|
||||
key 'name' holding the username, and may have two optional keys
|
||||
set - 'auth_state', a dictionary of of auth state that will be
|
||||
persisted; and 'admin', the admin setting value for the user.
|
||||
"""
|
||||
|
||||
def pre_spawn_start(self, user, spawner):
|
||||
|
@@ -336,7 +336,11 @@ class BaseHandler(RequestHandler):
|
||||
if authenticated:
|
||||
username = authenticated['name']
|
||||
auth_state = authenticated.get('auth_state')
|
||||
admin = authenticated.get('admin')
|
||||
user = self.user_from_username(username)
|
||||
# Only set `admin` if the authenticator returned an explicit value.
|
||||
if admin is not None:
|
||||
user.admin = admin
|
||||
# always set auth_state and commit,
|
||||
# because there could be key-rotation or clearing of previous values
|
||||
# going on.
|
||||
|
@@ -138,6 +138,8 @@ class FormSpawner(MockSpawner):
|
||||
|
||||
class MockPAMAuthenticator(PAMAuthenticator):
|
||||
auth_state = None
|
||||
# If true, return admin users marked as admin.
|
||||
return_admin = False
|
||||
@default('admin_users')
|
||||
def _admin_users_default(self):
|
||||
return {'admin'}
|
||||
@@ -161,6 +163,11 @@ class MockPAMAuthenticator(PAMAuthenticator):
|
||||
'name': username,
|
||||
'auth_state': self.auth_state,
|
||||
}
|
||||
elif self.return_admin:
|
||||
return {
|
||||
'name': username,
|
||||
'admin': username in self.admin_users,
|
||||
}
|
||||
else:
|
||||
return username
|
||||
|
||||
|
@@ -201,6 +201,49 @@ def test_auth_state(app, auth_state_enabled):
|
||||
assert auth_state == app.authenticator.auth_state
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def use_auth_admin(app):
|
||||
before_admin = app.authenticator.return_admin
|
||||
app.authenticator.return_admin = True
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
app.authenticator.return_admin = before_admin
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_auth_admin_non_admin(app, use_auth_admin):
|
||||
"""admin should be passed through for non-admin users"""
|
||||
name = 'kiwi'
|
||||
user = add_user(app.db, app, name=name, admin=False)
|
||||
assert user.admin is False
|
||||
cookies = yield app.login_user(name)
|
||||
assert user.admin is False
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_auth_admin_is_admin(app, use_auth_admin):
|
||||
"""admin should be passed through for admin users"""
|
||||
# Admin user defined in MockPAMAuthenticator.
|
||||
name = 'admin'
|
||||
user = add_user(app.db, app, name=name, admin=False)
|
||||
assert user.admin is False
|
||||
cookies = yield app.login_user(name)
|
||||
assert user.admin is True
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_auth_admin_retained_if_unset(app):
|
||||
"""admin should be unchanged if authenticator doesn't return admin value"""
|
||||
name = 'kiwi'
|
||||
# Add user as admin.
|
||||
user = add_user(app.db, app, name=name, admin=True)
|
||||
assert user.admin is True
|
||||
# User should remain unchanged.
|
||||
cookies = yield app.login_user(name)
|
||||
assert user.admin is True
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth_state_unavailable(auth_state_enabled):
|
||||
"""auth_state enabled at the Authenticator level,
|
||||
|
Reference in New Issue
Block a user