Added templates, javascript (jquery), and a cleaning script

master
John Hammond 2016-08-17 11:15:05 -04:00
parent 10ae797fa5
commit 5faabce182
10 changed files with 251 additions and 127 deletions

View File

@ -18,7 +18,11 @@ File & Directory Information
* [`static/`](static/)
This folder is required by [Flask] and it is where all "static" files live, like things for [CSS] or images or fonts or [HTML] templates.
This folder is required by [Flask] and it is where all "static" files live, like things for [CSS] or images or fonts.
* [`templates/`](templates/)
This is another folder required by [Flask], and it stores all of the [HTML] code that builds the markup of the website.
* [`schema.sql`](schema.sql)
@ -33,6 +37,9 @@ File & Directory Information
This is actual source code of the web application. __! Remember, it is _not_ what you will actually run to deploy the server; the [`setup.sh`](setup.sh) script will take it and configure it, to create a new, functional `server.py` which is what you will run when you deploy.__
* [`clean.sh`](clean.sh)
This is just a one-liner script that just gets rid of the created `server.py` and the private keys created for use with [HTTPS].
[Python]: https://www.python.org/
@ -41,3 +48,4 @@ File & Directory Information
[bash]: https://en.wikipedia.org/wiki/Bash_(Unix_shell)
[CSS]: https://www.w3.org/Style/CSS/Overview.en.html
[HTML]: https://en.wikipedia.org/wiki/HTML
[HTTPS:]: https://en.wikipedia.org/wiki/HTTPS

3
clean.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
rm -f server.py certificate.crt privateKey.key

View File

@ -12,10 +12,13 @@ from time import sleep
from uuid import uuid4
import flag_server
from passlib.hash import sha256_crypt
from contextlib import closing
flag_rotation_seconds = 60
correct_answers = {}
debug = True
@ -40,6 +43,7 @@ else:
# ===========================================================================
DATABASE = '$DATABASE'
CONFIG = '$CONFIGURATION'
CERTIFICATE = '$CERTIFICATE_FILE'
PRIVATE_KEY = '$PRIVATEKEY_FILE'
@ -49,6 +53,10 @@ if DATABASE == '$DATABASE':
error("This server has not yet been configured with a database file!")
exit(-1)
if CONFIG == '$CONFIGURATION':
error("This server has not yet been configured with a configuration file!")
exit(-1)
if CERTIFICATE == '$CERTIFICATE_FILE':
error("This server has not yet been configured with a certificate!")
exit(-1)
@ -61,6 +69,56 @@ app = Flask( __name__ )
app.config.from_object(__name__)
needed_configurations = [
"app_title", "app_about", "app_navigation_logged_out",
"app_navigation_logged_in", "services"
]
def flag_rotator( services ):
global correct_answers
round = 0
while 1:
print "FLAG ROUND", round, "="*50
correct_answers = {}
for service in services:
flag = flag_server.generate_flag()
flag_server.save_flag( flag, "services/" + service['folder_name'] )
correct_answers[ flag ] = service['points']
round += 1
sleep( flag_rotation_seconds )
if not ( os.path.exists(CONFIG) ):
error("This configuration file '" + CONFIG + "' does not seem to exist!")
exit(-1)
else:
success("The configuration file exists!")
handle = open( CONFIG )
configuration = json.loads(handle.read().replace("\n","").replace("\t",""))
try:
for needed_config in needed_configurations:
assert configuration[needed_config]
except Exception as e:
error("Configuration file '" + sys.argv[1] + "' does not have the following configuration tag:")
warning(e.message)
error("Please fix this and re-run the server.")
exit(-1)
handle.close()
success("The configuration looks good!")
success("Starting the flag rotator...")
flag_rotation = Thread( target = flag_rotator, args = ( configuration['services'],) )
flag_rotation.daemon = True
flag_rotation.start()
success("Spinning up the server...")
def init_db():
with closing(connect_db()) as db:
with app.open_resource('schema.sql', mode='r') as f:
@ -80,13 +138,13 @@ def teardown_request(exception):
if db is not None:
db.close()
# --------------------------------------------------------------------
@app.route("/")
def index():
if not ( session['logged_in'] ):
return redirect('login')
def render( template_name, **kwargs ):
return render_template( template_name,
app_title = configuration['app_title'],
app_navigation_logged_out = configuration['app_navigation_logged_out'],
app_navigation_logged_in = configuration['app_navigation_logged_in'],
**kwargs
)
@app.route("/login", methods=["GET", "POST"])
def login():
@ -108,179 +166,179 @@ def login():
session_login( request.form['username'] )
return redirect( "about" )
return redirect( "challenges" )
return render_template( 'login.html' )
return render( 'login.html', error = error )
# @app.route("/register", methods=["GET", "POST"])
# def register():
@app.route("/register", methods=["GET", "POST"])
def register():
# cur = g.db.execute('select username from users')
cur = g.db.execute('select username from users')
# usernames = [row[0] for row in cur.fetchall() ]
usernames = [row[0] for row in cur.fetchall() ]
# error = ""
# if request.method == "POST":
error = ""
if request.method == "POST":
# if unicode(request.form['username']) in usernames:
# error = 'This username is already in use!'
# elif (request.form['password'] == ""):
# error = "You must supply a password!"
# elif request.form['password'] != request.form['confirm']:
# error = 'Your passwords do not match!'
# else:
if unicode(request.form['username']) in usernames:
error = 'This username is already in use!'
elif (request.form['password'] == ""):
error = "You must supply a password!"
elif request.form['password'] != request.form['confirm']:
error = 'Your passwords do not match!'
else:
# # I use this for command-line submission...
# identifier = str(uuid4())
# I use this for command-line submission...
identifier = str(uuid4())
# cur = g.db.execute('insert into users (username, password, solved_challenges, score, last_submission, uuid) values ( ?, ?, ?, ?, ?, ? )', [
# request.form['username'],
# sha256_crypt.encrypt( request.form['password']),
# "", # No challenges completed
# 0, # no score.
# 0, # no last submission time,
# identifier # and a completely unique idenitifier
# ] )
cur = g.db.execute('insert into users (username, password, solved_challenges, score, last_submission, uuid) values ( ?, ?, ?, ?, ?, ? )', [
request.form['username'],
sha256_crypt.encrypt( request.form['password']),
"", # No challenges completed
0, # no score.
0, # no last submission time,
identifier # and a completely unique idenitifier
] )
# g.db.commit()
g.db.commit()
# flash("Hello " + request.form['username'] + ", you have successfully registered!")
# session_login( request.form['username'] )
# return redirect( "challenges" )
flash("Hello " + request.form['username'] + ", you have successfully registered!")
session_login( request.form['username'] )
return redirect( "challenges" )
# return render( 'register.html', error = error )
return render( 'register.html', error = error )
# @app.route("/scoreboard")
# def scoreboard():
@app.route("/scoreboard")
def scoreboard():
# cur = g.db.execute('select username, score from users order by score desc, last_submission asc')
# response = cur.fetchall()
cur = g.db.execute('select username, score from users order by score desc, last_submission asc')
response = cur.fetchall()
# users = [ { "username": row[0], "score": row[1] } for row in response]
users = [ { "username": row[0], "score": row[1] } for row in response]
# return render("scoreboard.html", users = users )
return render("scoreboard.html", users = users )
# @app.route("/logout")
# def logout():
@app.route("/logout")
def logout():
# session_logout()
# return redirect("about")
session_logout()
return redirect("about")
# @app.route("/")
# @app.route("/about")
# def about(): return render("about.html", app_about=configuration['app_about'])
@app.route("/")
@app.route("/about")
def about(): return render("about.html", app_about=configuration['app_about'])
# @app.route("/challenges")
# def challenges_page():
@app.route("/challenges")
def challenges_page():
# if not ( session['logged_in'] ):
# return render("login.html", error = "You must log in to be able to see the challenges!")
# try:
# cur = g.db.execute('select uuid from users where username =?',
# [ session['username'],] )
if not ( session['logged_in'] ):
return render("login.html", error = "You must log in to be able to see the challenges!")
try:
cur = g.db.execute('select uuid from users where username =?',
[ session['username'],] )
# uuid = cur.fetchone()[0]
# except Exception as e:
# print error(e.message)
# uuid = ''
uuid = cur.fetchone()[0]
except Exception as e:
print error(e.message)
uuid = ''
# return render("challenges.html", challenges = configuration['services'], url=request.url_root, session_value = uuid )
return render("challenges.html", challenges = configuration['services'], url=request.url_root, session_value = uuid )
# @app.route("/check_answer", methods=["GET", "POST"])
# def check_answer():
@app.route("/check_answer", methods=["GET", "POST"])
def check_answer():
# global correct_answers
global correct_answers
# if request.method == "POST":
# if request.form['answer'] in session['solved_challenges']:
if request.method == "POST":
if request.form['answer'] in session['solved_challenges']:
# return json.dumps({'correct': -1});
return json.dumps({'correct': -1});
# if ( request.form['answer'] in correct_answers.keys() ):
if ( request.form['answer'] in correct_answers.keys() ):
# flag = request.form['answer']
flag = request.form['answer']
# new_score = int(session['score']) + correct_answers[flag]
# cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')) where username = (?)", [
# new_score,
# session['username']
# ] );
new_score = int(session['score']) + correct_answers[flag]
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')) where username = (?)", [
new_score,
session['username']
] );
# session['solved_challenges'].append( request.form['answer'] )
# session['score'] = new_score
# g.db.commit();
session['solved_challenges'].append( request.form['answer'] )
session['score'] = new_score
g.db.commit();
# return json.dumps({'correct': 1, 'new_score': new_score});
# else:
# return json.dumps({'correct': 0});
return json.dumps({'correct': 1, 'new_score': new_score});
else:
return json.dumps({'correct': 0});
# @app.route("/submit", methods=[ "POST" ])
# def submit():
@app.route("/submit", methods=[ "POST" ])
def submit():
# global correct_answers
global correct_answers
# if request.method == "POST":
if request.method == "POST":
# if ( request.form['flag'] in correct_answers.keys() ):
if ( request.form['flag'] in correct_answers.keys() ):
# flag = request.form['flag']
flag = request.form['flag']
# cur = g.db.execute('select score, solved_challenges from users where uuid = (?)',
# [ request.form['uuid'], ])
cur = g.db.execute('select score, solved_challenges from users where uuid = (?)',
[ request.form['uuid'], ])
# current_score, solved_challenges = cur.fetchone()
current_score, solved_challenges = cur.fetchone()
# solved_challenges = solved_challenges.split()
solved_challenges = solved_challenges.split()
# if ( flag in solved_challenges ):
# return 'You already submitted this flag!\n'
if ( flag in solved_challenges ):
return 'You already submitted this flag!\n'
# print solved_challenges
print solved_challenges
# new_score = current_score + correct_answers[flag]
# solved_challenges.append( flag + " " )
# cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')), solved_challenges = (?) where uuid = (?)", [
# new_score,
# ' '.join(solved_challenges),
# request.form['uuid']
# ] );
new_score = current_score + correct_answers[flag]
solved_challenges.append( flag + " " )
cur = g.db.execute("update users set score = (?), last_submission = (SELECT strftime('%s')), solved_challenges = (?) where uuid = (?)", [
new_score,
' '.join(solved_challenges),
request.form['uuid']
] );
# # session['solved_challenges'].append( request.form['flag'] )
# session['score'] = new_score
# g.db.commit();
# session['solved_challenges'].append( request.form['flag'] )
session['score'] = new_score
g.db.commit();
# # return json.dumps({'correct': 1, 'new_score': new_score});
# return 'Correct!\n';
# else:
# # return json.dumps({'correct': 0});
# return 'Incorrect!\n';
# return json.dumps({'correct': 1, 'new_score': new_score});
return 'Correct!\n';
else:
# return json.dumps({'correct': 0});
return 'Incorrect!\n';
def session_login( username ):
flash("You were successfully logged in!")
# cur = g.db.execute('select solved_challenges, score from users where username = (?)',
# [username])
cur = g.db.execute('select solved_challenges, score from users where username = (?)',
[username])
# solved_challenges, score = cur.fetchone()
solved_challenges, score = cur.fetchone()
session['logged_in'] = True
# session['username'] = username
# session['score'] = score
# session['solved_challenges'] = []
session['username'] = username
session['score'] = score
session['solved_challenges'] = []
def session_logout():
flash("You have been successfully logged out.")
session['logged_in'] = False
# session.pop('username')
# session.pop('score')
session.pop('username')
session.pop('score')
if ( __name__ == "__main__" ):
context = (CERTIFICATE, PRIVATE_KEY)

View File

@ -8,7 +8,6 @@
# Optional variables: this should be modified by the commandline arguments
DATABASE=""
CONFIGURATION=""
# Internal variables; do not edit.
DEPENDENCIES="python-pip sqlite3 python-flask python-passlib"
@ -150,12 +149,6 @@ if [ "$DATABASE" == "" ]; then
exit -1
fi
# Make sure we entered a configuration file
if [ "$CONFIGURATION" == "" ]; then
echo "$0: ${RED}you must specify a configuration file!${NC}"
display_help
exit -1
fi
# This makes it so every function has a "pre-declaration" of all the functions
main "$@"

13
static/js/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

5
static/js/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

1
static/js/notify.js Normal file

File diff suppressed because one or more lines are too long

19
templates/base_page.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Login -- USCGA BearShop</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/master.css' ) }}">
<script src="{{ url_for('static', filename='js/jquery.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/notify.js' ) }}"></script>
<script src="{{ url_for('static', filename='js/jquery-ui.min.js' ) }}"></script>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>

24
templates/login.html Normal file
View File

@ -0,0 +1,24 @@
{% extends "base_page.html" %}
{% block content %}
<div id="login_box_background"></div>
<div id="login_box">
<h1>Welcome the USCGA BearShop!</h1>
<p>
Please login below with your EDU e-mail and your BearShop password.
</p>
<form>
<input type="text" name="email">
<input type="password" name="password">
<input type="submit" value="LOGIN" id="login">
</form>
<span id="register"> REGISTER </span>
</div>
{% endblock %}

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8">
<title> Login -- USCGA BearShop</title>
<link rel="stylesheet" type="text/css" href="css/master.css">
<link rel="stylesheet" type="text/css" href="../static/css/master.css">
</head>
<body>