diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..4006a0d --- /dev/null +++ b/__init__.py @@ -0,0 +1,41 @@ +import os + +from flask import render_template, Blueprint +from flask import request + +from .models import CheaterTeams +from . import globals + +from CTFd.plugins.migrations import upgrade +from CTFd.utils.decorators import admins_only +from CTFd.models import db + +PLUGIN_PATH = os.path.dirname(__file__) + +directory_name = PLUGIN_PATH.split(os.sep)[-1] # Get the directory name of this file + +bp = Blueprint(directory_name, __name__, template_folder="templates") + + +def add_cheater(challenge_id: int, cheater_id: int, helper_id: int, flag: str): + cheater = CheaterTeams(challenge_id, cheater_id, helper_id, flag) + db.session.add(cheater) + db.session.commit() + + +@bp.route("/admin/cheaters", methods=["GET"]) +@admins_only +def show_cheaters(): + if request.method == "GET": + cheaters = CheaterTeams.query.all() + return render_template("cheaters.html", cheaters=cheaters) + + +def load(app): + globals.initialize() + app.db.create_all() + upgrade(plugin_name="cheaters") + + app.register_blueprint(bp) + + load_hooks() diff --git a/models.py b/models.py new file mode 100644 index 0000000..e5adba6 --- /dev/null +++ b/models.py @@ -0,0 +1,42 @@ +from CTFd.models import db + + +class CheaterTeams(db.Model): + id = db.Column(db.Integer, primary_key=True) + challenge_id = db.Column( + db.Integer, db.ForeignKey("challenges.id", ondelete="CASCADE") + ) + cheater_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE")) + helper_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE")) + + flag = db.Column(db.String(128), nullable=False) + date = db.Column(db.DateTime, default=db.func.current_timestamp()) + + # Relationships + cheater = db.relationship( + "Users", foreign_keys="CheaterTeams.cheater_id", lazy="select" + ) + helper = db.relationship( + "Users", foreign_keys="CheaterTeams.helper_id", lazy="select" + ) + + challenge = db.relationship( + "BaseChallenge", + foreign_keys="CheaterTeams.challenge_id", + lazy="select", + ) + + def __init__(self, challenge_id: int, cheater_id: int, helper_id: int, flag: str): + self.challenge_id = challenge_id + self.cheater_id = cheater_id + self.helper_id = helper_id + self.flag = flag + + def __repr__(self): + return "".format( + self.cheater_id, + self.challenge_id, + self.flag, + self.helper_id, + self.date, + ) diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 0000000..e92f2f1 --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,5 @@ +{ + "include": ["."], + "extraPaths": ["/home/matteo/Gitted/CTFd"], + "reportMissingImports": true +} diff --git a/templates/cheaters.html b/templates/cheaters.html new file mode 100644 index 0000000..e90ed59 --- /dev/null +++ b/templates/cheaters.html @@ -0,0 +1,42 @@ +{% extends "base.html" %} + +{% block stylesheets %} +{% endblock %} + +{% block content %} +
+
+

Cheat Monitor

+
+
+
+
+
+ + + + + + + + + + + + + {% for cheater in cheaters %} + + + + + + + + + {% endfor %} + +
IDChallengeCheat UserHelper UserFlagDate
{{ loop.index }}{{ cheater.challenge_name() }}{{ cheater.cheated_team_name() }}{{ cheater.shared_team_name() }}{{ cheater.shared_team_name() }}{{cheater.date}}
+
+
+
+{% endblock %}