Skip to content
30 changes: 12 additions & 18 deletions app/routes/account_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,24 @@

from models import User
from utils.delete import delete_user
from utils.log import Log
from utils.route_guards import login_required

account_settings_blueprint = Blueprint("account_settings", __name__)


@account_settings_blueprint.route("/account-settings", methods=["GET", "POST"])
@login_required("account settings", redirect_to="/login/redirect=&account-settings")
def account_settings():
if "username" in session:
user = User.query.filter_by(username=session["username"]).first()
user = User.query.filter_by(username=session["username"]).first()

if not user:
return redirect("/")
if not user:
return redirect("/")

if request.method == "POST":
delete_user(user.username)
return redirect("/")
if request.method == "POST":
delete_user(user.username)
return redirect("/")

return render_template(
"account_settings.html",
user=(user.username,),
)
else:
Log.error(
f"{request.remote_addr} tried to reach account settings without being logged in"
)

return redirect("/login/redirect=&account-settings")
return render_template(
"account_settings.html",
user=(user.username,),
)
28 changes: 6 additions & 22 deletions app/routes/admin_panel.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
from flask import Blueprint, redirect, render_template, request, session
from flask import Blueprint, render_template, session

from models import User
from utils.log import Log
from utils.route_guards import admin_required

admin_panel_blueprint = Blueprint("admin_panel", __name__)


@admin_panel_blueprint.route("/admin")
@admin_required("admin panel")
def admin_panel():
if "username" in session:
user = User.query.filter_by(username=session["username"]).first()
Log.info(f"Admin: {session['username']} reached to the admin panel")

if not user:
return redirect("/")
Log.info("Rendering admin_panel.html: params: None")

if user.role == "admin":
Log.info(f"Admin: {session['username']} reached to the admin panel")

Log.info("Rendering admin_panel.html: params: None")

return render_template("admin_panel.html")
else:
Log.error(
f"{request.remote_addr} tried to reach admin panel without being admin"
)

return redirect("/")
else:
Log.error(f"{request.remote_addr} tried to reach admin panel being logged in")

return redirect("/")
return render_template("admin_panel.html")
48 changes: 19 additions & 29 deletions app/routes/admin_panel_comments.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,34 @@
from flask import (
Blueprint,
redirect,
render_template,
request,
session,
)

from models import Comment
from utils.log import Log
from utils.paginate import paginate_query
from utils.route_guards import admin_required

admin_panel_comments_blueprint = Blueprint("admin_panel_comments", __name__)


@admin_panel_comments_blueprint.route("/admin/comments", methods=["GET", "POST"])
@admin_required("comment admin panel")
def admin_panel_comments():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to comments admin panel")

query = Comment.query.order_by(Comment.time_stamp.desc())
comments_objects, page, total_pages = paginate_query(query)

comments = [
(c.id, c.post_id, c.comment, c.username, c.time_stamp)
for c in comments_objects
]

Log.info(
f"Rendering admin_panel_comments.html: params: comments={len(comments)}"
)

return render_template(
"admin_panel_comments.html",
comments=comments,
page=page,
total_pages=total_pages,
)
else:
Log.error(
f"{request.remote_addr} tried to reach comment admin panel being logged in"
)

return redirect("/")
Log.info(f"Admin: {session['username']} reached to comments admin panel")

query = Comment.query.order_by(Comment.time_stamp.desc())
comments_objects, page, total_pages = paginate_query(query)

comments = [
(c.id, c.post_id, c.comment, c.username, c.time_stamp) for c in comments_objects
]

Log.info(f"Rendering admin_panel_comments.html: params: comments={len(comments)}")

return render_template(
"admin_panel_comments.html",
comments=comments,
page=page,
total_pages=total_pages,
)
77 changes: 35 additions & 42 deletions app/routes/admin_panel_posts.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,51 @@
from flask import (
Blueprint,
redirect,
render_template,
request,
session,
)

from models import Post
from utils.log import Log
from utils.paginate import paginate_query
from utils.route_guards import admin_required

admin_panel_posts_blueprint = Blueprint("admin_panel_posts", __name__)


@admin_panel_posts_blueprint.route("/admin/posts", methods=["GET", "POST"])
@admin_required("post admin panel")
def admin_panel_posts():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to posts admin panel")

query = Post.query.order_by(Post.time_stamp.desc())
posts_objects, page, total_pages = paginate_query(query)

posts = [
(
p.id,
p.title,
p.tags,
p.content,
p.banner,
p.author,
p.views,
p.time_stamp,
p.last_edit_time_stamp,
p.category,
p.url_id,
p.abstract,
)
for p in posts_objects
]

Log.info(
f"Rendering dashboard.html: params: posts={len(posts)} and show_posts=True"
Log.info(f"Admin: {session['username']} reached to posts admin panel")

query = Post.query.order_by(Post.time_stamp.desc())
posts_objects, page, total_pages = paginate_query(query)

posts = [
(
p.id,
p.title,
p.tags,
p.content,
p.banner,
p.author,
p.views,
p.time_stamp,
p.last_edit_time_stamp,
p.category,
p.url_id,
p.abstract,
)

return render_template(
"dashboard.html",
posts=posts,
show_posts=True,
page=page,
total_pages=total_pages,
)
else:
Log.error(
f"{request.remote_addr} tried to reach post admin panel being logged in"
)

return redirect("/")
for p in posts_objects
]

Log.info(
f"Rendering dashboard.html: params: posts={len(posts)} and show_posts=True"
)

return render_template(
"dashboard.html",
posts=posts,
show_posts=True,
page=page,
total_pages=total_pages,
)
96 changes: 39 additions & 57 deletions app/routes/admin_panel_users.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from flask import (
Blueprint,
redirect,
render_template,
request,
render_template,
session,
)

Expand All @@ -11,71 +10,54 @@
from utils.delete import delete_user
from utils.log import Log
from utils.paginate import paginate_query
from utils.route_guards import admin_required

admin_panel_users_blueprint = Blueprint("admin_panel_users", __name__)


@admin_panel_users_blueprint.route("/admin/users", methods=["GET", "POST"])
@admin_required("user admin panel")
def admin_panel_users():
if "username" in session:
Log.info(f"Admin: {session['username']} reached to users admin panel")

user = User.query.filter_by(username=session["username"]).first()

if not user:
return redirect("/")

if request.method == "POST":
if "user_delete_button" in request.form:
Log.info(
f"Admin: {session['username']} deleted user: {request.form['username']}"
)

delete_user(request.form["username"])
Log.info(f"Admin: {session['username']} reached to users admin panel")

if "user_role_change_button" in request.form:
Log.info(
f"Admin: {session['username']} changed {request.form['username']}'s role"
)

change_user_role(request.form["username"])

if user.role == "admin":
query = User.query
users_objects, page, total_pages = paginate_query(query)

users = [
(
u.user_id,
u.username,
u.email,
u.password,
u.profile_picture,
u.role,
u.points,
u.time_stamp,
u.is_verified,
)
for u in users_objects
]
if request.method == "POST":
if "user_delete_button" in request.form:
Log.info(
f"Admin: {session['username']} deleted user: {request.form['username']}"
)

Log.info(f"Rendering admin_panel_users.html: params: users={len(users)}")
delete_user(request.form["username"])

return render_template(
"admin_panel_users.html",
users=users,
page=page,
total_pages=total_pages,
)
else:
Log.error(
f"{request.remote_addr} tried to reach user admin panel without being admin"
if "user_role_change_button" in request.form:
Log.info(
f"Admin: {session['username']} changed {request.form['username']}'s role"
)

return redirect("/")
else:
Log.error(
f"{request.remote_addr} tried to reach user admin panel being logged in"
change_user_role(request.form["username"])
Comment on lines +23 to +36
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Return values from delete_user and change_user_role are silently discarded — redirects won't fire.

Both delete_user() and change_user_role() can return redirect(...) responses (see app/utils/delete.py lines 67–86 and app/utils/change_user_role.py lines 25–27). Since their return values are not propagated here, the code falls through to the query/render block on lines 38–63. This means:

  1. After deleting a user, the flash message fires but the page re-renders (potentially showing the deleted user if the DB commit already happened, or crashing if it didn't).
  2. If an admin demotes themselves, the redirect("/") from change_user_role is lost — the page re-renders, and subsequent requests will fail because the @admin_required guard will reject the now-non-admin user.
🐛 Proposed fix — propagate redirect responses
     if request.method == "POST":
         if "user_delete_button" in request.form:
             Log.info(
                 f"Admin: {session['username']} deleted user: {request.form['username']}"
             )
-            delete_user(request.form["username"])
+            result = delete_user(request.form["username"])
+            if result:
+                return result

-        if "user_role_change_button" in request.form:
+        elif "user_role_change_button" in request.form:
             Log.info(
                 f"Admin: {session['username']} changed {request.form['username']}'s role"
             )
-            change_user_role(request.form["username"])
+            result = change_user_role(request.form["username"])
+            if result:
+                return result
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if request.method == "POST":
if "user_delete_button" in request.form:
Log.info(
f"Admin: {session['username']} deleted user: {request.form['username']}"
)
Log.info(f"Rendering admin_panel_users.html: params: users={len(users)}")
delete_user(request.form["username"])
return render_template(
"admin_panel_users.html",
users=users,
page=page,
total_pages=total_pages,
)
else:
Log.error(
f"{request.remote_addr} tried to reach user admin panel without being admin"
if "user_role_change_button" in request.form:
Log.info(
f"Admin: {session['username']} changed {request.form['username']}'s role"
)
return redirect("/")
else:
Log.error(
f"{request.remote_addr} tried to reach user admin panel being logged in"
change_user_role(request.form["username"])
if request.method == "POST":
if "user_delete_button" in request.form:
Log.info(
f"Admin: {session['username']} deleted user: {request.form['username']}"
)
result = delete_user(request.form["username"])
if result:
return result
elif "user_role_change_button" in request.form:
Log.info(
f"Admin: {session['username']} changed {request.form['username']}'s role"
)
result = change_user_role(request.form["username"])
if result:
return result
🤖 Prompt for AI Agents
In `@app/routes/admin_panel_users.py` around lines 23 - 36, The POST handlers call
delete_user(...) and change_user_role(...) but ignore their return values (which
may be Flask redirect responses); update the POST branch in the request.method
== "POST" block to capture the result of delete_user(request.form["username"])
and change_user_role(request.form["username"]) and, if the result is a
Response/redirect, immediately return it (otherwise continue). Ensure you still
log with Log.info(...) before calling those functions and propagate any redirect
returned by those functions so redirects from delete_user and change_user_role
are not lost.


query = User.query
users_objects, page, total_pages = paginate_query(query)

users = [
(
u.user_id,
u.username,
u.email,
u.password,
u.profile_picture,
u.role,
u.points,
u.time_stamp,
u.is_verified,
)
for u in users_objects
]
Comment on lines +41 to +54
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -E "(admin_panel|routes)" | head -20

Repository: DogukanUrker/FlaskBlog

Length of output: 603


🏁 Script executed:

fd 'admin_panel_users' --type f

Repository: DogukanUrker/FlaskBlog

Length of output: 134


🏁 Script executed:

cat -n app/routes/admin_panel_users.py 2>/dev/null | head -60

Repository: DogukanUrker/FlaskBlog

Length of output: 2117


🏁 Script executed:

cat -n app/templates/admin_panel_users.html

Repository: DogukanUrker/FlaskBlog

Length of output: 5791


Remove password from the user tuple passed to template — it's never used and exposes unnecessary sensitive data.

Line 46 includes u.password in the tuple passed to the template, but the template never accesses this field. Even though passwords are hashed, passing password hashes to the template violates the principle of least privilege and risks unnecessary exposure in HTML source, caches, or logs.

🔒 Proposed fix
     users = [
         (
             u.user_id,
             u.username,
             u.email,
-            u.password,
             u.profile_picture,
             u.role,
             u.points,
             u.time_stamp,
             u.is_verified,
         )
         for u in users_objects
     ]

Update the template indices: after removing u.password, the tuple indices shift by 1. In admin_panel_users.html, update:

  • user[4]user[3] (profile_picture)
  • user[5]user[4] (role)
  • user[6]user[5] (points)
  • user[7]user[6] (timestamp)
🤖 Prompt for AI Agents
In `@app/routes/admin_panel_users.py` around lines 41 - 54, Remove the password
field from the tuple built from users_objects in the users list comprehension
(currently includes u.password) so templates do not receive password hashes;
then update the corresponding index references in admin_panel_users.html to
account for the shifted tuple positions (change user[4]→user[3],
user[5]→user[4], user[6]→user[5], user[7]→user[6]). Locate the list construction
around the users = [ (... ) for u in users_objects ] in admin_panel_users.py and
the index uses in admin_panel_users.html and adjust them accordingly.


Log.info(f"Rendering admin_panel_users.html: params: users={len(users)}")

return redirect("/")
return render_template(
"admin_panel_users.html",
users=users,
page=page,
total_pages=total_pages,
)
Loading