Exemple #1
0
    def delete(self, user_id):
        # Admins should not be able to delete themselves
        if user_id == session["id"]:
            return (
                {
                    "success": False,
                    "errors": {
                        "id": "You cannot delete yourself"
                    }
                },
                400,
            )

        Notifications.query.filter_by(user_id=user_id).delete()
        Awards.query.filter_by(user_id=user_id).delete()
        Unlocks.query.filter_by(user_id=user_id).delete()
        Submissions.query.filter_by(user_id=user_id).delete()
        Solves.query.filter_by(user_id=user_id).delete()
        Tracking.query.filter_by(user_id=user_id).delete()
        Users.query.filter_by(id=user_id).delete()
        db.session.commit()
        db.session.close()

        clear_user_session(user_id=user_id)
        clear_standings()

        return {"success": True}
Exemple #2
0
    def patch(self, user_id):
        user = Users.query.filter_by(id=user_id).first_or_404()
        data = request.get_json()
        data["id"] = user_id

        # Admins should not be able to ban themselves
        if data["id"] == session["id"] and (data.get("banned") is True
                                            or data.get("banned") == "true"):
            return (
                {
                    "success": False,
                    "errors": {
                        "id": "You cannot ban yourself"
                    }
                },
                400,
            )

        schema = UserSchema(view="admin", instance=user, partial=True)
        response = schema.load(data)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        # This generates the response first before actually changing the type
        # This avoids an error during User type changes where we change
        # the polymorphic identity resulting in an ObjectDeletedError
        # https://github.com/CTFd/CTFd/issues/1794
        response = schema.dump(response.data)
        db.session.commit()
        db.session.close()

        clear_user_session(user_id=user_id)
        clear_standings()

        return {"success": True, "data": response.data}
Exemple #3
0
def gen_award(db, user_id, team_id=None, name="award_name", value=100):
    award = Awards(user_id=user_id, team_id=team_id, name=name, value=value)
    award.date = datetime.datetime.utcnow()
    db.session.add(award)
    db.session.commit()
    clear_standings()
    return award
Exemple #4
0
    def post(self):
        req = request.get_json()
        user = get_current_user()

        req["user_id"] = user.id
        req["team_id"] = user.team_id

        Model = get_class_by_tablename(req["type"])
        target = Model.query.filter_by(id=req["target"]).first_or_404()

        if target.cost > user.score:
            return (
                {
                    "success": False,
                    "errors": {
                        "score":
                        "You do not have enough points to unlock this hint"
                    },
                },
                400,
            )

        schema = UnlockSchema()
        response = schema.load(req, session=db.session)

        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        existing = Unlocks.query.filter_by(**req).first()
        if existing:
            return (
                {
                    "success": False,
                    "errors": {
                        "target": "You've already unlocked this this target"
                    },
                },
                400,
            )

        db.session.add(response.data)

        award_schema = AwardSchema()
        award = {
            "user_id": user.id,
            "team_id": user.team_id,
            "name": target.name,
            "description": target.description,
            "value": (-target.cost),
            "category": target.category,
        }

        award = award_schema.load(award)
        db.session.add(award.data)
        db.session.commit()
        clear_standings()

        response = schema.dump(response.data)

        return {"success": True, "data": response.data}
Exemple #5
0
    def patch(self, user_id):
        user = Users.query.filter_by(id=user_id).first_or_404()
        data = request.get_json()
        data["id"] = user_id

        # Admins should not be able to ban themselves
        if data["id"] == session["id"] and (data.get("banned") is True
                                            or data.get("banned") == "true"):
            return (
                {
                    "success": False,
                    "errors": {
                        "id": "You cannot ban yourself"
                    }
                },
                400,
            )

        schema = UserSchema(view="admin", instance=user, partial=True)
        response = schema.load(data)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.commit()

        response = schema.dump(response.data)

        db.session.close()

        clear_user_session(user_id=user_id)
        clear_standings()

        return {"success": True, "data": response}
Exemple #6
0
def truncate_database():
    # delete all table data (but keep tables)
    _pages = Pages.query.all()
    for p in _pages:
        for f in p.files:
            delete_file(file_id=f.id)

    Pages.query.delete()

    Notifications.query.delete()

    _challenges = Challenges.query.all()
    for c in _challenges:
        for f in c.files:
            delete_file(file_id=f.id)
    Challenges.query.delete()

    Users.query.delete()
    Teams.query.delete()

    Solves.query.delete()
    Submissions.query.delete()
    Awards.query.delete()
    Unlocks.query.delete()
    Tracking.query.delete()

    Configs.query.delete()
    clear_config()
    clear_pages()
    clear_standings()
    cache.clear()

    db.session.commit()
Exemple #7
0
    def post(self):
        req = request.get_json()
        user = get_current_user()

        req["user_id"] = user.id
        req["team_id"] = user.team_id

        Model = get_class_by_tablename(req["type"])
        target = Model.query.filter_by(id=req["target"]).first_or_404()

        if target.cost > user.score:
            return (
                {
                    "success": False,
                    "errors": {
                        "score":
                        "У вас недостаточно очков, чтобы разблокировать эту подсказку"
                    },
                },
                400,
            )

        schema = UnlockSchema()
        response = schema.load(req, session=db.session)

        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        existing = Unlocks.query.filter_by(**req).first()
        if existing:
            return (
                {
                    "success": False,
                    "errors": {
                        "target": "Вы уже разблокировали это"
                    },
                },
                400,
            )

        db.session.add(response.data)

        award_schema = AwardSchema()
        award = {
            "user_id": user.id,
            "team_id": user.team_id,
            "name": target.name,
            "description": target.description,
            "value": (-target.cost),
            "category": target.category,
        }

        award = award_schema.load(award)
        db.session.add(award.data)
        db.session.commit()
        clear_standings()

        response = schema.dump(response.data)

        return {"success": True, "data": response.data}
Exemple #8
0
def test_scoreboard_is_cached():
    """Test that /api/v1/scoreboard is properly cached and cleared"""
    app = create_ctfd()
    with app.app_context():
        # create user1
        register_user(app, name="user1", email="*****@*****.**")

        # create challenge
        chal = gen_challenge(app.db, value=100)
        gen_flag(app.db, challenge_id=chal.id, content="flag")
        chal_id = chal.id

        # create a solve for the challenge for user1. (the id is 2 because of the admin)
        gen_solve(app.db, user_id=2, challenge_id=chal_id)

        with login_as_user(app, "user1") as client:
            # No cached data
            assert app.cache.get("view/api.scoreboard_scoreboard_list") is None
            assert app.cache.get(
                "view/api.scoreboard_scoreboard_detail") is None

            # Load and check cached data
            client.get("/api/v1/scoreboard")
            assert app.cache.get("view/api.scoreboard_scoreboard_list")
            client.get("/api/v1/scoreboard/top/10")
            assert app.cache.get("view/api.scoreboard_scoreboard_detail")

            # Empty standings and check that the cached data is gone
            clear_standings()
            assert app.cache.get("view/api.scoreboard_scoreboard_list") is None
            assert app.cache.get(
                "view/api.scoreboard_scoreboard_detail") is None
    destroy_ctfd(app)
	def patch(self, config_key):
		config = Configs.query.filter_by(key=config_key).first()
		data = request.get_json()
		if config:
			schema = ConfigSchema(instance=config, partial=True)
			response = schema.load(data)
		else:
			schema = ConfigSchema()
			data['key'] = config_key
			response = schema.load(data)
			db.session.add(response.data)

		if response.errors:
			return response.errors, 400

		db.session.commit()

		response = schema.dump(response.data)
		db.session.close()

		clear_config()
		clear_standings()

		return {
			'success': True,
			'data': response.data
		}
Exemple #10
0
    def delete(self):
        team_disbanding = get_config("team_disbanding", default="inactive_only")
        if team_disbanding == "disabled":
            return (
                {
                    "success": False,
                    "errors": {"": ["Team disbanding is currently disabled"]},
                },
                403,
            )

        team = get_current_team()
        if team.captain_id != session["id"]:
            return (
                {
                    "success": False,
                    "errors": {"": ["Only team captains can disband their team"]},
                },
                403,
            )

        # The team must not have performed any actions in the CTF
        performed_actions = any(
            [
                team.solves != [],
                team.fails != [],
                team.awards != [],
                Submissions.query.filter_by(team_id=team.id).all() != [],
                Unlocks.query.filter_by(team_id=team.id).all() != [],
            ]
        )

        if performed_actions:
            return (
                {
                    "success": False,
                    "errors": {
                        "": [
                            "You cannot disband your team as it has participated in the event. "
                            "Please contact an admin to disband your team or remove a member."
                        ]
                    },
                },
                403,
            )

        for member in team.members:
            member.team_id = None
            clear_user_session(user_id=member.id)

        db.session.delete(team)
        db.session.commit()

        clear_team_session(team_id=team.id)
        clear_standings()

        db.session.close()

        return {"success": True}
Exemple #11
0
def reset():
    if request.method == "POST":
        require_setup = False
        logout = False
        next_url = url_for("admin.statistics")

        data = request.form

        if data.get("pages"):
            _pages = Pages.query.all()
            for p in _pages:
                for f in p.files:
                    delete_file(file_id=f.id)

            Pages.query.delete()

        if data.get("notifications"):
            Notifications.query.delete()

        if data.get("challenges"):
            _challenges = Challenges.query.all()
            for c in _challenges:
                for f in c.files:
                    delete_file(file_id=f.id)
            Challenges.query.delete()

        if data.get("accounts"):
            Users.query.delete()
            Teams.query.delete()
            require_setup = True
            logout = True

        if data.get("submissions"):
            Solves.query.delete()
            Submissions.query.delete()
            Awards.query.delete()
            Unlocks.query.delete()
            Tracking.query.delete()

        if require_setup:
            set_config("setup", False)
            cache.clear()
            logout_user()
            next_url = url_for("views.setup")

        db.session.commit()

        clear_pages()
        clear_standings()
        clear_config()

        if logout is True:
            cache.clear()
            logout_user()

        db.session.close()
        return redirect(next_url)

    return render_template("admin/reset.html")
Exemple #12
0
    def delete(self, award_id):
        award = Awards.query.filter_by(id=award_id).first_or_404()
        db.session.delete(award)
        db.session.commit()
        db.session.close()

        # Delete standings cache because awards can change scores
        clear_standings()

        return {"success": True}
Exemple #13
0
    def patch(self):
        req = request.get_json()

        for key, value in req.items():
            set_config(key=key, value=value)

        clear_config()
        clear_standings()

        return {"success": True}
Exemple #14
0
    def attempt_single(self, request, request_data, user, team, kpm,
                       challenge):
        challenge_id = challenge.id

        if challenge.state == "hidden":
            return False, ''

        if challenge.state == "locked":
            return False, ''

        if challenge.requirements:
            requirements = challenge.requirements.get("prerequisites", [])
            solve_ids = (Solves.query.with_entities(
                Solves.challenge_id).filter_by(
                    account_id=user.account_id).order_by(
                        Solves.challenge_id.asc()).all())
            solve_ids = set([solve_id for solve_id, in solve_ids])
            prereqs = set(requirements)
            if solve_ids >= prereqs:
                pass
            else:
                return False, ''

        chal_class = get_chal_class(challenge.type)

        solves = Solves.query.filter_by(account_id=user.account_id,
                                        challenge_id=challenge_id).first()

        # Challenge not solved yet
        if not solves:
            status, message = chal_class.attempt(challenge, request)
            if status:  # The challenge plugin says the input is right
                if ctftime() or current_user.is_admin():
                    chal_class.solve(user=user,
                                     team=team,
                                     challenge=challenge,
                                     request=request)
                    clear_standings()

                log(
                    "submissions",
                    "[{date}] {name} submitted {submission} with kpm {kpm} [CORRECT]",
                    submission=request_data["submission"].encode("utf-8"),
                    kpm=kpm,
                )
                return True, message
            else:  # The challenge plugin says the input is wrong
                if ctftime() or current_user.is_admin():
                    clear_standings()

                return False, message

        # Challenge already solved
        else:
            return False, ''
Exemple #15
0
    def delete(self, submission_id):
        submission = Submissions.query.filter_by(
            id=submission_id).first_or_404()
        db.session.delete(submission)
        db.session.commit()
        db.session.close()

        # Delete standings cache
        clear_standings()

        return {"success": True}
Exemple #16
0
    def delete(self, config_key):
        config = Configs.query.filter_by(key=config_key).first_or_404()

        db.session.delete(config)
        db.session.commit()
        db.session.close()

        clear_config()
        clear_standings()

        return {"success": True}
Exemple #17
0
    def delete(self, team_id):
        team = Teams.query.filter_by(id=team_id).first_or_404()

        for member in team.members:
            member.team_id = None

        db.session.delete(team)
        db.session.commit()
        db.session.close()

        clear_standings()

        return {"success": True}
Exemple #18
0
    def delete(self, user_id):
        Notifications.query.filter_by(user_id=user_id).delete()
        Awards.query.filter_by(user_id=user_id).delete()
        Unlocks.query.filter_by(user_id=user_id).delete()
        Submissions.query.filter_by(user_id=user_id).delete()
        Solves.query.filter_by(user_id=user_id).delete()
        Tracking.query.filter_by(user_id=user_id).delete()
        Users.query.filter_by(id=user_id).delete()
        db.session.commit()
        db.session.close()

        clear_standings()

        return {"success": True}
Exemple #19
0
    def patch(self):
        req = request.get_json()
        schema = ConfigSchema()

        for key, value in req.items():
            response = schema.load({"key": key, "value": value})
            if response.errors:
                return {"success": False, "errors": response.errors}, 400
            set_config(key=key, value=value)

        clear_config()
        clear_standings()

        return {"success": True}
Exemple #20
0
    def patch(self):
        user = get_current_user()
        data = request.get_json()
        schema = UserSchema(view="self", instance=user, partial=True)
        response = schema.load(data)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        clear_standings()

        return {"success": True, "data": response.data}
Exemple #21
0
    def post(self):
        req = request.get_json()
        schema = UserSchema('admin')
        response = schema.load(req)

        if response.errors:
            return {'success': False, 'errors': response.errors}, 400

        db.session.add(response.data)
        db.session.commit()

        clear_standings()

        response = schema.dump(response.data)

        return {'success': True, 'data': response.data}
Exemple #22
0
    def post(self):
        req = request.get_json()
        Model = Submissions.get_child(type=req.get("type"))
        schema = SubmissionSchema(instance=Model())
        response = schema.load(req)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400
        db.session.add(response.data)
        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        # Delete standings cache
        clear_standings()

        return {"success": True, "data": response.data}
Exemple #23
0
    def delete(self, user_id):
        # import time; time.sleep(60)
        if get_current_user().id == user_id:
            return {'success': False, 'data': 'Cannot delete own account'}
        Notifications.query.filter_by(user_id=user_id).delete()
        Awards.query.filter_by(user_id=user_id).delete()
        Unlocks.query.filter_by(user_id=user_id).delete()
        Submissions.query.filter_by(user_id=user_id).delete()
        Solves.query.filter_by(user_id=user_id).delete()
        Tracking.query.filter_by(user_id=user_id).delete()
        Users.query.filter_by(id=user_id).delete()
        db.session.commit()
        db.session.close()

        clear_standings()

        return {"success": True}
Exemple #24
0
def gen_solve(db,
              user_id,
              team_id=None,
              challenge_id=None,
              ip="127.0.0.1",
              provided="rightkey",
              **kwargs):
    solve = Solves(user_id=user_id,
                   team_id=team_id,
                   challenge_id=challenge_id,
                   ip=ip,
                   provided=provided,
                   **kwargs)
    solve.date = datetime.datetime.utcnow()
    db.session.add(solve)
    db.session.commit()
    clear_standings()
    return solve
Exemple #25
0
    def post(self):
        req = request.get_json()
        schema = AwardSchema()

        response = schema.load(req, session=db.session)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.add(response.data)
        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        # Delete standings cache because awards can change scores
        clear_standings()

        return {"success": True, "data": response.data}
Exemple #26
0
    def post(self):
        req = request.get_json()
        schema = ConfigSchema()
        response = schema.load(req)

        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.add(response.data)
        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        clear_config()
        clear_standings()

        return {"success": True, "data": response.data}
Exemple #27
0
    def patch(self, team_id):
        team = Teams.query.filter_by(id=team_id).first_or_404()
        data = request.get_json()
        data["id"] = team_id

        schema = TeamSchema(view="admin", instance=team, partial=True)

        response = schema.load(data)
        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        response = schema.dump(response.data)
        db.session.commit()
        db.session.close()

        clear_standings()

        return {"success": True, "data": response.data}
Exemple #28
0
    def post(self):
        req = request.get_json()
        view = TeamSchema.views.get(session.get("type", "self"))
        schema = TeamSchema(view=view)
        response = schema.load(req)

        if response.errors:
            return {"success": False, "errors": response.errors}, 400

        db.session.add(response.data)
        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        clear_standings()

        return {"success": True, "data": response.data}
    def post(self):
        req = request.get_json()
        view = TeamSchema.views.get(session.get('type', 'self'))
        schema = TeamSchema(view=view)
        response = schema.load(req)

        if response.errors:
            return {'success': False, 'errors': response.errors}, 400

        db.session.add(response.data)
        db.session.commit()

        response = schema.dump(response.data)
        db.session.close()

        clear_standings()

        return {'success': True, 'data': response.data}
Exemple #30
0
    def patch(self):
        req = request.get_json()
        schema = ConfigSchema()

        for key, value in req.items():
            response = schema.load({"key": key, "value": value})
            if response.errors:
                # Inject config key into error
                config_key = response.data["key"]
                response.errors["value"][
                    0] = f"{config_key} config is too long"
                return {"success": False, "errors": response.errors}, 400
            set_config(key=key, value=value)

        clear_config()
        clear_standings()

        return {"success": True}