We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Feature] Admin Team List - New Team
Admins should be able to create teams quickly for the admin team list page.

**TODO:**
- [x] MVP https://github.com/deckar01/CTFd/commit/c5df9994cbe61bc4815d71247eaa21ee5ed54d3c
- [ ] Fix inline style issue
- [ ] Add tests

![screen shot 2017-11-18 at 4 41 31 pm](https://user-images.githubusercontent.com/3108007/32985404-7a3b5ccc-cc7f-11e7-906f-9dcc20fc2dff.png)
![screen shot 2017-11-18 at 4 41 47 pm](https://user-images.githubusercontent.com/3108007/32985403-7a2946ae-cc7f-11e7-8fe5-fef5c83860a6.png)



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `CTFd/admin/teams.py`
Content:
```
1 from flask import current_app as app, render_template, request, redirect, jsonify, url_for, Blueprint
2 from CTFd.utils import admins_only, is_admin, cache
3 from CTFd.models import db, Teams, Solves, Awards, Unlocks, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError
4 from passlib.hash import bcrypt_sha256
5 from sqlalchemy.sql import not_
6 
7 from CTFd import utils
8 
9 admin_teams = Blueprint('admin_teams', __name__)
10 
11 
12 @admin_teams.route('/admin/teams', defaults={'page': '1'})
13 @admin_teams.route('/admin/teams/<int:page>')
14 @admins_only
15 def admin_teams_view(page):
16     q = request.args.get('q')
17     if q:
18         field = request.args.get('field')
19         teams = []
20         errors = []
21         if field == 'id':
22             if q.isnumeric():
23                 teams = Teams.query.filter(Teams.id == q).order_by(Teams.id.asc()).all()
24             else:
25                 teams = []
26                 errors.append('Your ID search term is not numeric')
27         elif field == 'name':
28             teams = Teams.query.filter(Teams.name.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()
29         elif field == 'email':
30             teams = Teams.query.filter(Teams.email.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()
31         elif field == 'affiliation':
32             teams = Teams.query.filter(Teams.affiliation.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()
33         elif field == 'country':
34             teams = Teams.query.filter(Teams.country.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()
35         return render_template('admin/teams.html', teams=teams, pages=None, curr_page=None, q=q, field=field)
36 
37     page = abs(int(page))
38     results_per_page = 50
39     page_start = results_per_page * (page - 1)
40     page_end = results_per_page * (page - 1) + results_per_page
41 
42     teams = Teams.query.order_by(Teams.id.asc()).slice(page_start, page_end).all()
43     count = db.session.query(db.func.count(Teams.id)).first()[0]
44     pages = int(count / results_per_page) + (count % results_per_page > 0)
45     return render_template('admin/teams.html', teams=teams, pages=pages, curr_page=page)
46 
47 
48 @admin_teams.route('/admin/team/<int:teamid>', methods=['GET', 'POST'])
49 @admins_only
50 def admin_team(teamid):
51     user = Teams.query.filter_by(id=teamid).first_or_404()
52 
53     if request.method == 'GET':
54         solves = Solves.query.filter_by(teamid=teamid).all()
55         solve_ids = [s.chalid for s in solves]
56         missing = Challenges.query.filter(not_(Challenges.id.in_(solve_ids))).all()
57         last_seen = db.func.max(Tracking.date).label('last_seen')
58         addrs = db.session.query(Tracking.ip, last_seen) \
59                           .filter_by(team=teamid) \
60                           .group_by(Tracking.ip) \
61                           .order_by(last_seen.desc()).all()
62         wrong_keys = WrongKeys.query.filter_by(teamid=teamid).order_by(WrongKeys.date.asc()).all()
63         awards = Awards.query.filter_by(teamid=teamid).order_by(Awards.date.asc()).all()
64         score = user.score(admin=True)
65         place = user.place(admin=True)
66         return render_template('admin/team.html', solves=solves, team=user, addrs=addrs, score=score, missing=missing,
67                                place=place, wrong_keys=wrong_keys, awards=awards)
68     elif request.method == 'POST':
69         admin_user = request.form.get('admin', None)
70         if admin_user:
71             admin_user = True if admin_user == 'true' else False
72             user.admin = admin_user
73             # Set user.banned to hide admins from scoreboard
74             user.banned = admin_user
75             db.session.commit()
76             db.session.close()
77             return jsonify({'data': ['success']})
78 
79         verified = request.form.get('verified', None)
80         if verified:
81             verified = True if verified == 'true' else False
82             user.verified = verified
83             db.session.commit()
84             db.session.close()
85             return jsonify({'data': ['success']})
86 
87         name = request.form.get('name', None)
88         password = request.form.get('password', None)
89         email = request.form.get('email', None)
90         website = request.form.get('website', None)
91         affiliation = request.form.get('affiliation', None)
92         country = request.form.get('country', None)
93 
94         errors = []
95 
96         name_used = Teams.query.filter(Teams.name == name).first()
97         if name_used and int(name_used.id) != int(teamid):
98             errors.append('That name is taken')
99 
100         email_used = Teams.query.filter(Teams.email == email).first()
101         if email_used and int(email_used.id) != int(teamid):
102             errors.append('That email is taken')
103 
104         if errors:
105             db.session.close()
106             return jsonify({'data': errors})
107         else:
108             user.name = name
109             if email:
110                 user.email = email
111             if password:
112                 user.password = bcrypt_sha256.encrypt(password)
113             user.website = website
114             user.affiliation = affiliation
115             user.country = country
116             db.session.commit()
117             db.session.close()
118             return jsonify({'data': ['success']})
119 
120 
121 @admin_teams.route('/admin/team/<int:teamid>/mail', methods=['POST'])
122 @admins_only
123 def email_user(teamid):
124     message = request.form.get('msg', None)
125     team = Teams.query.filter(Teams.id == teamid).first()
126     if message and team:
127         if utils.sendmail(team.email, message):
128             return '1'
129     return '0'
130 
131 
132 @admin_teams.route('/admin/team/<int:teamid>/ban', methods=['POST'])
133 @admins_only
134 def ban(teamid):
135     user = Teams.query.filter_by(id=teamid).first_or_404()
136     user.banned = True
137     db.session.commit()
138     db.session.close()
139     return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))
140 
141 
142 @admin_teams.route('/admin/team/<int:teamid>/unban', methods=['POST'])
143 @admins_only
144 def unban(teamid):
145     user = Teams.query.filter_by(id=teamid).first_or_404()
146     user.banned = False
147     db.session.commit()
148     db.session.close()
149     return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))
150 
151 
152 @admin_teams.route('/admin/team/<int:teamid>/delete', methods=['POST'])
153 @admins_only
154 def delete_team(teamid):
155     try:
156         Unlocks.query.filter_by(teamid=teamid).delete()
157         Awards.query.filter_by(teamid=teamid).delete()
158         WrongKeys.query.filter_by(teamid=teamid).delete()
159         Solves.query.filter_by(teamid=teamid).delete()
160         Tracking.query.filter_by(team=teamid).delete()
161         Teams.query.filter_by(id=teamid).delete()
162         db.session.commit()
163         db.session.close()
164     except DatabaseError:
165         return '0'
166     else:
167         return '1'
168 
169 
170 @admin_teams.route('/admin/solves/<teamid>', methods=['GET'])
171 @admins_only
172 def admin_solves(teamid="all"):
173     if teamid == "all":
174         solves = Solves.query.all()
175     else:
176         solves = Solves.query.filter_by(teamid=teamid).all()
177         awards = Awards.query.filter_by(teamid=teamid).all()
178     db.session.close()
179     json_data = {'solves': []}
180     for x in solves:
181         json_data['solves'].append({
182             'id': x.id,
183             'chal': x.chal.name,
184             'chalid': x.chalid,
185             'team': x.teamid,
186             'value': x.chal.value,
187             'category': x.chal.category,
188             'time': utils.unix_time(x.date)
189         })
190     for award in awards:
191         json_data['solves'].append({
192             'chal': award.name,
193             'chalid': None,
194             'team': award.teamid,
195             'value': award.value,
196             'category': award.category or "Award",
197             'time': utils.unix_time(award.date)
198         })
199     json_data['solves'].sort(key=lambda k: k['time'])
200     return jsonify(json_data)
201 
202 
203 @admin_teams.route('/admin/fails/all', defaults={'teamid': 'all'}, methods=['GET'])
204 @admin_teams.route('/admin/fails/<int:teamid>', methods=['GET'])
205 @admins_only
206 def admin_fails(teamid):
207     if teamid == "all":
208         fails = WrongKeys.query.join(Teams, WrongKeys.teamid == Teams.id).filter(Teams.banned == False).count()
209         solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).count()
210         db.session.close()
211         json_data = {'fails': str(fails), 'solves': str(solves)}
212         return jsonify(json_data)
213     else:
214         fails = WrongKeys.query.filter_by(teamid=teamid).count()
215         solves = Solves.query.filter_by(teamid=teamid).count()
216         db.session.close()
217         json_data = {'fails': str(fails), 'solves': str(solves)}
218         return jsonify(json_data)
219 
220 
221 @admin_teams.route('/admin/solves/<int:teamid>/<int:chalid>/solve', methods=['POST'])
222 @admins_only
223 def create_solve(teamid, chalid):
224     solve = Solves(teamid=teamid, chalid=chalid, ip='127.0.0.1', flag='MARKED_AS_SOLVED_BY_ADMIN')
225     db.session.add(solve)
226     db.session.commit()
227     db.session.close()
228     return '1'
229 
230 
231 @admin_teams.route('/admin/solves/<int:keyid>/delete', methods=['POST'])
232 @admins_only
233 def delete_solve(keyid):
234     solve = Solves.query.filter_by(id=keyid).first_or_404()
235     db.session.delete(solve)
236     db.session.commit()
237     db.session.close()
238     return '1'
239 
240 
241 @admin_teams.route('/admin/wrong_keys/<int:keyid>/delete', methods=['POST'])
242 @admins_only
243 def delete_wrong_key(keyid):
244     wrong_key = WrongKeys.query.filter_by(id=keyid).first_or_404()
245     db.session.delete(wrong_key)
246     db.session.commit()
247     db.session.close()
248     return '1'
249 
250 
251 @admin_teams.route('/admin/awards/<int:award_id>/delete', methods=['POST'])
252 @admins_only
253 def delete_award(award_id):
254     award = Awards.query.filter_by(id=award_id).first_or_404()
255     db.session.delete(award)
256     db.session.commit()
257     db.session.close()
258     return '1'
259 
260 
261 @admin_teams.route('/admin/teams/<int:teamid>/awards', methods=['GET'])
262 @admins_only
263 def admin_awards(teamid):
264     awards = Awards.query.filter_by(teamid=teamid).all()
265 
266     awards_list = []
267     for award in awards:
268         awards_list.append({
269             'id': award.id,
270             'name': award.name,
271             'description': award.description,
272             'date': award.date,
273             'value': award.value,
274             'category': award.category,
275             'icon': award.icon
276         })
277     json_data = {'awards': awards_list}
278     return jsonify(json_data)
279 
280 
281 @admin_teams.route('/admin/awards/add', methods=['POST'])
282 @admins_only
283 def create_award():
284     try:
285         teamid = request.form['teamid']
286         name = request.form.get('name', 'Award')
287         value = request.form.get('value', 0)
288         award = Awards(teamid, name, value)
289         award.description = request.form.get('description')
290         award.category = request.form.get('category')
291         db.session.add(award)
292         db.session.commit()
293         db.session.close()
294         return '1'
295     except Exception as e:
296         print(e)
297         return '0'
298
```
--- 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/CTFd/admin/teams.py b/CTFd/admin/teams.py
--- a/CTFd/admin/teams.py
+++ b/CTFd/admin/teams.py
@@ -6,6 +6,8 @@
 
 from CTFd import utils
 
+import re
+
 admin_teams = Blueprint('admin_teams', __name__)
 
 
@@ -45,6 +47,54 @@
     return render_template('admin/teams.html', teams=teams, pages=pages, curr_page=page)
 
 
+@admin_teams.route('/admin/team/new', methods=['POST'])
+@admins_only
+def admin_create_team():
+    name = request.form.get('name', None)
+    password = request.form.get('password', None)
+    email = request.form.get('email', None)
+    website = request.form.get('website', None)
+    affiliation = request.form.get('affiliation', None)
+    country = request.form.get('country', None)
+
+    errors = []
+
+    if not name:
+        errors.append('The team requires a name')
+    elif Teams.query.filter(Teams.name == name).first():
+        errors.append('That name is taken')
+
+    if not email:
+        errors.append('The team requires an email')
+    elif Teams.query.filter(Teams.email == email).first():
+        errors.append('That email is taken')
+
+    if email:
+        valid_email = re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email)
+        if not valid_email:
+            errors.append("That email address is invalid")
+
+    if not password:
+        errors.append('The team requires a password')
+
+    if website and (website.startswith('http://') or website.startswith('https://')) is False:
+        errors.append('Websites must start with http:// or https://')
+
+    if errors:
+        db.session.close()
+        return jsonify({'data': errors})
+
+    team = Teams(name, email, password)
+    team.website = website
+    team.affiliation = affiliation
+    team.country = country
+
+    db.session.add(team)
+    db.session.commit()
+    db.session.close()
+    return jsonify({'data': ['success']})
+
+
 @admin_teams.route('/admin/team/<int:teamid>', methods=['GET', 'POST'])
 @admins_only
 def admin_team(teamid):
@@ -93,6 +143,11 @@
 
         errors = []
 
+        if email:
+            valid_email = re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email)
+            if not valid_email:
+                errors.append("That email address is invalid")
+
         name_used = Teams.query.filter(Teams.name == name).first()
         if name_used and int(name_used.id) != int(teamid):
             errors.append('That name is taken')
@@ -101,6 +156,9 @@
         if email_used and int(email_used.id) != int(teamid):
             errors.append('That email is taken')
 
+        if website and (website.startswith('http://') or website.startswith('https://')) is False:
+            errors.append('Websites must start with http:// or https://')
+
         if errors:
             db.session.close()
             return jsonify({'data': errors})

{"golden_diff": "diff --git a/CTFd/admin/teams.py b/CTFd/admin/teams.py\n--- a/CTFd/admin/teams.py\n+++ b/CTFd/admin/teams.py\n@@ -6,6 +6,8 @@\n \n from CTFd import utils\n \n+import re\n+\n admin_teams = Blueprint('admin_teams', __name__)\n \n \n@@ -45,6 +47,54 @@\n     return render_template('admin/teams.html', teams=teams, pages=pages, curr_page=page)\n \n \n+@admin_teams.route('/admin/team/new', methods=['POST'])\n+@admins_only\n+def admin_create_team():\n+    name = request.form.get('name', None)\n+    password = request.form.get('password', None)\n+    email = request.form.get('email', None)\n+    website = request.form.get('website', None)\n+    affiliation = request.form.get('affiliation', None)\n+    country = request.form.get('country', None)\n+\n+    errors = []\n+\n+    if not name:\n+        errors.append('The team requires a name')\n+    elif Teams.query.filter(Teams.name == name).first():\n+        errors.append('That name is taken')\n+\n+    if not email:\n+        errors.append('The team requires an email')\n+    elif Teams.query.filter(Teams.email == email).first():\n+        errors.append('That email is taken')\n+\n+    if email:\n+        valid_email = re.match(r\"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)\", email)\n+        if not valid_email:\n+            errors.append(\"That email address is invalid\")\n+\n+    if not password:\n+        errors.append('The team requires a password')\n+\n+    if website and (website.startswith('http://') or website.startswith('https://')) is False:\n+        errors.append('Websites must start with http:// or https://')\n+\n+    if errors:\n+        db.session.close()\n+        return jsonify({'data': errors})\n+\n+    team = Teams(name, email, password)\n+    team.website = website\n+    team.affiliation = affiliation\n+    team.country = country\n+\n+    db.session.add(team)\n+    db.session.commit()\n+    db.session.close()\n+    return jsonify({'data': ['success']})\n+\n+\n @admin_teams.route('/admin/team/<int:teamid>', methods=['GET', 'POST'])\n @admins_only\n def admin_team(teamid):\n@@ -93,6 +143,11 @@\n \n         errors = []\n \n+        if email:\n+            valid_email = re.match(r\"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)\", email)\n+            if not valid_email:\n+                errors.append(\"That email address is invalid\")\n+\n         name_used = Teams.query.filter(Teams.name == name).first()\n         if name_used and int(name_used.id) != int(teamid):\n             errors.append('That name is taken')\n@@ -101,6 +156,9 @@\n         if email_used and int(email_used.id) != int(teamid):\n             errors.append('That email is taken')\n \n+        if website and (website.startswith('http://') or website.startswith('https://')) is False:\n+            errors.append('Websites must start with http:// or https://')\n+\n         if errors:\n             db.session.close()\n             return jsonify({'data': errors})\n", "issue": "[Feature] Admin Team List - New Team\nAdmins should be able to create teams quickly for the admin team list page.\r\n\r\n**TODO:**\r\n- [x] MVP https://github.com/deckar01/CTFd/commit/c5df9994cbe61bc4815d71247eaa21ee5ed54d3c\r\n- [ ] Fix inline style issue\r\n- [ ] Add tests\r\n\r\n![screen shot 2017-11-18 at 4 41 31 pm](https://user-images.githubusercontent.com/3108007/32985404-7a3b5ccc-cc7f-11e7-906f-9dcc20fc2dff.png)\r\n![screen shot 2017-11-18 at 4 41 47 pm](https://user-images.githubusercontent.com/3108007/32985403-7a2946ae-cc7f-11e7-8fe5-fef5c83860a6.png)\r\n\r\n\n", "before_files": [{"content": "from flask import current_app as app, render_template, request, redirect, jsonify, url_for, Blueprint\nfrom CTFd.utils import admins_only, is_admin, cache\nfrom CTFd.models import db, Teams, Solves, Awards, Unlocks, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError\nfrom passlib.hash import bcrypt_sha256\nfrom sqlalchemy.sql import not_\n\nfrom CTFd import utils\n\nadmin_teams = Blueprint('admin_teams', __name__)\n\n\n@admin_teams.route('/admin/teams', defaults={'page': '1'})\n@admin_teams.route('/admin/teams/<int:page>')\n@admins_only\ndef admin_teams_view(page):\n    q = request.args.get('q')\n    if q:\n        field = request.args.get('field')\n        teams = []\n        errors = []\n        if field == 'id':\n            if q.isnumeric():\n                teams = Teams.query.filter(Teams.id == q).order_by(Teams.id.asc()).all()\n            else:\n                teams = []\n                errors.append('Your ID search term is not numeric')\n        elif field == 'name':\n            teams = Teams.query.filter(Teams.name.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'email':\n            teams = Teams.query.filter(Teams.email.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'affiliation':\n            teams = Teams.query.filter(Teams.affiliation.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'country':\n            teams = Teams.query.filter(Teams.country.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        return render_template('admin/teams.html', teams=teams, pages=None, curr_page=None, q=q, field=field)\n\n    page = abs(int(page))\n    results_per_page = 50\n    page_start = results_per_page * (page - 1)\n    page_end = results_per_page * (page - 1) + results_per_page\n\n    teams = Teams.query.order_by(Teams.id.asc()).slice(page_start, page_end).all()\n    count = db.session.query(db.func.count(Teams.id)).first()[0]\n    pages = int(count / results_per_page) + (count % results_per_page > 0)\n    return render_template('admin/teams.html', teams=teams, pages=pages, curr_page=page)\n\n\n@admin_teams.route('/admin/team/<int:teamid>', methods=['GET', 'POST'])\n@admins_only\ndef admin_team(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n\n    if request.method == 'GET':\n        solves = Solves.query.filter_by(teamid=teamid).all()\n        solve_ids = [s.chalid for s in solves]\n        missing = Challenges.query.filter(not_(Challenges.id.in_(solve_ids))).all()\n        last_seen = db.func.max(Tracking.date).label('last_seen')\n        addrs = db.session.query(Tracking.ip, last_seen) \\\n                          .filter_by(team=teamid) \\\n                          .group_by(Tracking.ip) \\\n                          .order_by(last_seen.desc()).all()\n        wrong_keys = WrongKeys.query.filter_by(teamid=teamid).order_by(WrongKeys.date.asc()).all()\n        awards = Awards.query.filter_by(teamid=teamid).order_by(Awards.date.asc()).all()\n        score = user.score(admin=True)\n        place = user.place(admin=True)\n        return render_template('admin/team.html', solves=solves, team=user, addrs=addrs, score=score, missing=missing,\n                               place=place, wrong_keys=wrong_keys, awards=awards)\n    elif request.method == 'POST':\n        admin_user = request.form.get('admin', None)\n        if admin_user:\n            admin_user = True if admin_user == 'true' else False\n            user.admin = admin_user\n            # Set user.banned to hide admins from scoreboard\n            user.banned = admin_user\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n        verified = request.form.get('verified', None)\n        if verified:\n            verified = True if verified == 'true' else False\n            user.verified = verified\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n        name = request.form.get('name', None)\n        password = request.form.get('password', None)\n        email = request.form.get('email', None)\n        website = request.form.get('website', None)\n        affiliation = request.form.get('affiliation', None)\n        country = request.form.get('country', None)\n\n        errors = []\n\n        name_used = Teams.query.filter(Teams.name == name).first()\n        if name_used and int(name_used.id) != int(teamid):\n            errors.append('That name is taken')\n\n        email_used = Teams.query.filter(Teams.email == email).first()\n        if email_used and int(email_used.id) != int(teamid):\n            errors.append('That email is taken')\n\n        if errors:\n            db.session.close()\n            return jsonify({'data': errors})\n        else:\n            user.name = name\n            if email:\n                user.email = email\n            if password:\n                user.password = bcrypt_sha256.encrypt(password)\n            user.website = website\n            user.affiliation = affiliation\n            user.country = country\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n\n@admin_teams.route('/admin/team/<int:teamid>/mail', methods=['POST'])\n@admins_only\ndef email_user(teamid):\n    message = request.form.get('msg', None)\n    team = Teams.query.filter(Teams.id == teamid).first()\n    if message and team:\n        if utils.sendmail(team.email, message):\n            return '1'\n    return '0'\n\n\n@admin_teams.route('/admin/team/<int:teamid>/ban', methods=['POST'])\n@admins_only\ndef ban(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    user.banned = True\n    db.session.commit()\n    db.session.close()\n    return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))\n\n\n@admin_teams.route('/admin/team/<int:teamid>/unban', methods=['POST'])\n@admins_only\ndef unban(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    user.banned = False\n    db.session.commit()\n    db.session.close()\n    return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))\n\n\n@admin_teams.route('/admin/team/<int:teamid>/delete', methods=['POST'])\n@admins_only\ndef delete_team(teamid):\n    try:\n        Unlocks.query.filter_by(teamid=teamid).delete()\n        Awards.query.filter_by(teamid=teamid).delete()\n        WrongKeys.query.filter_by(teamid=teamid).delete()\n        Solves.query.filter_by(teamid=teamid).delete()\n        Tracking.query.filter_by(team=teamid).delete()\n        Teams.query.filter_by(id=teamid).delete()\n        db.session.commit()\n        db.session.close()\n    except DatabaseError:\n        return '0'\n    else:\n        return '1'\n\n\n@admin_teams.route('/admin/solves/<teamid>', methods=['GET'])\n@admins_only\ndef admin_solves(teamid=\"all\"):\n    if teamid == \"all\":\n        solves = Solves.query.all()\n    else:\n        solves = Solves.query.filter_by(teamid=teamid).all()\n        awards = Awards.query.filter_by(teamid=teamid).all()\n    db.session.close()\n    json_data = {'solves': []}\n    for x in solves:\n        json_data['solves'].append({\n            'id': x.id,\n            'chal': x.chal.name,\n            'chalid': x.chalid,\n            'team': x.teamid,\n            'value': x.chal.value,\n            'category': x.chal.category,\n            'time': utils.unix_time(x.date)\n        })\n    for award in awards:\n        json_data['solves'].append({\n            'chal': award.name,\n            'chalid': None,\n            'team': award.teamid,\n            'value': award.value,\n            'category': award.category or \"Award\",\n            'time': utils.unix_time(award.date)\n        })\n    json_data['solves'].sort(key=lambda k: k['time'])\n    return jsonify(json_data)\n\n\n@admin_teams.route('/admin/fails/all', defaults={'teamid': 'all'}, methods=['GET'])\n@admin_teams.route('/admin/fails/<int:teamid>', methods=['GET'])\n@admins_only\ndef admin_fails(teamid):\n    if teamid == \"all\":\n        fails = WrongKeys.query.join(Teams, WrongKeys.teamid == Teams.id).filter(Teams.banned == False).count()\n        solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).count()\n        db.session.close()\n        json_data = {'fails': str(fails), 'solves': str(solves)}\n        return jsonify(json_data)\n    else:\n        fails = WrongKeys.query.filter_by(teamid=teamid).count()\n        solves = Solves.query.filter_by(teamid=teamid).count()\n        db.session.close()\n        json_data = {'fails': str(fails), 'solves': str(solves)}\n        return jsonify(json_data)\n\n\n@admin_teams.route('/admin/solves/<int:teamid>/<int:chalid>/solve', methods=['POST'])\n@admins_only\ndef create_solve(teamid, chalid):\n    solve = Solves(teamid=teamid, chalid=chalid, ip='127.0.0.1', flag='MARKED_AS_SOLVED_BY_ADMIN')\n    db.session.add(solve)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/solves/<int:keyid>/delete', methods=['POST'])\n@admins_only\ndef delete_solve(keyid):\n    solve = Solves.query.filter_by(id=keyid).first_or_404()\n    db.session.delete(solve)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/wrong_keys/<int:keyid>/delete', methods=['POST'])\n@admins_only\ndef delete_wrong_key(keyid):\n    wrong_key = WrongKeys.query.filter_by(id=keyid).first_or_404()\n    db.session.delete(wrong_key)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/awards/<int:award_id>/delete', methods=['POST'])\n@admins_only\ndef delete_award(award_id):\n    award = Awards.query.filter_by(id=award_id).first_or_404()\n    db.session.delete(award)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/teams/<int:teamid>/awards', methods=['GET'])\n@admins_only\ndef admin_awards(teamid):\n    awards = Awards.query.filter_by(teamid=teamid).all()\n\n    awards_list = []\n    for award in awards:\n        awards_list.append({\n            'id': award.id,\n            'name': award.name,\n            'description': award.description,\n            'date': award.date,\n            'value': award.value,\n            'category': award.category,\n            'icon': award.icon\n        })\n    json_data = {'awards': awards_list}\n    return jsonify(json_data)\n\n\n@admin_teams.route('/admin/awards/add', methods=['POST'])\n@admins_only\ndef create_award():\n    try:\n        teamid = request.form['teamid']\n        name = request.form.get('name', 'Award')\n        value = request.form.get('value', 0)\n        award = Awards(teamid, name, value)\n        award.description = request.form.get('description')\n        award.category = request.form.get('category')\n        db.session.add(award)\n        db.session.commit()\n        db.session.close()\n        return '1'\n    except Exception as e:\n        print(e)\n        return '0'\n", "path": "CTFd/admin/teams.py"}], "after_files": [{"content": "from flask import current_app as app, render_template, request, redirect, jsonify, url_for, Blueprint\nfrom CTFd.utils import admins_only, is_admin, cache\nfrom CTFd.models import db, Teams, Solves, Awards, Unlocks, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config, DatabaseError\nfrom passlib.hash import bcrypt_sha256\nfrom sqlalchemy.sql import not_\n\nfrom CTFd import utils\n\nimport re\n\nadmin_teams = Blueprint('admin_teams', __name__)\n\n\n@admin_teams.route('/admin/teams', defaults={'page': '1'})\n@admin_teams.route('/admin/teams/<int:page>')\n@admins_only\ndef admin_teams_view(page):\n    q = request.args.get('q')\n    if q:\n        field = request.args.get('field')\n        teams = []\n        errors = []\n        if field == 'id':\n            if q.isnumeric():\n                teams = Teams.query.filter(Teams.id == q).order_by(Teams.id.asc()).all()\n            else:\n                teams = []\n                errors.append('Your ID search term is not numeric')\n        elif field == 'name':\n            teams = Teams.query.filter(Teams.name.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'email':\n            teams = Teams.query.filter(Teams.email.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'affiliation':\n            teams = Teams.query.filter(Teams.affiliation.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        elif field == 'country':\n            teams = Teams.query.filter(Teams.country.like('%{}%'.format(q))).order_by(Teams.id.asc()).all()\n        return render_template('admin/teams.html', teams=teams, pages=None, curr_page=None, q=q, field=field)\n\n    page = abs(int(page))\n    results_per_page = 50\n    page_start = results_per_page * (page - 1)\n    page_end = results_per_page * (page - 1) + results_per_page\n\n    teams = Teams.query.order_by(Teams.id.asc()).slice(page_start, page_end).all()\n    count = db.session.query(db.func.count(Teams.id)).first()[0]\n    pages = int(count / results_per_page) + (count % results_per_page > 0)\n    return render_template('admin/teams.html', teams=teams, pages=pages, curr_page=page)\n\n\n@admin_teams.route('/admin/team/new', methods=['POST'])\n@admins_only\ndef admin_create_team():\n    name = request.form.get('name', None)\n    password = request.form.get('password', None)\n    email = request.form.get('email', None)\n    website = request.form.get('website', None)\n    affiliation = request.form.get('affiliation', None)\n    country = request.form.get('country', None)\n\n    errors = []\n\n    if not name:\n        errors.append('The team requires a name')\n    elif Teams.query.filter(Teams.name == name).first():\n        errors.append('That name is taken')\n\n    if not email:\n        errors.append('The team requires an email')\n    elif Teams.query.filter(Teams.email == email).first():\n        errors.append('That email is taken')\n\n    if email:\n        valid_email = re.match(r\"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)\", email)\n        if not valid_email:\n            errors.append(\"That email address is invalid\")\n\n    if not password:\n        errors.append('The team requires a password')\n\n    if website and (website.startswith('http://') or website.startswith('https://')) is False:\n        errors.append('Websites must start with http:// or https://')\n\n    if errors:\n        db.session.close()\n        return jsonify({'data': errors})\n\n    team = Teams(name, email, password)\n    team.website = website\n    team.affiliation = affiliation\n    team.country = country\n\n    db.session.add(team)\n    db.session.commit()\n    db.session.close()\n    return jsonify({'data': ['success']})\n\n\n@admin_teams.route('/admin/team/<int:teamid>', methods=['GET', 'POST'])\n@admins_only\ndef admin_team(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n\n    if request.method == 'GET':\n        solves = Solves.query.filter_by(teamid=teamid).all()\n        solve_ids = [s.chalid for s in solves]\n        missing = Challenges.query.filter(not_(Challenges.id.in_(solve_ids))).all()\n        last_seen = db.func.max(Tracking.date).label('last_seen')\n        addrs = db.session.query(Tracking.ip, last_seen) \\\n                          .filter_by(team=teamid) \\\n                          .group_by(Tracking.ip) \\\n                          .order_by(last_seen.desc()).all()\n        wrong_keys = WrongKeys.query.filter_by(teamid=teamid).order_by(WrongKeys.date.asc()).all()\n        awards = Awards.query.filter_by(teamid=teamid).order_by(Awards.date.asc()).all()\n        score = user.score(admin=True)\n        place = user.place(admin=True)\n        return render_template('admin/team.html', solves=solves, team=user, addrs=addrs, score=score, missing=missing,\n                               place=place, wrong_keys=wrong_keys, awards=awards)\n    elif request.method == 'POST':\n        admin_user = request.form.get('admin', None)\n        if admin_user:\n            admin_user = True if admin_user == 'true' else False\n            user.admin = admin_user\n            # Set user.banned to hide admins from scoreboard\n            user.banned = admin_user\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n        verified = request.form.get('verified', None)\n        if verified:\n            verified = True if verified == 'true' else False\n            user.verified = verified\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n        name = request.form.get('name', None)\n        password = request.form.get('password', None)\n        email = request.form.get('email', None)\n        website = request.form.get('website', None)\n        affiliation = request.form.get('affiliation', None)\n        country = request.form.get('country', None)\n\n        errors = []\n\n        if email:\n            valid_email = re.match(r\"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)\", email)\n            if not valid_email:\n                errors.append(\"That email address is invalid\")\n\n        name_used = Teams.query.filter(Teams.name == name).first()\n        if name_used and int(name_used.id) != int(teamid):\n            errors.append('That name is taken')\n\n        email_used = Teams.query.filter(Teams.email == email).first()\n        if email_used and int(email_used.id) != int(teamid):\n            errors.append('That email is taken')\n\n        if website and (website.startswith('http://') or website.startswith('https://')) is False:\n            errors.append('Websites must start with http:// or https://')\n\n        if errors:\n            db.session.close()\n            return jsonify({'data': errors})\n        else:\n            user.name = name\n            if email:\n                user.email = email\n            if password:\n                user.password = bcrypt_sha256.encrypt(password)\n            user.website = website\n            user.affiliation = affiliation\n            user.country = country\n            db.session.commit()\n            db.session.close()\n            return jsonify({'data': ['success']})\n\n\n@admin_teams.route('/admin/team/<int:teamid>/mail', methods=['POST'])\n@admins_only\ndef email_user(teamid):\n    message = request.form.get('msg', None)\n    team = Teams.query.filter(Teams.id == teamid).first()\n    if message and team:\n        if utils.sendmail(team.email, message):\n            return '1'\n    return '0'\n\n\n@admin_teams.route('/admin/team/<int:teamid>/ban', methods=['POST'])\n@admins_only\ndef ban(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    user.banned = True\n    db.session.commit()\n    db.session.close()\n    return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))\n\n\n@admin_teams.route('/admin/team/<int:teamid>/unban', methods=['POST'])\n@admins_only\ndef unban(teamid):\n    user = Teams.query.filter_by(id=teamid).first_or_404()\n    user.banned = False\n    db.session.commit()\n    db.session.close()\n    return redirect(url_for('admin_scoreboard.admin_scoreboard_view'))\n\n\n@admin_teams.route('/admin/team/<int:teamid>/delete', methods=['POST'])\n@admins_only\ndef delete_team(teamid):\n    try:\n        Unlocks.query.filter_by(teamid=teamid).delete()\n        Awards.query.filter_by(teamid=teamid).delete()\n        WrongKeys.query.filter_by(teamid=teamid).delete()\n        Solves.query.filter_by(teamid=teamid).delete()\n        Tracking.query.filter_by(team=teamid).delete()\n        Teams.query.filter_by(id=teamid).delete()\n        db.session.commit()\n        db.session.close()\n    except DatabaseError:\n        return '0'\n    else:\n        return '1'\n\n\n@admin_teams.route('/admin/solves/<teamid>', methods=['GET'])\n@admins_only\ndef admin_solves(teamid=\"all\"):\n    if teamid == \"all\":\n        solves = Solves.query.all()\n    else:\n        solves = Solves.query.filter_by(teamid=teamid).all()\n        awards = Awards.query.filter_by(teamid=teamid).all()\n    db.session.close()\n    json_data = {'solves': []}\n    for x in solves:\n        json_data['solves'].append({\n            'id': x.id,\n            'chal': x.chal.name,\n            'chalid': x.chalid,\n            'team': x.teamid,\n            'value': x.chal.value,\n            'category': x.chal.category,\n            'time': utils.unix_time(x.date)\n        })\n    for award in awards:\n        json_data['solves'].append({\n            'chal': award.name,\n            'chalid': None,\n            'team': award.teamid,\n            'value': award.value,\n            'category': award.category or \"Award\",\n            'time': utils.unix_time(award.date)\n        })\n    json_data['solves'].sort(key=lambda k: k['time'])\n    return jsonify(json_data)\n\n\n@admin_teams.route('/admin/fails/all', defaults={'teamid': 'all'}, methods=['GET'])\n@admin_teams.route('/admin/fails/<int:teamid>', methods=['GET'])\n@admins_only\ndef admin_fails(teamid):\n    if teamid == \"all\":\n        fails = WrongKeys.query.join(Teams, WrongKeys.teamid == Teams.id).filter(Teams.banned == False).count()\n        solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).count()\n        db.session.close()\n        json_data = {'fails': str(fails), 'solves': str(solves)}\n        return jsonify(json_data)\n    else:\n        fails = WrongKeys.query.filter_by(teamid=teamid).count()\n        solves = Solves.query.filter_by(teamid=teamid).count()\n        db.session.close()\n        json_data = {'fails': str(fails), 'solves': str(solves)}\n        return jsonify(json_data)\n\n\n@admin_teams.route('/admin/solves/<int:teamid>/<int:chalid>/solve', methods=['POST'])\n@admins_only\ndef create_solve(teamid, chalid):\n    solve = Solves(teamid=teamid, chalid=chalid, ip='127.0.0.1', flag='MARKED_AS_SOLVED_BY_ADMIN')\n    db.session.add(solve)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/solves/<int:keyid>/delete', methods=['POST'])\n@admins_only\ndef delete_solve(keyid):\n    solve = Solves.query.filter_by(id=keyid).first_or_404()\n    db.session.delete(solve)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/wrong_keys/<int:keyid>/delete', methods=['POST'])\n@admins_only\ndef delete_wrong_key(keyid):\n    wrong_key = WrongKeys.query.filter_by(id=keyid).first_or_404()\n    db.session.delete(wrong_key)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/awards/<int:award_id>/delete', methods=['POST'])\n@admins_only\ndef delete_award(award_id):\n    award = Awards.query.filter_by(id=award_id).first_or_404()\n    db.session.delete(award)\n    db.session.commit()\n    db.session.close()\n    return '1'\n\n\n@admin_teams.route('/admin/teams/<int:teamid>/awards', methods=['GET'])\n@admins_only\ndef admin_awards(teamid):\n    awards = Awards.query.filter_by(teamid=teamid).all()\n\n    awards_list = []\n    for award in awards:\n        awards_list.append({\n            'id': award.id,\n            'name': award.name,\n            'description': award.description,\n            'date': award.date,\n            'value': award.value,\n            'category': award.category,\n            'icon': award.icon\n        })\n    json_data = {'awards': awards_list}\n    return jsonify(json_data)\n\n\n@admin_teams.route('/admin/awards/add', methods=['POST'])\n@admins_only\ndef create_award():\n    try:\n        teamid = request.form['teamid']\n        name = request.form.get('name', 'Award')\n        value = request.form.get('value', 0)\n        award = Awards(teamid, name, value)\n        award.description = request.form.get('description')\n        award.category = request.form.get('category')\n        db.session.add(award)\n        db.session.commit()\n        db.session.close()\n        return '1'\n    except Exception as e:\n        print(e)\n        return '0'\n", "path": "CTFd/admin/teams.py"}]}