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:
Kevin Chung
2016-10-20 23:31:24 -04:00
parent 92f9d93bf9
commit 3f596d87b1
6 changed files with 50 additions and 32 deletions

View File

@@ -731,16 +731,17 @@ def admin_stats():
solve_count = db.session.query(db.func.count(Solves.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, solves_raw) \
solves_sub = db.session.query(Solves.chalid, db.func.count(Solves.chalid).label('solves_cnt')) \
.join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False) \
.group_by(Solves.chalid).subquery()
solves_cnt = coalesce(solves_sub.columns.solves_raw, 0).label('solves_cnt')
most_solved_chal = Challenges.query.add_columns(solves_cnt) \
.outerjoin(solves_sub, solves_sub.columns.chalid == Challenges.id) \
.order_by(solves_cnt.desc()).first()
least_solved_chal = Challenges.query.add_columns(solves_cnt) \
.outerjoin(solves_sub, solves_sub.columns.chalid == Challenges.id) \
.order_by(solves_cnt.asc()).first()
solves = db.session.query(solves_sub.columns.chalid, solves_sub.columns.solves_cnt, Challenges.name) \
.join(Challenges, solves_sub.columns.chalid == Challenges.id).all()
solve_data = {}
for chal, count, name in solves:
solve_data[name] = count
most_solved = max(solve_data, key=solve_data.get)
least_solved = min(solve_data, key=solve_data.get)
db.session.expunge_all()
db.session.commit()
@@ -750,8 +751,9 @@ def admin_stats():
wrong_count=wrong_count,
solve_count=solve_count,
challenge_count=challenge_count,
most_solved=most_solved_chal,
least_solved=least_solved_chal
solve_data=solve_data,
most_solved=most_solved,
least_solved=least_solved
)

View File

@@ -23,11 +23,11 @@ def confirm_user(data=None):
if data and request.method == "GET": ## User is confirming email account
try:
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:
return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
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.verified = True
db.session.commit()
@@ -57,9 +57,11 @@ def reset_password(data=None):
if data is not None and request.method == "POST":
try:
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:
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.password = bcrypt_sha256.encrypt(request.form['password'].strip())
db.session.commit()
@@ -70,7 +72,7 @@ def reset_password(data=None):
email = request.form['email'].strip()
team = Teams.query.filter_by(email=email).first()
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'])
token = s.dumps(team.name)
text = """
@@ -78,11 +80,11 @@ Did you initiate a password reset?
{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)
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')
@@ -175,7 +177,7 @@ def login():
return redirect(request.args.get('next'))
return redirect(url_for('challenges.challenges_view'))
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()
return render_template('login.html', errors=errors)
else: # This user just doesn't exist

View File

@@ -59,15 +59,28 @@
}
function solves_graph() {
$.get('{{ request.script_root }}/admin/graphs/solves', function(data){
$.get('{{ request.script_root }}/admin/graphs/solves', function (data) {
var solves = $.parseJSON(JSON.stringify(data));
var chals = [];
var counts = [];
var colors = [];
var annotations = [];
var i = 1;
$.each(solves, function(key, value){
chals.push(key);
counts.push(value);
solves_order = Object.keys(solves).sort(function (a, b) {
return solves[b] - solves[a]
});
$.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++));
});
@@ -80,7 +93,8 @@
}];
var layout = {
title: 'Score Counts'
title: 'Score Counts',
annotations: annotations
};
Plotly.newPlot('solves-graph', data, layout);

View File

@@ -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>{{ challenge_count }}</b> challenges</h3>
{% 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 %}
{% 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 %}
</div>

View File

@@ -45,7 +45,7 @@
Please check your email to confirm your email address.
<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>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>

View File

@@ -126,11 +126,11 @@ def teams(page):
page_end = results_per_page * ( page - 1 ) + results_per_page
if get_config('verify_emails'):
count = Teams.query.filter_by(verified=True).count()
teams = Teams.query.filter_by(verified=True).slice(page_start, page_end).all()
count = Teams.query.filter_by(verified=True, banned=False).count()
teams = Teams.query.filter_by(verified=True, banned=False).slice(page_start, page_end).all()
else:
count = Teams.query.count()
teams = Teams.query.slice(page_start, page_end).all()
count = Teams.query.filter_by(banned=False).count()
teams = Teams.query.filter_by(banned=False).slice(page_start, page_end).all()
pages = int(count / results_per_page) + (count % results_per_page > 0)
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
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 \
(not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)):