diff --git a/CTFd/api/v1/challenges.py b/CTFd/api/v1/challenges.py index 2ccd9598..9f108747 100644 --- a/CTFd/api/v1/challenges.py +++ b/CTFd/api/v1/challenges.py @@ -6,7 +6,17 @@ from sqlalchemy.sql import and_ from CTFd.cache import clear_standings from CTFd.models import ChallengeFiles as ChallengeFilesModel -from CTFd.models import Challenges, Fails, Flags, Hints, HintUnlocks, Solves, Tags, db +from CTFd.models import ( + Challenges, + Fails, + Flags, + Hints, + HintUnlocks, + Solves, + Submissions, + Tags, + db, +) from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class from CTFd.schemas.flags import FlagSchema from CTFd.schemas.hints import HintSchema @@ -273,6 +283,15 @@ class Challenge(Resource): else: response["solves"] = None + if authed(): + # Get current attempts for the user + attempts = Submissions.query.filter_by( + account_id=user.account_id, challenge_id=challenge_id + ).count() + else: + attempts = 0 + + response["attempts"] = attempts response["files"] = files response["tags"] = tags response["hints"] = hints @@ -283,6 +302,8 @@ class Challenge(Resource): files=files, tags=tags, hints=[Hints(**h) for h in hints], + max_attempts=chal.max_attempts, + attempts=attempts, challenge=chal, ) diff --git a/CTFd/themes/core/templates/challenge.html b/CTFd/themes/core/templates/challenge.html index 817b1dfb..f5059eea 100644 --- a/CTFd/themes/core/templates/challenge.html +++ b/CTFd/themes/core/templates/challenge.html @@ -83,6 +83,16 @@ {% endfor %} + {% if max_attempts > 1 %} +
+
+

+ {{ attempts }}/{{ max_attempts }} attempt{{ attempts|pluralize(attempts) }} +

+
+
+ {% endif %} +
{% block input %} diff --git a/CTFd/utils/humanize/words.py b/CTFd/utils/humanize/words.py new file mode 100644 index 00000000..88647f9b --- /dev/null +++ b/CTFd/utils/humanize/words.py @@ -0,0 +1,5 @@ +def pluralize(number, singular="", plural="s"): + if number == 1: + return singular + else: + return plural diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py index b8247034..f16fd71f 100644 --- a/CTFd/utils/initialization/__init__.py +++ b/CTFd/utils/initialization/__init__.py @@ -23,6 +23,7 @@ from CTFd.utils.config.pages import get_pages from CTFd.utils.countries import get_countries, lookup_country_code from CTFd.utils.dates import isoformat, unix_time, unix_time_millis from CTFd.utils.events import EventManager, RedisEventManager +from CTFd.utils.humanize.words import pluralize from CTFd.utils.modes import generate_account_url, get_mode_as_word from CTFd.utils.plugins import ( get_configurable_plugins, @@ -48,6 +49,7 @@ def init_template_filters(app): app.jinja_env.filters["unix_time"] = unix_time app.jinja_env.filters["unix_time_millis"] = unix_time_millis app.jinja_env.filters["isoformat"] = isoformat + app.jinja_env.filters["pluralize"] = pluralize def init_template_globals(app):