We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Standardize theme interface
Themes should have a static set of requirements that all themes should have. This really just means we need to provide more guidance on designing themes. 

--- 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/constants/teams.py`
Content:
```
1 from collections import namedtuple
2 
3 TeamAttrs = namedtuple(
4     "TeamAttrs",
5     [
6         "id",
7         "oauth_id",
8         "name",
9         "email",
10         "secret",
11         "website",
12         "affiliation",
13         "country",
14         "bracket",
15         "hidden",
16         "banned",
17         "captain_id",
18         "created",
19     ],
20 )
21
```

Path: `CTFd/utils/initialization/__init__.py`
Content:
```
1 import datetime
2 import logging
3 import os
4 import sys
5 
6 from flask import abort, redirect, render_template, request, session, url_for
7 from sqlalchemy.exc import IntegrityError, InvalidRequestError
8 from werkzeug.middleware.dispatcher import DispatcherMiddleware
9 
10 from CTFd.cache import clear_user_recent_ips
11 from CTFd.exceptions import UserNotFoundException, UserTokenExpiredException
12 from CTFd.models import Tracking, db
13 from CTFd.utils import config, get_config, markdown
14 from CTFd.utils.config import (
15     can_send_mail,
16     ctf_logo,
17     ctf_name,
18     ctf_theme,
19     integrations,
20     is_setup,
21 )
22 from CTFd.utils.config.pages import get_pages
23 from CTFd.utils.countries import get_countries, lookup_country_code
24 from CTFd.utils.dates import isoformat, unix_time, unix_time_millis
25 from CTFd.utils.events import EventManager, RedisEventManager
26 from CTFd.utils.humanize.words import pluralize
27 from CTFd.utils.modes import generate_account_url, get_mode_as_word
28 from CTFd.utils.plugins import (
29     get_configurable_plugins,
30     get_registered_admin_scripts,
31     get_registered_admin_stylesheets,
32     get_registered_scripts,
33     get_registered_stylesheets,
34 )
35 from CTFd.utils.security.auth import login_user, logout_user, lookup_user_token
36 from CTFd.utils.security.csrf import generate_nonce
37 from CTFd.utils.user import (
38     authed,
39     get_current_team_attrs,
40     get_current_user_attrs,
41     get_current_user_recent_ips,
42     get_ip,
43     is_admin,
44 )
45 
46 
47 def init_template_filters(app):
48     app.jinja_env.filters["markdown"] = markdown
49     app.jinja_env.filters["unix_time"] = unix_time
50     app.jinja_env.filters["unix_time_millis"] = unix_time_millis
51     app.jinja_env.filters["isoformat"] = isoformat
52     app.jinja_env.filters["pluralize"] = pluralize
53 
54 
55 def init_template_globals(app):
56     from CTFd.constants.config import Configs
57     from CTFd.constants.plugins import Plugins
58     from CTFd.constants.sessions import Session
59     from CTFd.forms import Forms
60     from CTFd.utils.config.visibility import (
61         accounts_visible,
62         challenges_visible,
63         registration_visible,
64         scores_visible,
65     )
66 
67     app.jinja_env.globals.update(config=config)
68     app.jinja_env.globals.update(get_pages=get_pages)
69     app.jinja_env.globals.update(can_send_mail=can_send_mail)
70     app.jinja_env.globals.update(get_ctf_name=ctf_name)
71     app.jinja_env.globals.update(get_ctf_logo=ctf_logo)
72     app.jinja_env.globals.update(get_ctf_theme=ctf_theme)
73     app.jinja_env.globals.update(get_configurable_plugins=get_configurable_plugins)
74     app.jinja_env.globals.update(get_registered_scripts=get_registered_scripts)
75     app.jinja_env.globals.update(get_registered_stylesheets=get_registered_stylesheets)
76     app.jinja_env.globals.update(
77         get_registered_admin_scripts=get_registered_admin_scripts
78     )
79     app.jinja_env.globals.update(
80         get_registered_admin_stylesheets=get_registered_admin_stylesheets
81     )
82     app.jinja_env.globals.update(get_config=get_config)
83     app.jinja_env.globals.update(generate_account_url=generate_account_url)
84     app.jinja_env.globals.update(get_countries=get_countries)
85     app.jinja_env.globals.update(lookup_country_code=lookup_country_code)
86     app.jinja_env.globals.update(accounts_visible=accounts_visible)
87     app.jinja_env.globals.update(challenges_visible=challenges_visible)
88     app.jinja_env.globals.update(registration_visible=registration_visible)
89     app.jinja_env.globals.update(scores_visible=scores_visible)
90     app.jinja_env.globals.update(get_mode_as_word=get_mode_as_word)
91     app.jinja_env.globals.update(integrations=integrations)
92     app.jinja_env.globals.update(authed=authed)
93     app.jinja_env.globals.update(is_admin=is_admin)
94     app.jinja_env.globals.update(get_current_user_attrs=get_current_user_attrs)
95     app.jinja_env.globals.update(get_current_team_attrs=get_current_team_attrs)
96     app.jinja_env.globals.update(get_ip=get_ip)
97     app.jinja_env.globals.update(Configs=Configs)
98     app.jinja_env.globals.update(Plugins=Plugins)
99     app.jinja_env.globals.update(Session=Session)
100     app.jinja_env.globals.update(Forms=Forms)
101 
102 
103 def init_logs(app):
104     logger_submissions = logging.getLogger("submissions")
105     logger_logins = logging.getLogger("logins")
106     logger_registrations = logging.getLogger("registrations")
107 
108     logger_submissions.setLevel(logging.INFO)
109     logger_logins.setLevel(logging.INFO)
110     logger_registrations.setLevel(logging.INFO)
111 
112     log_dir = app.config["LOG_FOLDER"]
113     if not os.path.exists(log_dir):
114         os.makedirs(log_dir)
115 
116     logs = {
117         "submissions": os.path.join(log_dir, "submissions.log"),
118         "logins": os.path.join(log_dir, "logins.log"),
119         "registrations": os.path.join(log_dir, "registrations.log"),
120     }
121 
122     try:
123         for log in logs.values():
124             if not os.path.exists(log):
125                 open(log, "a").close()
126 
127         submission_log = logging.handlers.RotatingFileHandler(
128             logs["submissions"], maxBytes=10485760, backupCount=5
129         )
130         login_log = logging.handlers.RotatingFileHandler(
131             logs["logins"], maxBytes=10485760, backupCount=5
132         )
133         registration_log = logging.handlers.RotatingFileHandler(
134             logs["registrations"], maxBytes=10485760, backupCount=5
135         )
136 
137         logger_submissions.addHandler(submission_log)
138         logger_logins.addHandler(login_log)
139         logger_registrations.addHandler(registration_log)
140     except IOError:
141         pass
142 
143     stdout = logging.StreamHandler(stream=sys.stdout)
144 
145     logger_submissions.addHandler(stdout)
146     logger_logins.addHandler(stdout)
147     logger_registrations.addHandler(stdout)
148 
149     logger_submissions.propagate = 0
150     logger_logins.propagate = 0
151     logger_registrations.propagate = 0
152 
153 
154 def init_events(app):
155     if app.config.get("CACHE_TYPE") == "redis":
156         app.events_manager = RedisEventManager()
157     elif app.config.get("CACHE_TYPE") == "filesystem":
158         app.events_manager = EventManager()
159     else:
160         app.events_manager = EventManager()
161 
162 
163 def init_request_processors(app):
164     @app.url_defaults
165     def inject_theme(endpoint, values):
166         if "theme" not in values and app.url_map.is_endpoint_expecting(
167             endpoint, "theme"
168         ):
169             values["theme"] = ctf_theme()
170 
171     @app.before_request
172     def needs_setup():
173         if is_setup() is False:
174             if request.endpoint in (
175                 "views.setup",
176                 "views.integrations",
177                 "views.themes",
178             ):
179                 return
180             else:
181                 return redirect(url_for("views.setup"))
182 
183     @app.before_request
184     def tracker():
185         if request.endpoint == "views.themes":
186             return
187 
188         if authed():
189             user_ips = get_current_user_recent_ips()
190             ip = get_ip()
191 
192             track = None
193             if (ip not in user_ips) or (request.method != "GET"):
194                 track = Tracking.query.filter_by(
195                     ip=get_ip(), user_id=session["id"]
196                 ).first()
197 
198                 if track:
199                     track.date = datetime.datetime.utcnow()
200                 else:
201                     track = Tracking(ip=get_ip(), user_id=session["id"])
202                     db.session.add(track)
203 
204             if track:
205                 try:
206                     db.session.commit()
207                 except (InvalidRequestError, IntegrityError):
208                     db.session.rollback()
209                     db.session.close()
210                     logout_user()
211                 else:
212                     clear_user_recent_ips(user_id=session["id"])
213 
214     @app.before_request
215     def banned():
216         if request.endpoint == "views.themes":
217             return
218 
219         if authed():
220             user = get_current_user_attrs()
221             team = get_current_team_attrs()
222 
223             if user and user.banned:
224                 return (
225                     render_template(
226                         "errors/403.html", error="You have been banned from this CTF"
227                     ),
228                     403,
229                 )
230 
231             if team and team.banned:
232                 return (
233                     render_template(
234                         "errors/403.html",
235                         error="Your team has been banned from this CTF",
236                     ),
237                     403,
238                 )
239 
240     @app.before_request
241     def tokens():
242         token = request.headers.get("Authorization")
243         if token and request.content_type == "application/json":
244             try:
245                 token_type, token = token.split(" ", 1)
246                 user = lookup_user_token(token)
247             except UserNotFoundException:
248                 abort(401)
249             except UserTokenExpiredException:
250                 abort(401)
251             except Exception:
252                 abort(401)
253             else:
254                 login_user(user)
255 
256     @app.before_request
257     def csrf():
258         try:
259             func = app.view_functions[request.endpoint]
260         except KeyError:
261             abort(404)
262         if hasattr(func, "_bypass_csrf"):
263             return
264         if request.headers.get("Authorization"):
265             return
266         if not session.get("nonce"):
267             session["nonce"] = generate_nonce()
268         if request.method not in ("GET", "HEAD", "OPTIONS", "TRACE"):
269             if request.content_type == "application/json":
270                 if session["nonce"] != request.headers.get("CSRF-Token"):
271                     abort(403)
272             if request.content_type != "application/json":
273                 if session["nonce"] != request.form.get("nonce"):
274                     abort(403)
275 
276     application_root = app.config.get("APPLICATION_ROOT")
277     if application_root != "/":
278 
279         @app.before_request
280         def force_subdirectory_redirect():
281             if request.path.startswith(application_root) is False:
282                 return redirect(
283                     application_root + request.script_root + request.full_path
284                 )
285 
286         app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {application_root: app})
287
```

Path: `CTFd/constants/users.py`
Content:
```
1 from collections import namedtuple
2 
3 UserAttrs = namedtuple(
4     "UserAttrs",
5     [
6         "id",
7         "oauth_id",
8         "name",
9         "email",
10         "type",
11         "secret",
12         "website",
13         "affiliation",
14         "country",
15         "bracket",
16         "hidden",
17         "banned",
18         "verified",
19         "team_id",
20         "created",
21     ],
22 )
23
```
--- 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/constants/teams.py b/CTFd/constants/teams.py
--- a/CTFd/constants/teams.py
+++ b/CTFd/constants/teams.py
@@ -18,3 +18,32 @@
         "created",
     ],
 )
+
+
+class _TeamAttrsWrapper:
+    def __getattr__(self, attr):
+        from CTFd.utils.user import get_current_team_attrs
+
+        attrs = get_current_team_attrs()
+        return getattr(attrs, attr, None)
+
+    @property
+    def place(self):
+        from CTFd.utils.user import get_current_team
+
+        team = get_current_team()
+        if team:
+            return team.place
+        return None
+
+    @property
+    def score(self):
+        from CTFd.utils.user import get_current_team
+
+        team = get_current_team()
+        if team:
+            return team.score
+        return None
+
+
+Team = _TeamAttrsWrapper()
diff --git a/CTFd/constants/users.py b/CTFd/constants/users.py
--- a/CTFd/constants/users.py
+++ b/CTFd/constants/users.py
@@ -20,3 +20,32 @@
         "created",
     ],
 )
+
+
+class _UserAttrsWrapper:
+    def __getattr__(self, attr):
+        from CTFd.utils.user import get_current_user_attrs
+
+        attrs = get_current_user_attrs()
+        return getattr(attrs, attr, None)
+
+    @property
+    def place(self):
+        from CTFd.utils.user import get_current_user
+
+        user = get_current_user()
+        if user:
+            return user.place
+        return None
+
+    @property
+    def score(self):
+        from CTFd.utils.user import get_current_user
+
+        user = get_current_user()
+        if user:
+            return user.score
+        return None
+
+
+User = _UserAttrsWrapper()
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
@@ -56,6 +56,8 @@
     from CTFd.constants.config import Configs
     from CTFd.constants.plugins import Plugins
     from CTFd.constants.sessions import Session
+    from CTFd.constants.users import User
+    from CTFd.constants.teams import Team
     from CTFd.forms import Forms
     from CTFd.utils.config.visibility import (
         accounts_visible,
@@ -98,6 +100,8 @@
     app.jinja_env.globals.update(Plugins=Plugins)
     app.jinja_env.globals.update(Session=Session)
     app.jinja_env.globals.update(Forms=Forms)
+    app.jinja_env.globals.update(User=User)
+    app.jinja_env.globals.update(Team=Team)
 
 
 def init_logs(app):

{"golden_diff": "diff --git a/CTFd/constants/teams.py b/CTFd/constants/teams.py\n--- a/CTFd/constants/teams.py\n+++ b/CTFd/constants/teams.py\n@@ -18,3 +18,32 @@\n         \"created\",\n     ],\n )\n+\n+\n+class _TeamAttrsWrapper:\n+    def __getattr__(self, attr):\n+        from CTFd.utils.user import get_current_team_attrs\n+\n+        attrs = get_current_team_attrs()\n+        return getattr(attrs, attr, None)\n+\n+    @property\n+    def place(self):\n+        from CTFd.utils.user import get_current_team\n+\n+        team = get_current_team()\n+        if team:\n+            return team.place\n+        return None\n+\n+    @property\n+    def score(self):\n+        from CTFd.utils.user import get_current_team\n+\n+        team = get_current_team()\n+        if team:\n+            return team.score\n+        return None\n+\n+\n+Team = _TeamAttrsWrapper()\ndiff --git a/CTFd/constants/users.py b/CTFd/constants/users.py\n--- a/CTFd/constants/users.py\n+++ b/CTFd/constants/users.py\n@@ -20,3 +20,32 @@\n         \"created\",\n     ],\n )\n+\n+\n+class _UserAttrsWrapper:\n+    def __getattr__(self, attr):\n+        from CTFd.utils.user import get_current_user_attrs\n+\n+        attrs = get_current_user_attrs()\n+        return getattr(attrs, attr, None)\n+\n+    @property\n+    def place(self):\n+        from CTFd.utils.user import get_current_user\n+\n+        user = get_current_user()\n+        if user:\n+            return user.place\n+        return None\n+\n+    @property\n+    def score(self):\n+        from CTFd.utils.user import get_current_user\n+\n+        user = get_current_user()\n+        if user:\n+            return user.score\n+        return None\n+\n+\n+User = _UserAttrsWrapper()\ndiff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py\n--- a/CTFd/utils/initialization/__init__.py\n+++ b/CTFd/utils/initialization/__init__.py\n@@ -56,6 +56,8 @@\n     from CTFd.constants.config import Configs\n     from CTFd.constants.plugins import Plugins\n     from CTFd.constants.sessions import Session\n+    from CTFd.constants.users import User\n+    from CTFd.constants.teams import Team\n     from CTFd.forms import Forms\n     from CTFd.utils.config.visibility import (\n         accounts_visible,\n@@ -98,6 +100,8 @@\n     app.jinja_env.globals.update(Plugins=Plugins)\n     app.jinja_env.globals.update(Session=Session)\n     app.jinja_env.globals.update(Forms=Forms)\n+    app.jinja_env.globals.update(User=User)\n+    app.jinja_env.globals.update(Team=Team)\n \n \n def init_logs(app):\n", "issue": "Standardize theme interface\nThemes should have a static set of requirements that all themes should have. This really just means we need to provide more guidance on designing themes. \n", "before_files": [{"content": "from collections import namedtuple\n\nTeamAttrs = namedtuple(\n    \"TeamAttrs\",\n    [\n        \"id\",\n        \"oauth_id\",\n        \"name\",\n        \"email\",\n        \"secret\",\n        \"website\",\n        \"affiliation\",\n        \"country\",\n        \"bracket\",\n        \"hidden\",\n        \"banned\",\n        \"captain_id\",\n        \"created\",\n    ],\n)\n", "path": "CTFd/constants/teams.py"}, {"content": "import datetime\nimport logging\nimport os\nimport sys\n\nfrom flask import abort, redirect, render_template, request, session, url_for\nfrom sqlalchemy.exc import IntegrityError, InvalidRequestError\nfrom werkzeug.middleware.dispatcher import DispatcherMiddleware\n\nfrom CTFd.cache import clear_user_recent_ips\nfrom CTFd.exceptions import UserNotFoundException, UserTokenExpiredException\nfrom CTFd.models import Tracking, db\nfrom CTFd.utils import config, get_config, markdown\nfrom CTFd.utils.config import (\n    can_send_mail,\n    ctf_logo,\n    ctf_name,\n    ctf_theme,\n    integrations,\n    is_setup,\n)\nfrom CTFd.utils.config.pages import get_pages\nfrom CTFd.utils.countries import get_countries, lookup_country_code\nfrom CTFd.utils.dates import isoformat, unix_time, unix_time_millis\nfrom CTFd.utils.events import EventManager, RedisEventManager\nfrom CTFd.utils.humanize.words import pluralize\nfrom CTFd.utils.modes import generate_account_url, get_mode_as_word\nfrom CTFd.utils.plugins import (\n    get_configurable_plugins,\n    get_registered_admin_scripts,\n    get_registered_admin_stylesheets,\n    get_registered_scripts,\n    get_registered_stylesheets,\n)\nfrom CTFd.utils.security.auth import login_user, logout_user, lookup_user_token\nfrom CTFd.utils.security.csrf import generate_nonce\nfrom CTFd.utils.user import (\n    authed,\n    get_current_team_attrs,\n    get_current_user_attrs,\n    get_current_user_recent_ips,\n    get_ip,\n    is_admin,\n)\n\n\ndef init_template_filters(app):\n    app.jinja_env.filters[\"markdown\"] = markdown\n    app.jinja_env.filters[\"unix_time\"] = unix_time\n    app.jinja_env.filters[\"unix_time_millis\"] = unix_time_millis\n    app.jinja_env.filters[\"isoformat\"] = isoformat\n    app.jinja_env.filters[\"pluralize\"] = pluralize\n\n\ndef init_template_globals(app):\n    from CTFd.constants.config import Configs\n    from CTFd.constants.plugins import Plugins\n    from CTFd.constants.sessions import Session\n    from CTFd.forms import Forms\n    from CTFd.utils.config.visibility import (\n        accounts_visible,\n        challenges_visible,\n        registration_visible,\n        scores_visible,\n    )\n\n    app.jinja_env.globals.update(config=config)\n    app.jinja_env.globals.update(get_pages=get_pages)\n    app.jinja_env.globals.update(can_send_mail=can_send_mail)\n    app.jinja_env.globals.update(get_ctf_name=ctf_name)\n    app.jinja_env.globals.update(get_ctf_logo=ctf_logo)\n    app.jinja_env.globals.update(get_ctf_theme=ctf_theme)\n    app.jinja_env.globals.update(get_configurable_plugins=get_configurable_plugins)\n    app.jinja_env.globals.update(get_registered_scripts=get_registered_scripts)\n    app.jinja_env.globals.update(get_registered_stylesheets=get_registered_stylesheets)\n    app.jinja_env.globals.update(\n        get_registered_admin_scripts=get_registered_admin_scripts\n    )\n    app.jinja_env.globals.update(\n        get_registered_admin_stylesheets=get_registered_admin_stylesheets\n    )\n    app.jinja_env.globals.update(get_config=get_config)\n    app.jinja_env.globals.update(generate_account_url=generate_account_url)\n    app.jinja_env.globals.update(get_countries=get_countries)\n    app.jinja_env.globals.update(lookup_country_code=lookup_country_code)\n    app.jinja_env.globals.update(accounts_visible=accounts_visible)\n    app.jinja_env.globals.update(challenges_visible=challenges_visible)\n    app.jinja_env.globals.update(registration_visible=registration_visible)\n    app.jinja_env.globals.update(scores_visible=scores_visible)\n    app.jinja_env.globals.update(get_mode_as_word=get_mode_as_word)\n    app.jinja_env.globals.update(integrations=integrations)\n    app.jinja_env.globals.update(authed=authed)\n    app.jinja_env.globals.update(is_admin=is_admin)\n    app.jinja_env.globals.update(get_current_user_attrs=get_current_user_attrs)\n    app.jinja_env.globals.update(get_current_team_attrs=get_current_team_attrs)\n    app.jinja_env.globals.update(get_ip=get_ip)\n    app.jinja_env.globals.update(Configs=Configs)\n    app.jinja_env.globals.update(Plugins=Plugins)\n    app.jinja_env.globals.update(Session=Session)\n    app.jinja_env.globals.update(Forms=Forms)\n\n\ndef init_logs(app):\n    logger_submissions = logging.getLogger(\"submissions\")\n    logger_logins = logging.getLogger(\"logins\")\n    logger_registrations = logging.getLogger(\"registrations\")\n\n    logger_submissions.setLevel(logging.INFO)\n    logger_logins.setLevel(logging.INFO)\n    logger_registrations.setLevel(logging.INFO)\n\n    log_dir = app.config[\"LOG_FOLDER\"]\n    if not os.path.exists(log_dir):\n        os.makedirs(log_dir)\n\n    logs = {\n        \"submissions\": os.path.join(log_dir, \"submissions.log\"),\n        \"logins\": os.path.join(log_dir, \"logins.log\"),\n        \"registrations\": os.path.join(log_dir, \"registrations.log\"),\n    }\n\n    try:\n        for log in logs.values():\n            if not os.path.exists(log):\n                open(log, \"a\").close()\n\n        submission_log = logging.handlers.RotatingFileHandler(\n            logs[\"submissions\"], maxBytes=10485760, backupCount=5\n        )\n        login_log = logging.handlers.RotatingFileHandler(\n            logs[\"logins\"], maxBytes=10485760, backupCount=5\n        )\n        registration_log = logging.handlers.RotatingFileHandler(\n            logs[\"registrations\"], maxBytes=10485760, backupCount=5\n        )\n\n        logger_submissions.addHandler(submission_log)\n        logger_logins.addHandler(login_log)\n        logger_registrations.addHandler(registration_log)\n    except IOError:\n        pass\n\n    stdout = logging.StreamHandler(stream=sys.stdout)\n\n    logger_submissions.addHandler(stdout)\n    logger_logins.addHandler(stdout)\n    logger_registrations.addHandler(stdout)\n\n    logger_submissions.propagate = 0\n    logger_logins.propagate = 0\n    logger_registrations.propagate = 0\n\n\ndef init_events(app):\n    if app.config.get(\"CACHE_TYPE\") == \"redis\":\n        app.events_manager = RedisEventManager()\n    elif app.config.get(\"CACHE_TYPE\") == \"filesystem\":\n        app.events_manager = EventManager()\n    else:\n        app.events_manager = EventManager()\n\n\ndef init_request_processors(app):\n    @app.url_defaults\n    def inject_theme(endpoint, values):\n        if \"theme\" not in values and app.url_map.is_endpoint_expecting(\n            endpoint, \"theme\"\n        ):\n            values[\"theme\"] = ctf_theme()\n\n    @app.before_request\n    def needs_setup():\n        if is_setup() is False:\n            if request.endpoint in (\n                \"views.setup\",\n                \"views.integrations\",\n                \"views.themes\",\n            ):\n                return\n            else:\n                return redirect(url_for(\"views.setup\"))\n\n    @app.before_request\n    def tracker():\n        if request.endpoint == \"views.themes\":\n            return\n\n        if authed():\n            user_ips = get_current_user_recent_ips()\n            ip = get_ip()\n\n            track = None\n            if (ip not in user_ips) or (request.method != \"GET\"):\n                track = Tracking.query.filter_by(\n                    ip=get_ip(), user_id=session[\"id\"]\n                ).first()\n\n                if track:\n                    track.date = datetime.datetime.utcnow()\n                else:\n                    track = Tracking(ip=get_ip(), user_id=session[\"id\"])\n                    db.session.add(track)\n\n            if track:\n                try:\n                    db.session.commit()\n                except (InvalidRequestError, IntegrityError):\n                    db.session.rollback()\n                    db.session.close()\n                    logout_user()\n                else:\n                    clear_user_recent_ips(user_id=session[\"id\"])\n\n    @app.before_request\n    def banned():\n        if request.endpoint == \"views.themes\":\n            return\n\n        if authed():\n            user = get_current_user_attrs()\n            team = get_current_team_attrs()\n\n            if user and user.banned:\n                return (\n                    render_template(\n                        \"errors/403.html\", error=\"You have been banned from this CTF\"\n                    ),\n                    403,\n                )\n\n            if team and team.banned:\n                return (\n                    render_template(\n                        \"errors/403.html\",\n                        error=\"Your team has been banned from this CTF\",\n                    ),\n                    403,\n                )\n\n    @app.before_request\n    def tokens():\n        token = request.headers.get(\"Authorization\")\n        if token and request.content_type == \"application/json\":\n            try:\n                token_type, token = token.split(\" \", 1)\n                user = lookup_user_token(token)\n            except UserNotFoundException:\n                abort(401)\n            except UserTokenExpiredException:\n                abort(401)\n            except Exception:\n                abort(401)\n            else:\n                login_user(user)\n\n    @app.before_request\n    def csrf():\n        try:\n            func = app.view_functions[request.endpoint]\n        except KeyError:\n            abort(404)\n        if hasattr(func, \"_bypass_csrf\"):\n            return\n        if request.headers.get(\"Authorization\"):\n            return\n        if not session.get(\"nonce\"):\n            session[\"nonce\"] = generate_nonce()\n        if request.method not in (\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"):\n            if request.content_type == \"application/json\":\n                if session[\"nonce\"] != request.headers.get(\"CSRF-Token\"):\n                    abort(403)\n            if request.content_type != \"application/json\":\n                if session[\"nonce\"] != request.form.get(\"nonce\"):\n                    abort(403)\n\n    application_root = app.config.get(\"APPLICATION_ROOT\")\n    if application_root != \"/\":\n\n        @app.before_request\n        def force_subdirectory_redirect():\n            if request.path.startswith(application_root) is False:\n                return redirect(\n                    application_root + request.script_root + request.full_path\n                )\n\n        app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {application_root: app})\n", "path": "CTFd/utils/initialization/__init__.py"}, {"content": "from collections import namedtuple\n\nUserAttrs = namedtuple(\n    \"UserAttrs\",\n    [\n        \"id\",\n        \"oauth_id\",\n        \"name\",\n        \"email\",\n        \"type\",\n        \"secret\",\n        \"website\",\n        \"affiliation\",\n        \"country\",\n        \"bracket\",\n        \"hidden\",\n        \"banned\",\n        \"verified\",\n        \"team_id\",\n        \"created\",\n    ],\n)\n", "path": "CTFd/constants/users.py"}], "after_files": [{"content": "from collections import namedtuple\n\nTeamAttrs = namedtuple(\n    \"TeamAttrs\",\n    [\n        \"id\",\n        \"oauth_id\",\n        \"name\",\n        \"email\",\n        \"secret\",\n        \"website\",\n        \"affiliation\",\n        \"country\",\n        \"bracket\",\n        \"hidden\",\n        \"banned\",\n        \"captain_id\",\n        \"created\",\n    ],\n)\n\n\nclass _TeamAttrsWrapper:\n    def __getattr__(self, attr):\n        from CTFd.utils.user import get_current_team_attrs\n\n        attrs = get_current_team_attrs()\n        return getattr(attrs, attr, None)\n\n    @property\n    def place(self):\n        from CTFd.utils.user import get_current_team\n\n        team = get_current_team()\n        if team:\n            return team.place\n        return None\n\n    @property\n    def score(self):\n        from CTFd.utils.user import get_current_team\n\n        team = get_current_team()\n        if team:\n            return team.score\n        return None\n\n\nTeam = _TeamAttrsWrapper()\n", "path": "CTFd/constants/teams.py"}, {"content": "import datetime\nimport logging\nimport os\nimport sys\n\nfrom flask import abort, redirect, render_template, request, session, url_for\nfrom sqlalchemy.exc import IntegrityError, InvalidRequestError\nfrom werkzeug.middleware.dispatcher import DispatcherMiddleware\n\nfrom CTFd.cache import clear_user_recent_ips\nfrom CTFd.exceptions import UserNotFoundException, UserTokenExpiredException\nfrom CTFd.models import Tracking, db\nfrom CTFd.utils import config, get_config, markdown\nfrom CTFd.utils.config import (\n    can_send_mail,\n    ctf_logo,\n    ctf_name,\n    ctf_theme,\n    integrations,\n    is_setup,\n)\nfrom CTFd.utils.config.pages import get_pages\nfrom CTFd.utils.countries import get_countries, lookup_country_code\nfrom CTFd.utils.dates import isoformat, unix_time, unix_time_millis\nfrom CTFd.utils.events import EventManager, RedisEventManager\nfrom CTFd.utils.humanize.words import pluralize\nfrom CTFd.utils.modes import generate_account_url, get_mode_as_word\nfrom CTFd.utils.plugins import (\n    get_configurable_plugins,\n    get_registered_admin_scripts,\n    get_registered_admin_stylesheets,\n    get_registered_scripts,\n    get_registered_stylesheets,\n)\nfrom CTFd.utils.security.auth import login_user, logout_user, lookup_user_token\nfrom CTFd.utils.security.csrf import generate_nonce\nfrom CTFd.utils.user import (\n    authed,\n    get_current_team_attrs,\n    get_current_user_attrs,\n    get_current_user_recent_ips,\n    get_ip,\n    is_admin,\n)\n\n\ndef init_template_filters(app):\n    app.jinja_env.filters[\"markdown\"] = markdown\n    app.jinja_env.filters[\"unix_time\"] = unix_time\n    app.jinja_env.filters[\"unix_time_millis\"] = unix_time_millis\n    app.jinja_env.filters[\"isoformat\"] = isoformat\n    app.jinja_env.filters[\"pluralize\"] = pluralize\n\n\ndef init_template_globals(app):\n    from CTFd.constants.config import Configs\n    from CTFd.constants.plugins import Plugins\n    from CTFd.constants.sessions import Session\n    from CTFd.constants.users import User\n    from CTFd.constants.teams import Team\n    from CTFd.forms import Forms\n    from CTFd.utils.config.visibility import (\n        accounts_visible,\n        challenges_visible,\n        registration_visible,\n        scores_visible,\n    )\n\n    app.jinja_env.globals.update(config=config)\n    app.jinja_env.globals.update(get_pages=get_pages)\n    app.jinja_env.globals.update(can_send_mail=can_send_mail)\n    app.jinja_env.globals.update(get_ctf_name=ctf_name)\n    app.jinja_env.globals.update(get_ctf_logo=ctf_logo)\n    app.jinja_env.globals.update(get_ctf_theme=ctf_theme)\n    app.jinja_env.globals.update(get_configurable_plugins=get_configurable_plugins)\n    app.jinja_env.globals.update(get_registered_scripts=get_registered_scripts)\n    app.jinja_env.globals.update(get_registered_stylesheets=get_registered_stylesheets)\n    app.jinja_env.globals.update(\n        get_registered_admin_scripts=get_registered_admin_scripts\n    )\n    app.jinja_env.globals.update(\n        get_registered_admin_stylesheets=get_registered_admin_stylesheets\n    )\n    app.jinja_env.globals.update(get_config=get_config)\n    app.jinja_env.globals.update(generate_account_url=generate_account_url)\n    app.jinja_env.globals.update(get_countries=get_countries)\n    app.jinja_env.globals.update(lookup_country_code=lookup_country_code)\n    app.jinja_env.globals.update(accounts_visible=accounts_visible)\n    app.jinja_env.globals.update(challenges_visible=challenges_visible)\n    app.jinja_env.globals.update(registration_visible=registration_visible)\n    app.jinja_env.globals.update(scores_visible=scores_visible)\n    app.jinja_env.globals.update(get_mode_as_word=get_mode_as_word)\n    app.jinja_env.globals.update(integrations=integrations)\n    app.jinja_env.globals.update(authed=authed)\n    app.jinja_env.globals.update(is_admin=is_admin)\n    app.jinja_env.globals.update(get_current_user_attrs=get_current_user_attrs)\n    app.jinja_env.globals.update(get_current_team_attrs=get_current_team_attrs)\n    app.jinja_env.globals.update(get_ip=get_ip)\n    app.jinja_env.globals.update(Configs=Configs)\n    app.jinja_env.globals.update(Plugins=Plugins)\n    app.jinja_env.globals.update(Session=Session)\n    app.jinja_env.globals.update(Forms=Forms)\n    app.jinja_env.globals.update(User=User)\n    app.jinja_env.globals.update(Team=Team)\n\n\ndef init_logs(app):\n    logger_submissions = logging.getLogger(\"submissions\")\n    logger_logins = logging.getLogger(\"logins\")\n    logger_registrations = logging.getLogger(\"registrations\")\n\n    logger_submissions.setLevel(logging.INFO)\n    logger_logins.setLevel(logging.INFO)\n    logger_registrations.setLevel(logging.INFO)\n\n    log_dir = app.config[\"LOG_FOLDER\"]\n    if not os.path.exists(log_dir):\n        os.makedirs(log_dir)\n\n    logs = {\n        \"submissions\": os.path.join(log_dir, \"submissions.log\"),\n        \"logins\": os.path.join(log_dir, \"logins.log\"),\n        \"registrations\": os.path.join(log_dir, \"registrations.log\"),\n    }\n\n    try:\n        for log in logs.values():\n            if not os.path.exists(log):\n                open(log, \"a\").close()\n\n        submission_log = logging.handlers.RotatingFileHandler(\n            logs[\"submissions\"], maxBytes=10485760, backupCount=5\n        )\n        login_log = logging.handlers.RotatingFileHandler(\n            logs[\"logins\"], maxBytes=10485760, backupCount=5\n        )\n        registration_log = logging.handlers.RotatingFileHandler(\n            logs[\"registrations\"], maxBytes=10485760, backupCount=5\n        )\n\n        logger_submissions.addHandler(submission_log)\n        logger_logins.addHandler(login_log)\n        logger_registrations.addHandler(registration_log)\n    except IOError:\n        pass\n\n    stdout = logging.StreamHandler(stream=sys.stdout)\n\n    logger_submissions.addHandler(stdout)\n    logger_logins.addHandler(stdout)\n    logger_registrations.addHandler(stdout)\n\n    logger_submissions.propagate = 0\n    logger_logins.propagate = 0\n    logger_registrations.propagate = 0\n\n\ndef init_events(app):\n    if app.config.get(\"CACHE_TYPE\") == \"redis\":\n        app.events_manager = RedisEventManager()\n    elif app.config.get(\"CACHE_TYPE\") == \"filesystem\":\n        app.events_manager = EventManager()\n    else:\n        app.events_manager = EventManager()\n\n\ndef init_request_processors(app):\n    @app.url_defaults\n    def inject_theme(endpoint, values):\n        if \"theme\" not in values and app.url_map.is_endpoint_expecting(\n            endpoint, \"theme\"\n        ):\n            values[\"theme\"] = ctf_theme()\n\n    @app.before_request\n    def needs_setup():\n        if is_setup() is False:\n            if request.endpoint in (\n                \"views.setup\",\n                \"views.integrations\",\n                \"views.themes\",\n            ):\n                return\n            else:\n                return redirect(url_for(\"views.setup\"))\n\n    @app.before_request\n    def tracker():\n        if request.endpoint == \"views.themes\":\n            return\n\n        if authed():\n            user_ips = get_current_user_recent_ips()\n            ip = get_ip()\n\n            track = None\n            if (ip not in user_ips) or (request.method != \"GET\"):\n                track = Tracking.query.filter_by(\n                    ip=get_ip(), user_id=session[\"id\"]\n                ).first()\n\n                if track:\n                    track.date = datetime.datetime.utcnow()\n                else:\n                    track = Tracking(ip=get_ip(), user_id=session[\"id\"])\n                    db.session.add(track)\n\n            if track:\n                try:\n                    db.session.commit()\n                except (InvalidRequestError, IntegrityError):\n                    db.session.rollback()\n                    db.session.close()\n                    logout_user()\n                else:\n                    clear_user_recent_ips(user_id=session[\"id\"])\n\n    @app.before_request\n    def banned():\n        if request.endpoint == \"views.themes\":\n            return\n\n        if authed():\n            user = get_current_user_attrs()\n            team = get_current_team_attrs()\n\n            if user and user.banned:\n                return (\n                    render_template(\n                        \"errors/403.html\", error=\"You have been banned from this CTF\"\n                    ),\n                    403,\n                )\n\n            if team and team.banned:\n                return (\n                    render_template(\n                        \"errors/403.html\",\n                        error=\"Your team has been banned from this CTF\",\n                    ),\n                    403,\n                )\n\n    @app.before_request\n    def tokens():\n        token = request.headers.get(\"Authorization\")\n        if token and request.content_type == \"application/json\":\n            try:\n                token_type, token = token.split(\" \", 1)\n                user = lookup_user_token(token)\n            except UserNotFoundException:\n                abort(401)\n            except UserTokenExpiredException:\n                abort(401)\n            except Exception:\n                abort(401)\n            else:\n                login_user(user)\n\n    @app.before_request\n    def csrf():\n        try:\n            func = app.view_functions[request.endpoint]\n        except KeyError:\n            abort(404)\n        if hasattr(func, \"_bypass_csrf\"):\n            return\n        if request.headers.get(\"Authorization\"):\n            return\n        if not session.get(\"nonce\"):\n            session[\"nonce\"] = generate_nonce()\n        if request.method not in (\"GET\", \"HEAD\", \"OPTIONS\", \"TRACE\"):\n            if request.content_type == \"application/json\":\n                if session[\"nonce\"] != request.headers.get(\"CSRF-Token\"):\n                    abort(403)\n            if request.content_type != \"application/json\":\n                if session[\"nonce\"] != request.form.get(\"nonce\"):\n                    abort(403)\n\n    application_root = app.config.get(\"APPLICATION_ROOT\")\n    if application_root != \"/\":\n\n        @app.before_request\n        def force_subdirectory_redirect():\n            if request.path.startswith(application_root) is False:\n                return redirect(\n                    application_root + request.script_root + request.full_path\n                )\n\n        app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {application_root: app})\n", "path": "CTFd/utils/initialization/__init__.py"}, {"content": "from collections import namedtuple\n\nUserAttrs = namedtuple(\n    \"UserAttrs\",\n    [\n        \"id\",\n        \"oauth_id\",\n        \"name\",\n        \"email\",\n        \"type\",\n        \"secret\",\n        \"website\",\n        \"affiliation\",\n        \"country\",\n        \"bracket\",\n        \"hidden\",\n        \"banned\",\n        \"verified\",\n        \"team_id\",\n        \"created\",\n    ],\n)\n\n\nclass _UserAttrsWrapper:\n    def __getattr__(self, attr):\n        from CTFd.utils.user import get_current_user_attrs\n\n        attrs = get_current_user_attrs()\n        return getattr(attrs, attr, None)\n\n    @property\n    def place(self):\n        from CTFd.utils.user import get_current_user\n\n        user = get_current_user()\n        if user:\n            return user.place\n        return None\n\n    @property\n    def score(self):\n        from CTFd.utils.user import get_current_user\n\n        user = get_current_user()\n        if user:\n            return user.score\n        return None\n\n\nUser = _UserAttrsWrapper()\n", "path": "CTFd/constants/users.py"}]}