def load(app): """load overrides for smart_city to work properly""" logger.setLevel(app.logger.getEffectiveLevel()) app.db.create_all() register_plugin_assets_directory( app, base_path='/plugins/CTFd_SmartCity/assets') challenges.CHALLENGE_CLASSES['smart_city'] = SmartCity dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'new-register.html') override_template('register.html', open(template_path).read()) template_path = os.path.join(dir_path, 'new-admin-team.html') override_template('admin/teams.html', open(template_path).read()) template_path = os.path.join(dir_path, 'new-setup.html') override_template('setup.html', open(template_path).read()) template_path = os.path.join(dir_path, 'new-team.html') override_template('teams.html', open(template_path).read()) template_path = os.path.join(dir_path, 'new-base.html') override_template('base.html', open(template_path).read()) app.view_functions['auth.register'] = register_smart app.view_functions['challenges.chal'] = chal_custom app.view_functions['admin_teams.delete_team'] = delete_team_custom app.view_functions[ 'admin_teams.admin_create_team'] = admin_create_team_custom app.view_functions[ 'admin_teams.admin_teams_view'] = admin_teams_view_custom app.view_functions['views.setup'] = setup_custom app.view_functions['views.teams'] = teams_custom
def test_override_template(): """Does override_template work properly for regular themes""" app = create_ctfd() with app.app_context(): override_template('login.html', 'LOGIN OVERRIDE') with app.test_client() as client: r = client.get('/login') assert r.status_code == 200 output = r.get_data(as_text=True) assert 'LOGIN OVERRIDE' in output
def test_admin_override_template(): """Does override_template work properly for the admin panel""" app = create_ctfd() with app.app_context(): override_template('admin/team.html', 'ADMIN TEAM OVERRIDE') client = login_as_user(app, name="admin", password="******") r = client.get('/admin/team/1') assert r.status_code == 200 output = r.get_data(as_text=True) assert 'ADMIN TEAM OVERRIDE' in output
def override_register_template(): dir_path = path.dirname(path.realpath(__file__)) template_path = None selected_option = utils.get_config('private_registration_option') if selected_option == 'token': template_path = '/templates/private-registration-token.html' elif selected_option == 'email': template_path = '/templates/private-registration-email.html' if template_path: template_path = dir_path + template_path with open(template_path, 'r') as register_template: override_template('register.html', register_template.read())
def load(app): app.db.create_all() classification = Blueprint('classification', __name__, template_folder='./') dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'scoreboard.html') override_template('scoreboard.html', open(template_path).read()) register_plugin_asset(app, asset_path='/plugins/classification/config.js') # Server side Configuration menu @classification.route('/admin/plugins/classification/', methods=['GET', 'POST']) @utils.admins_only def classified(): if request.method == 'POST': teamid = request.form['id'] previous = Classification.query.filter_by(id=teamid) for x in previous: db.session.delete(x) errors = [] classification = request.form['classification'] if classification == 'other': classification = request.form['new_classification'] classify = Classification(int(teamid), classification) db.session.add(classify) db.session.commit() db.session.close() if request.method == 'GET' or request.method == 'POST': classifications = Classification.query.all() teams = [] scoring_teams = [] standings = get_standings() # Competitors with a score for i, x in enumerate(standings): pushed = 0 for classification in classifications: if classification.teamid == x.teamid: teams.append({ 'id': x.teamid, 'name': x.name, 'class': classification.classification, 'score': x.score }) pushed = 1 break scoring_teams.append(x.teamid) if (pushed == 0): teams.append({ 'id': x.teamid, 'name': x.name, 'class': '', 'score': x.score }) # Competitors with/without a score (limited to only without a score) for team in db.session.query(Teams.name, Teams.id, Teams.admin).all(): if (team.admin == False): pushed = 0 for classification in classifications: if classification.teamid == team.id: if (team.id not in scoring_teams): teams.append({ 'id': team.id, 'name': team.name, 'class': classification.classification, 'score': '' }) pushed = 1 if (pushed == 0 and (team.id not in scoring_teams)): teams.append({ 'id': team.id, 'name': team.name, 'class': '', 'score': '' }) classf = [] for clas in classifications: classf.append(clas.classification) classf = list(sorted(set(classf))) # -=- For TAMUctf, but can be left in without any problems -=- try: tamu_test() tamu = ["tamu"] except: tamu = [] # -=- db.session.close() return render_template('config.html', teams=teams, classifications=classf, tamu=tamu) def get_standings(admin=False, count=None, classification=None): scores = db.session.query( Solves.teamid.label('teamid'), db.func.sum(Challenges.value).label('score'), db.func.max(Solves.date).label('date')).join(Challenges).group_by( Solves.teamid) awards = db.session.query( Awards.teamid.label('teamid'), db.func.sum(Awards.value).label('score'), db.func.max(Awards.date).label('date')).group_by(Awards.teamid) freeze = utils.get_config('freeze') if not admin and freeze: scores = scores.filter( Solves.date < utils.unix_time_to_utc(freeze)) awards = awards.filter( Awards.date < utils.unix_time_to_utc(freeze)) results = union_all(scores, awards).alias('results') sumscores = db.session.query( results.columns.teamid, db.func.sum(results.columns.score).label('score'), db.func.max(results.columns.date).label('date')).group_by( results.columns.teamid).subquery() if admin: standings_query = db.session.query( Teams.id.label('teamid'), Teams.name.label('name'), Teams.banned, sumscores.columns.score, Classification.classification )\ .join(sumscores, Teams.id == sumscores.columns.teamid) \ .join(Classification, Teams.id == Classification.id) \ .order_by(sumscores.columns.score.desc(), sumscores.columns.date) else: standings_query = db.session.query( Teams.id.label('teamid'), Teams.name.label('name'), sumscores.columns.score, Classification.classification )\ .join(sumscores, Teams.id == sumscores.columns.teamid) \ .join(Classification, Teams.id == Classification.id) \ .filter(Teams.banned == False) \ .order_by(sumscores.columns.score.desc(), sumscores.columns.date) if classification and count: # -=- For TAMUctf, but can be left in without any problems -=- try: tamu_test() c = Classification if (classification == "tamu"): standings = standings_query.filter( or_(c.classification == "U0", c.classification == "U1", c.classification == "U2", c.classification == "U3", c.classification == "U4", c.classification == "U5", c.classification == "G5", c.classification == "G6", c.classification == "G7", c.classification == "G8", c.classification == "G9")).limit(count).all() elif (classification == "tamug"): standings = standings_query.filter( or_(c.classification == "G5", c.classification == "G6", c.classification == "G7", c.classification == "G8", c.classification == "G9")).limit(count).all() elif (classification == "tamuu"): standings = standings_query.filter( or_(c.classification == "U0", c.classification == "U1", c.classification == "U2", c.classification == "U3", c.classification == "U4", c.classification == "U5")).limit(count).all() elif (classification == "U4"): standings = standings_query.filter( or_(c.classification == "U4", c.classification == "U5")).limit(count).all() elif (classification == "tamum"): standings = standings_query.filter( or_(c.other == 3, c.other == 5, c.other == 7, c.other == 8, c.other == 12, c.other == 10, c.other == 15)).limit(count).all() elif (classification == "tamumc"): standings = standings_query.filter( or_(c.other == 3, c.other == 8, c.other == 10, c.other == 15)).limit(count).all() elif (classification == "tamumr"): standings = standings_query.filter( or_(c.other == 5, c.other == 8, c.other == 12, c.other == 15)).limit(count).all() elif (classification == "tamumd"): standings = standings_query.filter( or_(c.other == 7, c.other == 12, c.other == 10, c.other == 15)).limit(count).all() else: standings = standings_query.filter( Classification.classification == classification).limit( count).all() except: standings = standings_query.filter( Classification.classification == classification).limit( count).all() #-=- elif classification: # -=- For TAMUctf, but can be left in without any problems -=- try: tamu_test() c = Classification if (classification == "tamu"): standings = standings_query.filter( or_(c.classification == "U0", c.classification == "U1", c.classification == "U2", c.classification == "U3", c.classification == "U4", c.classification == "U5", c.classification == "G5", c.classification == "G6", c.classification == "G7", c.classification == "G8", c.classification == "G9")).all() elif (classification == "tamug"): standings = standings_query.filter( or_(c.classification == "G5", c.classification == "G6", c.classification == "G7", c.classification == "G8", c.classification == "G9")).all() elif (classification == "tamuu"): standings = standings_query.filter( or_(c.classification == "U01", c.classification == "U1", c.classification == "U2", c.classification == "U3", c.classification == "U4", c.classification == "U5")).all() elif (classification == "tamuu"): standings = standings_query.filter( or_(c.classification == "U4", c.classification == "U5")).all() elif (classification == "tamum"): standings = standings_query.filter( or_(c.other == 3, c.other == 5, c.other == 7, c.other == 8, c.other == 12, c.other == 10, c.other == 15)).all() elif (classification == "tamumc"): standings = standings_query.filter( or_(c.other == 3, c.other == 8, c.other == 10, c.other == 15)).all() elif (classification == "tamumr"): standings = standings_query.filter( or_(c.other == 5, c.other == 8, c.other == 12, c.other == 15)).all() elif (classification == "tamumd"): standings = standings_query.filter( or_(c.other == 7, c.other == 12, c.other == 10, c.other == 15)).all() else: standings = standings_query.filter( Classification.classification == classification).all() except: standings = standings_query.filter( Classification.classification == classification).all() #-=- elif count: standings = standings_query.limit(count).all() else: standings = standings_query.all() return standings def scoreboard_view(): classifications = [] for classification in db.session.query( Classification.classification).distinct(): classifications.append(classification[0]) db.session.close() classifications = sorted(classifications, reverse=True) # -=- For TAMUctf, but can be left in without any problems -=- try: tamu_test() tamu = ["tamu"] except: tamu = [] #-=- try: current_user_class = Classification.query.filter_by( id=session.get('id')).first().classification except: current_user_class = "ALL" try: current_user_other = Classification.query.filter_by( id=session.get('id')).first().other except: current_user_other = 0 if utils.get_config( 'view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return render_template('scoreboard.html', errors=['Scores are currently hidden']) standings = get_standings() return render_template('scoreboard.html', teams=standings, score_frozen=utils.is_scoreboard_frozen(), classifications=classifications, tamu=tamu, current_user_class=current_user_class, current_user_other=current_user_other) def scores(): json = {'standings': []} if utils.get_config( 'view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return jsonify(json) standings = get_standings() for i, x in enumerate(standings): json['standings'].append({ 'pos': i + 1, 'id': x.teamid, 'team': x.name, 'score': int(x.score) }) return jsonify(json) @app.route('/scores/<classification>') def classified_scores(classification): json = {'standings': []} if utils.get_config( 'view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return jsonify(json) standings = get_standings(classification=classification) for i, x in enumerate(standings): json['standings'].append({ 'pos': i + 1, 'id': x.teamid, 'team': x.name, 'score': int(x.score) }) return jsonify(json) @app.route('/top/<int:count>/<classification>') def classified_topteams(count, classification): json = {'places': {}} if utils.get_config( 'view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return jsonify(json) if count > 20 or count < 0: count = 10 standings = get_standings(count=count, classification=classification) team_ids = [team.teamid for team in standings] solves = Solves.query.filter(Solves.teamid.in_(team_ids)) awards = Awards.query.filter(Awards.teamid.in_(team_ids)) freeze = utils.get_config('freeze') if freeze: solves = solves.filter( Solves.date < utils.unix_time_to_utc(freeze)) awards = awards.filter( Awards.date < utils.unix_time_to_utc(freeze)) solves = solves.all() awards = awards.all() for i, team in enumerate(team_ids): json['places'][i + 1] = { 'id': standings[i].teamid, 'name': standings[i].name, 'solves': [] } for solve in solves: if solve.teamid == team: json['places'][i + 1]['solves'].append({ 'chal': solve.chalid, 'team': solve.teamid, 'value': solve.chal.value, 'time': utils.unix_time(solve.date) }) for award in awards: if award.teamid == team: json['places'][i + 1]['solves'].append({ 'chal': None, 'team': award.teamid, 'value': award.value, 'time': utils.unix_time(award.date) }) json['places'][i + 1]['solves'] = sorted( json['places'][i + 1]['solves'], key=lambda k: k['time']) return jsonify(json) app.view_functions['scoreboard.scoreboard_view'] = scoreboard_view app.view_functions['scoreboard.scores'] = scores app.register_blueprint(classification)
def load(app): app.db.create_all() register_plugin_assets_directory(app, base_path='/plugins/CCTFd/assets/') # create new challenge type CHALLENGE_CLASSES['community'] = CommunityChallenge # Replace templates dir_path = os.path.dirname(os.path.realpath(__file__)) base_path = os.path.join(dir_path, 'community-base.html') create_path = os.path.join(dir_path, 'create.html') chal_path = os.path.join(dir_path, 'challenges.html') override_template('base.html', open(base_path).read()) override_template('admin/chals/create.html', open(create_path).read()) override_template('challenges.html', open(chal_path).read()) # replace /chals route def chals(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: abort(403) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed abort(403) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): teamid = session.get('id') chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).order_by( Challenges.value).all() json = {'game': []} for x in chals: tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=x.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) chal_type = get_chal_class(x.type) if chal_type == CommunityChallenge: owner_id = CommunityChallengeModel.query.filter( CommunityChallengeModel.id == x.id).first().owner else: owner_id = 1 owner = Teams.query.filter(Teams.id == owner_id).first().name own = (owner_id == session['id']) chal_data = { 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': files, 'tags': tags, 'hints': hints, 'owner': owner, 'own': own, 'template': chal_type.templates['modal'], 'script': chal_type.scripts['modal'] } if own == True: chal_data.update({'nonce': session.get('nonce')}) json['game'].append(chal_data) db.session.close() return jsonify(json) else: db.session.close() abort(403) app.view_functions['challenges.chals'] = chals # create /community/chal_types route @app.route('/community/chal_types', methods=['GET']) def user_chal_types(): data = {} for class_id in CHALLENGE_CLASSES: challenge_class = CHALLENGE_CLASSES.get(class_id) # only allow CommunityChallenge for non-admin users if not utils.is_admin() and challenge_class != CommunityChallenge: continue data[challenge_class.id] = { 'id': challenge_class.id, 'name': challenge_class.name, 'templates': challenge_class.templates, 'scripts': challenge_class.scripts, } return jsonify(data) # create /community/new route @app.route('/community/new', methods=['GET', 'POST']) def user_create_chal(): if request.method == 'POST': chal_type = request.form['chaltype'] chal_class = get_chal_class(chal_type) # do not allow non-admin users to create non-community challenges if not utils.is_admin() and chal_class != CommunityChallenge: abort(403) chal_class.create(request) return redirect(url_for('challenges.challenges_view')) else: return render_template('admin/chals/create.html', content=open(create_path).read()) # create /community/update route @app.route('/community/update', methods=['POST']) def user_update_chal(): challenge = Challenges.query.filter_by( id=request.form['id']).first_or_404() chal_class = get_chal_class(challenge.type) # only allow updating Community challenges if chal_class != CommunityChallenge: abort(403) # only allow updating the challenge if the user is the owner owner = CommunityChallengeModel.query.filter( CommunityChallengeModel.id == challenge.id).first().owner if owner != session['id']: abort(403) chal_class.update(challenge, request) return redirect(url_for('challenges.challenges_view'))
def load(app): dir_path = os.path.dirname(os.path.realpath(__file__)) template_path = os.path.join(dir_path, 'scoreboard-matrix.html') override_template('scoreboard.html', open(template_path).read()) matrix = Blueprint('matrix', __name__, static_folder='static') app.register_blueprint(matrix, url_prefix='/matrix') def get_standings(): standings = scoreboard.get_standings() # TODO faster lookup here jstandings = [] for team in standings: teamid = team[0] solves = db.session.query(Solves.chalid.label('chalid')).filter(Solves.teamid==teamid) freeze = utils.get_config('freeze') if freeze: freeze = utils.unix_time_to_utc(freeze) if teamid != session.get('id'): solves = solves.filter(Solves.date < freeze) solves = solves.all() jsolves = [] for solve in solves: jsolves.append(solve.chalid) jstandings.append({'teamid':team.teamid, 'score':team.score, 'name':team.name,'solves':jsolves}) db.session.close() return jstandings def get_challenges(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: return [] if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): chals = db.session.query( Challenges.id, Challenges.name, Challenges.category ).filter(or_(Challenges.hidden != True, Challenges.hidden == None)).all() jchals = [] for x in chals: jchals.append({ 'id':x.id, 'name':x.name, 'category':x.category }) # Sort into groups categories = set(map(lambda x:x['category'], jchals)) jchals = [j for c in categories for j in jchals if j['category'] == c] return jchals return [] def scoreboard_view(): if utils.get_config('view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return render_template('scoreboard.html', errors=['Scores are currently hidden']) standings = get_standings() return render_template('scoreboard.html', teams=standings, score_frozen=utils.is_scoreboard_frozen(), challenges=get_challenges()) def scores(): json = {'standings': []} if utils.get_config('view_scoreboard_if_authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) if utils.hide_scores(): return jsonify(json) standings = get_standings() for i, x in enumerate(standings): json['standings'].append({'pos': i + 1, 'id': x['name'], 'team': x['name'], 'score': int(x['score']), 'solves':x['solves']}) return jsonify(json) app.view_functions['scoreboard.scoreboard_view'] = scoreboard_view app.view_functions['scoreboard.scores'] = scores