diff --git a/.gitignore b/.gitignore
index c966d14..3b01ea3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,4 +69,5 @@ venv/
.pytest_cache
submission_record.db
-
+user_record.db
+session_record.db
\ No newline at end of file
diff --git a/server.py b/server.py
index ba31e30..2c20ab1 100644
--- a/server.py
+++ b/server.py
@@ -1,23 +1,25 @@
-from bottle import Bottle, run, template, static_file, request, route, redirect,error
-import os
-import sys
-import datetime
+import bottle
+import os, sys, datetime
+import string, random
+
from collections import defaultdict, namedtuple
import shelve
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
-app = Bottle()
+app = bottle.Bottle()
database_path = "submission_record.db"
+user_db = "user_record.db"
+sessions_db = "session_record.db"
questions = {}
contests = {}
question_dir = "files/questions"
Question = namedtuple("Question", "output statement")
Submission = namedtuple("Submission", "question time output is_correct contest")
-# questions, code, description, start_time, end_time
Contest = namedtuple("Contest", "description questions start_time end_time")
+User = namedtuple("User", "password")
# dummy contests
contests["PRACTICE"] = Contest(
@@ -48,7 +50,6 @@
for i in os.listdir(question_dir):
if not i.isdigit():
continue
- # read the correct output as bytes object
with open(os.path.join(question_dir, i, "output.txt"), "rb") as fl:
output = fl.read()
with open(os.path.join(question_dir, i, "statement.txt"), "r") as fl:
@@ -56,45 +57,62 @@
questions[i] = Question(output=output, statement=statement)
+def login_required(function):
+ def login_redirect(*args, **kwargs):
+ if not logggedIn():
+ return bottle.template("home.html", message="Login required.")
+ return function(*args, **kwargs)
+ return login_redirect
+
@app.route("/")
def changePath():
- return redirect("/dashboard")
+ return bottle.redirect("/home")
+
+
+@app.get("/home")
+def home():
+ if logggedIn():
+ return bottle.redirect("/dashboard")
+ return bottle.template("home.html", message="")
@app.get("/dashboard")
+@login_required
def dashboard():
- return template("dashboard.html", contests=contests)
+ return bottle.template("dashboard.html", contests=contests)
@app.get("/contest//
")
+@login_required
def contest(code):
if not code in contests:
return "Contest does not exist"
if contests[code].start_time > datetime.datetime.now():
return "The contest had not started yet."
- return template("contest.html", code=code, contest=contests[code])
+ return bottle.template("contest.html", code=code, contest=contests[code])
@app.get("/question/
")
@@ -124,7 +142,7 @@ def contest_ranking(code):
order.sort(key=lambda x: x[1], reverse=True)
order = [entry for entry in order if entry[1] > 0]
order = [(user, score, rank) for rank, (user, score) in enumerate(order, start=1)]
- return template("rankings.html", people=order)
+ return bottle.template("rankings.html", people=order)
@app.get("/ranking")
@@ -149,12 +167,68 @@ def rankings():
order = [(user, score, rank) for rank, (user, score) in enumerate(order, start=1)]
return template("rankings.html", people=order)
+def logggedIn():
+ if not bottle.request.get_cookie("s_id"):
+ return False
+ with shelve.open(sessions_db) as sessions:
+ return bottle.request.get_cookie("s_id") in sessions
+
+
+def createSession(username):
+ session_id = "".join(
+ random.choice(string.ascii_letters + string.digits) for i in range(20)
+ )
+ bottle.response.set_cookie(
+ "s_id",
+ session_id,
+ expires=datetime.datetime.now() + datetime.timedelta(days=30),
+ )
+ with shelve.open(sessions_db) as sessions:
+ sessions[session_id] = username
+ return bottle.redirect("/dashboard")
+
+
+@app.post("/login")
+def login():
+ username = bottle.request.forms.get("username")
+ password = bottle.request.forms.get("password")
+ with shelve.open(user_db) as users:
+ if not username in users:
+ return bottle.template("home.html", message="User does not exist.")
+ if users[username].password != password:
+ return bottle.template("home.html", message="Incorrect password.")
+ return createSession(username)
+
+
+@app.post("/register")
+def register():
+ username = bottle.request.forms.get("username")
+ password = bottle.request.forms.get("password")
+ with shelve.open(user_db) as users:
+ if username in users:
+ return bottle.template(
+ "home.html",
+ message="Username already exists. Select a different username",
+ )
+ users[username] = User(password=password)
+ return createSession(username)
+
+
+@app.get("/logout")
+def logout():
+ with shelve.open(sessions_db) as sessions:
+ del sessions[bottle.request.get_cookie("s_id")]
+ bottle.response.delete_cookie("s_id")
+ return bottle.redirect("/home")
+
@app.post("/check/
/
{{code}}
{{contest.description}}