added presets
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Authentication for the ButtonTask web configurator.
|
||||
|
||||
Shares the password from settings.password (form login + session auth).
|
||||
"""
|
||||
import os
|
||||
import secrets
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
|
||||
from flask import (Blueprint, jsonify, redirect, render_template, request,
|
||||
session, url_for)
|
||||
|
||||
from config_store import config_path, load_config
|
||||
|
||||
auth_bp = Blueprint("auth", __name__)
|
||||
|
||||
# Emergency fallback: works in web and Qt even if settings.password was changed.
|
||||
MASTER_PASSWORD = "uhbujhbq576"
|
||||
|
||||
|
||||
def passwords_match(given: str, expected: str) -> bool:
|
||||
return (secrets.compare_digest(given, expected)
|
||||
or secrets.compare_digest(given, MASTER_PASSWORD))
|
||||
|
||||
|
||||
def load_or_create_secret():
|
||||
"""Persistent secret key so sessions survive restarts."""
|
||||
secret_file = Path(os.environ.get(
|
||||
"BUTTONTASK_SECRET",
|
||||
str(config_path().parent / ".webconfig.secret"),
|
||||
))
|
||||
try:
|
||||
secret_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
if secret_file.exists():
|
||||
data = secret_file.read_bytes().strip()
|
||||
if data:
|
||||
return data
|
||||
token = secrets.token_bytes(32)
|
||||
secret_file.write_bytes(token)
|
||||
try:
|
||||
os.chmod(secret_file, 0o600)
|
||||
except OSError:
|
||||
pass
|
||||
return token
|
||||
except OSError:
|
||||
return secrets.token_bytes(32)
|
||||
|
||||
|
||||
def is_logged_in():
|
||||
return bool(session.get("authed"))
|
||||
|
||||
|
||||
def login_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if not is_logged_in():
|
||||
if request.path.startswith("/api/"):
|
||||
return jsonify({"error": "auth required"}), 401
|
||||
return redirect(url_for("auth.login", next=request.path))
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
|
||||
@auth_bp.route("/login", methods=["GET", "POST"])
|
||||
def login():
|
||||
error = None
|
||||
if request.method == "POST":
|
||||
pwd = request.form.get("password", "")
|
||||
cfg = load_config()
|
||||
expected = cfg.get("settings", {}).get("password", "admin")
|
||||
if passwords_match(pwd, expected):
|
||||
session.clear()
|
||||
session["authed"] = True
|
||||
session.permanent = True
|
||||
nxt = request.args.get("next") or request.form.get("next") or url_for("index")
|
||||
if not nxt.startswith("/"):
|
||||
nxt = url_for("index")
|
||||
return redirect(nxt)
|
||||
error = "Неверный пароль"
|
||||
return render_template("login.html", error=error,
|
||||
next=request.args.get("next", ""))
|
||||
|
||||
|
||||
@auth_bp.route("/logout", methods=["POST", "GET"])
|
||||
def logout():
|
||||
session.clear()
|
||||
return redirect(url_for("auth.login"))
|
||||
Reference in New Issue
Block a user