Repository navigation
Expand file tree
/
Copy pathroutes.py
More file actions
140 lines (120 loc) · 4.43 KB
/
Copy pathroutes.py
File metadata and controls
140 lines (120 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
from flask import Blueprint, render_template, request, redirect, session, flash, clean_url
import sqlite3
from werkzeug.security import generate_password_hash, check_password_hash
from functools import wraps
from database import get_db
# Organize routes into a neat blueprint module
main_bp = Blueprint('main', __name__)
# --- Authentication Guard Decorator ---
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if "user_id" not in session:
return redirect("/login")
return f(*args, **kwargs)
return decorated_function
# --- Routes ---
@main_bp.route("/")
@login_required
def home():
db = get_db()
user_id = session["user_id"]
# Highly optimized aggregate query fetching all 4 metric counts in a single network trip
stats = db.execute("""
SELECT
COUNT(*) as total,
SUM(CASE WHEN difficulty = 'Easy' THEN 1 ELSE 0 END) as easy,
SUM(CASE WHEN difficulty = 'Medium' THEN 1 ELSE 0 END) as medium,
SUM(CASE WHEN difficulty = 'Hard' THEN 1 ELSE 0 END) as hard
FROM problems
WHERE user_id = ?
""", (user_id,)).fetchone()
recent = db.execute(
"SELECT * FROM problems WHERE user_id = ? ORDER BY id DESC LIMIT 10",
(user_id,)
).fetchall()
return render_template(
"dashboard.html",
total=stats['total'] or 0,
easy=stats['easy'] or 0,
medium=stats['medium'] or 0,
hard=stats['hard'] or 0,
recent=recent
)
@main_bp.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
if not username or not password:
return "Username and password are required credentials.", 400
db = get_db()
try:
db.execute(
"INSERT INTO users (username, password) VALUES (?, ?)",
(username, generate_password_hash(password))
)
db.commit()
return redirect("/login")
except sqlite3.IntegrityError:
return "That username is already taken.", 400
return render_template("register.html")
@main_bp.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
db = get_db()
user = db.execute("SELECT * FROM users WHERE username = ?", (username,)).fetchone()
if user and check_password_hash(user["password"], password):
session.clear() # Securely clears any dead session remnants before writing new cookies
session["user_id"] = user["id"]
session["username"] = user["username"]
return redirect("/")
return "Invalid username or password.", 401
return render_template("login.html")
@main_bp.route("/logout")
def logout():
session.clear()
return redirect("/login")
@main_bp.route("/add-problem", methods=["POST"])
@login_required
def add_problem():
db = get_db()
db.execute(
"""
INSERT INTO problems (user_id, problem_name, platform, difficulty, topic, solved_date)
VALUES (?, ?, ?, ?, ?, ?)
""",
(
session["user_id"],
request.form.get("problem_name"),
request.form.get("platform"),
request.form.get("difficulty"),
request.form.get("topic"),
request.form.get("solved_date")
)
)
db.commit()
return redirect("/")
@main_bp.route("/leaderboard")
def leaderboard():
db = get_db()
rankings = db.execute(
"""
SELECT users.username, COUNT(problems.id) AS solved
FROM users
LEFT JOIN problems ON users.id = problems.user_id
GROUP BY users.id
ORDER BY solved DESC
"""
).fetchall()
return render_template("leaderboard.html", rankings=rankings)
@main_bp.route("/delete-problem/<int:id>")
@login_required
def delete_problem(id):
db = get_db()
# Explicit ownership validation - ensures hackers cannot delete another user's entries
db.execute("DELETE FROM problems WHERE id = ? AND user_id = ?", (id, session["user_id"]))
db.commit()
return redirect("/")