From 951da7663f7aa60120577ca6488cabf306d3fbe1 Mon Sep 17 00:00:00 2001 From: LpCote <73721863+LpCote4@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:39:29 -0500 Subject: [PATCH] feat: migration file and integration in challenges page --- CTFd/plugins/sport_challenges/__init__.py | 4 ++ CTFd/themes/core-beta/assets/js/challenges.js | 1 + .../themes/core-beta/templates/challenge.html | 27 ++++++++++++- .../cf1a32af89a7_add_sportchallenge_class.py | 39 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 migrations/versions/cf1a32af89a7_add_sportchallenge_class.py diff --git a/CTFd/plugins/sport_challenges/__init__.py b/CTFd/plugins/sport_challenges/__init__.py index a7bcf07a..a960c2ee 100644 --- a/CTFd/plugins/sport_challenges/__init__.py +++ b/CTFd/plugins/sport_challenges/__init__.py @@ -24,6 +24,8 @@ class SportChallenge(Challenges): db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE"), primary_key=True ) max_points = db.Column(db.Integer, default=0) + unit = db.Column(db.String(32), default="km") #Unitées associées à l'activité + points = db.Column(db.Integer, default=0) def __init__(self, *args, **kwargs): super(SportChallenge, self).__init__(**kwargs) @@ -77,7 +79,9 @@ class SportValueChallenge(BaseChallenge): "category": challenge.category, "state": challenge.state, "max_points": challenge.max_points, + "unit": challenge.unit, "type": challenge.type, + "points": challenge.points, "type_data": { "id": cls.id, "name": cls.name, diff --git a/CTFd/themes/core-beta/assets/js/challenges.js b/CTFd/themes/core-beta/assets/js/challenges.js index 5b5dfff0..602b28e7 100644 --- a/CTFd/themes/core-beta/assets/js/challenges.js +++ b/CTFd/themes/core-beta/assets/js/challenges.js @@ -223,6 +223,7 @@ Alpine.data("Challenge", () => ({ }, async submitManualChallenge(type) { + alert(type); //dans le cas ou le user envoit des fichier if (!document.getElementById("file-input").hidden){ diff --git a/CTFd/themes/core-beta/templates/challenge.html b/CTFd/themes/core-beta/templates/challenge.html index 9e155c53..d1d0e65a 100644 --- a/CTFd/themes/core-beta/templates/challenge.html +++ b/CTFd/themes/core-beta/templates/challenge.html @@ -246,7 +246,7 @@ </div> {% endif %} - {% if (not solved_by_me and attempts == 0) or ((max_attempts == 0 or max_attempts > attempts) and challenge.type == "manualRecursive") or ((max_attempts == 0 or max_attempts > attempts) and challenge.type == "standard" and not solved_by_me) or (challenge.type == "sport" and (points < max_points)) %} + {% if (not solved_by_me and attempts == 0) or ((max_attempts == 0 or max_attempts > attempts) and challenge.type == "manualRecursive") or ((max_attempts == 0 or max_attempts > attempts) and challenge.type == "standard" and not solved_by_me) or (challenge.type == "sport" and (challenge.max_points > challenge.points)) %} <div class="row submit-row"> <div class="col-12 col-sm-8 w-100"> {% block input %} @@ -261,6 +261,27 @@ @keyup.enter="submitChallenge()" placeholder="{% trans %}Flag{% endtrans %}" x-model="submission" > + {% elif challenge.type == "sport" %} + <input + id="challenge-id" class="challenge-id" type="hidden" + value="{{ challenge.id }}"> + {{challenge.unit}} + {{challenge.max_points}} + {{challenge.points}} + <input + id="challenge-input" + type="hidden"> + <h3 style="font-size: 1em!important; font-weight: bold;" id="soumettre-media-label">Soumettre un ou plusieurs médias</h3> + <label for="form-file-input-btn" id="file-input" style="display: flex;" class="btn btn-outline-secondary"> + Sélectionnez un fichier + </label> + + + <textarea id="text-input" style="display: flex; width: 100%;--bs-btn-hover-color:black;--bs-btn-hover-bg:white;--bs-btn-active-bg:white;" class="btn btn-outline-secondary" hidden></textarea> + <form id="form-file-input" > + <input id="form-file-input-btn" onchange="changeLabel(event)" class="challenge-input form-control" + type="file" name="file" multiple style="display: none;"> + </form> {% else %} <input id="challenge-id" class="challenge-id" type="hidden" @@ -324,6 +345,10 @@ <h3 class="challenge-value text-center"> Défi déjà complété! </h3> + {% elif attempts > 0 and challenge.type == "sport" %} + <h3 class="challenge-value text-center" style="display: flex; justify-content: center; align-items: center; width: 100%;"> + Vous avez déjà atteint la limite de points pour ce challenge. [{{challenge.points}}/{{challenge.max_points}}] + </h3> {% elif attempts > 0 and challenge.type != "standard" %} <h3 class="challenge-value text-center"> Défi soumis. Si vous êtes le propriétaire, vous pouvez le supprimer dans la section Équipe. Sinon, demandez à un admin ou à votre capitaine d'équipe ! diff --git a/migrations/versions/cf1a32af89a7_add_sportchallenge_class.py b/migrations/versions/cf1a32af89a7_add_sportchallenge_class.py new file mode 100644 index 00000000..fde60203 --- /dev/null +++ b/migrations/versions/cf1a32af89a7_add_sportchallenge_class.py @@ -0,0 +1,39 @@ +"""Add SportChallenge class + +Revision ID: cf1a32af89a7 +Revises: f27b6be89c67 +Create Date: 2024-11-12 15:57:58.814728 + +""" +from alembic import op +import sqlalchemy as sa + + + + +# revision identifiers, used by Alembic. +revision = 'cf1a32af89a7' +down_revision = 'f27b6be89c67' +branch_labels = None +depends_on = None + + +def upgrade(): + # op.create_table('sport_challenge', + # sa.Column('id', sa.Integer(), nullable=False), + # sa.ForeignKeyConstraint(['id'], ['challenges.id'], ondelete='CASCADE'), + # sa.PrimaryKeyConstraint('id') + # ) + op.create_table( + "sport_challenge", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("unit", sa.Integer(), nullable=True), + sa.Column("points", sa.Integer(), nullable=True), + sa.Column("category", sa.String(length=32), nullable=True), + sa.ForeignKeyConstraint(['id'], ['challenges.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + + +def downgrade(): + op.drop_table("sport_challenge") \ No newline at end of file -- GitLab