internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: CTFd/CTFd

Issue:
Unnecessary ping event
**Environment**:

- CTFd Version/Commit: 3.1.1, latest commit
- Operating System: any
- Web Browser and Version: any

in the comment you said "Immediately yield a ping event to force Response headers to be set", but this event seems to lies inside the while True loop, which results to an unnecessary ping event every 5 seconds.
I believe that's an unintended behavior, though it doesn't break anything.

https://github.com/CTFd/CTFd/blob/4c31dc23e8cfa0308367732d603b16e01871b00e/CTFd/utils/events/__init__.py#L57-L67


Discussion:
sounds like this is the intended thing to do:

```python
yield PingEvent
while True:
	wait for event, send ping if timed out
```
these lines are introduced in #1400 btw
may I ask for some comments  on this?

Resolving patch:
diff --git a/CTFd/utils/events/__init__.py b/CTFd/utils/events/__init__.py
--- a/CTFd/utils/events/__init__.py
+++ b/CTFd/utils/events/__init__.py
@@ -54,12 +54,11 @@ def subscribe(self, channel="ctf"):
         q = defaultdict(Queue)
         self.clients[id(q)] = q
         try:
+            # Immediately yield a ping event to force Response headers to be set
+            # or else some reverse proxies will incorrectly buffer SSE
+            yield ServerSentEvent(data="", type="ping")
             while True:
                 try:
-                    # Immediately yield a ping event to force Response headers to be set
-                    # or else some reverse proxies will incorrectly buffer SSE
-                    yield ServerSentEvent(data="", type="ping")
-
                     with Timeout(5):
                         message = q[channel].get()
                         yield ServerSentEvent(**message)
@@ -106,12 +105,11 @@ def subscribe(self, channel="ctf"):
         q = defaultdict(Queue)
         self.clients[id(q)] = q
         try:
+            # Immediately yield a ping event to force Response headers to be set
+            # or else some reverse proxies will incorrectly buffer SSE
+            yield ServerSentEvent(data="", type="ping")
             while True:
                 try:
-                    # Immediately yield a ping event to force Response headers to be set
-                    # or else some reverse proxies will incorrectly buffer SSE
-                    yield ServerSentEvent(data="", type="ping")
-
                     with Timeout(5):
                         message = q[channel].get()
                         yield ServerSentEvent(**message)


Test patch:
Repository: CTFd/CTFd

Issue:
Incorrect update alert in Admin panel
<!--
If this is a bug report please fill out the template below.

If this is a feature request please describe the behavior that you'd like to see.
-->

**Environment**:

- CTFd Version/Commit: 3.1.1
- Operating System: Ubuntu 20.4
- Web Browser and Version: Chrome 85

**What happened?**
The admin panel shows an alert: "A new CTFd version is available!", which links to "https://github.com/CTFd/CTFd/releases/tag/2.4.2". I encountered the issue with version 3.0.2. as well. After complete reinstall and upgrade to version 3.1.1 the problem persisted

**What did you expect to happen?**
I expected no alert, as my CTFd version is the newest, and certainly newer than 2.4.2.

**How to reproduce your issue**
Go to the admin pages.

**Any associated stack traces or error logs**
No


Discussion:
Are update checks enabled? This can happen if you disable updates checking but a prior update check left data there. I think you can clear it out by setting `version_latest` in the Configs table to null. 
I never changed the updates checking and according to /CTFd/config.ini line 161 it defaults to true, so I can't see how that could be the issue.
If that's the case then if you restart the CTFd server the update should go away after it's startup update check. 
I've tried that multiple times but it doesn't seem to work. I've also tried changing update_check(Force=False) to true (CTFd/utils/updates/__init__.py, line 15) and changing CTFd/config.py line 214 to True but it just doesn't seem to update for some reason.
Very odd. Perhaps you can remove some of the exception handling code in https://github.com/CTFd/CTFd/blob/master/CTFd/utils/updates/__init__.py#L38-L75 to see if maybe you're getting an invalid response or not getting a response fast enough. Aside from that I don't have any idea until I can spend some time to dig into this. 

If you just want to clear out the alert I think you can just do `python manage.py set_config version_latest ""`. Normally you would set it to be None but I don't think think manage.py understands raw Python values. 
I've looked into it but can't get it to work. I guess I'm just gonna have to live with it. Thanks for your time anyway!
I've seen this before myself so I'll re-open this issue to track progress on investigating it. 

Resolving patch:
diff --git a/CTFd/utils/updates/__init__.py b/CTFd/utils/updates/__init__.py
--- a/CTFd/utils/updates/__init__.py
+++ b/CTFd/utils/updates/__init__.py
@@ -53,7 +53,7 @@ def update_check(force=False):
                 "channel": app.CHANNEL,
             }
             check = requests.get(
-                "https://versioning.ctfd.io/check", params=params, timeout=0.1
+                "https://versioning.ctfd.io/check", params=params, timeout=3
             ).json()
         except requests.exceptions.RequestException:
             pass


Test patch:
Repository: CTFd/CTFd

Issue:
Ability to add members to a team via Admin Panel
Hey there!

I'm making a CTF and I am making users and team registration externally. I have seen that you are able to remove players from teams via the Admin Panel, but you are unable to do the reverse. It'd be great to add users from there, and not having to login into the player account and click "Join team".

Thanks!


Discussion:
This will be done in a later version of CTFd. The kind of searching functionality that this requires isn't something that has been prioritized in CTFd before. I would probably look to do this from a plugin/script or with database access for the time being. 
It looks like this already kind of exists via `POST /api/v1/teams/[team_id]/memberes`. 

Resolving patch:
diff --git a/CTFd/api/v1/users.py b/CTFd/api/v1/users.py
--- a/CTFd/api/v1/users.py
+++ b/CTFd/api/v1/users.py
@@ -132,7 +132,6 @@ def get(self, query_args):
             "data": response.data,
         }
 
-    @users_namespace.doc()
     @admins_only
     @users_namespace.doc(
         description="Endpoint to create a User object",
diff --git a/CTFd/schemas/users.py b/CTFd/schemas/users.py
--- a/CTFd/schemas/users.py
+++ b/CTFd/schemas/users.py
@@ -316,6 +316,7 @@ def process_fields(self, data):
             "id",
             "oauth_id",
             "fields",
+            "team_id",
         ],
         "self": [
             "website",
@@ -328,6 +329,7 @@ def process_fields(self, data):
             "oauth_id",
             "password",
             "fields",
+            "team_id",
         ],
         "admin": [
             "website",
@@ -346,6 +348,7 @@ def process_fields(self, data):
             "type",
             "verified",
             "fields",
+            "team_id",
         ],
     }
 


Test patch:
Repository: CTFd/CTFd

Issue:
CTFd pages route is relative when it shouldn't be
For some reason CTFd page routes are being generated in the navbar as relative when they shouldn't be. E.g. (`page` instead of `/page`).


Discussion:

Resolving patch:
diff --git a/CTFd/plugins/__init__.py b/CTFd/plugins/__init__.py
--- a/CTFd/plugins/__init__.py
+++ b/CTFd/plugins/__init__.py
@@ -4,7 +4,7 @@
 from collections import namedtuple
 
 from flask import current_app as app
-from flask import send_file, send_from_directory
+from flask import send_file, send_from_directory, url_for
 
 from CTFd.utils.config.pages import get_pages
 from CTFd.utils.decorators import admins_only as admins_only_wrapper
@@ -145,7 +145,15 @@ def get_user_page_menu_bar():
 
     :return: Returns a list of Menu namedtuples. They have name, and route attributes.
     """
-    return get_pages() + app.plugin_menu_bar
+    pages = []
+    for p in get_pages() + app.plugin_menu_bar:
+        if p.route.startswith("http"):
+            route = p.route
+        else:
+            route = url_for("views.static_html", route=p.route)
+            print(route)
+        pages.append(Menu(title=p.title, route=route))
+    return pages
 
 
 def bypass_csrf_protection(f):


Test patch:
diff --git a/tests/test_plugin_utils.py b/tests/test_plugin_utils.py
--- a/tests/test_plugin_utils.py
+++ b/tests/test_plugin_utils.py
@@ -165,14 +165,14 @@ def test_register_user_page_menu_bar():
 
         with app.test_client() as client:
             r = client.get("/")
+            output = r.get_data(as_text=True)
+            assert "/test_user_href" in output
+            assert "test_user_menu_link" in output
 
-        output = r.get_data(as_text=True)
-        assert "/test_user_href" in output
-        assert "test_user_menu_link" in output
-
-        menu_item = get_user_page_menu_bar()[0]
-        assert menu_item.title == "test_user_menu_link"
-        assert menu_item.route == "/test_user_href"
+        with app.test_request_context():
+            menu_item = get_user_page_menu_bar()[0]
+            assert menu_item.title == "test_user_menu_link"
+            assert menu_item.route == "/test_user_href"
     destroy_ctfd(app)
Repository: CTFd/CTFd

Issue:
Invalid model identifier
https://github.com/CTFd/CTFd/blob/master/CTFd/themes/core/templates/scoreboard.html#L26

This should change depending on the mode of the CTF


Discussion:

Resolving patch:
diff --git a/CTFd/plugins/__init__.py b/CTFd/plugins/__init__.py
--- a/CTFd/plugins/__init__.py
+++ b/CTFd/plugins/__init__.py
@@ -151,7 +151,6 @@ def get_user_page_menu_bar():
             route = p.route
         else:
             route = url_for("views.static_html", route=p.route)
-            print(route)
         pages.append(Menu(title=p.title, route=route))
     return pages
 


Test patch:
Repository: CTFd/CTFd

Issue:
Feature request: disable team creation
I have a use case where the teams are manually created and the students receive the teamname+passcode. Team creation should be disabled so that they only can join an existing team.


Discussion:
Do you directly insert the Teams in the Database then?

Resolving patch:
diff --git a/CTFd/forms/config.py b/CTFd/forms/config.py
--- a/CTFd/forms/config.py
+++ b/CTFd/forms/config.py
@@ -33,8 +33,15 @@ class AccountSettingsForm(BaseForm):
         "Account Email Whitelist",
         description="Comma-seperated email domains which users can register under (e.g. ctfd.io, gmail.com, yahoo.com)",
     )
+    team_creation = SelectField(
+        "Team Creation",
+        description="Control whether users can create their own teams (Teams mode only)",
+        choices=[("true", "Enabled"), ("false", "Disabled")],
+        default="true",
+    )
     team_size = IntegerField(
-        widget=NumberInput(min=0), description="Amount of users per team"
+        widget=NumberInput(min=0),
+        description="Amount of users per team (Teams mode only)",
     )
     verify_emails = SelectField(
         "Verify Emails",
diff --git a/CTFd/teams.py b/CTFd/teams.py
--- a/CTFd/teams.py
+++ b/CTFd/teams.py
@@ -191,6 +191,12 @@ def new():
     infos = get_infos()
     errors = get_errors()
 
+    if bool(get_config("team_creation", default=True)) is False:
+        abort(
+            403,
+            description="Team creation is currently disabled. Please join an existing team.",
+        )
+
     user = get_current_user_attrs()
     if user.team_id:
         errors.append("You are already in a team. You cannot join another.")


Test patch:
diff --git a/tests/teams/test_teams.py b/tests/teams/test_teams.py
--- a/tests/teams/test_teams.py
+++ b/tests/teams/test_teams.py
@@ -179,3 +179,31 @@ def test_team_size_limit():
             resp = r.get_data(as_text=True)
             assert len(Teams.query.filter_by(id=team_id).first().members) == 2
     destroy_ctfd(app)
+
+
+def test_team_creation_disable():
+    app = create_ctfd(user_mode="teams")
+    with app.app_context():
+        register_user(app)
+        with login_as_user(app) as client:
+            # Team creation page should be available
+            r = client.get("/teams/new")
+            assert r.status_code == 200
+
+            # Disable team creation in config
+            set_config("team_creation", False)
+
+            # Can't access the public team creation page
+            r = client.get("/teams/new")
+            assert r.status_code == 403
+
+            # User should be blocked from creating teams as well
+            with client.session_transaction() as sess:
+                data = {
+                    "name": "team_name",
+                    "password": "password",
+                    "nonce": sess.get("nonce"),
+                }
+            r = client.post("/teams/new", data=data)
+            assert r.status_code == 403
+    destroy_ctfd(app)
Repository: CTFd/CTFd

Issue:
Submissions should link directly to the user that submitted
Submissions don't link directly to the user in team mode which means you need to search to see what user submitted for a given team.




Discussion:

Resolving patch:
diff --git a/CTFd/admin/submissions.py b/CTFd/admin/submissions.py
--- a/CTFd/admin/submissions.py
+++ b/CTFd/admin/submissions.py
@@ -33,17 +33,7 @@ def submissions_listing(submission_type):
     Model = get_model()
 
     submissions = (
-        Submissions.query.add_columns(
-            Submissions.id,
-            Submissions.type,
-            Submissions.challenge_id,
-            Submissions.provided,
-            Submissions.account_id,
-            Submissions.date,
-            Challenges.name.label("challenge_name"),
-            Model.name.label("account_name"),
-        )
-        .filter_by(**filters_by)
+        Submissions.query.filter_by(**filters_by)
         .filter(*filters)
         .join(Challenges)
         .join(Model)
diff --git a/CTFd/constants/config.py b/CTFd/constants/config.py
--- a/CTFd/constants/config.py
+++ b/CTFd/constants/config.py
@@ -13,6 +13,12 @@ class ConfigTypes(str, RawEnum):
     REGISTRATION_VISIBILITY = "registration_visibility"
 
 
+@JinjaEnum
+class UserModeTypes(str, RawEnum):
+    USERS = "users"
+    TEAMS = "teams"
+
+
 @JinjaEnum
 class ChallengeVisibilityTypes(str, RawEnum):
     PUBLIC = "public"
diff --git a/CTFd/utils/modes/__init__.py b/CTFd/utils/modes/__init__.py
--- a/CTFd/utils/modes/__init__.py
+++ b/CTFd/utils/modes/__init__.py
@@ -3,6 +3,7 @@
 from CTFd.models import Teams, Users
 from CTFd.utils import get_config
 
+# TODO: Replace these constants with the UserModeTypes enum
 USERS_MODE = "users"
 TEAMS_MODE = "teams"
 


Test patch:
Repository: CTFd/CTFd

Issue:
Set plugin migration version in between each migration
https://github.com/CTFd/CTFd/blob/e1991e16963b10302baa7cc50d52071a5053bf2f/CTFd/plugins/migrations.py#L72-L77

This code here probably should be setting the plugin version in between each migration so that if a migration fails it doesn't need to be started from the beginning again. 


Discussion:

Resolving patch:
diff --git a/CTFd/plugins/migrations.py b/CTFd/plugins/migrations.py
--- a/CTFd/plugins/migrations.py
+++ b/CTFd/plugins/migrations.py
@@ -73,6 +73,9 @@ def upgrade(plugin_name=None, revision=None, lower="current"):
         for r in revs:
             with context.begin_transaction():
                 r.module.upgrade(op=op)
+            # Set revision that succeeded so we don't need
+            # to start from the beginning on failure
+            set_config(plugin_name + "_alembic_version", r.revision)
     finally:
         conn.close()
 


Test patch:
Repository: CTFd/CTFd

Issue:
Potentially expose user standings in admin scoreboard
This could let people give out awards for users who earn the most points or something like that. 

The issue with this is that user standings don't really mean anything. A user that earned all the points in a team might just have been the person to submit all the flags, not actually doing the work of a challenge. 

I don't know if I want to expose this data for people to rely on when it fundamentally is based on a flawed data source. 


Discussion:

Resolving patch:
diff --git a/CTFd/admin/scoreboard.py b/CTFd/admin/scoreboard.py
--- a/CTFd/admin/scoreboard.py
+++ b/CTFd/admin/scoreboard.py
@@ -1,12 +1,16 @@
 from flask import render_template
 
 from CTFd.admin import admin
-from CTFd.scoreboard import get_standings
+from CTFd.utils.config import is_teams_mode
 from CTFd.utils.decorators import admins_only
+from CTFd.utils.scores import get_standings, get_user_standings
 
 
 @admin.route("/admin/scoreboard")
 @admins_only
 def scoreboard_listing():
     standings = get_standings(admin=True)
-    return render_template("admin/scoreboard.html", standings=standings)
+    user_standings = get_user_standings(admin=True) if is_teams_mode() else None
+    return render_template(
+        "admin/scoreboard.html", standings=standings, user_standings=user_standings
+    )


Test patch:
Repository: CTFd/CTFd

Issue:
Add solves and solved_by_me to the ChallengesList endpoint
Follow up to #1811. We need to update the Pydantic models that generates documentation to include the new solves and solved_by_me properties.
Add solves and solved_by_me to the ChallengesList endpoint
Follow up to #1811. We need to update the Pydantic models that generates documentation to include the new solves and solved_by_me properties.


Discussion:

Resolving patch:
diff --git a/CTFd/api/v1/challenges.py b/CTFd/api/v1/challenges.py
--- a/CTFd/api/v1/challenges.py
+++ b/CTFd/api/v1/challenges.py
@@ -62,7 +62,9 @@
     "challenges", description="Endpoint to retrieve Challenges"
 )
 
-ChallengeModel = sqlalchemy_to_pydantic(Challenges)
+ChallengeModel = sqlalchemy_to_pydantic(
+    Challenges, include={"solves": int, "solved_by_me": bool}
+)
 TransientChallengeModel = sqlalchemy_to_pydantic(Challenges, exclude=["id"])
 
 
diff --git a/CTFd/api/v1/helpers/schemas.py b/CTFd/api/v1/helpers/schemas.py
--- a/CTFd/api/v1/helpers/schemas.py
+++ b/CTFd/api/v1/helpers/schemas.py
@@ -1,4 +1,4 @@
-from typing import Container, Type
+from typing import Container, Dict, Type
 
 from pydantic import BaseModel, create_model
 from sqlalchemy.inspection import inspect
@@ -6,7 +6,7 @@
 
 
 def sqlalchemy_to_pydantic(
-    db_model: Type, *, exclude: Container[str] = None
+    db_model: Type, *, include: Dict[str, type] = None, exclude: Container[str] = None
 ) -> Type[BaseModel]:
     """
     Mostly copied from https://github.com/tiangolo/pydantic-sqlalchemy
@@ -27,6 +27,10 @@ def sqlalchemy_to_pydantic(
                 if column.default is None and not column.nullable:
                     default = ...
                 fields[name] = (python_type, default)
+    if bool(include):
+        for name, python_type in include.items():
+            default = None
+            fields[name] = (python_type, default)
     pydantic_model = create_model(
         db_model.__name__, **fields  # type: ignore
     )


Test patch:
Repository: CTFd/CTFd

Issue:
Bump pybluemonday to latest
Just tracking this so we don't forget. Latest should be 0.0.6 with bluemonday at 1.0.10. It adds support for comments in the HTML output. 


Discussion:

Resolving patch:
diff --git a/CTFd/utils/security/sanitize.py b/CTFd/utils/security/sanitize.py
--- a/CTFd/utils/security/sanitize.py
+++ b/CTFd/utils/security/sanitize.py
@@ -92,6 +92,9 @@
 SANITIZER.RequireNoReferrerOnFullyQualifiedLinks(True)
 SANITIZER.RequireNoReferrerOnLinks(True)
 
+# Allow Comments
+SANITIZER.AllowComments()
+
 
 def sanitize_html(html):
     return SANITIZER.sanitize(html)


Test patch:
Repository: CTFd/CTFd

Issue:
IP to City Database
I think we can provide an IP to city database now instead of just showing country. 


Discussion:
I believe we'll use https://db-ip.com/ and mention the usage of their IP resolution data in the Admin UI. We will need a better way to distribute it than downloading it manually. I'd rather if it were distributed with pip. 

Resolving patch:
diff --git a/CTFd/utils/countries/geoip.py b/CTFd/utils/countries/geoip.py
--- a/CTFd/utils/countries/geoip.py
+++ b/CTFd/utils/countries/geoip.py
@@ -1,9 +1,9 @@
-import geoacumen
+import geoacumen_city
 import maxminddb
 from flask import current_app
 
 IP_ADDR_LOOKUP = maxminddb.open_database(
-    current_app.config.get("GEOIP_DATABASE_PATH", geoacumen.db_path)
+    current_app.config.get("GEOIP_DATABASE_PATH", geoacumen_city.db_path)
 )
 
 
@@ -11,5 +11,13 @@ def lookup_ip_address(addr):
     try:
         response = IP_ADDR_LOOKUP.get(addr)
         return response["country"]["iso_code"]
-    except (KeyError, ValueError):
+    except (KeyError, ValueError, TypeError):
+        return None
+
+
+def lookup_ip_address_city(addr):
+    try:
+        response = IP_ADDR_LOOKUP.get(addr)
+        return response["city"]["names"]["en"]
+    except (KeyError, ValueError, TypeError):
         return None
diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py
--- a/CTFd/utils/initialization/__init__.py
+++ b/CTFd/utils/initialization/__init__.py
@@ -67,7 +67,7 @@ def init_template_globals(app):
         scores_visible,
     )
     from CTFd.utils.countries import get_countries, lookup_country_code
-    from CTFd.utils.countries.geoip import lookup_ip_address
+    from CTFd.utils.countries.geoip import lookup_ip_address, lookup_ip_address_city
 
     app.jinja_env.globals.update(config=config)
     app.jinja_env.globals.update(get_pages=get_pages)
@@ -89,6 +89,7 @@ def init_template_globals(app):
     app.jinja_env.globals.update(get_countries=get_countries)
     app.jinja_env.globals.update(lookup_country_code=lookup_country_code)
     app.jinja_env.globals.update(lookup_ip_address=lookup_ip_address)
+    app.jinja_env.globals.update(lookup_ip_address_city=lookup_ip_address_city)
     app.jinja_env.globals.update(accounts_visible=accounts_visible)
     app.jinja_env.globals.update(challenges_visible=challenges_visible)
     app.jinja_env.globals.update(registration_visible=registration_visible)


Test patch:
Repository: CTFd/CTFd

Issue:
Users in admin scoreboard show user position instead of team position
In teams mode on the admin panel, users are shown with their user position on the scoreboard instead of their teams position. We should be showing both. 


Discussion:

Resolving patch:
diff --git a/CTFd/admin/users.py b/CTFd/admin/users.py
--- a/CTFd/admin/users.py
+++ b/CTFd/admin/users.py
@@ -88,8 +88,8 @@ def users_detail(user_id):
     awards = user.get_awards(admin=True)
 
     # Get user properties
-    score = user.get_score(admin=True)
-    place = user.get_place(admin=True)
+    score = user.account.get_score(admin=True)
+    place = user.account.get_place(admin=True)
 
     return render_template(
         "admin/users/user.html",


Test patch: