diff --git a/jupyterhub/apihandlers/users.py b/jupyterhub/apihandlers/users.py index eb7337a3..e76e73b7 100644 --- a/jupyterhub/apihandlers/users.py +++ b/jupyterhub/apihandlers/users.py @@ -18,6 +18,43 @@ class UserListAPIHandler(APIHandler): users = self.db.query(orm.User) data = [ self.user_model(u) for u in users ] self.write(json.dumps(data)) + + @admin_only + @gen.coroutine + def post(self): + data = self.get_json_body() + print(data) + if not data or not isinstance(data, dict) or not data.get('usernames'): + raise web.HTTPError(400, "Must specify at least one user to create") + + usernames = data.pop('usernames') + self._check_user_model(data) + + for name in usernames: + user = self.find_user(name) + if user is not None: + raise web.HTTPError(400, "User %s already exists" % name) + + created = [] + for name in usernames: + user = self.user_from_username(name) + if data: + self._check_user_model(data) + if 'admin' in data: + user.admin = data['admin'] + self.db.commit() + try: + yield gen.maybe_future(self.authenticator.add_user(user)) + except Exception: + self.log.error("Failed to create user: %s" % name, exc_info=True) + self.db.delete(user) + self.db.commit() + raise web.HTTPError(400, "Failed to create user: %s" % name) + else: + created.append(user) + + self.write(json.dumps([ self.user_model(u) for u in created ])) + self.set_status(201) def admin_or_self(method): diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index 3299be9a..cac9e83c 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -132,6 +132,71 @@ def test_add_user(app): assert user.name == name assert not user.admin + +def test_get_user(app): + name = 'user' + r = api_request(app, 'users', name) + assert r.status_code == 200 + user = r.json() + user.pop('last_activity') + assert user == { + 'name': name, + 'admin': False, + 'server': None, + 'pending': None, + } + + +def test_add_multi_user_bad(app): + r = api_request(app, 'users', method='post') + assert r.status_code == 400 + r = api_request(app, 'users', method='post', data='{}') + assert r.status_code == 400 + r = api_request(app, 'users', method='post', data='[]') + assert r.status_code == 400 + +def test_add_multi_user(app): + db = app.db + names = ['a', 'b'] + r = api_request(app, 'users', method='post', + data=json.dumps({'usernames': names}), + ) + assert r.status_code == 201 + reply = r.json() + r_names = [ user['name'] for user in reply ] + assert names == r_names + + for name in names: + user = find_user(db, name) + assert user is not None + assert user.name == name + assert not user.admin + + # try to create the same users again + r = api_request(app, 'users', method='post', + data=json.dumps({'usernames': names}), + ) + assert r.status_code == 400 + + +def test_add_multi_user_admin(app): + db = app.db + names = ['c', 'd'] + r = api_request(app, 'users', method='post', + data=json.dumps({'usernames': names, 'admin': True}), + ) + assert r.status_code == 201 + reply = r.json() + r_names = [ user['name'] for user in reply ] + assert names == r_names + + for name in names: + user = find_user(db, name) + assert user is not None + assert user.name == name + assert user.admin + + def test_add_user_bad(app): db = app.db name = 'dne_newuser'