From a42cefbbee178498afdd65ae0f774c2cdd99493f Mon Sep 17 00:00:00 2001 From: Frederick Yin Date: Wed, 27 Oct 2021 23:07:55 +0800 Subject: Admin console requires login to admin account --- jimbrella/admin.py | 17 ++++++++++++++++- jimbrella/auth.py | 33 +++++++++++++++++++++++++-------- jimbrella/users.py | 10 ++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/jimbrella/admin.py b/jimbrella/admin.py index 4c604be..04a3f88 100644 --- a/jimbrella/admin.py +++ b/jimbrella/admin.py @@ -1,11 +1,26 @@ -from flask import Blueprint, request, render_template, redirect, url_for +from flask import Blueprint, request, session, render_template, redirect, url_for, abort from user_agents import parse as user_agent from .database import Database +from .users import Users from .exceptions import * from .config import * bp = Blueprint("admin", __name__, url_prefix="/admin") db = Database(DATABASE_PATH) +users = Users(USERS_PATH) + + +@bp.before_request +def check_privilege(): + # only clients who have obtained a session and sent it in the Cookie header + # will have a decryptable username here + if "username" not in session: + return redirect(url_for("auth.login")) + + username = session["username"] + user = users.find(username) # under normal circumstances it must exist + if user["role"] != "admin": + abort(403) @bp.route("/") diff --git a/jimbrella/auth.py b/jimbrella/auth.py index ca0f64a..2c33807 100644 --- a/jimbrella/auth.py +++ b/jimbrella/auth.py @@ -1,11 +1,19 @@ -from flask import Blueprint, request, render_template, redirect, url_for +from flask import Blueprint, request, session, render_template, redirect, url_for from werkzeug.security import generate_password_hash, check_password_hash from .users import Users from .exceptions import UsernameTakenError from .config import * bp = Blueprint("auth", __name__, url_prefix="/") -db = Users(USERS_PATH) +users = Users(USERS_PATH) + + +def show_error(action, message): + return render_template( + "auth.html", + action=action, + error=message, + ) @bp.route("/login", methods=["GET", "POST"]) @@ -17,11 +25,19 @@ def login(): username = request.form.get("username") password = request.form.get("password") if not all([username, password]): - return render_template( - "auth.html", - action="login", - error="Please fill in both the username and password.", - ) + return show_erro("login", "Please fill in both the username and password.") + + user = users.find(username) + if user is None: + return show_error("login", f"User {username} does not exist.") + + if not check_password_hash(user["password"], password): + return show_error("login", "Incorrect password. Sorry.") + + # give access + session.clear() + session["username"] = username + return redirect(url_for("admin.index")) @bp.route("/register", methods=["GET", "POST"]) @@ -39,7 +55,7 @@ def register(): ) try: - db.register(username, generate_password_hash(password), "en-US") + users.register(username, generate_password_hash(password), "en-US") except UsernameTakenError as e: return render_template( "auth.html", @@ -47,4 +63,5 @@ def register(): error=e.message, ) + session["username"] = username return redirect(url_for("admin.index")) diff --git a/jimbrella/users.py b/jimbrella/users.py index c68908f..3276062 100644 --- a/jimbrella/users.py +++ b/jimbrella/users.py @@ -72,3 +72,13 @@ class Users(CsvTable): "email": "", } self._append(user) + + def find(self, username) -> dict: + """Find a user and return it in its `dict` structure.""" + + users = self._read() + for user in users: + if user["username"] == username: + return user + + return None -- cgit v1.2.3