We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Admin panel - Add ability to import multiple users at once
It would be nice to add a list of users as a bulk list of newline delimited users.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `jupyterhub/apihandlers/users.py`
Content:
```
1 """User handlers"""
2 
3 # Copyright (c) Jupyter Development Team.
4 # Distributed under the terms of the Modified BSD License.
5 
6 import json
7 
8 from tornado import gen, web
9 
10 from .. import orm
11 from ..utils import admin_only
12 from .base import APIHandler
13 
14 
15 class UserListAPIHandler(APIHandler):
16     @admin_only
17     def get(self):
18         users = self.db.query(orm.User)
19         data = [ self.user_model(u) for u in users ]
20         self.write(json.dumps(data))
21 
22 
23 def admin_or_self(method):
24     """Decorator for restricting access to either the target user or admin"""
25     def m(self, name):
26         current = self.get_current_user()
27         if current is None:
28             raise web.HTTPError(403)
29         if not (current.name == name or current.admin):
30             raise web.HTTPError(403)
31         
32         # raise 404 if not found
33         if not self.find_user(name):
34             raise web.HTTPError(404)
35         return method(self, name)
36     return m
37 
38 class UserAPIHandler(APIHandler):
39     
40     @admin_or_self
41     def get(self, name):
42         user = self.find_user(name)
43         self.write(json.dumps(self.user_model(user)))
44     
45     @admin_only
46     @gen.coroutine
47     def post(self, name):
48         data = self.get_json_body()
49         user = self.find_user(name)
50         if user is not None:
51             raise web.HTTPError(400, "User %s already exists" % name)
52         
53         user = self.user_from_username(name)
54         if data:
55             self._check_user_model(data)
56             if 'admin' in data:
57                 user.admin = data['admin']
58                 self.db.commit()
59         
60         try:
61             yield gen.maybe_future(self.authenticator.add_user(user))
62         except Exception:
63             self.log.error("Failed to create user: %s" % name, exc_info=True)
64             self.db.delete(user)
65             self.db.commit()
66             raise web.HTTPError(400, "Failed to create user: %s" % name)
67         
68         self.write(json.dumps(self.user_model(user)))
69         self.set_status(201)
70     
71     @admin_only
72     @gen.coroutine
73     def delete(self, name):
74         user = self.find_user(name)
75         if user is None:
76             raise web.HTTPError(404)
77         if user.name == self.get_current_user().name:
78             raise web.HTTPError(400, "Cannot delete yourself!")
79         if user.stop_pending:
80             raise web.HTTPError(400, "%s's server is in the process of stopping, please wait." % name)
81         if user.running:
82             yield self.stop_single_user(user)
83             if user.stop_pending:
84                 raise web.HTTPError(400, "%s's server is in the process of stopping, please wait." % name)
85         
86         yield gen.maybe_future(self.authenticator.delete_user(user))
87         
88         # remove from the db
89         self.db.delete(user)
90         self.db.commit()
91         
92         self.set_status(204)
93     
94     @admin_only
95     def patch(self, name):
96         user = self.find_user(name)
97         if user is None:
98             raise web.HTTPError(404)
99         data = self.get_json_body()
100         self._check_user_model(data)
101         for key, value in data.items():
102             setattr(user, key, value)
103         self.db.commit()
104         self.write(json.dumps(self.user_model(user)))
105 
106 
107 class UserServerAPIHandler(APIHandler):
108     @gen.coroutine
109     @admin_or_self
110     def post(self, name):
111         user = self.find_user(name)
112         if user.spawner:
113             state = yield user.spawner.poll()
114             if state is None:
115                 raise web.HTTPError(400, "%s's server is already running" % name)
116 
117         yield self.spawn_single_user(user)
118         status = 202 if user.spawn_pending else 201
119         self.set_status(status)
120 
121     @gen.coroutine
122     @admin_or_self
123     def delete(self, name):
124         user = self.find_user(name)
125         if user.stop_pending:
126             self.set_status(202)
127             return
128         if not user.running:
129             raise web.HTTPError(400, "%s's server is not running" % name)
130         status = yield user.spawner.poll()
131         if status is not None:
132             raise web.HTTPError(400, "%s's server is not running" % name)
133         yield self.stop_single_user(user)
134         status = 202 if user.stop_pending else 204
135         self.set_status(status)
136 
137 class UserAdminAccessAPIHandler(APIHandler):
138     """Grant admins access to single-user servers
139     
140     This handler sets the necessary cookie for an admin to login to a single-user server.
141     """
142     @admin_only
143     def post(self, name):
144         current = self.get_current_user()
145         self.log.warn("Admin user %s has requested access to %s's server",
146             current.name, name,
147         )
148         if not self.settings.get('admin_access', False):
149             raise web.HTTPError(403, "admin access to user servers disabled")
150         user = self.find_user(name)
151         if user is None:
152             raise web.HTTPError(404)
153         if not user.running:
154             raise web.HTTPError(400, "%s's server is not running" % name)
155         self.set_server_cookie(user)
156 
157 
158 default_handlers = [
159     (r"/api/users", UserListAPIHandler),
160     (r"/api/users/([^/]+)", UserAPIHandler),
161     (r"/api/users/([^/]+)/server", UserServerAPIHandler),
162     (r"/api/users/([^/]+)/admin-access", UserAdminAccessAPIHandler),
163 ]
164
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/jupyterhub/apihandlers/users.py b/jupyterhub/apihandlers/users.py
--- a/jupyterhub/apihandlers/users.py
+++ b/jupyterhub/apihandlers/users.py
@@ -18,6 +18,49 @@
         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()
+        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)
+        # admin is set for all users
+        # to create admin and non-admin users requires at least two API requests
+        admin = data.get('admin', False)
+        
+        to_create = []
+        for name in usernames:
+            user = self.find_user(name)
+            if user is not None:
+                self.log.warn("User %s already exists" % name)
+            else:
+                to_create.append(name)
+        
+        if not to_create:
+            raise web.HTTPError(400, "All %i users already exist" % len(usernames))
+        
+        created = []
+        for name in to_create:
+            user = self.user_from_username(name)
+            if admin:
+                user.admin = True
+                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):

{"golden_diff": "diff --git a/jupyterhub/apihandlers/users.py b/jupyterhub/apihandlers/users.py\n--- a/jupyterhub/apihandlers/users.py\n+++ b/jupyterhub/apihandlers/users.py\n@@ -18,6 +18,49 @@\n         users = self.db.query(orm.User)\n         data = [ self.user_model(u) for u in users ]\n         self.write(json.dumps(data))\n+    \n+    @admin_only\n+    @gen.coroutine\n+    def post(self):\n+        data = self.get_json_body()\n+        if not data or not isinstance(data, dict) or not data.get('usernames'):\n+            raise web.HTTPError(400, \"Must specify at least one user to create\")\n+        \n+        usernames = data.pop('usernames')\n+        self._check_user_model(data)\n+        # admin is set for all users\n+        # to create admin and non-admin users requires at least two API requests\n+        admin = data.get('admin', False)\n+        \n+        to_create = []\n+        for name in usernames:\n+            user = self.find_user(name)\n+            if user is not None:\n+                self.log.warn(\"User %s already exists\" % name)\n+            else:\n+                to_create.append(name)\n+        \n+        if not to_create:\n+            raise web.HTTPError(400, \"All %i users already exist\" % len(usernames))\n+        \n+        created = []\n+        for name in to_create:\n+            user = self.user_from_username(name)\n+            if admin:\n+                user.admin = True\n+                self.db.commit()\n+            try:\n+                yield gen.maybe_future(self.authenticator.add_user(user))\n+            except Exception:\n+                self.log.error(\"Failed to create user: %s\" % name, exc_info=True)\n+                self.db.delete(user)\n+                self.db.commit()\n+                raise web.HTTPError(400, \"Failed to create user: %s\" % name)\n+            else:\n+                created.append(user)\n+        \n+        self.write(json.dumps([ self.user_model(u) for u in created ]))\n+        self.set_status(201)\n \n \n def admin_or_self(method):\n", "issue": "Admin panel - Add ability to import multiple users at once\nIt would be nice to add a list of users as a bulk list of newline delimited users.\n\n", "before_files": [{"content": "\"\"\"User handlers\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom tornado import gen, web\n\nfrom .. import orm\nfrom ..utils import admin_only\nfrom .base import APIHandler\n\n\nclass UserListAPIHandler(APIHandler):\n    @admin_only\n    def get(self):\n        users = self.db.query(orm.User)\n        data = [ self.user_model(u) for u in users ]\n        self.write(json.dumps(data))\n\n\ndef admin_or_self(method):\n    \"\"\"Decorator for restricting access to either the target user or admin\"\"\"\n    def m(self, name):\n        current = self.get_current_user()\n        if current is None:\n            raise web.HTTPError(403)\n        if not (current.name == name or current.admin):\n            raise web.HTTPError(403)\n        \n        # raise 404 if not found\n        if not self.find_user(name):\n            raise web.HTTPError(404)\n        return method(self, name)\n    return m\n\nclass UserAPIHandler(APIHandler):\n    \n    @admin_or_self\n    def get(self, name):\n        user = self.find_user(name)\n        self.write(json.dumps(self.user_model(user)))\n    \n    @admin_only\n    @gen.coroutine\n    def post(self, name):\n        data = self.get_json_body()\n        user = self.find_user(name)\n        if user is not None:\n            raise web.HTTPError(400, \"User %s already exists\" % name)\n        \n        user = self.user_from_username(name)\n        if data:\n            self._check_user_model(data)\n            if 'admin' in data:\n                user.admin = data['admin']\n                self.db.commit()\n        \n        try:\n            yield gen.maybe_future(self.authenticator.add_user(user))\n        except Exception:\n            self.log.error(\"Failed to create user: %s\" % name, exc_info=True)\n            self.db.delete(user)\n            self.db.commit()\n            raise web.HTTPError(400, \"Failed to create user: %s\" % name)\n        \n        self.write(json.dumps(self.user_model(user)))\n        self.set_status(201)\n    \n    @admin_only\n    @gen.coroutine\n    def delete(self, name):\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        if user.name == self.get_current_user().name:\n            raise web.HTTPError(400, \"Cannot delete yourself!\")\n        if user.stop_pending:\n            raise web.HTTPError(400, \"%s's server is in the process of stopping, please wait.\" % name)\n        if user.running:\n            yield self.stop_single_user(user)\n            if user.stop_pending:\n                raise web.HTTPError(400, \"%s's server is in the process of stopping, please wait.\" % name)\n        \n        yield gen.maybe_future(self.authenticator.delete_user(user))\n        \n        # remove from the db\n        self.db.delete(user)\n        self.db.commit()\n        \n        self.set_status(204)\n    \n    @admin_only\n    def patch(self, name):\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        data = self.get_json_body()\n        self._check_user_model(data)\n        for key, value in data.items():\n            setattr(user, key, value)\n        self.db.commit()\n        self.write(json.dumps(self.user_model(user)))\n\n\nclass UserServerAPIHandler(APIHandler):\n    @gen.coroutine\n    @admin_or_self\n    def post(self, name):\n        user = self.find_user(name)\n        if user.spawner:\n            state = yield user.spawner.poll()\n            if state is None:\n                raise web.HTTPError(400, \"%s's server is already running\" % name)\n\n        yield self.spawn_single_user(user)\n        status = 202 if user.spawn_pending else 201\n        self.set_status(status)\n\n    @gen.coroutine\n    @admin_or_self\n    def delete(self, name):\n        user = self.find_user(name)\n        if user.stop_pending:\n            self.set_status(202)\n            return\n        if not user.running:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        status = yield user.spawner.poll()\n        if status is not None:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        yield self.stop_single_user(user)\n        status = 202 if user.stop_pending else 204\n        self.set_status(status)\n\nclass UserAdminAccessAPIHandler(APIHandler):\n    \"\"\"Grant admins access to single-user servers\n    \n    This handler sets the necessary cookie for an admin to login to a single-user server.\n    \"\"\"\n    @admin_only\n    def post(self, name):\n        current = self.get_current_user()\n        self.log.warn(\"Admin user %s has requested access to %s's server\",\n            current.name, name,\n        )\n        if not self.settings.get('admin_access', False):\n            raise web.HTTPError(403, \"admin access to user servers disabled\")\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        if not user.running:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        self.set_server_cookie(user)\n\n\ndefault_handlers = [\n    (r\"/api/users\", UserListAPIHandler),\n    (r\"/api/users/([^/]+)\", UserAPIHandler),\n    (r\"/api/users/([^/]+)/server\", UserServerAPIHandler),\n    (r\"/api/users/([^/]+)/admin-access\", UserAdminAccessAPIHandler),\n]\n", "path": "jupyterhub/apihandlers/users.py"}], "after_files": [{"content": "\"\"\"User handlers\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport json\n\nfrom tornado import gen, web\n\nfrom .. import orm\nfrom ..utils import admin_only\nfrom .base import APIHandler\n\n\nclass UserListAPIHandler(APIHandler):\n    @admin_only\n    def get(self):\n        users = self.db.query(orm.User)\n        data = [ self.user_model(u) for u in users ]\n        self.write(json.dumps(data))\n    \n    @admin_only\n    @gen.coroutine\n    def post(self):\n        data = self.get_json_body()\n        if not data or not isinstance(data, dict) or not data.get('usernames'):\n            raise web.HTTPError(400, \"Must specify at least one user to create\")\n        \n        usernames = data.pop('usernames')\n        self._check_user_model(data)\n        # admin is set for all users\n        # to create admin and non-admin users requires at least two API requests\n        admin = data.get('admin', False)\n        \n        to_create = []\n        for name in usernames:\n            user = self.find_user(name)\n            if user is not None:\n                self.log.warn(\"User %s already exists\" % name)\n            else:\n                to_create.append(name)\n        \n        if not to_create:\n            raise web.HTTPError(400, \"All %i users already exist\" % len(usernames))\n        \n        created = []\n        for name in to_create:\n            user = self.user_from_username(name)\n            if admin:\n                user.admin = True\n                self.db.commit()\n            try:\n                yield gen.maybe_future(self.authenticator.add_user(user))\n            except Exception:\n                self.log.error(\"Failed to create user: %s\" % name, exc_info=True)\n                self.db.delete(user)\n                self.db.commit()\n                raise web.HTTPError(400, \"Failed to create user: %s\" % name)\n            else:\n                created.append(user)\n        \n        self.write(json.dumps([ self.user_model(u) for u in created ]))\n        self.set_status(201)\n\n\ndef admin_or_self(method):\n    \"\"\"Decorator for restricting access to either the target user or admin\"\"\"\n    def m(self, name):\n        current = self.get_current_user()\n        if current is None:\n            raise web.HTTPError(403)\n        if not (current.name == name or current.admin):\n            raise web.HTTPError(403)\n        \n        # raise 404 if not found\n        if not self.find_user(name):\n            raise web.HTTPError(404)\n        return method(self, name)\n    return m\n\nclass UserAPIHandler(APIHandler):\n    \n    @admin_or_self\n    def get(self, name):\n        user = self.find_user(name)\n        self.write(json.dumps(self.user_model(user)))\n    \n    @admin_only\n    @gen.coroutine\n    def post(self, name):\n        data = self.get_json_body()\n        user = self.find_user(name)\n        if user is not None:\n            raise web.HTTPError(400, \"User %s already exists\" % name)\n        \n        user = self.user_from_username(name)\n        if data:\n            self._check_user_model(data)\n            if 'admin' in data:\n                user.admin = data['admin']\n                self.db.commit()\n        \n        try:\n            yield gen.maybe_future(self.authenticator.add_user(user))\n        except Exception:\n            self.log.error(\"Failed to create user: %s\" % name, exc_info=True)\n            self.db.delete(user)\n            self.db.commit()\n            raise web.HTTPError(400, \"Failed to create user: %s\" % name)\n        \n        self.write(json.dumps(self.user_model(user)))\n        self.set_status(201)\n    \n    @admin_only\n    @gen.coroutine\n    def delete(self, name):\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        if user.name == self.get_current_user().name:\n            raise web.HTTPError(400, \"Cannot delete yourself!\")\n        if user.stop_pending:\n            raise web.HTTPError(400, \"%s's server is in the process of stopping, please wait.\" % name)\n        if user.running:\n            yield self.stop_single_user(user)\n            if user.stop_pending:\n                raise web.HTTPError(400, \"%s's server is in the process of stopping, please wait.\" % name)\n        \n        yield gen.maybe_future(self.authenticator.delete_user(user))\n        \n        # remove from the db\n        self.db.delete(user)\n        self.db.commit()\n        \n        self.set_status(204)\n    \n    @admin_only\n    def patch(self, name):\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        data = self.get_json_body()\n        self._check_user_model(data)\n        for key, value in data.items():\n            setattr(user, key, value)\n        self.db.commit()\n        self.write(json.dumps(self.user_model(user)))\n\n\nclass UserServerAPIHandler(APIHandler):\n    @gen.coroutine\n    @admin_or_self\n    def post(self, name):\n        user = self.find_user(name)\n        if user.spawner:\n            state = yield user.spawner.poll()\n            if state is None:\n                raise web.HTTPError(400, \"%s's server is already running\" % name)\n\n        yield self.spawn_single_user(user)\n        status = 202 if user.spawn_pending else 201\n        self.set_status(status)\n\n    @gen.coroutine\n    @admin_or_self\n    def delete(self, name):\n        user = self.find_user(name)\n        if user.stop_pending:\n            self.set_status(202)\n            return\n        if not user.running:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        status = yield user.spawner.poll()\n        if status is not None:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        yield self.stop_single_user(user)\n        status = 202 if user.stop_pending else 204\n        self.set_status(status)\n\nclass UserAdminAccessAPIHandler(APIHandler):\n    \"\"\"Grant admins access to single-user servers\n    \n    This handler sets the necessary cookie for an admin to login to a single-user server.\n    \"\"\"\n    @admin_only\n    def post(self, name):\n        current = self.get_current_user()\n        self.log.warn(\"Admin user %s has requested access to %s's server\",\n            current.name, name,\n        )\n        if not self.settings.get('admin_access', False):\n            raise web.HTTPError(403, \"admin access to user servers disabled\")\n        user = self.find_user(name)\n        if user is None:\n            raise web.HTTPError(404)\n        if not user.running:\n            raise web.HTTPError(400, \"%s's server is not running\" % name)\n        self.set_server_cookie(user)\n\n\ndefault_handlers = [\n    (r\"/api/users\", UserListAPIHandler),\n    (r\"/api/users/([^/]+)\", UserAPIHandler),\n    (r\"/api/users/([^/]+)/server\", UserServerAPIHandler),\n    (r\"/api/users/([^/]+)/admin-access\", UserAdminAccessAPIHandler),\n]\n", "path": "jupyterhub/apihandlers/users.py"}]}