mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-20 07:14:24 +01:00
Fixing a variety of glitches
Fixing statistics reporting banned users as well Fixing url encoding and some error messages Ordering solves in the admin graphs Removing banned users (includes admins) from public teams page Fixing email regex in profile
This commit is contained in:
@@ -731,16 +731,17 @@ def admin_stats():
|
|||||||
solve_count = db.session.query(db.func.count(Solves.id)).first()[0]
|
solve_count = db.session.query(db.func.count(Solves.id)).first()[0]
|
||||||
challenge_count = db.session.query(db.func.count(Challenges.id)).first()[0]
|
challenge_count = db.session.query(db.func.count(Challenges.id)).first()[0]
|
||||||
|
|
||||||
solves_raw = db.func.count(Solves.chalid).label('solves_raw')
|
solves_sub = db.session.query(Solves.chalid, db.func.count(Solves.chalid).label('solves_cnt')) \
|
||||||
solves_sub = db.session.query(Solves.chalid, solves_raw) \
|
.join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False) \
|
||||||
.group_by(Solves.chalid).subquery()
|
.group_by(Solves.chalid).subquery()
|
||||||
solves_cnt = coalesce(solves_sub.columns.solves_raw, 0).label('solves_cnt')
|
solves = db.session.query(solves_sub.columns.chalid, solves_sub.columns.solves_cnt, Challenges.name) \
|
||||||
most_solved_chal = Challenges.query.add_columns(solves_cnt) \
|
.join(Challenges, solves_sub.columns.chalid == Challenges.id).all()
|
||||||
.outerjoin(solves_sub, solves_sub.columns.chalid == Challenges.id) \
|
solve_data = {}
|
||||||
.order_by(solves_cnt.desc()).first()
|
for chal, count, name in solves:
|
||||||
least_solved_chal = Challenges.query.add_columns(solves_cnt) \
|
solve_data[name] = count
|
||||||
.outerjoin(solves_sub, solves_sub.columns.chalid == Challenges.id) \
|
|
||||||
.order_by(solves_cnt.asc()).first()
|
most_solved = max(solve_data, key=solve_data.get)
|
||||||
|
least_solved = min(solve_data, key=solve_data.get)
|
||||||
|
|
||||||
db.session.expunge_all()
|
db.session.expunge_all()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -750,8 +751,9 @@ def admin_stats():
|
|||||||
wrong_count=wrong_count,
|
wrong_count=wrong_count,
|
||||||
solve_count=solve_count,
|
solve_count=solve_count,
|
||||||
challenge_count=challenge_count,
|
challenge_count=challenge_count,
|
||||||
most_solved=most_solved_chal,
|
solve_data=solve_data,
|
||||||
least_solved=least_solved_chal
|
most_solved=most_solved,
|
||||||
|
least_solved=least_solved
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
CTFd/auth.py
16
CTFd/auth.py
@@ -23,11 +23,11 @@ def confirm_user(data=None):
|
|||||||
if data and request.method == "GET": ## User is confirming email account
|
if data and request.method == "GET": ## User is confirming email account
|
||||||
try:
|
try:
|
||||||
s = Signer(app.config['SECRET_KEY'])
|
s = Signer(app.config['SECRET_KEY'])
|
||||||
email = s.unsign(urllib.unquote(data.decode('base64')))
|
email = s.unsign(urllib.unquote_plus(data.decode('base64')))
|
||||||
except BadSignature:
|
except BadSignature:
|
||||||
return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
|
return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
|
||||||
except:
|
except:
|
||||||
return render_template('reset_password.html', errors=['Your link appears broken, please try again.'])
|
return render_template('confirm.html', errors=['Your link appears broken, please try again.'])
|
||||||
team = Teams.query.filter_by(email=email).first()
|
team = Teams.query.filter_by(email=email).first()
|
||||||
team.verified = True
|
team.verified = True
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -57,9 +57,11 @@ def reset_password(data=None):
|
|||||||
if data is not None and request.method == "POST":
|
if data is not None and request.method == "POST":
|
||||||
try:
|
try:
|
||||||
s = TimedSerializer(app.config['SECRET_KEY'])
|
s = TimedSerializer(app.config['SECRET_KEY'])
|
||||||
name = s.loads(urllib.unquote(data.decode('base64')), max_age=1800)
|
name = s.loads(urllib.unquote_plus(data.decode('base64')), max_age=1800)
|
||||||
except BadTimeSignature:
|
except BadTimeSignature:
|
||||||
return render_template('reset_password.html', errors=['Your link has expired'])
|
return render_template('reset_password.html', errors=['Your link has expired'])
|
||||||
|
except:
|
||||||
|
return render_template('reset_password.html', errors=['Your link appears broken, please try again.'])
|
||||||
team = Teams.query.filter_by(name=name).first()
|
team = Teams.query.filter_by(name=name).first()
|
||||||
team.password = bcrypt_sha256.encrypt(request.form['password'].strip())
|
team.password = bcrypt_sha256.encrypt(request.form['password'].strip())
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -70,7 +72,7 @@ def reset_password(data=None):
|
|||||||
email = request.form['email'].strip()
|
email = request.form['email'].strip()
|
||||||
team = Teams.query.filter_by(email=email).first()
|
team = Teams.query.filter_by(email=email).first()
|
||||||
if not team:
|
if not team:
|
||||||
return render_template('reset_password.html', errors=['Check your email'])
|
return render_template('reset_password.html', errors=['If that account exists you will receive an email, please check your inbox'])
|
||||||
s = TimedSerializer(app.config['SECRET_KEY'])
|
s = TimedSerializer(app.config['SECRET_KEY'])
|
||||||
token = s.dumps(team.name)
|
token = s.dumps(team.name)
|
||||||
text = """
|
text = """
|
||||||
@@ -78,11 +80,11 @@ Did you initiate a password reset?
|
|||||||
|
|
||||||
{0}/{1}
|
{0}/{1}
|
||||||
|
|
||||||
""".format(url_for('auth.reset_password', _external=True), token.encode('base64'))
|
""".format(url_for('auth.reset_password', _external=True), urllib.quote_plus(token.encode('base64')))
|
||||||
|
|
||||||
sendmail(email, text)
|
sendmail(email, text)
|
||||||
|
|
||||||
return render_template('reset_password.html', errors=['Check your email'])
|
return render_template('reset_password.html', errors=['If that account exists you will receive an email, please check your inbox'])
|
||||||
return render_template('reset_password.html')
|
return render_template('reset_password.html')
|
||||||
|
|
||||||
|
|
||||||
@@ -175,7 +177,7 @@ def login():
|
|||||||
return redirect(request.args.get('next'))
|
return redirect(request.args.get('next'))
|
||||||
return redirect(url_for('challenges.challenges_view'))
|
return redirect(url_for('challenges.challenges_view'))
|
||||||
else: # This user exists but the password is wrong
|
else: # This user exists but the password is wrong
|
||||||
errors.append("That account doesn't seem to exist")
|
errors.append("Your username or password is incorrect")
|
||||||
db.session.close()
|
db.session.close()
|
||||||
return render_template('login.html', errors=errors)
|
return render_template('login.html', errors=errors)
|
||||||
else: # This user just doesn't exist
|
else: # This user just doesn't exist
|
||||||
|
|||||||
@@ -64,10 +64,23 @@
|
|||||||
var chals = [];
|
var chals = [];
|
||||||
var counts = [];
|
var counts = [];
|
||||||
var colors = [];
|
var colors = [];
|
||||||
|
var annotations = [];
|
||||||
var i = 1;
|
var i = 1;
|
||||||
$.each(solves, function(key, value){
|
solves_order = Object.keys(solves).sort(function (a, b) {
|
||||||
chals.push(key);
|
return solves[b] - solves[a]
|
||||||
counts.push(value);
|
});
|
||||||
|
$.each(solves_order, function (key, value) {
|
||||||
|
chals.push(value);
|
||||||
|
counts.push(solves[value]);
|
||||||
|
var result = {
|
||||||
|
x: value,
|
||||||
|
y: solves[value],
|
||||||
|
text: solves[value],
|
||||||
|
xanchor: 'center',
|
||||||
|
yanchor: 'bottom',
|
||||||
|
showarrow: false
|
||||||
|
};
|
||||||
|
annotations.push(result);
|
||||||
colors.push(colorhash(i++));
|
colors.push(colorhash(i++));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -80,7 +93,8 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
var layout = {
|
var layout = {
|
||||||
title: 'Score Counts'
|
title: 'Score Counts',
|
||||||
|
annotations: annotations
|
||||||
};
|
};
|
||||||
|
|
||||||
Plotly.newPlot('solves-graph', data, layout);
|
Plotly.newPlot('solves-graph', data, layout);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
<h3><b>{{ solve_count }}</b> <a href="{{ request.script_root }}/admin/correct_keys/1">right keys</a> submitted</h3>
|
<h3><b>{{ solve_count }}</b> <a href="{{ request.script_root }}/admin/correct_keys/1">right keys</a> submitted</h3>
|
||||||
<h3><b>{{ challenge_count }}</b> challenges</h3>
|
<h3><b>{{ challenge_count }}</b> challenges</h3>
|
||||||
{% if most_solved %}
|
{% if most_solved %}
|
||||||
<h3>Most solved: <b>{{ most_solved[0].name }}</b> with {{ most_solved[1] }}</b> solves</h3>
|
<h3>Most solved: <b>{{ most_solved }}</b> with {{ solve_data[most_solved] }}</b> solves</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if least_solved %}
|
{% if least_solved %}
|
||||||
<h3>Least solved: <b>{{ least_solved[0].name }}</b> with {{ least_solved[1] }}</b> solves</h3>
|
<h3>Least solved: <b>{{ least_solved }}</b> with {{ solve_data[least_solved] }}</b> solves</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
Please check your email to confirm your email address.
|
Please check your email to confirm your email address.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
To have the confirmation email reset please <a href="{{ request.script_root }}/confirm">click
|
To have the confirmation email resent please <a href="{{ request.script_root }}/confirm">click
|
||||||
here.</a>
|
here.</a>
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
||||||
aria-hidden="true">×</span></button>
|
aria-hidden="true">×</span></button>
|
||||||
|
|||||||
@@ -126,11 +126,11 @@ def teams(page):
|
|||||||
page_end = results_per_page * ( page - 1 ) + results_per_page
|
page_end = results_per_page * ( page - 1 ) + results_per_page
|
||||||
|
|
||||||
if get_config('verify_emails'):
|
if get_config('verify_emails'):
|
||||||
count = Teams.query.filter_by(verified=True).count()
|
count = Teams.query.filter_by(verified=True, banned=False).count()
|
||||||
teams = Teams.query.filter_by(verified=True).slice(page_start, page_end).all()
|
teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()
|
||||||
else:
|
else:
|
||||||
count = Teams.query.count()
|
count = Teams.query.filter_by(banned=False).count()
|
||||||
teams = Teams.query.slice(page_start, page_end).all()
|
teams = Teams.query.filter_by(banned=False).slice(page_start, page_end).all()
|
||||||
pages = int(count / results_per_page) + (count % results_per_page > 0)
|
pages = int(count / results_per_page) + (count % results_per_page > 0)
|
||||||
return render_template('teams.html', teams=teams, team_pages=pages, curr_page=page)
|
return render_template('teams.html', teams=teams, team_pages=pages, curr_page=page)
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ def profile():
|
|||||||
name_len = len(request.form['name']) == 0
|
name_len = len(request.form['name']) == 0
|
||||||
|
|
||||||
emails = Teams.query.filter_by(email=email).first()
|
emails = Teams.query.filter_by(email=email).first()
|
||||||
valid_email = re.match("[^@]+@[^@]+\.[^@]+", email)
|
valid_email = re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email)
|
||||||
|
|
||||||
if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
|
if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \
|
||||||
(not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
|
(not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):
|
||||||
|
|||||||
Reference in New Issue
Block a user