def create_new_category(): """ Create a new category given parameters in application/json body """ data = request.get_json() check_existing_category = Category.query.filter_by(name=data['name'].lower()).first() if check_existing_category: return collision() upload_required = bool(data.get("upload_required")) new_category = Category.create(data['name'].lower(), data['description'], upload_required) return jsonify(new_category), 201
def create_difficulty(): """ Creates a difficulty Takes 'name' value from application/json body and creates a Difficulty """ data = request.get_json() check_difficulty = Difficulty.query.filter_by(name=data['name'].lower()).first() if check_difficulty: return collision() new_difficulty = Difficulty.create(data['name'].lower()) return jsonify(new_difficulty), 201
def purchase_hint(challenge_id: int = 0, flag_id: int = 0, hint_id: int = 0, **kwargs): # pylint: disable=unused-argument """ Operations relating to used hints :POST: Allow a user to pay for a hint """ hint = Hint.query.filter_by(id=hint_id).first() if not hint: return not_found() current_username = kwargs['userinfo'].get('preferred_username') if not current_username: return no_username() # Check that the relation doesn't already exist used_hints_check = UsedHint.query.filter_by(hint_id=hint_id, username=current_username).first() if used_hints_check: return collision() if current_username == hint.flag.challenge.submitter: return jsonify({ 'status': "error", 'message': "You created this hint!" }), 403 if Solved.query.filter_by(flag_id=hint.flag.id).first(): return jsonify({ 'status': "error", 'message': "You already solved the flag associated with this hint!" }), 422 if get_user_score(current_username)[0] - hint.cost < 0: return jsonify({ 'status': "error", 'message': "You don't have enough points to purchase this hint!" }), 422 new_used_hint = UsedHint.create(hint_id, current_username) return jsonify(new_used_hint.hint.to_dict()), 201
def single_tag(challenge_id: int, tag_name: str, **kwargs): """ Creates a tag """ challenge = Challenge.query.filter_by(id=challenge_id).first() if not challenge: return not_found() tag = ChallengeTag.query.filter_by(tag=tag_name, challenge_id=challenge_id).first() if tag: return collision() current_username = kwargs['userinfo'].get('preferred_username') if not current_username: return no_username() groups = kwargs['userinfo'].get('groups') if current_username != challenge.submitter and not is_ctf_admin(groups): return not_authorized() new_tag = ChallengeTag.create(challenge_id, tag_name) return jsonify(new_tag), 201
def create_challenge(**kwargs): """ Creates a challenge given parameters in application/json body """ data = request.form.to_dict() category = Category.query.filter_by(name=data['category'].lower()).first() difficulty = Difficulty.query.filter_by(name=data['difficulty'].lower()).first() if not (category and difficulty): return jsonify({ 'status': "error", 'message': "The category or difficulty doesn't exist" }), 422 submitter = kwargs['userinfo'].get('preferred_username') if not submitter: return no_username() # check if challenge with matching title already exists if Challenge.query.filter(Challenge.title.ilike('test')).first(): return collision() file = request.files.get('file') if category.upload_required and not file: return missing_body_parts("multipart/form-data", "file") else: split = os.path.splitext(secure_filename(file.filename)) filename = secure_filename(data['title'] + str(split[-1])) filepath = os.path.join(app.config['UPLOAD_PATH'], filename) file.save(filepath) mime = magic.Magic(mime=True) if not mime.from_file(filepath) in app.config['ALLOWED_MIME_TYPES']: return invalid_mime_type(mime.from_file(filepath)) tags = [] if tag_names := data.get('tags'): tags = list(dict.fromkeys(tag_names.split(",")))
def add_flag(challenge_id: int, **kwargs): """ Create a flag given parameters in application/json body """ challenge = Challenge.query.filter_by(id=challenge_id).first() if not challenge: return not_found() data = request.get_json() flag_exists = Flag.query.filter_by(challenge_id=challenge_id, flag=data['flag']).first() if flag_exists: return collision() current_username = kwargs['userinfo'].get('preferred_username') if not current_username: return no_username() groups = kwargs['userinfo'].get('groups') if current_username != challenge.submitter and not is_ctf_admin(groups): return not_authorized() new_flag = Flag.create(data['point_value'], data['flag'], challenge_id) return jsonify(new_flag), 201
def solve_flag(challenge_id: int, **kwargs): """ Operations pertaining to the solved relations on a challenge (but really a flag). :param challenge_id: The challenge that a solution is being attempted on :POST: Attempt solution of all flags associated with this challenge """ challenge = Challenge.query.filter_by(id=challenge_id).first() if not challenge: return not_found() data = request.get_json() flag_attempt = data['flag'] flags = Flag.query.filter_by(challenge_id=challenge_id).all() current_username = kwargs['userinfo'].get('preferred_username') if not current_username: return no_username() if challenge.submitter == current_username: return jsonify({ 'status': "error", 'message': "You created this flag!" }), 403 for flag in flags: if flag.flag == flag_attempt: check_solved = Solved.query.filter_by( flag_id=flag.id, username=current_username).first() if check_solved: return collision() Solved.create(flag.id, current_username) return jsonify(challenge.to_dict()), 201 return jsonify({'status': "error", 'message': "Incorrect flag"}), 400