Refactor login flow to use auth blueprint

Moved login route and logic from app.py to application/auth/routes.py under the 'auth' blueprint. Updated all references to the login route to use 'auth.login'. Added a dedicated login.html template under application/auth/templates. Adjusted login_required utility and default_return logic for consistency.
This commit is contained in:
2025-08-11 17:43:46 +02:00
parent ea2ea27d9e
commit 0da580faf1
6 changed files with 74 additions and 34 deletions

27
app.py
View File

@@ -1,17 +1,13 @@
from flask import ( from flask import (
render_template,
redirect, redirect,
url_for, url_for,
request,
send_from_directory, send_from_directory,
) )
from flask_login import ( from flask_login import (
login_required, login_required,
logout_user, logout_user,
login_user,
current_user, current_user,
) )
from forms import LoginForm
from models import User from models import User
from application import db, app, login_manager from application import db, app, login_manager
from application.admin.routes import admin_bp from application.admin.routes import admin_bp
@@ -23,7 +19,7 @@ from typing import Optional
# Config # Config
app.config["SECRET_KEY"] = "Stef123" app.config["SECRET_KEY"] = "Stef123"
login_manager.login_view = "login" # type: ignore login_manager.login_view = "auth.login" # type: ignore
@login_manager.user_loader # type: ignore @login_manager.user_loader # type: ignore
@@ -51,7 +47,7 @@ def default_return(next_page: Optional[str] = None):
@app.route("/") @app.route("/")
@login_required @login_required
def index(): def index():
return redirect(url_for("login")) return redirect(url_for("auth.login"))
@app.route("/favicon.ico") @app.route("/favicon.ico")
@@ -59,25 +55,6 @@ def favicon():
return send_from_directory("static", "favicon.ico") return send_from_directory("static", "favicon.ico")
@app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return default_return()
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and user.check_password(password=form.password.data):
# User found and password correct
next_page = request.args.get("next") # Get next page if given
login_user(user) # Log in the user
return default_return(next_page=next_page)
else:
pass
# invalid user
return render_template("login.html", form=form)
@app.route("/logout") @app.route("/logout")
@login_required @login_required
def logout(): def logout():

View File

@@ -28,7 +28,7 @@ bp = Blueprint(
@bp.before_request @bp.before_request
def login_required(): def login_required():
if not current_user.is_authenticated: if not current_user.is_authenticated:
return redirect(url_for("login")) return redirect(url_for("auth.login"))
@bp.route("/select_meal/<int:meal_type>", methods=["GET"]) @bp.route("/select_meal/<int:meal_type>", methods=["GET"])

View File

@@ -1,13 +1,30 @@
from flask import ( from flask import Blueprint, request, render_template
Blueprint, from flask_login import current_user, login_user
) from forms import LoginForm
from application.utils import login_required from models import User
from application.utils import default_return
bp = Blueprint( bp = Blueprint(
"user", "auth",
__name__, __name__,
template_folder="templates", template_folder="templates",
) )
bp.before_request(login_required) @bp.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return default_return()
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and user.check_password(password=form.password.data):
# User found and password correct
next_page = request.args.get("next") # Get next page if given
login_user(user) # Log in the user
return default_return(next_page=next_page)
else:
pass
# invalid user
return render_template("login.html", form=form)

View File

@@ -0,0 +1,36 @@
{% extends "base.html" %}
{% block content %}
<div class="container d-flex justify-content-center align-items-center">
<div class="card shadow-sm p-4" style="width: 100%; max-width: 400px;">
<h3 class="mb-4 text-center">Login</h3>
<form method="post" novalidate>
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.username.label(class="form-label") }}
{{ form.username(class="form-control", placeholder="Enter username") }}
{% if form.username.errors %}
<div class="text-danger small">
{{ form.username.errors[0] }}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control", placeholder="Enter password") }}
{% if form.password.errors %}
<div class="text-danger small">
{{ form.password.errors[0] }}
</div>
{% endif %}
</div>
<div class="d-grid">
{{ form.submit(class="btn btn-primary btn-lg") }}
</div>
</form>
</div>
</div>
{% endblock%}

View File

@@ -1,11 +1,21 @@
from flask_login import current_user from flask_login import current_user
from flask import redirect, url_for, flash from flask import redirect, url_for, flash
from typing import Optional
def login_required(): def login_required():
if not current_user.is_authenticated: if not current_user.is_authenticated:
return redirect(url_for("auth.login")) return redirect(url_for("auth.login"))
if current_user.must_change_password: # if current_user.must_change_password:
flash("You have to change your password") flash("You have to change your password")
return redirect(url_for("auth.change_password")) return redirect(url_for("auth.change_password"))
return return
def default_return(next_page: Optional[str] = None):
return redirect(url_for("user.daily_log"))
if next_page:
return redirect(next_page)
if current_user.is_admin:
return redirect(url_for("admin.food_items"))
return redirect(url_for("dashboard"))

View File

@@ -11,7 +11,7 @@ from wtforms.validators import DataRequired, InputRequired, Optional
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()]) username = StringField("Username", validators=[DataRequired()])
password = PasswordField("Password", validators=[DataRequired()]) password = PasswordField("Password", validators=[DataRequired()])
submit = SubmitField("Login") submit = SubmitField("auth.login")
class FoodItemForm(FlaskForm): class FoodItemForm(FlaskForm):