Files
yaris-obd/server/modules/user_auth.py
T
Mathieu MoranandCopilot 693848aba1 Fix remote portal trip list
- /api/trips now returns {trips:[...]} to match what history.js expects (result.trips)
- odo_start_km null guard in history.js (server trips have no odometer data)
- require_login returns 401 JSON for /api/* paths instead of HTML redirect

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:27:57 -04:00

52 lines
1.4 KiB
Python

"""Browser session authentication using Flask-Login + bcrypt.
A single admin user is created via scripts/create_user.py.
Device upload auth (X-Api-Key) is separate and unchanged.
"""
import bcrypt
from functools import wraps
from flask import redirect, url_for
from flask_login import LoginManager, UserMixin, current_user
from modules import db
login_manager = LoginManager()
login_manager.login_view = "login_page"
class User(UserMixin):
def __init__(self, id, username):
self.id = id
self.username = username
@login_manager.user_loader
def load_user(user_id):
row = db.get_user_by_id(int(user_id))
if row is None:
return None
return User(row["id"], row["username"])
def check_password(plain, hashed):
return bcrypt.checkpw(plain.encode("utf-8"), hashed.encode("utf-8"))
def hash_password(plain):
return bcrypt.hashpw(plain.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
def require_login(view):
"""Decorator: redirect to login page if not authenticated (HTML routes),
or return 401 JSON for /api/* routes."""
@wraps(view)
def wrapped(*args, **kwargs):
if not current_user.is_authenticated:
from flask import request, jsonify
if request.path.startswith("/api/"):
return jsonify(error="not authenticated"), 401
return redirect(url_for("login_page"))
return view(*args, **kwargs)
return wrapped