diff --git a/docs/getting-started.md b/docs/getting-started.md index 758013f1..be019c48 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -191,7 +191,7 @@ Admin users of JupyterHub have the ability to take actions on users' behalf, suc restarting their servers, and adding and removing new users from the whitelist. Any users in the admin list are automatically added to the whitelist, if they are not already present. The set of initial Admin users can configured as follows: ```python -c.JupyterHub.admin_users = {'mal', 'zoe'} +c.Authenticator.admin_users = {'mal', 'zoe'} ``` If `JupyterHub.admin_access` is True (not default), then admin users have permission to log in *as other @@ -314,7 +314,7 @@ c.LocalAuthenticator.create_system_users = True # specify users and admin c.Authenticator.whitelist = {'rgbkrk', 'minrk', 'jhamrick'} -c.JupyterHub.admin_users = {'jhamrick', 'rgbkrk'} +c.Authenticator.admin_users = {'jhamrick', 'rgbkrk'} # start single-user notebook servers in ~/assignments, # with ~/assignments/Welcome.ipynb as the default landing page diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 48f2ff37..8c9d3537 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -351,11 +351,9 @@ class JupyterHub(Application): """ ) admin_users = Set(config=True, - help="""set of usernames of admin users - - If unspecified, only the user that launches the server will be admin. - """ + help="""DEPRECATED, use Authenticator.admin_users instead.""" ) + tornado_settings = Dict(config=True) cleanup_servers = Bool(True, config=True, @@ -580,16 +578,24 @@ class JupyterHub(Application): def init_users(self): """Load users into and from the database""" db = self.db - - if not self.admin_users: + + if self.admin_users and not self.authenticator.admin_users: + self.log.warn( + "\nJupyterHub.admin_users is deprecated." + "\nUse Authenticator.admin_users instead." + ) + self.authenticator.admin_users = self.admin_users + admin_users = self.authenticator.admin_users + + if not admin_users: # add current user as admin if there aren't any others admins = db.query(orm.User).filter(orm.User.admin==True) if admins.first() is None: - self.admin_users.add(getuser()) + admin_users.add(getuser()) new_users = [] - for name in self.admin_users: + for name in admin_users: # ensure anyone specified as admin in config is admin in db user = orm.User.find(db, name) if user is None: @@ -810,7 +816,7 @@ class JupyterHub(Application): db=self.db, proxy=self.proxy, hub=self.hub, - admin_users=self.admin_users, + admin_users=self.authenticator.admin_users, admin_access=self.admin_access, authenticator=self.authenticator, spawner_class=self.spawner_class, diff --git a/jupyterhub/auth.py b/jupyterhub/auth.py index 9c235e9b..74427d1e 100644 --- a/jupyterhub/auth.py +++ b/jupyterhub/auth.py @@ -23,6 +23,12 @@ class Authenticator(LoggingConfigurable): """ db = Any() + admin_users = Set(config=True, + help="""set of usernames of admin users + + If unspecified, only the user that launches the server will be admin. + """ + ) whitelist = Set(config=True, help="""Username whitelist. diff --git a/jupyterhub/tests/mocking.py b/jupyterhub/tests/mocking.py index 02a38c1b..fe8842e5 100644 --- a/jupyterhub/tests/mocking.py +++ b/jupyterhub/tests/mocking.py @@ -72,6 +72,9 @@ class NeverSpawner(MockSpawner): class MockPAMAuthenticator(PAMAuthenticator): + def _admin_users_default(self): + return {'admin'} + def system_user_exists(self, user): # skip the add-system-user bit return not user.name.startswith('dne') @@ -94,9 +97,6 @@ class MockHub(JupyterHub): def _spawner_class_default(self): return MockSpawner - def _admin_users_default(self): - return {'admin'} - def init_signal(self): pass