diff --git a/CTFd/themes/admin/templates/config.html b/CTFd/themes/admin/templates/config.html index 3fae030e..1e097069 100644 --- a/CTFd/themes/admin/templates/config.html +++ b/CTFd/themes/admin/templates/config.html @@ -23,6 +23,9 @@ + @@ -73,6 +76,8 @@ {% include "admin/configs/accounts.html" %} + {% include "admin/configs/pages.html" %} + {% include "admin/configs/fields.html" %} {% include "admin/configs/mlc.html" %} diff --git a/CTFd/themes/admin/templates/configs/pages.html b/CTFd/themes/admin/templates/configs/pages.html new file mode 100644 index 00000000..972f425c --- /dev/null +++ b/CTFd/themes/admin/templates/configs/pages.html @@ -0,0 +1,14 @@ +
+
+
+ + +
+ +
+
diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py index 8e0c376c..7379b36e 100644 --- a/CTFd/utils/initialization/__init__.py +++ b/CTFd/utils/initialization/__init__.py @@ -204,6 +204,7 @@ def init_request_processors(app): "views.themes", "views.files", "views.healthcheck", + "views.robots", ): return else: diff --git a/CTFd/views.py b/CTFd/views.py index d94cecf3..8876bab8 100644 --- a/CTFd/views.py +++ b/CTFd/views.py @@ -2,7 +2,15 @@ import os from flask import Blueprint, abort from flask import current_app as app -from flask import redirect, render_template, request, send_file, session, url_for +from flask import ( + make_response, + redirect, + render_template, + request, + send_file, + session, + url_for, +) from flask.helpers import safe_join from jinja2.exceptions import TemplateNotFound from sqlalchemy.exc import IntegrityError @@ -514,3 +522,11 @@ def healthcheck(): if check_config() is False: return "ERR", 500 return "OK", 200 + + +@views.route("/robots.txt") +def robots(): + text = get_config("robots_txt", "User-agent: *\nDisallow: /admin\n") + r = make_response(text, 200) + r.mimetype = "text/plain" + return r diff --git a/tests/test_views.py b/tests/test_views.py index 3b814940..55da66bf 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -451,3 +451,19 @@ def test_user_can_access_files_if_view_after_ctf(): rmdir(directory) destroy_ctfd(app) + + +def test_robots_txt(): + """Does the robots.txt page work""" + app = create_ctfd() + with app.app_context(): + with app.test_client() as client: + r = client.get("/robots.txt") + assert r.status_code == 200 + assert r.get_data(as_text=True) == "User-agent: *\nDisallow: /admin\n" + set_config("robots_txt", "testing") + with app.test_client() as client: + r = client.get("/robots.txt") + assert r.status_code == 200 + assert r.get_data(as_text=True) == "testing" + destroy_ctfd(app)